/* ==========================================================================
   FRONTGRADE  ·  ACCESSIBILITY WIDGET  ·  v2
   A persistent on-page control that hands four real presentation settings to
   the visitor: contrast, text size, link underlines, and motion. Every
   setting changes the live page. Nothing here is an overlay, a simulated
   reading mode, or a substitute for the conformance already built into the
   token system; these controls sit on top of a page that is already
   WCAG 2.1 AA at rest.

   FILE BOUNDARY
   All widget styling lives in this file and all widget behaviour lives in
   a11y.js. Nothing in tokens.css, components.css, home.css, home.js or
   motion.js is edited. The single existing element this file touches is the
   standalone pause control, which is hidden once the widget has taken over
   its function; the control itself is still created and still driven by
   motion.js, and this file only removes it from view.

   --------------------------------------------------------------------------
   CONTRAST NOTATION
   Same convention as tokens.css. Every pair below carries its computed
   WCAG 2.1 contrast ratio, from the sRGB relative-luminance formula
     L = 0.2126R + 0.7152G + 0.0722B  on linearized channels
     ratio = (Llighter + 0.05) / (Ldarker + 0.05)
   Alpha values are composited against the surface first, then measured.
   Targets: 4.5:1 normal text · 3:1 large text
            3:1 non-text UI (control boundaries, glyph strokes, focus,
            switch tracks and knobs).

   SINGLE-ORANGE RULE
   #e35530 is the only orange, in every mode this file defines. High contrast
   does not lighten it, darken it, or introduce a second hue. Where the
   orange would not clear a threshold the element moves down the surface
   ladder instead, exactly as tokens.css requires.

   SURFACE CHOICE
   The widget sits entirely on --surface-raised (#0e1220), the same surface
   the megamenu card uses, so every ratio quoted below is measured against
   that value and nothing in the widget depends on what it happens to be
   floating over.
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. ROOT  ·  fixed anchor, bottom right
   The wrapper is only as large as the trigger, so the closed widget never
   covers page content. The panel is positioned against it.
   -------------------------------------------------------------------------- */

.fg-a11y {
  position: fixed;
  right: max(var(--space-5), env(safe-area-inset-right));
  bottom: max(var(--space-5), env(safe-area-inset-bottom));
  z-index: var(--z-motion);
  width: 48px;
  height: 48px;
  font-family: var(--font-body);
}

/* The mobile navigation panel is a takeover: motion.js marks every other body
   child inert while it is open, so the widget would be visible but not
   operable. It is withdrawn instead of left as a dead target. */
body[data-nav-open] .fg-a11y { display: none; }

/* Every glyph in the widget is a thin-line stroke. components.css sets
   `svg { fill: currentColor }` globally, so the fill is reset here rather
   than with a presentation attribute, which CSS would outrank. */
.fg-a11y svg {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}


/* --------------------------------------------------------------------------
   2. TRIGGER
   48px square, above the 44px minimum in both axes. Dark surface, functional
   hairline, orange glyph.
     --border-ui   #666f88 on --surface-raised   3.72:1   clears 3:1 non-text
     --accent      #e35530 on --surface-raised   4.98:1   clears 3:1 non-text
   -------------------------------------------------------------------------- */

.fg-a11y__trigger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  padding: 0;
  background: var(--surface-raised);
  border: var(--border-hairline-w) solid var(--border-ui);   /* 3.72:1 */
  border-radius: 0;
  box-shadow: var(--shadow-lift);
  color: var(--accent);                                      /* 4.98:1 */
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  transition: var(--t-color);
}
.fg-a11y__trigger svg { width: 22px; height: 22px; }

/* Hover and open state. The boundary moves to the accent, which measures
   4.98:1 on this surface and clears the 3:1 non-text minimum, and the fill
   picks up the same 0.05 accent tint the cards use.
     --accent    #e35530 on the tinted surface #191521   4.79:1
     --border-ui #666f88 on the tinted surface #191521   3.58:1              */
.fg-a11y__trigger:hover,
.fg-a11y__trigger[aria-expanded="true"] {
  background-color: var(--surface-raised);
  background-image: linear-gradient(var(--accent-tint), var(--accent-tint));
  border-color: var(--border-accent);   /* 4.98:1 */
}


/* --------------------------------------------------------------------------
   3. PANEL
   Dark card, hairline boundary, sharp corners, generous padding. Matches the
   megamenu dropdown so the widget reads as part of the system rather than a
   bolt-on. Width is set in rem so the panel grows with the text-size setting.
   -------------------------------------------------------------------------- */

.fg-a11y__panel {
  position: absolute;
  right: 0;
  bottom: calc(100% + var(--space-3));
  width: min(21.25rem, calc(100vw - 40px));
  max-height: calc(100vh - 140px);
  max-height: calc(100dvh - 140px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--space-6);
  background: var(--surface-raised);
  border: var(--border-hairline-w) solid var(--border-hairline-strong);
  border-radius: 0;
  box-shadow: var(--shadow-panel);
  opacity: 0;
  visibility: hidden;
  transform: translateY(6px);
  transition: var(--t-panel);
  pointer-events: none;
}
.fg-a11y__panel[data-open="true"] {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  transition-delay: 0s;
  pointer-events: auto;
}

.fg-a11y__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
}

/* --text-display #f3f5f8 on --surface-raised   17.08:1   AAA */
.fg-a11y__title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--fw-display);
  font-size: var(--fs-h4);
  line-height: var(--lh-h3);
  letter-spacing: var(--ls-h3);
  text-transform: uppercase;
  color: var(--text-display);          /* 17.08:1 */
}

/* --text-muted #7d89a3 on --surface-raised   5.31:1   AA */
.fg-a11y__intro {
  margin: var(--space-2) 0 0;
  max-width: 26em;
  font-size: var(--fs-xs);
  line-height: var(--lh-body);
  color: var(--text-muted);            /* 5.31:1 */
}

/* Close control. 40px target, quiet until hovered.
     --text-muted   #7d89a3 on --surface-raised   5.31:1
     --text-display #f3f5f8 on --surface-raised  17.08:1                     */
.fg-a11y__close {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  margin: -8px -8px 0 0;
  padding: 0;
  background: transparent;
  border: var(--border-hairline-w) solid transparent;
  border-radius: 0;
  color: var(--text-muted);            /* 5.31:1 */
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  transition: var(--t-color);
}
.fg-a11y__close svg { width: 14px; height: 14px; stroke-width: 2.4; }
.fg-a11y__close:hover {
  color: var(--text-display);          /* 17.08:1 */
  border-color: var(--border-ui);      /* 3.72:1 */
}


/* --------------------------------------------------------------------------
   4. GROUPS AND ROWS
   Sections are separated by the system hairline, the same device the page
   bands use.
   -------------------------------------------------------------------------- */

.fg-a11y__group {
  margin-top: var(--space-5);
  padding-top: var(--space-5);
  border-top: var(--border-hairline-w) solid var(--border-hairline);
}

/* Group label, eyebrow setting.
     --text-muted #7d89a3 on --surface-raised   5.31:1   AA */
.fg-a11y__group-label {
  display: block;
  margin: 0 0 var(--space-3);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--text-muted);            /* 5.31:1 */
}

/* Toggle row. Full width, 44px minimum, label left and switch right.
     --text-primary #e8eaed on --surface-raised            15.47:1   AAA
     --text-primary #e8eaed on the row hover #181b29       14.19:1   AAA     */
.fg-a11y__toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  width: 100%;
  min-height: 44px;
  margin: 0;
  padding: var(--space-2) 0;
  background: transparent;
  border: 0;
  border-radius: 0;
  font-family: var(--font-body);
  font-size: var(--fs-small);
  font-weight: var(--fw-medium);
  letter-spacing: var(--ls-body);
  text-align: left;
  color: var(--text-primary);          /* 15.47:1 */
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  transition: var(--t-color);
}
.fg-a11y__toggle + .fg-a11y__toggle { border-top: var(--border-hairline-w) solid var(--border-hairline); }
.fg-a11y__toggle:hover { background: rgba(255, 255, 255, 0.04); }
.fg-a11y__toggle[hidden] { display: none; }

.fg-a11y__toggle-label { flex: 1 1 auto; }

/* Switch. State is carried by knob POSITION as well as by fill, so colour is
   never the only visual means of conveying it.
     track border --border-ui #666f88 on --surface-raised   3.72:1
     knob, off    --border-ui #666f88 on --surface-raised   3.72:1
     track, on    --accent    #e35530 on --surface-raised   4.98:1
     knob, on     --surface-ink #090c14 on --accent         5.22:1           */
.fg-a11y__switch {
  position: relative;
  flex: none;
  display: block;
  width: 38px;
  height: 20px;
  background: transparent;
  border: var(--border-hairline-w) solid var(--border-ui);   /* 3.72:1 */
  border-radius: 0;
  transition: var(--t-color);
}
.fg-a11y__knob {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 12px;
  height: 12px;
  background: var(--border-ui);        /* 3.72:1 */
  transition: transform var(--dur-quick) var(--ease-out-quart), background-color var(--dur-quick) var(--ease-standard);
}
.fg-a11y__toggle[aria-pressed="true"] .fg-a11y__switch {
  background: var(--accent);           /* 4.98:1 against the panel */
  border-color: var(--accent);
}
.fg-a11y__toggle[aria-pressed="true"] .fg-a11y__knob {
  background: var(--surface-ink);      /* 5.22:1 on --accent */
  transform: translateX(18px);
}


/* --------------------------------------------------------------------------
   5. TEXT SIZE  ·  three-step segmented control
   Buttons carry the chip treatment, but the resting boundary is --border-ui
   rather than a decorative hairline, because this boundary identifies a
   control and must clear 3:1.
     --border-ui    #666f88 on --surface-raised   3.72:1
     --text-primary #e8eaed on --surface-raised  15.47:1
     selected: --text-on-accent #090c14 on --accent #e35530   5.22:1
   -------------------------------------------------------------------------- */

.fg-a11y__sizes {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-2);
}

.fg-a11y__size {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 44px;
  padding: var(--space-2) 6px;
  background: transparent;
  border: var(--border-hairline-w) solid var(--border-ui);   /* 3.72:1 */
  border-radius: 0;
  font-family: var(--font-body);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  line-height: 1.2;
  letter-spacing: var(--ls-chip);
  text-align: center;
  color: var(--text-primary);          /* 15.47:1 */
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  transition: var(--t-color);
}
.fg-a11y__size:hover { border-color: var(--border-strong); }   /* 5.31:1 */

/* Selected. The fill is accompanied by a check glyph, so the state is not
   carried by colour alone, matching the chip convention in components.css.  */
.fg-a11y__size[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--text-on-accent);        /* 5.22:1 */
}
.fg-a11y .fg-a11y__check { display: none; width: 12px; height: 12px; flex: none; stroke-width: 3; }
.fg-a11y .fg-a11y__size[aria-pressed="true"] .fg-a11y__check { display: block; }


/* --------------------------------------------------------------------------
   6. FOCUS  ·  the system's two-tone ring, replicated
   Copied from components.css rather than referenced, so this file owns every
   rule it needs and no shared file is edited. 2px white outline at a 2px
   offset, the offset gap filled by a dark shadow, a 1px accent halo outside.
     --focus-ring-inner #ffffff on --focus-ring-outer #090c14   19.55:1
     --focus-ring-inner #ffffff on --surface-raised   #0e1220   18.65:1
     --focus-ring-inner #ffffff on --accent           #e35530    3.74:1
       (clears the 3:1 non-text minimum on the selected size button)
   -------------------------------------------------------------------------- */

.fg-a11y__trigger:focus,
.fg-a11y__close:focus,
.fg-a11y__toggle:focus,
.fg-a11y__size:focus { outline: none; }

/* The panel itself takes focus on open so its name and role are announced.
   That is a programmatic landing point, not an operable target, so it carries
   no ring; the first control the visitor tabs to carries one.               */
.fg-a11y__panel:focus,
.fg-a11y__panel:focus-visible { outline: none; box-shadow: var(--shadow-panel); }

.fg-a11y__trigger:focus-visible,
.fg-a11y__close:focus-visible,
.fg-a11y__toggle:focus-visible,
.fg-a11y__size:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-inner);
  outline-offset: var(--focus-ring-offset);
  box-shadow:
    0 0 0 var(--focus-ring-offset) var(--focus-ring-outer),
    0 0 0 5px var(--focus-ring-halo);
  border-radius: 0;
}


/* --------------------------------------------------------------------------
   7. PAUSE CONTROL FOLD-IN
   The standalone pause control keeps doing its job; motion.js still creates
   it, still owns its state, and still decides whether a page has any ambient
   motion to control. The widget drives it and mirrors it, so the same
   function is no longer offered twice in the same corner. The attribute is
   set by a11y.js only after the widget has been built, so a page where the
   script does not run keeps its original control.
   -------------------------------------------------------------------------- */

html[data-fg-a11y="true"] .fg-motion-toggle { display: none; }


/* --------------------------------------------------------------------------
   8. TEXT SIZE  ·  applied state
   Root font size drives the whole type system: every size token in tokens.css
   is expressed in rem, so one value here scales headings, body, navigation,
   chips, and the widget itself. The three px-valued type rules in the kit are
   restated in rem for the duration of the setting, so they scale with
   everything else. Their default rendering is untouched.
     .fg-logo__word  15px   components.css
     .fg-node__num   19px   home.css, and 15px below 1024px
   -------------------------------------------------------------------------- */

html.fg-a11y-text-lg { font-size: 112.5%; }   /* 16px -> 18px */
html.fg-a11y-text-xl { font-size: 125%; }     /* 16px -> 20px */

html.fg-a11y-text-lg .fg-logo__word,
html.fg-a11y-text-xl .fg-logo__word { font-size: 0.9375rem; }    /* 15px at 100% */

html.fg-a11y-text-lg .fg-node__num,
html.fg-a11y-text-xl .fg-node__num { font-size: 1.1875rem; }     /* 19px at 100% */

@media (max-width: 1023px) {
  html.fg-a11y-text-lg .fg-node__num,
  html.fg-a11y-text-xl .fg-node__num { font-size: 0.9375rem; }   /* 15px at 100% */
}


/* --------------------------------------------------------------------------
   9. UNDERLINE LINKS  ·  applied state
   Scoped to in-content links. Navigation, buttons, chips, tags, tiles, and
   arrow links are excluded: each is already identified by a boundary, a fill,
   or a glyph rather than by colour, and underlining them would read as damage
   rather than as help.
   -------------------------------------------------------------------------- */

html.fg-a11y-underline main a[href] {
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
html.fg-a11y-underline main nav a[href],
html.fg-a11y-underline main .fg-btn,
html.fg-a11y-underline main .fg-chip,
html.fg-a11y-underline main .fg-tag,
html.fg-a11y-underline main .fg-tile,
html.fg-a11y-underline main .fg-link-arrow {
  text-decoration: none;
}


/* --------------------------------------------------------------------------
   10. HIGH CONTRAST  ·  applied state
   A lift, not an inversion. The four surfaces, the single orange, and the
   near-black ink on the orange fill are all unchanged, so the dark theme
   survives intact and no new hue enters the system. What changes is that the
   quiet tone stops being quiet and every hairline becomes a boundary that
   clears the 3:1 non-text minimum on all four surfaces.

   The display and primary text tones are deliberately left alone. They
   already measure 17.90:1 and 16.22:1 on the page ground, which is AAA at
   every size, and pushing them to pure white would introduce the halation
   the token set was designed to avoid.
   -------------------------------------------------------------------------- */

html.fg-a11y-contrast {

  /* THE QUIET TONE, LIFTED.  #7d89a3 -> #e0e6f0
     Body copy, deks, descriptors, captions, meta, navigation links, and
     utility links all resolve to one of these four names.
       #e0e6f0  base 15.59:1 · raised 14.87:1 · panel 13.99:1 · elevated 13.40:1  AAA
     Over the row hover rgba(255,255,255,0.04):
       base 14.43:1 · raised 13.64:1 · panel 12.66:1 · elevated 12.06:1     AAA
     Over the card hover tint rgba(227,85,48,0.05):
       base 15.02:1 · raised 14.31:1 · panel 13.41:1 · elevated 12.81:1     AAA
     For comparison, the resting values are 5.57 / 5.31 / 4.99 / 4.79.      */
  --text-muted:     #e0e6f0;
  --text-secondary: #e0e6f0;
  --text-nav:       #e0e6f0;
  --text-utility:   #e0e6f0;

  /* NON-TEXT STROKES, LIFTED.  #6b7a94 -> #cbd3e0
     Thin icon strokes, decorative glyphs, chart lines. Threshold 3:1.
       #cbd3e0  base 12.97:1 · raised 12.37:1 · panel 11.64:1 · elevated 11.15:1 */
  --stroke-quiet:   #cbd3e0;

  /* FUNCTIONAL CONTROL BOUNDARIES, LIFTED.
       --border-ui     #666f88 -> #a8b3c6
         base 9.24:1 · raised 8.82:1 · panel 8.29:1 · elevated 7.95:1
         resting values 3.90 / 3.72 / 3.50 / 3.36
       --border-strong #7d89a3 -> #cbd3e0
         base 12.97:1 · raised 12.37:1 · panel 11.64:1 · elevated 11.15:1
         resting values 5.57 / 5.31 / 4.99 / 4.79                          */
  --border-ui:      #a8b3c6;
  --border-strong:  #cbd3e0;

  /* DECORATIVE HAIRLINES, PROMOTED TO BOUNDARIES.
     At rest these carry no 3:1 minimum, because they separate panels that
     are already identified by tone and content. In this mode every one of
     them clears 3:1 on all four surfaces, which is the whole point of the
     setting: section rules, card edges, and table seams become perceivable
     structure rather than texture. Composited against each surface:
       white/0.34  base 3.06:1 · raised 3.11:1 · panel 3.10:1 · elevated 3.10:1
       white/0.44  base 4.36:1 · raised 4.36:1 · panel 4.32:1 · elevated 4.26:1
       white/0.58  base 6.86:1 · raised 6.73:1 · panel 6.55:1 · elevated 6.42:1
     Resting values for the same three, for comparison:
       white/0.04  1.08 to 1.11 · white/0.08  1.19 to 1.26 · white/0.14  1.44 to 1.55 */
  --border-hairline-faint:  rgba(255, 255, 255, 0.34);
  --border-hairline:        rgba(255, 255, 255, 0.44);
  --border-hairline-strong: rgba(255, 255, 255, 0.58);
  --border-subtle:          rgba(255, 255, 255, 0.44);
  --border-default:         rgba(255, 255, 255, 0.58);

  /* --accent, --border-accent, --text-on-accent, and every surface are
     deliberately absent from this block. The orange stays #e35530 at 5.22:1
     on the page ground with near-black ink on its fill, and the four dark
     surfaces stay exactly where they are.                                  */
}


/* --------------------------------------------------------------------------
   11. REDUCED MOTION
   tokens.css already collapses every duration to 1ms under the preference.
   The panel transition is stated again here so the open and close are
   unambiguously instant even if the widget is read in isolation.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .fg-a11y__panel,
  .fg-a11y__knob,
  .fg-a11y__trigger,
  .fg-a11y__toggle,
  .fg-a11y__size,
  .fg-a11y__close {
    transition: none;
  }
  .fg-a11y__panel { transform: none; }
  .fg-a11y__panel[data-open="true"] { transform: none; }
}


/* --------------------------------------------------------------------------
   12. FORCED COLORS
   In Windows high contrast the system palette replaces every value above, so
   the switch and the selected size button are restated in system colours to
   keep their state visible.
   -------------------------------------------------------------------------- */

@media (forced-colors: active) {
  .fg-a11y__trigger,
  .fg-a11y__panel,
  .fg-a11y__switch { border: 1px solid CanvasText; }
  .fg-a11y__knob { background: CanvasText; }
  .fg-a11y__toggle[aria-pressed="true"] .fg-a11y__switch { background: Highlight; }
  .fg-a11y__toggle[aria-pressed="true"] .fg-a11y__knob { background: HighlightText; }
  .fg-a11y__size[aria-pressed="true"] { background: Highlight; color: HighlightText; }
  .fg-a11y__trigger:focus-visible,
  .fg-a11y__close:focus-visible,
  .fg-a11y__toggle:focus-visible,
  .fg-a11y__size:focus-visible {
    outline: 3px solid Highlight;
    outline-offset: 2px;
  }
}


/* --------------------------------------------------------------------------
   13. PRINT
   -------------------------------------------------------------------------- */

@media print {
  .fg-a11y { display: none !important; }
}


/* --------------------------------------------------------------------------
   14. CONSENT NOTICE CLEARANCE
   The consent notice is drawn by the consent manager, is position:fixed
   across the foot of the viewport, and is painted above the page. Both of
   the widget's corners are therefore its corners too: the trigger sat inside
   the notice's footprint and beneath it in the stack, so a first-time
   visitor could neither see nor click the control the site tells them to use.

   Two rules, both live only while the notice is up. The widget is lifted by
   the notice's own measured height so the two never overlap, and it is
   raised past the notice in the stack so a notice that grows between one
   measurement and the next still cannot cover it. The height and the state
   are published by fg2/js/klaro-theme.js; both are withdrawn with the notice,
   and the widget returns to its resting corner.
   -------------------------------------------------------------------------- */

html[data-fg-consent="open"] .fg-a11y {
  bottom: calc(max(var(--space-5), env(safe-area-inset-bottom)) + var(--fg-consent-h, 0px));
  z-index: 100000;   /* one above the module's own 99999 */
}

/* The panel opens upward from the trigger, so a trigger that has moved up by
   the notice's height has that much less room above it. */
html[data-fg-consent="open"] .fg-a11y__panel {
  max-height: calc(100vh - 140px - var(--fg-consent-h, 0px));
  max-height: calc(100dvh - 140px - var(--fg-consent-h, 0px));
}
