/* ── Site-wide accessibility layer (audit Part H · WCAG 2.2 AA) ───────────────────────────────────────────
 *
 * Loaded LAST — below <HeadOutlet/> in App.razor, which matters: pages inject their own stylesheets through
 * <HeadContent>, so a link above HeadOutlet is not actually last and ai-intelligence.css (which contains
 * explicit `outline: none` focus rules) would win same-specificity ties across the whole Compass surface.
 *
 * The rules here restore affordances the vendor bundles remove. Three of them are global enough to change
 * layout, and are called out where they appear rather than being described as harmless: the media max-width,
 * the scroll-margin, and the reduced-motion block.
 *
 * Legal footing on both sides of the market we sell into: ADA / Unruh Act for a California operator, and the
 * European Accessibility Act — applicable to e-commerce services offered to EU consumers since 28 June 2025,
 * with EN 301 549 as the harmonised baseline. EN 301 549 v3.2.1 currently references WCAG 2.1 AA and the
 * v4.x revision moves to 2.2; building to 2.2 AA satisfies both today and after that revision lands.
 *
 * Each rule below names the success criterion it serves. A rule nobody can trace back to a criterion tends to
 * be the one that gets "cleaned up" later by someone who cannot tell it apart from decoration.
 */

/* ── 2.4.1 Bypass Blocks ─────────────────────────────────────────────────────────────────────────────────
 * A keyboard or screen-reader user lands on the nav on every single page. Without a skip link they tab through
 * the whole of it every time — and this site's Compass menu is a multi-level dropdown, so "the whole of it" is
 * dozens of stops. The link is visually hidden until focused, then becomes a real, visible control. */
.skip-to-content {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 2000;
    padding: .7rem 1.1rem;
    background: #0f172a;
    color: #fff !important;
    font-weight: 700;
    text-decoration: none;
    border-radius: 0 0 8px 0;
}
.skip-to-content:focus,
.skip-to-content:focus-visible {
    left: 0;
    outline: 3px solid #F8A347;
    outline-offset: 2px;
}

/* ── 2.4.7 Focus Visible + 2.4.11 Focus Not Obscured (Minimum) ───────────────────────────────────────────
 * Bootstrap and the theme bundle both suppress the UA focus ring in places. :focus-visible (rather than
 * :focus) means a mouse click does not paint a ring, so restoring it costs nothing visually for pointer users
 * while giving keyboard users the indicator 2.4.7 requires.
 *
 * scroll-margin-top on focusable elements is the 2.4.11 half: the nav is sticky, so an element scrolled to by
 * Tab can end up underneath it — technically focused, visually gone. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:not(h1, h2, h3, h4, h5, h6):focus-visible,
[role="button"]:focus-visible,
[role="tab"]:focus-visible {
    outline: 3px solid #F8A347;
    outline-offset: 2px;
    border-radius: 3px;
}
/* Why headings are excluded from [tabindex] above — this was a real bug, not a hypothetical.
 * Blazor's <FocusOnNavigate RouteData="@routeData" Selector="h1" /> (Routes.razor, a template default) stamps
 * tabindex="-1" onto the first heading of every page and focuses it after each navigation, so a screen-reader
 * user hears the new page instead of being dumped at the top of an unchanged-sounding document. That affordance
 * is AUDIBLE. But pressing F5 is itself a keyboard action, so the browser is in keyboard modality when that
 * programmatic focus lands, :focus-visible matches, and the bare [tabindex] selector painted a 3px ring around
 * the hero headline on every single page load — and again on any click, because the heading is now permanently
 * mouse-focusable.
 *
 * A heading carrying tabindex="-1" is never a keyboard TAB STOP; it can only be reached programmatically or by
 * pointer. 2.4.7 is about showing a keyboard user where Tab landed, so no ring here communicates anything.
 * main#main-content is deliberately NOT excluded: landing there IS keyboard navigation (the skip link), and
 * that ring is the whole point of it. */
/* NOTE: this changes scrollIntoView / :target landing positions app-wide — that is the point (the nav is
 * sticky and would otherwise cover the element that was just focused), but it is a layout-affecting rule, not
 * a purely additive one. [tabindex] is excluded because it matches main#main-content and every dialog. */
a, button, input, select, textarea, summary, [role="button"] {
    scroll-margin-top: 6rem;
}

/* Dark surfaces need a different ring colour to keep 3:1 against their own background (1.4.11 Non-text
 * Contrast). Orange on near-black is fine; orange on the amber-tinted panels is not, so those get cyan. */
.compass-dark a:focus-visible,
.compass-dark button:focus-visible,
.compass-dark input:focus-visible,
.compass-dark select:focus-visible,
.compass-dark [tabindex]:not(h1, h2, h3, h4, h5, h6):focus-visible,
.ai-page a:focus-visible,
.ai-page button:focus-visible,
.ai-page input:focus-visible,
.ai-page select:focus-visible,
.ai-page [tabindex]:not(h1, h2, h3, h4, h5, h6):focus-visible {
    outline-color: #67e8f9;
}

/* ── 2.5.8 Target Size (Minimum) — 24×24 CSS px ──────────────────────────────────────────────────────────
 * Applied to the controls this site actually renders small: icon buttons, chart legend toggles, chip filters,
 * close buttons. Deliberately NOT a blanket `button { min-height: 24px }` — 2.5.8 exempts targets in a
 * sentence of text, and forcing a size on inline links inside prose would break the line box for everyone. */
.btn-close,
.compass-chip,
.ai-chip {
    min-width: 24px;
    min-height: 24px;
}

/* ── 2.3.3 Animation from Interactions + 2.2.2 Pause, Stop, Hide ─────────────────────────────────────────
 * The theme ships WOW.js scroll animations and the owl carousel, neither of which asks about motion
 * preference. This disables non-essential motion outright for users who have said they do not want it —
 * including the carousel's autoplay, which is the "moving content that starts automatically" 2.2.2 is about.
 * Kept to a near-zero duration rather than `animation: none` so animation-end handlers still fire and
 * scripts that wait for them do not hang. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
    .wow { visibility: visible !important; }
}

/* ── 1.4.4 Resize Text + 1.4.10 Reflow ──────────────────────────────────────────────────────────────────
 * At 400% zoom a 1280px viewport reflows to roughly 320px wide, and 1.4.10 forbids two-directional scrolling.
 * Wide content — data tables, code blocks, the SVG charts — must therefore scroll inside its own container
 * instead of pushing the page sideways. `max-width: 100%` on media is the other half. */
.table-responsive,
.pp-table-wrap,
.a11y-scroll-x {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* Media never forces the PAGE wider. Scoped with :not() because the unscoped form contradicted the rule above
 * it: a wide chart inside a scroll container would shrink to fit rather than scroll, which loses the detail
 * 1.4.10 is trying to keep reachable. Inside a scroll container, overflow is the correct behaviour. */
:is(img, svg, video, canvas, iframe):not(.a11y-scroll-x *):not(.table-responsive *) { max-width: 100%; }

/* ── 1.3.1 Info and Relationships ────────────────────────────────────────────────────────────────────────
 * The utility to use for a label that must reach a screen reader but not the screen. Provided so nobody
 * reaches for `display: none`, which removes the label from the accessibility tree as well as from view.
 * (Currently unused — it exists as the correct answer for the next label that needs it.) */
.visually-hidden-a11y {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    margin: -1px !important;
    padding: 0 !important;
    overflow: hidden !important;
    clip: rect(0 0 0 0) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

/* ── 1.4.12 Text Spacing ─────────────────────────────────────────────────────────────────────────────────
 * A user stylesheet that raises line-height to 1.5× and letter-spacing to 0.12em must not clip content.
 * Fixed-height text containers are the usual failure; this makes the common ones grow instead. */
.legal-body p,
.legal-body li,
.ai-page p,
.compass-dark p {
    overflow-wrap: break-word;
}

/* ── 1.4.1 Use of Colour ─────────────────────────────────────────────────────────────────────────────────
 * Links inside running prose need a non-colour cue. Nav, buttons, cards and chips are excluded: they are
 * identifiable by shape and position, which is the distinction 1.4.1 actually draws. */
.legal-body a:not(.btn):not(.cab-secondary),
.ai-page p > a:not(.btn):not(.ai-btn-primary):not(.cgm-primary) {
    text-decoration: underline;
    text-underline-offset: .15em;
}

/* ── 4.1.3 Status Messages ───────────────────────────────────────────────────────────────────────────────
 * The shared live regions EnginerdsA11y.announce() creates. Styled here rather than inline so a region that
 * somehow reaches the DOM without its inline style still cannot appear on screen. */
#enginerds-live-polite,
#enginerds-live-assertive {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    overflow: hidden !important;
    clip: rect(0 0 0 0) !important;
    white-space: nowrap !important;
}

/* ── 1.4.11 Non-text Contrast, forced-colours mode ───────────────────────────────────────────────────────
 * Windows High Contrast replaces our palette wholesale. Borders drawn with a background colour vanish, so
 * controls lose their edges. Asking for a system-coloured outline puts them back. */
@media (forced-colors: active) {
    button, .btn, [role="button"], input, select, textarea {
        border: 1px solid ButtonBorder;
    }
    a:focus-visible, button:focus-visible, [tabindex]:focus-visible {
        outline: 3px solid Highlight;
    }
}
