/**
 * base.css — reset + the cross-surface primitives every screen (public, portal, office)
 * shares: the `:lang(ar)` base layer, focus ring, cursor policy, and the small set of
 * components (`.chip`/`.chip--ghost`, `.skip-link`, `.visually-hidden`) that are not
 * specific to any one surface. Surface-specific layout lives in public.css / portal.css
 * / office.css. Every value here is `var(--token)` from tokens.css — see design.md §0.
 */

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* The `hidden` attribute must win over any component's own `display` — the UA
   `[hidden] { display: none }` rule has zero specificity, so a `.chip`
   (`display: inline-flex`) with `hidden` set stayed visible. This surfaced as a
   dead "Back" chip on S6 step 1 and a dead "Next" beside "Send application" on
   step 3, because the step controller toggles `.hidden` on real `.chip`
   buttons (design review, this session). One `!important` guard fixes every
   such element product-wide. */
[hidden] {
  display: none !important;
}

html {
  scrollbar-gutter: stable both-edges; /* design.md §10 — RTL on Windows puts the bar on the LEFT */
}

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-stack-text-lat);
  font-size: var(--text-body-lat-size);
  line-height: var(--text-body-lat-leading);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1,
h2,
h3,
p,
ul,
ol,
figure {
  margin: 0;
}

ul,
ol {
  padding-inline-start: 0;
  list-style: none;
}

img,
video {
  max-inline-size: 100%;
  display: block;
}

a {
  color: inherit;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
}

/* ── design.md §2.2 — the cursor policy ──────────────────────────────────────
   System cursor, always. `pointer` on enabled interactive elements is the ONLY
   cursor rule this product ships — no `cursor: none`, no pointer-following
   element, no keyword swap on disabled controls (they keep the system arrow). */
a,
button:not(:disabled),
[role="button"]:not([aria-disabled="true"]) {
  cursor: pointer;
}

/* ── design.md §4.5 — the `:lang(ar)` base layer, shipped verbatim ─────────── */
:lang(ar),
:lang(ar) * {
  letter-spacing: 0 !important;
}
:lang(ar) {
  font-family: var(--font-stack-text-ar);
  font-style: normal;
  font-synthesis: none;
  text-transform: none;
  line-height: 1.85;
  text-align: start;
  word-break: normal;
  overflow-wrap: normal;
}
:lang(ar) :is(h1, h2, h3, .display) {
  line-height: 1.35;
}
:lang(ar) :is(em, i) {
  font-style: normal;
  font-weight: 700;
}

/* ── design.md §3.3 — focus, unconditional. Never `outline: none`. Visible on
   keyboard focus AND on programmatic focus after a validation failure, so this
   binds on `:focus`, not only `:focus-visible`. ─────────────────────────── */
:focus {
  outline: var(--focus-outline-width) solid var(--color-focus);
  outline-offset: var(--focus-outline-offset);
  box-shadow: var(--focus-inner-ring);
}
[data-on-inverted]:focus {
  outline-color: var(--color-focus-on-light);
  box-shadow: var(--focus-inner-ring-on-light);
}

.visually-hidden {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ── design.md §11.7 — the hazard chip and its ghost variant ────────────────
   `.chip--ghost` is what the skip link (below) and every secondary CTA use. */
.chip,
.chip--ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-block-size: var(--chip-block-size);
  padding-inline: var(--chip-pad-inline);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  font-family: var(--font-stack-display-lat);
  font-weight: var(--text-chip-lat-weight);
  font-size: var(--text-chip-lat-size);
  line-height: var(--text-chip-lat-leading);
  letter-spacing: var(--text-chip-lat-tracking);
  text-transform: uppercase;
  text-decoration: none;
  transition:
    background-color var(--duration-instant),
    border-color var(--duration-instant),
    color var(--duration-instant);
}
:lang(ar) .chip,
:lang(ar) .chip--ghost {
  font-family: var(--font-stack-display-ar);
  font-weight: var(--text-chip-ar-weight);
  font-size: var(--text-chip-ar-size);
  line-height: var(--text-chip-ar-leading);
  text-transform: none;
}
.chip {
  background: var(--chip-bg);
  color: var(--chip-color);
  border: none;
}
.chip:hover {
  background: var(--chip-hover-bg);
}
.chip--ghost {
  background: var(--chip-ghost-bg);
  color: var(--chip-ghost-color);
  border: 1px solid var(--chip-ghost-border-color);
}
.chip--ghost:hover {
  border-color: var(--chip-ghost-hover-border-color);
}
/* S14/S29 (slice A-2): the sign-in/submit chip is full-inline-size in the single-column
   auth form (docs/03-design.md S14: "the primary chip, full inline-size"). A modifier
   here rather than a per-page inline style, matching every other chip variant's shape. */
.chip--full {
  inline-size: 100%;
}
/* design.md §11.7 — the featured-tier CTA (S2): hazard yellow on the inverted
   (chalk) plate is unreadable, so this control inverts instead of turning ghost.
   Pair with `data-on-inverted` so the global `[data-on-inverted]:focus` rule above
   switches its focus ring to the on-light variant. */
.chip--invert {
  background: var(--chip-invert-bg);
  color: var(--chip-invert-color);
  border: none;
}
.chip--invert:hover {
  background: var(--chip-invert-hover-bg);
}

/* ── design.md §11's shared chrome — skip link ───────────────────────────────
   First focusable element; hidden until focused, then a `chip--ghost` inset
   `edge-safe` from the corner. A transform (not display/visibility) keeps it
   in the tab order at all times. */
.skip-link {
  position: fixed;
  inset-block-start: var(--edge-safe);
  inset-inline-start: var(--edge-safe);
  z-index: var(
    --skip-link-z
  ); /* design.md §11.3a — above everything: seam < rail < nav < skip link */
  transform: translateY(-150%);
  transition: transform var(--duration-fast) var(--ease-enter);
}
.skip-link:focus {
  transform: translateY(0);
}

/* ── design.md §7.6 — reduced motion: state-flip transitions collapse ──────── */
@media (prefers-reduced-motion: reduce) {
  .skip-link {
    transition: none;
  }
}

/* ── Plate (design.md §11.13) — S14's card, every S28 state, and S4's failure/
   offline states. Moved here from `office.css` when S4 (public) became the second
   consumer — none of these rules ever had an office-specific dependency. ────── */
.plate {
  background: var(--plate-bg);
  border: var(--seam-size) solid var(--color-rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: var(--plate-pad);
}
.plate--standalone {
  max-inline-size: var(--plate-max-inline-size);
  inline-size: 100%;
  padding: var(--plate-standalone-pad);
}
.plate--warn {
  border-inline-start: var(--plate-border-inline-start-width) solid
    var(--plate-warn-color);
}
.plate--neutral {
  border-inline-start: var(--plate-border-inline-start-width) solid
    var(--plate-neutral-color);
}
.plate--info {
  border-inline-start: var(--plate-border-inline-start-width) solid
    var(--plate-info-color);
}
.plate__label {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  margin: 0 0 var(--space-8);
  font-family: var(--font-stack-mono);
  font-weight: var(--text-label-lat-weight);
  font-size: var(--text-label-lat-size);
  letter-spacing: var(--text-label-lat-tracking);
  text-transform: uppercase;
  color: var(--color-ink-muted);
}
/* IBM Plex Mono carries no Arabic — without this the Arabic plate label
   dropped to a system fallback face at 13px, below the 15px Arabic label
   floor. The Arabic label tier is the text face, not mono, and never
   uppercased/tracked (design review, this session). */
:lang(ar) .plate__label {
  font-family: var(--font-stack-text-ar);
  font-weight: var(--text-label-ar-weight);
  font-size: var(--text-label-ar-size);
  line-height: var(--text-label-ar-leading);
  letter-spacing: 0;
  text-transform: none;
}
.plate__label-icon {
  inline-size: 16px;
  block-size: 16px;
  flex: none;
}
.plate__body {
  margin: 0;
  font-size: var(--text-body-lat-size);
  line-height: var(--text-body-lat-leading);
  color: var(--color-ink);
}
:lang(ar) .plate__body {
  font-size: var(--text-body-ar-size);
  line-height: var(--text-body-ar-leading);
  letter-spacing: 0 !important;
}
.plate__reference {
  display: block;
  margin-block-start: var(--space-8);
  font-family: var(--font-stack-mono);
  font-size: var(--text-data-lat-size);
  color: var(--color-ink-muted);
  direction: ltr;
  unicode-bidi: isolate;
}
.plate__action {
  margin-block-start: var(--space-16);
}

/* ── Fields (design.md §11.11) ───────────────────────────────────────────────── */
.field-stack {
  display: flex;
  flex-direction: column;
  gap: var(--field-stack-gap);
}
.field {
  display: flex;
  flex-direction: column;
  gap: var(--field-label-gap);
}
.field__label {
  /* The label tier is IBM Plex Mono (design.md §type) — the Latin TEXT face
     (Inter) was paired with the label tier's mono size/weight/tracking/caps,
     so field labels read in the wrong face against every other label on the
     site (the stencils, the manifest keys). Fixed to the mono stack the tier
     actually names. (design review, this session.) */
  font-family: var(--font-stack-mono);
  font-weight: var(--text-label-lat-weight);
  font-size: var(--text-label-lat-size);
  letter-spacing: var(--text-label-lat-tracking);
  text-transform: uppercase;
  color: var(--color-ink-muted);
}
.field__control {
  position: relative;
}
.field__input,
.field__textarea {
  inline-size: 100%;
  min-block-size: var(--field-min-block-size);
  padding-inline: var(--field-pad-inline);
  background: var(--field-bg);
  border: var(--field-border-width) solid var(--field-border-color);
  border-radius: var(--field-radius);
  color: var(--color-ink);
  font-family: var(--font-stack-text-lat);
  font-size: var(--text-control-lat-size);
  line-height: var(--text-control-lat-leading);
}
.field__textarea {
  padding-block: var(--space-12);
  resize: vertical;
}
/* design.md §10 inputs-ltr: email/password/tel stay LTR regardless of page direction. */
.field__input[type="email"],
.field__input[type="tel"],
.field__input[type="password"],
.field__input[type="text"].field__input--ltr {
  direction: ltr;
  text-align: start;
}
.field__input:disabled {
  background: var(--field-disabled-bg);
  border-color: var(--field-disabled-border-color);
  color: var(--field-disabled-color);
}
.field__input--with-reveal {
  padding-inline-end: var(--field-pad-inline-end-with-reveal);
}
.field__input--readonly {
  background: var(--field-disabled-bg);
  border-color: var(--field-disabled-border-color);
  color: var(--color-ink-muted);
}
.field__error {
  display: flex;
  align-items: baseline;
  gap: var(--space-8);
  margin: 0;
  font-size: var(--text-legal-lat-size);
  line-height: var(--text-legal-lat-leading);
  color: var(--field-error-color);
}
/* §11.11 field-error-icon (required — never colour-only). One rule covers every
   error surface, since server-rendered, client-rendered (public.ts showFieldError)
   and the consent-missing message are all `.field__error`. The mask + currentColor
   keeps it achromatic (§3.4), painted in `--field-error-color`; top-aligned so it
   sits with the first line of a wrapping message. */
.field__error::before {
  content: "";
  flex: none;
  align-self: flex-start;
  inline-size: 1.05em;
  block-size: 1.05em;
  margin-block-start: 0.1em;
  background-color: currentColor;
  -webkit-mask: var(--field-error-icon) center / contain no-repeat;
  mask: var(--field-error-icon) center / contain no-repeat;
}
.field--error .field__input,
.field--error .field__textarea {
  border-color: var(--field-error-color);
}
.field__help {
  margin: 0;
  font-size: var(--text-legal-lat-size);
  line-height: var(--text-legal-lat-leading);
  color: var(--color-ink-muted);
}
/* The Arabic ERROR/HELP text is body-adjacent (legal tier is fine there), but
   the Arabic LABEL belongs to the label tier (15px), not the 18px legal tier —
   grouping them flattened the label/input hierarchy on both public forms.
   Split out so the label takes its own tier. (design review, this session.) */
:lang(ar) .field__error,
:lang(ar) .field__help {
  font-family: var(--font-stack-text-ar);
  font-size: var(--text-legal-ar-size);
  text-transform: none;
}
:lang(ar) .field__label {
  font-family: var(--font-stack-text-ar);
  font-weight: var(--text-label-ar-weight);
  font-size: var(--text-label-ar-size);
  line-height: var(--text-label-ar-leading);
  letter-spacing: 0;
  text-transform: none;
}
:lang(ar) .field__input,
:lang(ar) .field__textarea {
  font-family: var(--font-stack-text-ar);
  font-size: var(--text-control-ar-size);
  line-height: var(--text-control-ar-leading);
}

.plate__label + .field-stack,
.plate__body + .field-stack {
  margin-block-start: var(--space-16);
}

/* ── Checkbox + radio (design.md §11.11) — S6's first real consumer. Both are
   a real native `<input>` sized to its own box via `appearance: none` plus a
   fixed inline-size/block-size, wrapped in a label that provides the >=44px
   hit area design.md requires without a separate absolutely-positioned
   target element. ───────────────────────────────────────────────────────── */
.checkbox-field,
.radio-field {
  display: flex;
  align-items: flex-start;
  gap: var(--checkbox-label-gap);
  min-block-size: var(--checkbox-target);
  cursor: default;
}
.checkbox-field__input,
.radio-field__input {
  appearance: none;
  flex-shrink: 0;
  margin: 0;
  inline-size: var(--checkbox-size);
  block-size: var(--checkbox-size);
  border: var(--checkbox-border);
  background: var(--field-bg);
  display: grid;
  place-content: center;
}
.checkbox-field__input {
  border-radius: 0;
}
.checkbox-field__input:checked {
  background: var(--checkbox-checked-bg);
  border-color: var(--checkbox-checked-bg);
}
.checkbox-field__input:checked::after {
  content: "";
  inline-size: var(--radio-checked-mark-size);
  block-size: var(--radio-checked-mark-size);
  background: var(--checkbox-checked-glyph);
}
.radio-field__input {
  border-radius: var(--radio-radius);
}
.radio-field__input:checked::after {
  content: "";
  inline-size: var(--radio-checked-mark-size);
  block-size: var(--radio-checked-mark-size);
  background: var(--radio-checked-mark-color);
}
.checkbox-field__label,
.radio-field__label {
  padding-block-start: 2px; /* optical alignment with the 24px box's centre line */
  font-size: var(--text-body-lat-size);
  line-height: var(--text-body-lat-leading);
  color: var(--color-ink);
}
/* The consent CHECKBOX label is legal copy (text-legal-ar, 18px is correct there,
   docs/03-design.md S6). The residency RADIO labels are ordinary body content —
   forcing them to 18px put them under design.md §4.4's unconditional
   type-floor-body-ar: 19px. Split so the radio labels take the body-ar pairing.
   (design review, this session.) */
:lang(ar) .checkbox-field__label {
  font-size: var(--text-legal-ar-size);
  line-height: var(--text-legal-ar-leading);
}
:lang(ar) .radio-field__label {
  font-size: var(--text-body-ar-size);
  line-height: var(--text-body-ar-leading);
}
.radio-group {
  display: flex;
  flex-direction: column;
  gap: var(--radio-group-gap);
}
.checkbox-field--error .checkbox-field__input {
  border-color: var(--field-error-color);
}

/* ── Submitting state (busy-tick — design.md §11.12: "a 12-position mechanical tick
   rotating in steps(12), 900ms linear"). Twelve RECTANGULAR marks (radius 0 — §6 is
   unconditional, no loading-indicator exception), positioned radially and faded in
   sequence — a dial, not a smooth circular spinner (which would need a curved
   border-radius:50% arc). ───────────────────────────────────────────────────── */
@keyframes busy-tick-fade {
  0%,
  91.6% {
    opacity: 1;
  }
  8.3%,
  100% {
    opacity: 0.25;
  }
}
.busy-tick {
  position: relative;
  display: inline-block;
  inline-size: 16px;
  block-size: 16px;
  margin-inline-end: var(--space-8);
  vertical-align: middle;
}
.busy-tick__mark {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 50%;
  inline-size: 2px;
  block-size: 5px;
  margin-inline-start: -1px;
  background: var(--busy-tick-color);
  border-radius: 0;
  transform-origin: 1px 8px;
  opacity: 0.25;
  animation: busy-tick-fade var(--busy-tick-duration) steps(1) infinite;
}
.busy-tick__mark:nth-child(1) {
  transform: rotate(0deg);
  animation-delay: 0ms;
}
.busy-tick__mark:nth-child(2) {
  transform: rotate(30deg);
  animation-delay: 75ms;
}
.busy-tick__mark:nth-child(3) {
  transform: rotate(60deg);
  animation-delay: 150ms;
}
.busy-tick__mark:nth-child(4) {
  transform: rotate(90deg);
  animation-delay: 225ms;
}
.busy-tick__mark:nth-child(5) {
  transform: rotate(120deg);
  animation-delay: 300ms;
}
.busy-tick__mark:nth-child(6) {
  transform: rotate(150deg);
  animation-delay: 375ms;
}
.busy-tick__mark:nth-child(7) {
  transform: rotate(180deg);
  animation-delay: 450ms;
}
.busy-tick__mark:nth-child(8) {
  transform: rotate(210deg);
  animation-delay: 525ms;
}
.busy-tick__mark:nth-child(9) {
  transform: rotate(240deg);
  animation-delay: 600ms;
}
.busy-tick__mark:nth-child(10) {
  transform: rotate(270deg);
  animation-delay: 675ms;
}
.busy-tick__mark:nth-child(11) {
  transform: rotate(300deg);
  animation-delay: 750ms;
}
.busy-tick__mark:nth-child(12) {
  transform: rotate(330deg);
  animation-delay: 825ms;
}
@media (prefers-reduced-motion: reduce) {
  /* design.md §7.6: reduced motion collapses to a static tick + text, not a frozen
     mid-animation frame — every mark settles at full opacity together. */
  .busy-tick__mark {
    animation: none;
    opacity: 1;
  }
}
