/* ============================================================================
 * usability-a11y-fix.css — consolidated remediation for two audit reports
 *   Report A: Usability heuristics (9 issues)
 *   Report B: WCAG 2.2 AA (95 issues, two passes)
 *
 * Why a single file instead of editing every class=""
 *   The codebase has a clear convention — every fix so far has lived in an
 *   additive stylesheet (a11y-fix.css, gsmwhale-contrast-fix.css,
 *   design-tokens.css) loaded after Tailwind CDN, so it wins on specificity
 *   (when prefixed with html / html.dark) and on source order. This file
 *   follows the same pattern: drop-in, no markup churn required for any
 *   item that has a pure-CSS fix; only a small set of cases (touch target
 *   size, td->th, role on aria-label elements, uppercase copy edits) needs
 *   a markup change and those are documented per-issue in
 *   USABILITY-A11Y-REPORT.md alongside this file.
 *
 * Load order (in <head>, after the existing CSS chain):
 *     <link rel="stylesheet" href="assets/css/usability-a11y-fix.css?v=1">
 *
 * All rules below are gated by html / html:not(.dark) / html.dark prefixes so
 * they beat equal-specificity Tailwind utilities that CDN Tailwind injects
 * later. Keep those prefixes when editing this file.
 * ========================================================================== */

/* ----------------------------------------------------------------------------
 * 1.  USABILITY HEURISTICS
 *
 *   #1 No consistent type scale  -> tokens already in design-tokens.css; the
 *       11px floor for body copy is enforced by an extra `font-size: 12px !important`
 *       on the small status labels in the walkthrough so the audit's "11px"
 *       reading disappears even when the design-token remap hasn't yet won
 *       the cascade race.
 *   #2 Too many text colours      -> handled in design-tokens.css / a11y-fix.css.
 *   #3 Many button styles         -> handled in design-tokens.css (.gw-btn).
 *   #4 / #6 / #8 Long all-caps text -> markup edit, see report.
 *   #5 / #7 Body text very small    -> .gw-fs-xs already remaps text-[10..11.5px]
 *       to 12px; the status label below adds an !important floor for the two
 *       eyebrow styles the audit caught.
 *   #9 Text is truncated           -> markup edit, see report.
 * ---------------------------------------------------------------------------- */

/* Floors the "IN STOCK" / "STATUS" / "PAID" pills to the AA-min body-copy size. */
html .gw-status-pulse + span[class*="text-["],
html .gw-flow-svg text:not(.gw-pill-num):not(.gw-pill-label),
html .gw-orbit-svg text:not(.gw-pill-num):not(.gw-pill-label) {
    font-size: var(--gw-fs-xs, 0.75rem) !important;   /* 12px */
}

/* The orbit scene renders its own SVG text on tinted dark pill fills, so the
   generic label overrides below (scoped to .gw-flow-svg) must not touch it. */
html .gw-orbit-svg text {
    opacity: 1 !important;
    font-size: 8.5px !important;
}
html .gw-orbit-svg .gw-pill-num {
    font-size: 9.5px !important;
}

/* The "Explore the ecosystem", "Built for every GSM business" and "v1.0.0 —
   WHALE AI is live" eyebrows are flagged for their long all-caps runs. The
   markup fixes drop the uppercase transform on the literal copy. While a
   few stale copies may still ship, neutralising the transform at the CSS
   level guarantees the audit clears regardless of order. */
html .no-u[class*="uppercase"][class*="tracking-[0.28em]"],
html .no-u[class*="font-mono"][class*="uppercase"][class*="tracking-[0.28em]"] {
    text-transform: none;
}

/* ----------------------------------------------------------------------------
 * 2.  WCAG 1.4.3  Color contrast — flow-diagram nodes
 *
 *   #1-6 (light) / #1-3 (dark): 11px badges inside .gw-node-dimmed nodes.
 *   Root cause: .gw-node-dimmed used `opacity: .55` which blended every
 *   text colour inside the node to ~2.5:1 against the panel.
 *
 *   Fix: remove the subtree opacity and dim the surface instead. The active
 *   node still gets its cyan glow + scale (gw-node-active) which carries
 *   the active-step signal without darkening any text.
 *
 *   The flow nodes also use `bg-white/95` / `bg-zinc-900/95`, which kept
 *   their backgrounds undecidable for axe (#59-95). Override to opaque so
 *   the contrast checks resolve to a real number.
 *
 *   The status-label colour ramps are pinned below in :root so the new
 *   tokens win the cascade after design-tokens.css.
 * ---------------------------------------------------------------------------- */
:root {
    --gw-ink-faint:   #5f5f69;   /* was #71717a; 5.5:1 on the dim surface below */
    --gw-ink-warning: #92400e;   /* was #b45309; 6.2:1 on the dim surface below */
}

/* Stop dimming the entire subtree, dim only the surface and border. */
.gw-node-dimmed {
    opacity: 1 !important;
    filter: none !important;
    transition: background-color 0.4s ease, border-color 0.4s ease;
}
/* `.gw-node-wrap.gw-node-dimmed` — BOTH classes land on the same element, and
   the plain `.gw-node-wrap` rule below has equal specificity, so without the
   extra class this tint loses on source order and inactive steps stop looking
   inactive at all. */
html:not(.dark) .gw-node-wrap.gw-node-dimmed:not(.gw-node-orb) {
    background-color: #eef0f3 !important;
    border-color: #d9dde3 !important;
}
html.dark .gw-node-wrap.gw-node-dimmed:not(.gw-node-orb) {
    background-color: #101216 !important;
    border-color: #2b3038 !important;
}

/* Active node keeps its cyan halo + lift; just make sure the surface is
   opaque so the contrast on the chip text is decidable. The orbit core card
   (gw-orbit-core) is excluded: its tinted glass globe surface is part of the
   solar-system design. */
html:not(.dark) .gw-node-wrap:not(.gw-orbit-core):not(.gw-node-orb) { background-color: #ffffff !important; }
html.dark .gw-node-wrap:not(.gw-orbit-core):not(.gw-node-orb)       { background-color: #1f232b !important; }

/* The core globe uses a branded tinted surface instead of the opaque node
   surfaces; pin explicit light/dark values so contrast stays decidable. */
html:not(.dark) .gw-orbit-core { background-color: #f2f9ff !important; }
html.dark .gw-orbit-core       { background-color: #101b2e !important; }

/* Light *inactive* steps: the tinted surface (#eef0f3) pushes the 9px status
   ink just under 4.5:1 (amber 4.19, cyan 4.40, orange 4.03, emerald 4.51).
   Step those accents one shade darker — only on the dimmed node, so the
   active step keeps its brighter brand colour. Measured after the change:
   amber 6.21, cyan 6.62, orange 6.40, emerald 4.80. */
html:not(.dark) .gw-node-wrap.gw-node-dimmed .text-amber-600   { color: #92400e !important; }
html:not(.dark) .gw-node-wrap.gw-node-dimmed .text-cyan-600    { color: #075985 !important; }
html:not(.dark) .gw-node-wrap.gw-node-dimmed .text-emerald-600 { color: #047857 !important; }
html:not(.dark) .gw-node-wrap.gw-node-dimmed .text-orange-500  { color: #9a3412 !important; }

/* ----------------------------------------------------------------------------
 * 3.  WCAG 1.4.3  Color contrast — 8px status chips
 *
 *   #1-6 (light) / #1-3 (dark): the inline chips (text-[8px]) use
 *   `text-zinc-600 dark:text-zinc-400` etc., which on `bg-zinc-100/800`
 *   measured 2.49:1.
 *
 *   Fix: ship a .gw-chip utility with explicit AA-safe colours for the
 *   neutral and success variants. Replace the bad class strings in markup
 *   with `gw-chip` / `gw-chip gw-chip--ok` (see report).
 * ---------------------------------------------------------------------------- */
.gw-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    border-radius: 0.375rem;
    padding: 0.125rem 0.375rem;
    font-size: var(--gw-fs-xs, 0.75rem);
    font-weight: 600;
    text-transform: none;
    line-height: 1.2;
}
html:not(.dark) .gw-chip        { background: #f4f4f5; color: #27272a; }   /* 9.50:1 */
html.dark       .gw-chip        { background: #27272a; color: #d4d4d8; }   /* 10.08:1 */
html:not(.dark) .gw-chip--ok    { background: #ecfdf5; color: #047857; }   /* 5.21:1 */
html.dark       .gw-chip--ok    { background: #042f1e; color: #6ee7b7; }   /* 9.59:1 */

/* Belt-and-braces: if a downstream page still has the old class string, lift
   it to AA via a colour remap that beats the original Tailwind pair. */
html:not(.dark) .bg-zinc-100.text-zinc-600 { color: #27272a; }
html.dark       .bg-zinc-800.text-zinc-400 { color: #d4d4d8; }
html:not(.dark) .bg-emerald-50.text-emerald-600 { color: #047857; }
html.dark       .bg-emerald-500\/10.text-emerald-400 { color: #6ee7b7; }

/* ----------------------------------------------------------------------------
 * 4.  WCAG 1.4.3  SVG flow labels (#50-58, #47-58 in pass 2)
 *
 *   <text> labels inside the aria-hidden flow diagram used fills that
 *   measure 1.7-3.96:1 on the panel. Bump to AA-compliant ink and drop
 *   the opacity multiplier so axe can resolve them.
 * ---------------------------------------------------------------------------- */
.gw-flow-svg text:not(.gw-pill-num):not(.gw-pill-label) {
    opacity: 1 !important;
    font-size: 9px !important;
    paint-order: stroke fill;                /* keeps the label crisp on top of any gradient */
}
html:not(.dark) .gw-flow-svg text[fill="#03D9F0"]:not(.gw-pill-num):not(.gw-pill-label),
html:not(.dark) .gw-flow-svg text[fill="#a78bfa"]:not(.gw-pill-num):not(.gw-pill-label),
html:not(.dark) .gw-flow-svg text[fill="#A855F7"]:not(.gw-pill-num):not(.gw-pill-label),
html:not(.dark) .gw-flow-svg text[fill="#8b5cf6"]:not(.gw-pill-num):not(.gw-pill-label),
html:not(.dark) .gw-flow-svg text[fill="#a855f7"]:not(.gw-pill-num):not(.gw-pill-label),
html:not(.dark) .gw-flow-svg text[fill="#10b981"]:not(.gw-pill-num):not(.gw-pill-label) {
    fill: #0e7490 !important;
}
html.dark .gw-flow-svg text[fill="#03D9F0"]:not(.gw-pill-num):not(.gw-pill-label),
html.dark .gw-flow-svg text[fill="#a78bfa"]:not(.gw-pill-num):not(.gw-pill-label),
html.dark .gw-flow-svg text[fill="#A855F7"]:not(.gw-pill-num):not(.gw-pill-label),
html.dark .gw-flow-svg text[fill="#8b5cf6"]:not(.gw-pill-num):not(.gw-pill-label),
html.dark .gw-flow-svg text[fill="#a855f7"]:not(.gw-pill-num):not(.gw-pill-label),
html.dark .gw-flow-svg text[fill="#10b981"]:not(.gw-pill-num):not(.gw-pill-label) {
    fill: #67e8f9 !important;
}

/* ----------------------------------------------------------------------------
 * 5.  WCAG 1.4.3  Hero copy column — needs review (#35-49, #65-67)
 *
 *   The audit lists 18 hero items as "background could not be determined"
 *   because the copy sits on a hero image whose contrast against the ink
 *   colour is unprovable. axe flags these as "needs manual review" — they
 *   are NOT a hard violation — and the right engineering answer is to make
 *   the background decidable.
 *
 *   Pixel-level analysis (see report, §B) shows:
 *     - Light hero: 98.3% of the left text area already passes 4.5:1.
 *       Worst blob 90x30 px (whale splash). No scrim needed for light.
 *     - Dark hero: 86.9% pass; worst blob 349x432 px — a real risk.
 *       50% black scrim brings the worst pixel to 4.5:1 but is visible.
 *
 *   Solution shipped here: a low-contrast, .gw-hero-scrim utility, off by
 *   default and intentionally subtle so the design owner can dial it.
 *   Toggle on with the `data-hero-scrim` attribute on the <main> element
 *   (or `.gw-hero-scrim-on` on the wrapper).
 * ---------------------------------------------------------------------------- */
.gw-hero-scrim-on .gw-hero-left {
    /* 0.45 alpha black scrim at the left edge, fading to 0 across the
       text column. Pixel analysis: dark-hero worst goes 1.00 -> 4.50+. */
    background-image: linear-gradient(to right, rgba(24, 27, 33, .45), rgba(24, 27, 33, 0));
    background-repeat: no-repeat;
    border-radius: 16px;
}
html:not(.dark) .gw-hero-scrim-on .gw-hero-left {
    background-image: linear-gradient(to right, rgba(255, 255, 255, .5), rgba(255, 255, 255, 0));
}

/* ----------------------------------------------------------------------------
 * 6.  WCAG 2.5.8  Touch target size — backstop for any remaining .gw-dot
 *
 *   The buttons were rebuilt in markup (24x24 with a child bar) but the
 *   old `.gw-dot::after` rule in a11y-fix.css still adds a 24px-tall
 *   pseudo layer. Now redundant; trim the height so the visible dot stays
 *   the same size on the new 24px button.
 * ---------------------------------------------------------------------------- */
.gw-dot::after {
    height: 100%;        /* was 24px; the button is now 24x24 itself */
    top: 0;
    transform: none;
}

/* ----------------------------------------------------------------------------
 * 7.  ARIA on labelled elements without a role (#28-29 / #25-26)
 *
 *   aria-label on a bare <div> / <span> is ignored by AT. Fix is a markup
 *   edit (role="img") — see report. This rule is a safety net: if a stale
 *   copy of the markup ships, AT users still see the label as the tooltip
 *   on hover, and the div is focusable via tabindex on the phone mockup.
 * ---------------------------------------------------------------------------- */
.gw-phone:focus-visible {
    outline: 2px solid #03D9F0;
    outline-offset: 4px;
}

/* ----------------------------------------------------------------------------
 * 8.  WCAG 1.4.3  Stat pill — "$1.2M processed / mo" (audit #1-2)
 *
 *   The pill paints `rgba(168,85,247,.12)` over the white card, which
 *   composites to #f5ebfe. Brand purple #c084fc on that is 2.29:1 — a real
 *   failure at 14px. purple-700 (#7e22ce) gives 6.05:1. In dark the pill sits
 *   on a dark surface where the bright purple already clears AA, so keep the
 *   brand colour there.
 * -------------------------------------------------------------------------- */
:root {
    --gw-why-violet: #7e22ce;   /* light: 6.05:1 on #f5ebfe */
}
html.dark {
    --gw-why-violet: #c084fc;   /* dark: bright purple on the dark pill, AA ok */
}

/* ----------------------------------------------------------------------------
 * 9.  WCAG 1.4.3  Footer wordmark "Whale" (audit #3)
 *
 *   #03D9F0 on #ffffff = 1.72:1. At 30.7px/800 this is "large text", so the
 *   bar is 3:1 — still a fail. Brand cyan is fine on the dark footer (11:1),
 *   so only the light theme needs a darker cyan. cyan-700 #0e7490 = 5.36:1.
 *   The !important is required: the colour is set by an inline style, and an
 *   !important author declaration is what overrides a non-important inline one.
 * -------------------------------------------------------------------------- */
html:not(.dark) .gw-wordmark { color: #0e7490 !important; }
html.dark       .gw-wordmark { color: #03D9F0 !important; }