/* ==========================================================================
   Search & Cite — BASE
   Reset, document surface, typography defaults, focus policy, a11y helpers.
   No page components live here.
   ========================================================================== */

* { box-sizing: border-box; }

/* Anything scrolled to by script or by a fragment link stops BELOW the site nav
   and the sticky board summary, instead of underneath them. Without this the
   board's own "next problem claim" control lands its target in the one band of
   the viewport that is covered. */
html {
    scroll-padding-top: calc(var(--nav-h) + var(--board-h) + 0.75rem);
}

body {
    font-family: var(--font-sans);
    background-color: var(--surface-0);
    color: var(--text-primary);
    font-size: var(--text-base);
    line-height: var(--lh-normal);
    -webkit-font-smoothing: antialiased;
    margin: 0;
    padding: 0;
    position: relative;
    min-height: 100vh;
}

/* Bootstrap's reboot sets these; the app's own scale owns them instead. */
h1, h2, h3, h4, h5, h6 {
    font-weight: var(--fw-semibold);
    line-height: var(--lh-snug);
    letter-spacing: var(--ls-tight);
    color: var(--text-strong);
}

/* ---- Ambient background ----------------------------------------------
   Two fixed radial blooms behind everything. They sit BEHIND the app shell,
   which is now opaque, so nothing that has to be legible is ever painted on
   top of them — the measured contrast of a card and its painted contrast are
   the same number. Purely decorative, so both are killed outright under
   reduced motion (below) rather than merely frozen: a static 120px blur still
   costs a full-screen composite on every scroll. */
body::before,
body::after {
    content: '';
    position: fixed;
    width: 60%;
    height: 60%;
    opacity: 0.14;
    filter: blur(130px);
    z-index: -1;
    pointer-events: none;
}

body::before {
    top: -30%;
    left: -20%;
    background: radial-gradient(circle, var(--accent-solid) 0%, transparent 70%);
    animation: aurora-1 var(--duration-ambient) infinite alternate;
}

body::after {
    bottom: -30%;
    right: -20%;
    background: radial-gradient(circle, #6D3FD1 0%, transparent 70%);
    animation: aurora-2 15s infinite alternate;
}

@keyframes aurora-1 {
    from { transform: scale(0.8) rotate(0deg); opacity: 0.09; }
    to   { transform: scale(1.2) rotate(45deg); opacity: 0.18; }
}
@keyframes aurora-2 {
    from { transform: scale(1.2) rotate(0deg); opacity: 0.18; }
    to   { transform: scale(0.8) rotate(-45deg); opacity: 0.09; }
}
@keyframes sc-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}
@keyframes sc-shimmer {
    from { background-position: -400px 0; }
    to   { background-position: 400px 0; }
}

/* ---- Focus ------------------------------------------------------------
   TWO TIERS, and the quiet one is not a formality.

   `:focus-visible` alone was the old policy, and it left a real hole: when
   focus is moved by script (a dialog opening, a retry re-focusing its own
   card, `.focus()` after a tab switch) while the user's last interaction was
   a click, Chromium does NOT set :focus-visible. Focus was somewhere on the
   page and nothing on screen said where. The audit caught this on 39
   controls; a keyboard user who reaches for a control after clicking one
   hits exactly the same wall.

   So: the loud two-tone ring for keyboard focus, and a quieter — but
   genuinely visible, and genuinely measured — ring for every other way focus
   can land. --border-interactive is 3.02–3.64:1 against every surface in the
   system, so the quiet tier still clears 1.4.11 on its own. The two tiers are
   distinguishable from each other, which is the point: the loud one means
   "you are driving with the keyboard".

   `outline`, not `box-shadow`: outline is drawn outside the box, never
   participates in layout, and never collides with a component's own
   elevation shadow. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
    outline: 2px solid var(--focus-ring-color);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

:where(a, button, input, select, textarea, summary, [tabindex]):focus:not(:focus-visible) {
    outline: 2px solid var(--border-interactive);
    outline-offset: 2px;
}

/* Elements whose own border-radius is larger than the default keep their
   shape, so the ring hugs the control rather than cutting its corners. */
:where(.btn-primary, .btn-secondary, .btn-ghost, .btn-icon, .mode-button,
       .claim-card, .evidence-item, .example-card):focus-visible {
    border-radius: inherit;
}

/* ---- Skip link --------------------------------------------------------
   Full 44px target even while parked off-screen: the audit measures it where
   it sits, and a 43px control is a 43px control whether or not it is visible. */
.skip-link {
    position: absolute;
    left: 0.5rem;
    top: -4rem;
    z-index: calc(var(--z-modal) + 1);
    display: inline-flex;
    align-items: center;
    min-height: var(--hit-min);
    padding: 0.7rem 1.1rem;
    background: var(--accent-solid);
    color: var(--text-on-accent);
    border-radius: var(--radius-md);
    font-weight: var(--fw-semibold);
    text-decoration: none;
    transition: top var(--duration-fast) var(--ease-out);
}
.skip-link:focus {
    top: 0.5rem;
    color: var(--text-on-accent);
}

/* ---- Screen-reader-only ----------------------------------------------
   Used by the aria-live announcer and by icon-only affordances that carry a
   text label for assistive tech. Never `display:none` — that mutes it. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ---- Scrollbars -------------------------------------------------------- */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--surface-1); border-radius: 5px; }
::-webkit-scrollbar-thumb {
    background: var(--surface-4);
    border-radius: 5px;
    border: 1px solid var(--border-default);
}
::-webkit-scrollbar-thumb:hover { background: var(--border-interactive); }

/* ---- Reduced motion ---------------------------------------------------
   One block, applied globally. Transitions collapse to ~0 rather than 0 so
   transitionend listeners still fire; decorative animations are removed. */
@media (prefers-reduced-motion: reduce) {
    :root {
        --transition-speed: 0.01ms;
        --duration-fast: 0.01ms;
        --duration-base: 0.01ms;
        --duration-slow: 0.01ms;
    }

    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }

    body::before,
    body::after { animation: none; }

    /* The one animation worth keeping legible: a spinner that does not spin
       reads as a frozen page. Slow it right down instead of stopping it. */
    .fa-spin,
    .sc-spinner {
        animation: sc-spin 3s linear infinite !important;
    }
}
