/* ============================================================
   ShiftBee — accessibility layer (IS 5568 / WCAG 2.0 AA)
   Loaded on every page, after styles.css / legal.css.

   Three jobs:
     1. Skip link + a real focus indicator (2.4.1, 2.4.7)
     2. The a11y preferences widget chrome
     3. The a11y-* preference classes applied to <html>

   Scope fence: this file only reacts to classes the user turned
   on themselves. It never rewrites content, alt text or ARIA.
   It is a comfort tool, not an overlay. See accessibility.html.
   ============================================================ */

/* Fallback tokens — legal.css does not define the landing palette. */
:root {
  --a11y-gold: var(--gold, #f5b724);
  /* --gold-fold, not --gold-deep: the focus ring is a non-text UI component and
     owes 3:1 (WCAG 1.4.11). On the v6 bright canvas --gold-deep #c88a12 measures
     2.71:1 and fails; --gold-fold #b57a0e measures 3.35:1. --gold-deep keeps its
     other jobs (fills, borders, link ink) where it is on cream at body size. */
  --a11y-gold-deep: var(--gold-fold, #b57a0e);
  --a11y-espresso: var(--espresso, #1a120b);
  --a11y-on-dark: var(--on-dark, #f5f0e6);
  --a11y-ink: var(--ink, #221a10);
  --a11y-surface: var(--white, #ffffff);
  --a11y-line: var(--line-strong, #e1dccf);
  --a11y-body: var(--body, #423a2b);
}

/* ---------- 1. Skip link (WCAG 2.4.1) ---------- */
/* Logical inset so it lands correctly in both RTL and LTR. */
.skip-link {
  /* fixed, not absolute: a user shift-tabbing back from mid-page must
     still see it, rather than have it sit at the document's top edge. */
  position: fixed;
  inset-block-start: 0;
  inset-inline-start: 0;
  z-index: 200;
  transform: translateY(-140%);
  background: var(--a11y-espresso);
  color: var(--a11y-on-dark);
  font: 600 0.95rem/1.4 'Heebo', system-ui, sans-serif;
  padding: 14px 22px;
  border-radius: 0 0 10px 0;
  text-decoration: none;
  box-shadow: 0 6px 24px rgba(16, 18, 26, 0.3);
  transition: transform 0.18s ease;
}
.skip-link:focus {
  transform: translateY(0);
}
/* The skip target must not paint a ring when focused programmatically. */
[tabindex='-1']:focus {
  outline: none;
}

/* ---------- 2. Global focus indicator (WCAG 2.4.7) ---------- */
/* styles.css only styled three controls. Everything focusable now
   gets the same high-contrast ring, and it inverts on dark sections
   so it stays visible on espresso as well as cream. */
:where(a, button, summary, input, select, textarea, [tabindex]):focus-visible {
  outline: 3px solid var(--a11y-gold-deep);
  outline-offset: 3px;
  border-radius: 4px;
}
/* The bright ring belongs on the DARK bands, and ONLY there: on a light surface
   --a11y-gold (#f5b724) measures 1.65:1 and the ring disappears (WCAG 1.4.11 /
   2.4.11). v6.1 returned .hero and .nav to espresso, so they are dark bands
   again and belong in this list. .engine is the dark mid-panel. Everything else
   falls through to the default ring below. Keep this list == the dark surfaces. */
.hero :where(a, button, summary):focus-visible,
.nav :where(a, button, summary):focus-visible,
.engine :where(a, button, summary):focus-visible,
.outro :where(a, button, summary):focus-visible,
.footer :where(a, button):focus-visible {
  outline-color: var(--a11y-gold);
}
/* v6.2 §A1: .outro is a dark BAND, but every focusable inside it lives on the
   WHITE .dform card - the submit button, the three inputs and the privacy link.
   The bright --a11y-gold ring measured 1.64-1.78:1 on the button and 1.80:1 on
   the link, i.e. the .outro entry above never once painted on a dark pixel; it
   only degraded. Pin the ring back to the light-surface gold for that subtree.
   .outro STAYS in the dark list: it is correct the day a focusable is added to
   the espresso band itself. Must come after that block - same (0,2,0). */
.dform :where(a, button, summary, input):focus-visible {
  outline-color: var(--a11y-gold-deep);
}
/* Keep the existing bespoke rings — they already pass. */
.calc__wage:focus-visible,
.calc__range:focus-visible {
  outline-offset: 2px;
}

/* ---------- Form error states (WCAG 3.3.1) ---------- */
.dform .field__err {
  display: none;
  color: #a8321f;
  font-size: 0.86rem;
  font-weight: 600;
  margin-block-start: 6px;
}
.dform .field__err.is-shown {
  display: block;
}
.dform input[aria-invalid='true'] {
  border-color: #a8321f;
  box-shadow: 0 0 0 3px rgba(168, 50, 31, 0.16);
}

/* ============================================================
   3. The widget
   ============================================================ */
.a11y-trigger {
  position: fixed;
  inset-block-end: 20px;
  inset-inline-start: 20px;
  z-index: 120;
  inline-size: 50px;
  block-size: 50px;
  display: grid;
  place-items: center;
  border: 1px solid rgba(245, 240, 230, 0.16);
  border-radius: 50%;
  background: var(--a11y-espresso);
  color: var(--a11y-gold);
  cursor: pointer;
  /* Icon-only, so no glyph is at risk - but the UA hands every control its own
     family and an unset line-height, and neither belongs on this page. */
  font-family: inherit;
  line-height: 1;
  box-shadow: 0 4px 18px rgba(16, 18, 26, 0.28);
  /* inset-block-end animates so the button glides clear of the sticky CTA
     instead of teleporting when the bar appears. */
  transition: transform 0.18s ease, box-shadow 0.18s ease,
    inset-block-end 0.3s var(--ease-out, ease);
}
.a11y-trigger:hover {
  transform: scale(1.06);
  box-shadow: 0 6px 24px rgba(16, 18, 26, 0.36);
}
.a11y-trigger svg {
  inline-size: 26px;
  block-size: 26px;
}

.a11y-panel {
  position: fixed;
  inset-block-end: 82px;
  inset-inline-start: 20px;
  z-index: 121;
  inline-size: min(340px, calc(100vw - 40px));
  background: var(--a11y-surface);
  color: var(--a11y-ink);
  border: 1px solid var(--a11y-line);
  border-radius: 16px;
  box-shadow: 0 10px 50px rgba(16, 18, 26, 0.28);
  padding: 18px;
  font-family: 'Heebo', system-ui, sans-serif;
  max-block-size: min(78vh, 620px);
  overflow-y: auto;
}
.a11y-panel[hidden] {
  display: none;
}
.a11y-panel__head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-block-end: 14px;
}
.a11y-panel__head h2 {
  font-size: 1.05rem;
  margin: 0;
  margin-inline-end: auto;
  font-weight: 800;
}
/* font-family is stated, not inherited from body: form controls take the UA's
   own stack (Arial here), and this button renders a visible "×". The same
   guard exists in styles.css for the marketing pages, but the LEGAL pages load
   a11y.css without styles.css - so the widget has to carry its own. */
.a11y-panel__close {
  border: 0;
  background: transparent;
  cursor: pointer;
  font-family: inherit;
  font-size: 1.3rem;
  line-height: 1;
  color: var(--a11y-body);
  padding: 4px 8px;
  border-radius: 6px;
}
.a11y-panel__close:hover {
  background: rgba(0, 0, 0, 0.06);
}

.a11y-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
.a11y-opt {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-block-size: 78px;
  padding: 10px 6px;
  border: 1px solid var(--a11y-line);
  border-radius: 11px;
  background: #fbfaf7;
  color: var(--a11y-body);
  font: 600 0.76rem/1.25 'Heebo', system-ui, sans-serif;
  text-align: center;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.a11y-opt:hover {
  border-color: var(--a11y-gold-deep);
}
.a11y-opt svg {
  inline-size: 20px;
  block-size: 20px;
  flex: none;
}
.a11y-opt[aria-pressed='true'],
.a11y-opt.is-active {
  background: #fdf4de;
  border-color: var(--a11y-gold-deep);
  color: #6b4708;
}
/* v6.2 §C7: the panel set Hebrew option labels at 12.16px and their current
   VALUE at 10.88px - Hebrew has no ascenders or descenders, so below ~12.8px the
   word shape is simply gone, and this is the widget a low-vision reader opens
   first. Both are lifted over the floor and both carry an explicit line-height
   (the .a11y-opt `font` shorthand only supplies 1.25). */
.a11y-opt > span:not(.a11y-opt__val) {
  font-size: 0.85rem;   /* 13.6px */
  line-height: 1.4;
}

.a11y-opt__val {
  font-size: 0.8rem;    /* 12.8px */
  line-height: 1.4;
  font-weight: 700;
  opacity: 0.72;
}

.a11y-reset {
  margin-block-start: 12px;
  inline-size: 100%;
  padding: 10px;
  border: 1px solid var(--a11y-line);
  border-radius: 10px;
  background: #fff;
  /* /1.25 is stated: the `font:` shorthand resets line-height to `normal`,
     and this button's label is Hebrew on the default page. */
  font: 700 0.85rem/1.25 'Heebo', system-ui, sans-serif;
  color: var(--a11y-body);
  cursor: pointer;
}
.a11y-reset:hover {
  border-color: var(--a11y-gold-deep);
}
.a11y-panel__note {
  margin: 12px 0 0;
  font-size: 0.8rem;
  line-height: 1.5;
  color: #6b6353;
}
.a11y-panel__note a {
  color: #6b4708;
}

/* Screen-reader-only live region. */
.a11y-sr {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ============================================================
   4. Preference classes — applied to <html> by a11y.js
   ============================================================ */

html.a11y-links a {
  text-decoration: underline !important;
  text-underline-offset: 3px !important;
}

html.a11y-headings :is(h1, h2, h3, h4) {
  outline: 2px dashed currentColor;
  outline-offset: 4px;
}

/* The contrast filters go on the ROOT element, not <body>.
   A CSS `filter` on any non-root element makes it the containing block for
   every `position: fixed` descendant — so filtering <body> flung this
   widget (and .nav/.mcta) to the bottom of the page and it "disappeared".
   A filter on the root element is special-cased: it applies to the whole
   canvas without trapping fixed positioning. Verified on the live page. */
html.a11y-contrast-high {
  filter: contrast(1.32);
}
html.a11y-contrast-invert {
  filter: invert(1) hue-rotate(180deg);
}
html.a11y-contrast-mono {
  filter: grayscale(1) contrast(1.12);
}

/* The widget must stay readable while a page filter is on, or the
   user cannot reach the control that turns the filter back off. */
html.a11y-contrast-invert .a11y-trigger,
html.a11y-contrast-invert .a11y-panel {
  filter: invert(1) hue-rotate(180deg);
}
html.a11y-contrast-mono .a11y-trigger,
html.a11y-contrast-mono .a11y-panel {
  filter: grayscale(0);
}

html.a11y-text-115 body { font-size: 115%; }
html.a11y-text-130 body { font-size: 130%; }
html.a11y-text-150 body { font-size: 150%; }
/* Don't let the widget itself scale away from its own layout. */
html[class*='a11y-text-'] .a11y-panel,
html[class*='a11y-text-'] .a11y-trigger {
  font-size: 16px;
}

/* Both steps must clear the site's ~1.67 default, or the first one tightens
   text instead of loosening it. Tokens 16/20 kept (the FOUC bootstrap in
   every page keys off them) but mapped to values that actually increase. */
html.a11y-lines-16 body :is(p, li, dd, blockquote) { line-height: 1.9 !important; }
html.a11y-lines-20 body :is(p, li, dd, blockquote) { line-height: 2.4 !important; }

/* OS stack only — no webfont, so text width does not re-flow past
   critical content the way an injected font would. */
html.a11y-font body,
html.a11y-font body :is(h1, h2, h3, h4, p, li, a, span, button, input, label) {
  font-family: Arial, 'Segoe UI', system-ui, sans-serif !important;
  letter-spacing: normal !important;
}

html.a11y-cursor-black,
html.a11y-cursor-black * {
  cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath d='M6 2l18 13-8 1.5 4.5 9-3.5 1.8-4.5-9L6 24z' fill='%23000' stroke='%23fff' stroke-width='1.5'/%3E%3C/svg%3E") 4 2, auto !important;
}
html.a11y-cursor-large,
html.a11y-cursor-large * {
  cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='56' viewBox='0 0 32 32'%3E%3Cpath d='M6 2l18 13-8 1.5 4.5 9-3.5 1.8-4.5-9L6 24z' fill='%23fff' stroke='%23000' stroke-width='1.5'/%3E%3C/svg%3E") 7 3, auto !important;
}

html.a11y-reduce-motion *,
html.a11y-reduce-motion *::before,
html.a11y-reduce-motion *::after {
  animation-duration: 0.001ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.001ms !important;
  scroll-behavior: auto !important;
}
/* The reveal-on-scroll elements start at opacity 0 — force them
   visible, otherwise stopping animation hides half the page. */
html.a11y-reduce-motion .rv {
  opacity: 1 !important;
  transform: none !important;
}

/* ---------- Print: never carry preferences onto paper ---------- */
@media print {
  html[class*='a11y-'] { filter: none !important; }
  html[class*='a11y-text-'] body { font-size: 100% !important; }
  html[class*='a11y-lines-'] body :is(p, li, dd, blockquote) { line-height: normal !important; }
  .a11y-trigger,
  .a11y-panel,
  .skip-link { display: none !important; }
}

@media (max-width: 560px) {
  .a11y-trigger {
    inset-block-end: 14px;
    inset-inline-start: 14px;
    inline-size: 46px;
    block-size: 46px;
  }
  .a11y-panel {
    inset-block-end: 70px;
    inset-inline: 14px;
    inline-size: auto;
  }
}

/* ---------- Clear the sticky mobile CTA ----------
   `.mcta` (styles.css) is a full-width bar pinned to the bottom edge, shown
   at <=880px once the reader is past the hero. The trigger's z-index (120)
   is above the bar's (55), so at its default offset it sits directly on top
   of the primary conversion button — blocking part of its tap target.

   Bar height measured at 75px: 10px padding + 55px button + 10px padding,
   plus the safe-area inset on devices with a home indicator. Lift both the
   trigger and the panel clear of it, keeping the same 12px breathing room
   the trigger normally has from the viewport edge. */
@media (max-width: 880px) {
  html.js body.past-hero .a11y-trigger {
    inset-block-end: calc(87px + env(safe-area-inset-bottom, 0px));
  }
  html.js body.past-hero .a11y-panel {
    inset-block-end: calc(149px + env(safe-area-inset-bottom, 0px));
  }
}
