/* =============================================================================
   forms.css — the field frame and the text-entry controls.

   A REAL stylesheet, not a scoped .razor.css, and deliberately so. Scoped CSS is
   per component: a class defined in FormField.razor.css does not reach the markup
   TextField.razor renders (skill §8). These classes are shared by every control in
   the form inventory, so they need one shared home.

   Semantic tokens only. No hard-coded colour, spacing, radius or height anywhere in
   this file — DesignTokenTests enforces it.
   ========================================================================== */

/* -- the field frame -------------------------------------------------------- */

.hrc-field {
  display: flex;
  flex-direction: column;
  gap: var(--hrc-space-2xs);

  /* Without this, one long unbreakable value — a pasted token, an email address —
     widens the whole form instead of scrolling or wrapping inside the field.
     Skill §1b: min-inline-size: 0 on every flex/grid child that can hold wide content. */
  min-inline-size: 0;
}

.hrc-field__label {
  /* P5.4-fixes (2026-08-03) MYS Option 1: field labels adopt the prototype .lbl
     shape - smaller (12.5px), semibold (600), softer ink (--hrc-ink-muted).
     Cascades to every form in the app: setup wizard, change-password, tenant
     setup, /masters edit, audit-log filter, My Activities. */
  font-size: var(--hrc-text-xs);
  font-weight: var(--hrc-weight-semibold);
  color: var(--hrc-ink-muted);
  line-height: var(--hrc-leading-tight);
  /* P5.4-fixes MYS bugfix (mastername-bug.png): "Master Name" was clipping to
     "Master Na" inside an inline-flex parent. Labels never wrap; when they sit
     in an inline field they must also refuse to shrink. */
  white-space: nowrap;
}

.hrc-field__required {
  color: var(--hrc-crit);
  margin-inline-start: var(--hrc-space-2xs);
}

/* The two non-default layouts (stage 5). Only the label's element and position
   change — ids, ARIA, the required marker and the hint/error rendering are shared,
   which is the whole reason these are a modifier on the one frame rather than a
   second field frame. See FieldLayout. */

/* INLINE — a single checkbox: control first, label beside it. Baseline alignment
   rather than centre, so a label that wraps to two lines keeps its first line level
   with the box instead of floating half a line below it. */
.hrc-field__row {
  display: flex;
  align-items: baseline;
  gap: var(--hrc-space-xs);
  min-inline-size: 0;
}

.hrc-field--inline .hrc-field__label {
  /* The label is now the click target for the box beside it, so it must say so. */
  cursor: pointer;

  /* Normal weight: beside a control it reads as the control's text, not as a
     heading over a group of fields. */
  font-weight: var(--hrc-weight-regular);
  min-inline-size: 0;
}

/* The hint and error still belong to the field, not to the row — indent them to the
   label's edge so they read as attached to it rather than to the page. */
.hrc-field--inline .hrc-field__hint,
.hrc-field--inline .hrc-field__error {
  margin-inline-start: calc(var(--hrc-choice-size) + var(--hrc-space-xs));
}

/* GROUP — a fieldset. Browsers give fieldset a default border, padding and margin
   that no other element has; all three are cleared so it lays out exactly like the
   div every other field uses. */
.hrc-field__group {
  margin: 0;
  padding: 0;
  border: 0;
  min-inline-size: 0;
}

.hrc-field__group > .hrc-field__label {
  /* legend is not a flex/block child in the ordinary way — padding: 0 removes the
     inline padding browsers add, so the legend's text lines up with the options. */
  padding: 0;
  margin-block-end: var(--hrc-space-2xs);
}

.hrc-field__hint {
  font-size: var(--hrc-text-xs);
  color: var(--hrc-ink-muted);
  line-height: var(--hrc-leading);
  margin: 0;
}

.hrc-field__error {
  font-size: var(--hrc-text-xs);
  color: var(--hrc-crit);
  line-height: var(--hrc-leading);
  margin: 0;
}

/* -- the control itself ----------------------------------------------------- */

.hrc-input {
  inline-size: 100%;
  /* Cap on inline-size so a field inside a wide section doesn't stretch to the whole
     section width — an oversized single-line input reads as "type paragraphs here" when
     the value is a code or an email. Token defaults to 32rem (tokens.css §5). Opt-out
     per field with .hrc-input--wide. Packet edit-tenant 2026-07-30. */
  max-inline-size: var(--hrc-input-max-inline-size);
  min-inline-size: 0;
  block-size: var(--hrc-field-height);
  padding-inline: var(--hrc-space-sm);
  color: var(--hrc-ink);
  background-color: var(--hrc-surface);
  /* P5.4-fixes (2026-08-03) MYS Option 1: crisper border matches prototype .ctl
     (var(--border-hard)); soft --hrc-border made the fields look "unstyled" on
     the P5.4 verify walk. Cascades to every text/number/date/select field. */
  border: 1px solid var(--hrc-border-strong);
  border-radius: var(--hrc-radius-sm);
  font-size: var(--hrc-density-text);

  /* Colour and border only. Never transition block-size or padding: density switches
     rebind those tokens, and animating the change makes every field on screen slide. */
  transition:
    border-color var(--hrc-duration) var(--hrc-ease),
    background-color var(--hrc-duration) var(--hrc-ease);
}

/* OPT-OUT — the field is legitimately freeform-width (street address, multi-line note,
   a code block). Documents the deviation at the call site rather than removing the
   cap globally. */
.hrc-input--wide {
  max-inline-size: none;
}

.hrc-input:hover:not(:disabled):not([readonly]) {
  border-color: var(--hrc-border-strong);
}

.hrc-input:disabled {
  background-color: var(--hrc-surface-raised);
  color: var(--hrc-ink-subtle);
  cursor: not-allowed;
}

.hrc-input[readonly] {
  background-color: var(--hrc-surface-raised);
}

.hrc-input::placeholder {
  color: var(--hrc-ink-subtle);
}

/* The invalid border is on the WRAPPER's modifier, not on :invalid. The browser's own
   :invalid fires while the user is still typing — a half-entered email is not an error
   yet — and it cannot know about a server-side failure at all, which is the case that
   actually matters here (client validation is UX; the server is the control). */
.hrc-field--invalid .hrc-input {
  border-color: var(--hrc-crit);
}

.hrc-field--invalid .hrc-input:focus-visible {
  outline-color: var(--hrc-crit);
}

/* MID-CORRECTION. Added by forms.js while the current value differs from the one
   that failed. Under static SSR there is no live validation, so without this a
   field stays red for the whole time the user spends fixing it — red on a box the
   user just corrected says "still wrong" when the truth is "unknown".

   Deliberately NEUTRAL, not green. The server has not spoken and cannot until the
   next post, so the only honest claim is "changed since the error". A green tick
   here would be the component asserting something it does not know. */
.hrc-field--correcting .hrc-input {
  border-color: var(--hrc-border-strong);
}

.hrc-field--correcting .hrc-input:focus-visible {
  outline-color: var(--hrc-accent);
}

.hrc-field--correcting .hrc-field__error {
  /* Dimmed, not hidden. Removing it would reflow the form under the user's cursor
     mid-typing, and they may still want to read what was wrong. */
  color: var(--hrc-ink-muted);
}

/* -- textarea --------------------------------------------------------------- */

.hrc-input--multiline {
  /* Overrides the fixed control height: a textarea is sized in rows, not by density. */
  block-size: auto;
  min-block-size: calc(var(--hrc-field-height) * 2);
  padding-block: var(--hrc-space-2xs);
  line-height: var(--hrc-leading);

  /* Vertical only. Horizontal resize lets a user drag a field wider than its container
     and produce the page-level scroll the responsive contract forbids. */
  resize: vertical;
}

/* -- button ----------------------------------------------------------------- */
/* Three variants, and only three: PRIMARY (the one recommended action), SECONDARY
   (an alternative that is not the main path — a quiet, bordered surface button),
   and DANGER (an action that destroys work, styled to make the user pause). Bare
   `.hrc-button` IS primary, so every existing Save keeps working unchanged.

   Pulled forward from stage 5 to fix a real defect: the two concurrency-clash
   actions weighed the same, though one discards YOUR typing and the other
   overwrites a COLLEAGUE'S saved change. They must not look alike. Sizes and
   icon-only are still deferred — nothing needs them yet (YAGNI); when they land,
   grow THIS rule set rather than forking a second one.

   NOTE: a button is NOT .hrc-input. It carries no dir="auto", because its text is
   our English chrome rather than customer data, and a viewport test asserts that.
   Meaning is never carried by colour alone — the LABEL says what the action does;
   the danger colour only adds emphasis (WCAG 1.4.1). */

.hrc-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  block-size: var(--hrc-field-height);
  padding-inline: var(--hrc-space-md);
  border: 1px solid transparent;
  border-radius: var(--hrc-radius-sm);
  font-size: var(--hrc-density-text);
  font-weight: var(--hrc-weight-medium);
  cursor: pointer;

  /* An ANCHOR can wear this class, and from stage 6 onward it routinely does: a
     destructive control is a link to a confirm route, and Cancel is a link back.
     Without this the browser's own <a> underline leaks through, so the same class
     rendered two visibly different controls side by side. A <button> has no such
     default, which is why this stayed invisible until the first anchor wore it. */
  text-decoration: none;

  transition:
    background-color var(--hrc-duration) var(--hrc-ease),
    border-color var(--hrc-duration) var(--hrc-ease),
    color var(--hrc-duration) var(--hrc-ease);

  /* Primary is the default appearance, so `class="hrc-button"` alone is the main
     action. --secondary and --danger override the three colour properties below. */
  border-color: var(--hrc-accent);
  background-color: var(--hrc-accent);
  color: var(--hrc-accent-on);
}

.hrc-button:hover:not(:disabled):not([data-hrc-busy]) {
  background-color: var(--hrc-accent-hover);
  border-color: var(--hrc-accent-hover);
}

/* SECONDARY — a real alternative, visually quieter than primary. Surface fill and
   a border, so it reads as "you could, but this isn't the main thing". */
.hrc-button--secondary {
  border-color: var(--hrc-border-strong);
  background-color: var(--hrc-surface);
  color: var(--hrc-ink);
}

.hrc-button--secondary:hover:not(:disabled):not([data-hrc-busy]) {
  border-color: var(--hrc-border-strong);
  background-color: var(--hrc-surface-hover);
}

/* COMPACT — a tighter button variant for dense chrome (DataGrid toolbar, filter bars).
   Not a new "size" — the primary/secondary/danger meanings still apply. Reduces the
   vertical height + inline padding + font-size for the DataTables-style dense aesthetic
   MYS's reference grid uses (small buttons that do not eat screen space). Composable:
   `hrc-button hrc-button--secondary hrc-button--compact`. */
.hrc-button--compact {
  block-size: calc(var(--hrc-field-height) - 0.5rem);
  padding-inline: var(--hrc-space-sm);
  font-size: 0.8125rem;
}

/* DANGER — destroys work. Outlined rather than filled: a solid red button INVITES
   the click it should make the user hesitate over. Red border and text carry the
   warning; the fill stays calm until hover. */
.hrc-button--danger {
  border-color: var(--hrc-crit);
  background-color: var(--hrc-surface);
  color: var(--hrc-crit);
}

.hrc-button--danger:hover:not(:disabled):not([data-hrc-busy]) {
  border-color: var(--hrc-crit);
  background-color: var(--hrc-crit-soft);
  color: var(--hrc-crit);
}

/* GHOST — a borderless button for card headers, per-row actions, subtle affordances
   (Harbor primitive .btn--ghost). Composable with --sm for the Card.actions cluster
   pattern where you want a low-weight action next to the title. Distinct from
   --secondary (which is bordered): --ghost DOES NOT compete visually with the
   content it sits beside. */
.hrc-button--ghost {
  border-color: transparent;
  background-color: transparent;
  color: var(--hrc-ink-muted);
}

.hrc-button--ghost:hover:not(:disabled):not([data-hrc-busy]) {
  background-color: var(--hrc-surface-hover);
  color: var(--hrc-ink);
  border-color: transparent;
}

a.hrc-button--ghost,
a.hrc-button--ghost:hover {
  color: var(--hrc-ink-muted);
}

a.hrc-button--ghost:hover {
  color: var(--hrc-ink);
}

/* SMALL — a shorter, tighter button for card action clusters, dl row edits, and
   any header-level action that should not tower over its title (Harbor .btn--sm).
   Composable with any variant. Distinct from --compact: --sm is the header/inline
   size in Harbor's tenant-detail cards; --compact is the DataGrid toolbar size,
   with different padding/font weight from the DataTables lineage. */
.hrc-button--sm {
  block-size: calc(var(--hrc-field-height) - 0.375rem);
  padding-inline: var(--hrc-space-sm);
  font-size: var(--hrc-text-sm);
}

/* ICON — square, icon-only row action (P7.5, 2026-08-06). Used for Edit / Reset
   password / Archive on the Users and User Groups grids. Compose with --secondary
   or --danger for tone. Every consumer must supply a `title` attribute AND either
   an aria-label or an <span class="hrc-sr-only"> so screen readers still read the
   action - the visual icon is not a label. */
.hrc-button--icon {
  inline-size: 32px;
  block-size: 32px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
}

.hrc-button--icon > svg {
  inline-size: 14px;
  block-size: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* When the button links away, the anchor inherits icon-btn shape via composed
   class. The base anchor-color rule further down still applies for tone. */

/* sr-only helper - screen-reader-only text for icon buttons whose visual is the
   only cue for sighted users. Standard clip pattern. */
.hrc-sr-only {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Every interactive element shows a visible ring (WCAG 2.2 AA). The base button
   had none — a gap this session closes while it is in here. */
.hrc-button:focus-visible {
  outline: var(--hrc-focus-ring);
  outline-offset: var(--hrc-focus-offset);
}

/* An <a> wearing this class inherits `a:hover { color: var(--hrc-accent-hover) }`
   from base.css, whose PSEUDO-CLASS specificity (0,1,1) beats a bare `.hrc-button`
   (0,1,0). Under hover that dragged text colour toward the button's background, so a
   sign-in button in dark mode rendered near-invisible on approach — spotted running
   the shell (task 3.2) after signing out onto /logout. Fix specificity by tagging
   the anchor form explicitly for each variant so hover only changes background. */
a.hrc-button,
a.hrc-button:hover {
  color: var(--hrc-accent-on);
}

a.hrc-button--secondary,
a.hrc-button--secondary:hover {
  color: var(--hrc-ink);
}

a.hrc-button--danger,
a.hrc-button--danger:hover {
  color: var(--hrc-crit);
}

.hrc-button:disabled {
  background-color: var(--hrc-surface-raised);
  border-color: var(--hrc-border);
  color: var(--hrc-ink-subtle);
  cursor: not-allowed;
}

/* Set by forms.js on the first submit. NOT :disabled — disabling a submit button
   during its own submit event can drop its name/value from the payload, which
   would break any form distinguishing Save from Save-and-new. The actual guard is
   the second submit event being prevented; this is only the visible half. */
.hrc-button[data-hrc-busy] {
  cursor: progress;
  opacity: 0.7;
  pointer-events: none;
}

/* -- alert ------------------------------------------------------------------
   A submission outcome that is NOT a validation failure: a concurrency clash, a
   downstream service that did not answer. Validation — including whole-form rules
   — belongs in the error summary below, because it is the user's data and the
   user can fix it. See FormAlert's own remarks for why conflating the two misleads.

   Meaning is carried by the TITLE TEXT, never by colour alone (WCAG 1.4.1). The
   accent bar is decoration on top of a sentence that already says what happened. */

.hrc-alert {
  display: flex;
  flex-direction: column;
  gap: var(--hrc-space-xs);
  min-inline-size: 0;
  padding: var(--hrc-space-md);
  border: 1px solid var(--hrc-border);
  border-inline-start: var(--hrc-space-2xs) solid var(--hrc-ink-subtle);
  border-radius: var(--hrc-radius-sm);
  background-color: var(--hrc-surface-raised);
  color: var(--hrc-ink);
}

.hrc-alert:focus-visible {
  outline: var(--hrc-focus-ring);
  outline-offset: var(--hrc-focus-offset);
}

.hrc-alert--info {
  border-inline-start-color: var(--hrc-accent);
  background-color: var(--hrc-accent-soft);
}

.hrc-alert--success {
  border-inline-start-color: var(--hrc-ok);
  background-color: var(--hrc-ok-soft);
}

.hrc-alert--warning {
  border-inline-start-color: var(--hrc-warn);
  background-color: var(--hrc-warn-soft);
}

.hrc-alert--critical {
  border-inline-start-color: var(--hrc-crit);
  background-color: var(--hrc-crit-soft);
}

.hrc-alert__title {
  margin: 0;
  font-size: var(--hrc-density-text);
  font-weight: var(--hrc-weight-semibold);
  line-height: var(--hrc-leading-tight);
}

/* The record the alert is about. Shrink-wrapped deliberately: a full-width block carrying
   dir="auto" aligns to its OWN direction, so an Arabic name would sit at the far right of a wide
   alert while a Latin one sits at the left — the same message changing sides with the data.
   Hugging the text keeps it beside the title either way; the text inside still flows correctly. */
.hrc-alert__subject {
  margin: 0;
  inline-size: fit-content;
  max-inline-size: 100%;
  overflow-wrap: anywhere;
  font-size: var(--hrc-density-text);
  font-weight: var(--hrc-weight-medium);
  line-height: var(--hrc-leading-tight);
}

.hrc-alert__body {
  font-size: var(--hrc-text-sm);
  color: var(--hrc-ink-muted);
  line-height: var(--hrc-leading);
}

.hrc-alert__body p {
  margin: 0;
}

.hrc-alert__reference {
  margin: 0;
  font-size: var(--hrc-text-xs);
  color: var(--hrc-ink-muted);
}

.hrc-alert__code {
  font-family: var(--hrc-font-mono);
  /* A support reference gets read out over a phone, so it must be selectable and
     unambiguous — never wrapped mid-token. */
  white-space: nowrap;
}

.hrc-alert__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--hrc-space-xs);
}

/* -- error summary -----------------------------------------------------------
   Everything wrong with this submission, at the top, each entry a link to its
   field. The duplication with the field messages is the FEATURE: this is
   navigation, the message under the box is correction context.

   Both render from EditContext.GetValidationMessages, so they cannot drift. */

.hrc-error-summary {
  min-inline-size: 0;
  padding: var(--hrc-space-md);
  border: 1px solid var(--hrc-crit);
  border-inline-start: var(--hrc-space-2xs) solid var(--hrc-crit);
  border-radius: var(--hrc-radius-sm);
  background-color: var(--hrc-crit-soft);
  color: var(--hrc-ink);
}

.hrc-error-summary:focus-visible {
  outline: var(--hrc-focus-ring);
  outline-offset: var(--hrc-focus-offset);
}

.hrc-error-summary__title {
  margin: 0 0 var(--hrc-space-xs) 0;
  font-size: var(--hrc-text-lg);
  font-weight: var(--hrc-weight-semibold);
  line-height: var(--hrc-leading-tight);
}

.hrc-error-summary__list {
  margin: 0;
  padding-inline-start: var(--hrc-space-md);
  font-size: var(--hrc-density-text);
  line-height: var(--hrc-leading);
}

.hrc-error-summary__item {
  /* One long unbroken value in a message must wrap rather than widen the page. */
  overflow-wrap: anywhere;
}

.hrc-error-summary__item + .hrc-error-summary__item {
  margin-block-start: var(--hrc-space-2xs);
}

.hrc-error-summary__link {
  color: var(--hrc-crit);
  /* Underlined by default, not only on hover: inside a coloured panel, "this is a
     link" cannot rest on colour, which is already doing the job of "this is an
     error". */
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.hrc-error-summary__link:focus-visible {
  outline: var(--hrc-focus-ring);
  outline-offset: var(--hrc-focus-offset);
  border-radius: var(--hrc-radius-xs);
}

.hrc-error-summary__field {
  font-weight: var(--hrc-weight-medium);
}

/* Matches the field's own mid-correction state: the user has edited this field
   since it failed, so the entry is no longer a live complaint. Dimmed rather than
   removed — removing it would leave the heading's count disagreeing with the list. */
.hrc-error-summary__link--stale {
  color: var(--hrc-ink-muted);
}

/* -- numbers ---------------------------------------------------------------- */

.hrc-input--numeric {
  /* Tabular figures so digits line up column-wise — money and counts are read by
     comparing them, and proportional digits make that harder than it needs to be. */
  font-variant-numeric: tabular-nums;
}

/* UI-P8-4 (2026-08-07). Small integer fields: retry counts, minimum length, lockout
   attempts. A wide box for a 2-digit number reads "type paragraphs here" and drags the
   next field far to the right — see Password Policy defect screenshot 2026-08-05. */
.hrc-input--narrow {
  max-inline-size: 9ch;
  text-align: end;
}

/* Packet P8.1 (2026-08-08). In-card group heading. Used when a single Section
   card holds several logical groups (User Edit: Identity + Group membership).
   Smaller than the card's own .hrc-section__title (h2), separated with an
   accent line so it reads as a divider inside the card rather than a new card. */
.hrc-form-subhead {
  font-size: var(--hrc-text-sm);
  font-weight: var(--hrc-weight-semibold);
  color: var(--hrc-ink);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin: var(--hrc-space-md) 0 var(--hrc-space-2xs);
  padding-block-end: var(--hrc-space-2xs);
  border-block-end: 1px solid var(--hrc-border);
}

.hrc-form-subhead:first-child {
  margin-block-start: 0;
}
