/* ============================================================
   jb-a11y.css — styling for the JobBored a11y primitives (T0 / P0-F)

   Companion to jb-a11y.js. Contract doc: JB-A11Y.md.

   DELIBERATELY UNSCOPED. jb-ui.css scopes every component under `body.jb-v2`
   and ships a `body:not(.jb-v2) { display: none }` kill-switch. These
   primitives serve the LEGACY view too — the settings modal, the first-run
   wizard, the onboarding wizard and the fit-profile wizard all render without
   the v2 flag, and that is the user path the a11y audit walked. Scoping this
   file under body.jb-v2 would make every dialog invisible there. Do not add
   the scope. See JB-A11Y.md § "Why this file is not v2-scoped".

   Own file on purpose: tools/check-jb-ui-budget.mjs caps jb-ui.js at 12000 B
   and jb-ui.css at 6000 B minified. Nothing here counts against those budgets.

   Tokens only — tools/lint-tokens.mjs scans jb-*.css and rejects raw hex.
   ============================================================ */

:root {
  /* Scrim behind a modal surface. Expressed as an alpha of the brand navy
     (--jb-navy: rgb(14 58 78)); tokens-v2.css uses the same rgba() style for
     its own overlay-ish tokens. */
  --jb-a11y-scrim: rgba(14, 58, 78, 0.42);
  /* Fallback stage colour for menu items; overridden inline per item. */
  --jb-a11y-stage-color: var(--jb-ink-3);
  /* The 44px touch floor as a token so the phone breakpoints below and any
     consuming board reference ONE number. 2.75rem is 44px at the default
     root size and keeps scaling with the user's font-size setting. */
  --jb-touch-min: 2.75rem;
  /* Simulated soft-keyboard inset. env(keyboard-inset-bottom) wins on real
     devices that report one; the hermetic phone harness overrides this token
     instead (tests/fixtures/phone-geometry.json). */
  --jb-keyboard-inset: 0px;
}

/* ============================================================
   Visually hidden — live regions and skip targets.
   NOT display:none and NOT [hidden]: either would remove the node from the
   accessibility tree and silence the announcement entirely.
   ============================================================ */

.jb-a11y-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ============================================================
   Touch targets — the 44px floor (MOBILE-01).
   2.75rem matches the repo's single existing precedent (style.css:1681).
   min-width matters as much as min-height: an icon-only button is commonly
   44px tall and 16px wide, which fails the same guideline.
   ============================================================ */

.jb-a11y-touch-target {
  min-height: 2.75rem;
  min-width: 2.75rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.375rem;
}

.jb-a11y-touch-target:focus-visible,
.jb-a11y-stage-menu__trigger:focus-visible,
.jb-a11y-stage-menu__item:focus-visible,
.jb-a11y-dialog__btn:focus-visible,
.jb-a11y-field__control:focus-visible {
  outline: none;
  box-shadow: var(--jb-shadow-focus);
}

/* ============================================================
   Dialog surface — used by dialog.confirm(). Surfaces that bring their own
   markup (the settings modal, the discovery drawer, the fit-profile wizard)
   keep their own styling; the primitive only adds behavior to those.
   ============================================================ */

.jb-a11y-dialog {
  position: fixed;
  inset: 0;
  z-index: 3000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  background: var(--jb-a11y-scrim);
}

.jb-a11y-dialog__panel {
  width: min(32rem, 100%);
  max-height: 90vh;
  overflow-y: auto;
  padding: 1.5rem;
  background: var(--jb-paper);
  color: var(--jb-ink);
  border: 1px solid var(--jb-line);
  border-radius: var(--jb-radius-md);
  box-shadow: var(--jb-shadow-card);
}

.jb-a11y-dialog__title {
  margin: 0 0 0.5rem;
  font-size: var(--jb-text-lg);
  color: var(--jb-navy);
}

.jb-a11y-dialog__body {
  margin: 0 0 1rem;
  color: var(--jb-ink-2);
  font-size: var(--jb-text-sm);
}

.jb-a11y-dialog__actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  margin-top: 1.25rem;
}

.jb-a11y-dialog__btn {
  padding: 0 1rem;
  font: inherit;
  border-radius: var(--jb-radius-sm);
  border: 1px solid var(--jb-line);
  background: var(--jb-surface-raised);
  color: var(--jb-ink);
  cursor: pointer;
  transition: background var(--jb-transition-fast);
}

/* TR-06 / TA-04: the confirm is the one filled navy primary (it also carries
   .jb-btn--primary; this rule keeps it navy where the kit is not loaded). */
.jb-a11y-dialog__btn--confirm {
  background: var(--jb-action);
  border-color: var(--jb-action);
  color: var(--jb-on-action);
  font-weight: 600;
}

.jb-a11y-dialog__btn--confirm:hover {
  background: color-mix(in srgb, var(--jb-action) 82%, var(--jb-ink));
}

.jb-a11y-dialog__btn--cancel {
  background: var(--jb-paper);
  color: var(--jb-action);
}

.jb-a11y-dialog__btn--cancel:hover {
  background: var(--jb-paper-3);
}

/* TA-21: "Sent with it" — the files that went with the application. */
.jb-a11y-checks {
  display: flex;
  flex-wrap: wrap;
  gap: var(--jb-space-2) var(--jb-space-4);
  margin: 0 0 0.875rem;
  padding: 0;
  border: 0;
}

.jb-a11y-checks__legend {
  width: 100%;
  margin-bottom: var(--jb-space-2);
  padding: 0;
  font: 500 var(--jb-type-label) / 1.2 var(--jb-font-mono);
  letter-spacing: var(--jb-label-tracking);
  text-transform: uppercase;
  color: var(--jb-ink-2);
}

.jb-a11y-checks__item {
  display: inline-flex;
  align-items: center;
  gap: var(--jb-space-2);
  min-height: 2.75rem;
  font-size: var(--jb-type-small);
  color: var(--jb-ink);
  cursor: pointer;
}

.jb-a11y-checks__item input {
  width: 1.125rem;
  height: 1.125rem;
  margin: 0;
  accent-color: var(--jb-action);
}

.jb-a11y-dialog__note {
  margin: 0;
  font-size: var(--jb-type-small);
  color: var(--jb-ink-3);
}

/* ============================================================
   Field — label / control / hint
   ============================================================ */

.jb-a11y-field {
  display: block;
  margin-bottom: 0.875rem;
}

.jb-a11y-field__label {
  display: block;
  margin-bottom: 0.25rem;
  font-size: var(--jb-text-xs);
  font-family: var(--jb-font-mono);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--jb-ink-2);
}

.jb-a11y-field__control {
  width: 100%;
  min-height: 2.75rem;
  padding: 0.5rem 0.625rem;
  font: inherit;
  color: var(--jb-ink);
  background: var(--jb-paper);
  border: 1px solid var(--jb-line);
  border-radius: var(--jb-radius-sm);
}

.jb-a11y-field__control--multiline {
  min-height: 5rem;
  resize: vertical;
}

.jb-a11y-field__hint {
  margin: 0.25rem 0 0;
  font-size: var(--jb-text-xs);
  color: var(--jb-ink-3);
}

/* ============================================================
   Stage menu — the explicit "Move to stage" affordance (MOBILE-01)
   ============================================================ */

.jb-a11y-stage-menu {
  position: relative;
  display: block;
  margin-top: 0.5rem;
}

.jb-a11y-stage-menu__trigger {
  width: 100%;
  padding: 0 0.75rem;
  font: inherit;
  font-size: var(--jb-text-xs);
  color: var(--jb-ink-2);
  background: var(--jb-surface-raised);
  border: 1px dashed var(--jb-line);
  border-radius: var(--jb-radius-sm);
  cursor: pointer;
  transition: border-color var(--jb-transition-fast),
    background var(--jb-transition-fast);
}

.jb-a11y-stage-menu__trigger:hover {
  border-style: solid;
  border-color: var(--jb-navy-soft);
  background: var(--jb-paper);
}

.jb-a11y-stage-menu__list {
  position: absolute;
  z-index: 40;
  left: 0;
  right: 0;
  margin-top: 0.25rem;
  padding: 0.25rem;
  background: var(--jb-paper);
  border: 1px solid var(--jb-line);
  border-radius: var(--jb-radius-sm);
  box-shadow: var(--jb-shadow-card);
}

/* TR-07 / AX-02: shown as a popover, the list lives in the top layer and is
   positioned (fixed) from the trigger's rect by jb-a11y.js. Reset the UA
   popover box so it keeps the card-list look above. */
.jb-a11y-stage-menu__list[popover] {
  position: fixed;
  inset: auto;
  z-index: 2000;
  margin: 0;
  color: var(--jb-ink);
  overflow: auto;
  max-height: min(60vh, 28rem);
}

.jb-a11y-stage-menu__list[popover]:not(:popover-open) {
  display: none;
}

.jb-a11y-stage-menu__item {
  display: flex;
  align-items: center;
  width: 100%;
  justify-content: flex-start;
  padding: 0 0.625rem;
  font: inherit;
  font-size: var(--jb-text-sm);
  text-align: left;
  color: var(--jb-ink);
  background: transparent;
  border: 0;
  border-left: 3px solid var(--jb-a11y-stage-color);
  border-radius: var(--jb-radius-xs);
  cursor: pointer;
  transition: background var(--jb-transition-fast);
}

.jb-a11y-stage-menu__item:hover {
  background: var(--jb-paper-2);
}

/* ============================================================
   Phone geometry — 320 / 375 / 393 (MOBILE-01).

   Re-expressed from the F3-D breakpoint block onto the LIVE .jb-a11y-*
   selectors. The F3-D original styled .jb-move-to / .jb-overlay, which no
   surface renders any more; keeping it would have left the phone contract
   green against rules nothing uses.

   Shared fixture: tests/fixtures/phone-geometry.json (consumed by the
   hermetic Playwright harness). The keyboard inset there is a RECORDED
   value, not real-device proof.

   Declared BEFORE @media (pointer: coarse) on purpose: coarse pointers must
   keep the roomier 3rem target, and the later rule wins at equal specificity.
   ============================================================ */

@media (max-width: 393px) {
  .jb-a11y-touch-target,
  .jb-a11y-stage-menu__trigger,
  .jb-a11y-stage-menu__item {
    min-height: var(--jb-touch-min);
    min-width: var(--jb-touch-min);
  }

  /* A stage menu or dialog pinned low must clear the soft keyboard, or its
     primary action renders underneath it and is unreachable by touch. */
  .jb-a11y-stage-menu__list,
  .jb-a11y-dialog {
    padding-bottom: env(keyboard-inset-bottom, var(--jb-keyboard-inset, 0px));
  }
}

@media (max-width: 375px) {
  .jb-a11y-dialog {
    padding: 0.75rem;
  }

  .jb-a11y-dialog__panel {
    width: 100%;
    max-height: calc(
      90vh - env(keyboard-inset-bottom, var(--jb-keyboard-inset, 0px))
    );
  }
}

@media (max-width: 320px) {
  /* At 320px an inline trigger and its menu cannot sit side by side without
     the label truncating below its own touch target. */
  .jb-a11y-stage-menu,
  .jb-a11y-stage-menu__trigger {
    width: 100%;
  }

  .jb-a11y-stage-menu__list {
    min-width: 100%;
  }
}

/* Coarse pointers get more room; the 2.75rem floor is the minimum, not the
   target, on touch devices. */
@media (pointer: coarse) {
  .jb-a11y-touch-target {
    min-height: 3rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .jb-a11y-dialog__btn,
  .jb-a11y-stage-menu__trigger,
  .jb-a11y-stage-menu__item {
    transition: none;
  }
}
