/* Ursula — minimal, accessible CSS. No framework. */

/* ─── Variables ─────────────────────────────────────────────────────────────── */
/*
 * Theming has two layers, both pure CSS (no JS, no cookies):
 *
 *   1. PRIMARY — `prefers-color-scheme`. The light palette lives in `:root`;
 *      the dark palette is applied automatically from the OS setting via the
 *      media query below. This persists for free (follows the OS).
 *   2. OVERRIDE — `?theme=dark|light`. Ursula reads the param server-side and
 *      sets `class="theme-dark"` / `class="theme-light"` on <html>. The
 *      forcing classes win over the media query by specificity, and the media
 *      query is gated with `:not(.theme-light)` so forcing light on a dark OS
 *      fully reverts. When the param is absent, the page falls back to the
 *      automatic media query.
 *
 * Every color is a custom property so both palettes flow from one place.
 */
:root {
    --font: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    --mono: ui-monospace, "Cascadia Code", "Fira Code", monospace;
    --max-width: 800px;

    /* Light palette (default) */
    --color-bg: #ffffff;
    --color-text: #1a1a1a;
    --color-muted: #666666;
    --color-border: #e0e0e0;
    --color-link: #1a56b0;
    --color-link-hover: #0d3e8c;
    --color-primary: #1a56b0;
    --color-primary-hover: #0d3e8c;
    --color-on-primary: #ffffff;
    --color-mark: #fff3b0;
    --color-mark-text: #1a1a1a;
    --color-badge-bg: #e8f0fe;
    --color-badge-text: #1a56b0;
    --color-warning: #856404;
    --color-warning-bg: #fff3cd;
    --color-focus-ring: rgba(26, 86, 176, 0.2);
    --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.08);
    --shadow-card-hover: 0 2px 8px rgba(0, 0, 0, 0.12);

    /* Per-collection badge palette (light) */
    --badge-guidance-bg: #e3f2fd;
    --badge-guidance-text: #1565c0;
    --badge-clearance-bg: #e8f5e9;
    --badge-clearance-text: #2e7d32;
    --badge-fedreg-bg: #fce4ec;
    --badge-fedreg-text: #c62828;
    --badge-legislative-bg: #f3e5f5;
    --badge-legislative-text: #6a1b9a;
    --badge-cdrh-bg: #fff3e0;
    --badge-cdrh-text: #c44200; /* darkened from #e65100 for WCAG AA (4.6:1) */

    --radius: 4px;
    --spacing-sm: 0.5rem;
    --spacing-md: 1rem;
    --spacing-lg: 1.5rem;
    --spacing-xl: 2rem;
}

/*
 * Dark palette. Defined identically in two places so both entry points share
 * the same values: the media query (OS-automatic, opted out of by an explicit
 * `?theme=light`) and the `.theme-dark` forcing class (explicit `?theme=dark`).
 */
@media (prefers-color-scheme: dark) {
    :root:not(.theme-light) {
        --color-bg: #121212;
        --color-text: #e8e8e8;
        --color-muted: #9a9a9a;
        --color-border: #333333;
        --color-link: #7baaf7;
        --color-link-hover: #a8c7fa;
        --color-primary: #7baaf7;
        --color-primary-hover: #a8c7fa;
        --color-on-primary: #121212;
        --color-mark: #665c00;
        --color-mark-text: #e8e8e8;
        --color-badge-bg: #1e2b4a;
        --color-badge-text: #7baaf7;
        --color-warning: #ffc107;
        --color-warning-bg: #332701;
        --color-focus-ring: rgba(123, 170, 247, 0.3);
        --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.4);
        --shadow-card-hover: 0 2px 8px rgba(0, 0, 0, 0.6);

        --badge-guidance-bg: #0d2f4f;
        --badge-guidance-text: #7baaf7;
        --badge-clearance-bg: #0d2f1a;
        --badge-clearance-text: #66bb6a;
        --badge-fedreg-bg: #3b0d17;
        --badge-fedreg-text: #ef9a9a;
        --badge-legislative-bg: #2a0d3b;
        --badge-legislative-text: #ce93d8;
        --badge-cdrh-bg: #3b1f0d;
        --badge-cdrh-text: #ffb74d;
    }
}

/* Explicit `?theme=dark` override — wins over the media query by specificity. */
:root.theme-dark {
    --color-bg: #121212;
    --color-text: #e8e8e8;
    --color-muted: #9a9a9a;
    --color-border: #333333;
    --color-link: #7baaf7;
    --color-link-hover: #a8c7fa;
    --color-primary: #7baaf7;
    --color-primary-hover: #a8c7fa;
    --color-on-primary: #121212;
    --color-mark: #665c00;
    --color-mark-text: #e8e8e8;
    --color-badge-bg: #1e2b4a;
    --color-badge-text: #7baaf7;
    --color-warning: #ffc107;
    --color-warning-bg: #332701;
    --color-focus-ring: rgba(123, 170, 247, 0.3);
    --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.4);
    --shadow-card-hover: 0 2px 8px rgba(0, 0, 0, 0.6);

    --badge-guidance-bg: #0d2f4f;
    --badge-guidance-text: #7baaf7;
    --badge-clearance-bg: #0d2f1a;
    --badge-clearance-text: #66bb6a;
    --badge-fedreg-bg: #3b0d17;
    --badge-fedreg-text: #ef9a9a;
    --badge-legislative-bg: #2a0d3b;
    --badge-legislative-text: #ce93d8;
    --badge-cdrh-bg: #3b1f0d;
    --badge-cdrh-text: #ffb74d;
}

/* ─── Reset ──────────────────────────────────────────────────────────────────── */
*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

/* ─── Base ───────────────────────────────────────────────────────────────────── */
html {
    font-size: 16px;
    scroll-behavior: smooth;
}

body {
    font-family: var(--font);
    background-color: var(--color-bg);
    color: var(--color-text);
    line-height: 1.6;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

a {
    color: var(--color-link);
    text-decoration: none;
}

a:hover {
    color: var(--color-link-hover);
    text-decoration: underline;
}

/* ─── Skip link (accessibility) ──────────────────────────────────────────────── */
.skip-link {
    position: absolute;
    top: -100px;
    left: 0;
    background: var(--color-primary);
    color: var(--color-on-primary);
    padding: var(--spacing-sm) var(--spacing-md);
    z-index: 100;
    border-radius: 0 0 var(--radius) 0;
}

.skip-link:focus {
    top: 0;
}

/* ─── Screen-reader only ─────────────────────────────────────────────────────── */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border-width: 0;
}

/* ─── Header / Nav ───────────────────────────────────────────────────────────── */
header {
    border-bottom: 1px solid var(--color-border);
    padding: var(--spacing-sm) var(--spacing-md);
    background-color: var(--color-bg);
}

nav {
    max-width: var(--max-width);
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-md);
}

.nav-brand {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--color-text);
    text-decoration: none;
    letter-spacing: -0.02em;
}

.nav-brand:hover {
    color: var(--color-primary);
    text-decoration: none;
}

/* "(Beta)" tag next to the brand: smaller, muted, non-bold, normal letter-spacing
   so it reads as a status marker rather than part of the product name. */
.beta-tag {
    margin-left: 0.4em;
    font-size: 0.7rem;
    font-weight: 400;
    letter-spacing: normal;
    color: var(--color-text-muted);
    vertical-align: super;
}

/* CSS-only hamburger disclosure (#127): a native <details>/<summary> menu — no
   JavaScript, no checkbox-hack. The open panel is `position: absolute` so it
   OVERLAYS the header rather than growing it: opening the menu causes zero layout
   shift of the search band at any viewport (Adv-P). Reuses existing --color-*
   custom properties only (no new palette pair). */
.nav-menu {
    position: relative;
}

.nav-menu-toggle {
    cursor: pointer;
    color: var(--color-muted);
    font-size: 0.9rem;
    padding: var(--spacing-sm);
    /* Suppress the default disclosure triangle so it reads as a menu control. */
    list-style: none;
}

.nav-menu-toggle::-webkit-details-marker {
    display: none;
}

.nav-menu-toggle:hover {
    color: var(--color-text);
}

.nav-menu-panel {
    list-style: none;
    position: absolute;
    right: 0;
    top: 100%;
    z-index: 20;
    margin-top: var(--spacing-sm);
    padding: var(--spacing-sm);
    min-width: 11rem;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
    background-color: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
}

.nav-menu-panel a {
    display: block;
    color: var(--color-muted);
    font-size: 0.9rem;
}

.nav-menu-panel a:hover,
.nav-menu-panel a.active {
    color: var(--color-text);
    text-decoration: none;
}

/* ─── Main content ───────────────────────────────────────────────────────────── */
main {
    flex: 1;
    max-width: var(--max-width);
    width: 100%;
    margin: 0 auto;
    padding: var(--spacing-xl) var(--spacing-md);
}

/* ─── Search hero (index page) ───────────────────────────────────────────────── */
.search-hero {
    text-align: center;
    padding: var(--spacing-xl) 0;
}

.search-hero h1 {
    font-size: 2rem;
    font-weight: 700;
    margin-bottom: var(--spacing-sm);
    letter-spacing: -0.03em;
}

.tagline {
    color: var(--color-muted);
    margin-bottom: var(--spacing-lg);
    font-size: 1rem;
}

/* ─── Search form ────────────────────────────────────────────────────────────── */
.search-row {
    display: flex;
    gap: var(--spacing-sm);
    max-width: 600px;
    margin: 0 auto;
}

input[type="search"],
input[type="text"] {
    flex: 1;
    padding: 0.6rem 0.8rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    font-family: var(--font);
    font-size: 1rem;
    color: var(--color-text);
    background-color: var(--color-bg);
    outline: none;
    min-width: 0;
}

input[type="search"]:focus,
input[type="text"]:focus {
    border-color: var(--color-primary);
    box-shadow: 0 0 0 2px var(--color-focus-ring);
}

button[type="submit"],
button {
    padding: 0.6rem 1.2rem;
    background-color: var(--color-primary);
    color: var(--color-on-primary);
    border: none;
    border-radius: var(--radius);
    font-family: var(--font);
    font-size: 1rem;
    cursor: pointer;
    white-space: nowrap;
    transition: background-color 0.1s;
}

button:hover {
    background-color: var(--color-primary-hover);
}

/* ─── Search bar (results page) ──────────────────────────────────────────────── */
.search-bar {
    margin-bottom: var(--spacing-md);
}

.search-bar .search-row {
    margin: 0;
    max-width: 100%;
}

/* The compact bar is hoisted into the header band (#96) on every non-index
   page; center it to the same max-width as the nav (#124). A larger top margin
   pads the bar clear of the brand/nav row so the banner and the search bar read
   as two separated bands rather than a cramped stack (#126); no bottom margin
   in the header (the header padding closes the band). */
header .search-bar {
    max-width: var(--max-width);
    margin: var(--spacing-md) auto 0;
}

/* ─── Result meta (heading area) ─────────────────────────────────────────────── */
.result-meta {
    margin-bottom: var(--spacing-lg);
    padding-bottom: var(--spacing-sm);
    border-bottom: 1px solid var(--color-border);
}

/* Primary line: "N results for X" — sits at body size, query echo in bold. */
.result-summary {
    font-size: 1rem;
    color: var(--color-text);
}

/* Secondary line: page position + timing, demoted and muted. */
.result-stats {
    margin-top: 0.15rem;
    font-size: 0.8rem;
    color: var(--color-muted);
}

/* Keyword-vs-related split (#88): the count summary + no-JS filter link. Sits
   just below the primary summary, demoted like .result-stats but a touch larger
   so the filter link is easy to find and tap. */
.result-provenance {
    margin-top: 0.25rem;
    font-size: 0.85rem;
    color: var(--color-muted);
}

.provenance-link {
    white-space: nowrap;
}

.no-results {
    color: var(--color-text);
    padding: var(--spacing-lg) 0;
}

/* Degraded-response disclosure (#48): shown only when one or more collections
   timed out and were omitted. Uses the warning palette so it reads as a caveat,
   not an error. */
.result-incomplete,
/* Honest-results disclosure (F-0421 P0): shown when the leading result does not
   clear the confidence floor. Deliberately its OWN class sharing this styling
   rather than reusing `.result-incomplete` — the two say different things
   ("we could not search everything" vs "what we found is not a direct match"),
   and a shared class would make them indistinguishable to the tests that assert
   each one appears only when it should. */
.result-confidence {
    margin-top: var(--spacing-sm);
    padding: var(--spacing-sm);
    font-size: 0.85rem;
    color: var(--color-warning);
    background-color: var(--color-warning-bg);
    border-radius: 4px;
}

/* ─── Results list ───────────────────────────────────────────────────────────── */
.results-list {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-lg);
}

/* ─── Result card (whole-card click target, #204) ────────────────────────────────
   A subtle bordered card gives a large, obvious click target. The whole card is
   clickable with NO JavaScript (invariant R-001) via the "stretched link" pattern:
   the card is the positioned containing block, and the title anchor's `::after`
   overlay (below) covers the card, so a click anywhere on it opens the detail
   page. Inner links (the external source URL) sit above the overlay so they stay
   independently clickable and keyboard-focusable. */
.result-card {
    position: relative;
    display: flex;
    align-items: baseline;
    gap: var(--spacing-md);
    padding: var(--spacing-md);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    transition:
        border-color 0.15s ease,
        box-shadow 0.15s ease;
}

/* Hover affordance: the whole card lights up, signalling it is one click target. */
.result-card:hover {
    border-color: var(--color-primary);
    box-shadow: 0 1px 4px rgb(0 0 0 / 8%);
}

/* Rank hangs in a fixed left gutter; the body block is indented beside it and
   wraps aligned under itself (hanging-indent, numbered-list feel). Kept subtle
   so it orients without competing with the title. */
.result-rank {
    flex-shrink: 0;
    min-width: 1.5rem;
    text-align: right;
    font-size: 0.8rem;
    font-weight: 400;
    color: var(--color-muted);
    /* Nudge the lighter rank down to baseline-align with the title text. */
    position: relative;
    top: 0.05rem;
}

.result-body {
    flex: 1;
    min-width: 0;
}

.result-title {
    font-size: 1rem;
    font-weight: 600;
    margin-bottom: var(--spacing-sm);
    line-height: 1.3;
}

.result-title a {
    color: var(--color-text);
}

.result-title a:hover {
    color: var(--color-primary);
}

/* Stretched-link overlay (#204): the title anchor's `::after` covers the whole
   card, making the entire card a single click target with no JS. Sits below inner
   links (which raise their own z-index) so those stay clickable. */
.result-title a::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
}

/* Card-wide, visible focus ring: the stretched title anchor is the focusable
   element, so its focus outline is drawn on the overlay spanning the whole card. */
.result-title a:focus-visible::after {
    outline: 2px solid var(--color-primary);
    outline-offset: -2px;
    border-radius: var(--radius);
}

.result-meta-line {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--spacing-sm);
    margin-bottom: var(--spacing-sm);
    font-size: 0.85rem;
}

.result-date,
.page-ref,
.chunk-ref,
.result-passages,
/* The matched capture's standing + capture date (#244). Sits in the muted meta
   line with the other provenance facts — it is a disclosure, not a warning. */
.result-standing,
/* How strictly this result matched the query (F-0421 P0) — exact / near /
   all-terms-present / related-by-meaning. A disclosure, in the same muted meta
   line as the other provenance facts, never a warning: the set-level banner is
   where a low-confidence RESULT SET is called out. */
.result-match-tier {
    color: var(--color-muted);
}

.result-snippet {
    font-size: 0.9rem;
    color: var(--color-text);
    line-height: 1.5;
    margin-bottom: var(--spacing-sm);
}

/* Full destination URL under the result title — the complete URL is the link
   text, so it must wrap rather than overflow on narrow screens (mirrors
   `.doc-source`). */
.result-source {
    font-size: 0.8rem;
    margin-bottom: var(--spacing-sm);
    word-break: break-all;
    line-height: 1.4;
    /* Sit above the whole-card stretched-link overlay (#204) so this inner link
       stays independently clickable and keyboard-focusable. */
    position: relative;
    z-index: 2;
}

.result-source a {
    color: var(--color-link);
}

.result-source a:hover {
    color: var(--color-primary);
}

/* ─── Document detail page (#55) ─────────────────────────────────────────────── */
.doc-detail {
    max-width: 50rem;
    margin: 0 auto;
}

.doc-header {
    margin-bottom: var(--spacing-lg);
    padding-bottom: var(--spacing-md);
    border-bottom: 1px solid var(--color-border);
}

.doc-title {
    font-size: 1.5rem;
    line-height: 1.25;
    margin-bottom: var(--spacing-sm);
}

/* Populate-timing line — muted and small, mirroring .result-stats. */
.doc-stats {
    margin-top: 0.15rem;
    font-size: 0.8rem;
    color: var(--color-muted);
}

.doc-author {
    color: var(--color-muted);
    font-size: 0.85rem;
}

.doc-source {
    margin-top: var(--spacing-sm);
    font-size: 0.85rem;
    word-break: break-all;
}

.doc-source a {
    color: var(--color-link);
}

/* Copyable BibTeX cite block at the top of the detail page (#62). */
.doc-cite {
    margin-top: var(--spacing-md);
}

.doc-cite-label {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--color-muted);
    margin-bottom: var(--spacing-xs, 0.25rem);
}

.doc-bibtex {
    background-color: var(--color-code-bg, var(--color-badge-bg));
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm, 4px);
    padding: var(--spacing-sm);
    font-size: 0.8rem;
    line-height: 1.4;
    overflow-x: auto;
    white-space: pre-wrap;
    word-break: break-word;
}

/* Structured bibliographic fields (author / source / date / DOI / type). */
.doc-bib-fields {
    margin-top: var(--spacing-md);
    font-size: 0.85rem;
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 0.15rem var(--spacing-sm);
}

.doc-bib-fields dt {
    color: var(--color-muted);
    font-weight: 600;
}

.doc-bib-fields dd {
    margin: 0;
    color: var(--color-text);
}

.doc-body {
    line-height: 1.6;
}

/* One matching passage: page reference above its (highlighted) text (#63). */
.doc-passage {
    margin-bottom: var(--spacing-md);
    padding-bottom: var(--spacing-sm);
    border-bottom: 1px solid var(--color-border);
}

.doc-passage-meta {
    font-size: 0.8rem;
    margin-bottom: var(--spacing-xs, 0.25rem);
}

.doc-passage-note {
    color: var(--color-muted);
    font-style: italic;
    font-size: 0.85rem;
    margin-bottom: var(--spacing-md);
}

.doc-chunk {
    color: var(--color-text);
    white-space: pre-wrap;
}

.doc-empty {
    color: var(--color-muted);
    font-style: italic;
}

/* ─── Collection badges ──────────────────────────────────────────────────────── */
.collection-badge {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: 9999px;
    font-size: 0.75rem;
    font-weight: 600;
    background-color: var(--color-badge-bg);
    color: var(--color-badge-text);
    white-space: nowrap;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

/* Per-collection color overrides. Colors come from custom properties so both
   the automatic media query and the `?theme=` forcing classes drive them from
   one place — no direct-selector dark block to leave half-themed. */
.collection-guidance {
    background-color: var(--badge-guidance-bg);
    color: var(--badge-guidance-text);
}

.collection-clearance-package,
.collection-decision-summary {
    background-color: var(--badge-clearance-bg);
    color: var(--badge-clearance-text);
}

.collection-federal-register {
    background-color: var(--badge-fedreg-bg);
    color: var(--badge-fedreg-text);
}

.collection-legislative,
.collection-laws {
    background-color: var(--badge-legislative-bg);
    color: var(--badge-legislative-text);
}

.collection-cdrh-learn {
    background-color: var(--badge-cdrh-bg);
    color: var(--badge-cdrh-text);
}

/* ─── Highlighting ───────────────────────────────────────────────────────────── */
mark {
    background-color: var(--color-mark);
    color: var(--color-mark-text);
    padding: 0 0.1em;
    border-radius: 2px;
}

/* ─── Pagination (classic Google style: prev left, numbers centered, next right) */
.pagination {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    margin-top: var(--spacing-lg);
    padding-top: var(--spacing-md);
    border-top: 1px solid var(--color-border);
    font-size: 0.9rem;
}

/* Prev/Next sit in equal-width flanks so the numbers stay centered even when
   one side is empty (first/last page). */
.page-side {
    flex: 1;
    display: flex;
}

.page-side-prev {
    justify-content: flex-start;
}

.page-side-next {
    justify-content: flex-end;
}

.page-numbers {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: center;
    gap: var(--spacing-md);
}

/* Plain "little blue links" — no box/border. Applies to numbered pages and
   Prev/Next alike. */
.page-link {
    color: var(--color-link);
    font-size: 0.9rem;
}

a.page-link:hover {
    text-decoration: underline;
}

/* Current page: highlighted, non-interactive. A subtle pill (no border) marks
   "you are here" while the other links stay plain blue text. */
.page-current {
    background-color: var(--color-badge-bg);
    color: var(--color-text);
    padding: 0.1rem 0.5rem;
    border-radius: var(--radius);
    font-weight: 700;
    cursor: default;
}

/* ─── About page ─────────────────────────────────────────────────────────────── */
.about-content h1 {
    font-size: 1.8rem;
    font-weight: 700;
    margin-bottom: var(--spacing-lg);
    letter-spacing: -0.02em;
}

.about-content h2 {
    font-size: 1.2rem;
    font-weight: 600;
    margin-top: var(--spacing-xl);
    margin-bottom: var(--spacing-md);
}

.about-content p {
    margin-bottom: var(--spacing-md);
    line-height: 1.7;
}

.about-content ul {
    margin-bottom: var(--spacing-md);
    padding-left: var(--spacing-lg);
}

.about-content li {
    margin-bottom: var(--spacing-sm);
    line-height: 1.6;
}

.about-content code {
    font-family: var(--mono);
    font-size: 0.9em;
    background-color: var(--color-border);
    padding: 0.1em 0.3em;
    border-radius: 3px;
}

/* ─── Warning banner ──────────────────────────────────────────────────────────── */
.warning {
    color: var(--color-warning);
    background-color: var(--color-warning-bg);
    padding: var(--spacing-sm) var(--spacing-md);
    border-radius: var(--radius);
    font-size: 0.9rem;
    margin-top: var(--spacing-md);
    display: inline-block;
}

/* ─── Footer ─────────────────────────────────────────────────────────────────── */
footer {
    border-top: 1px solid var(--color-border);
    padding: var(--spacing-md);
    text-align: center;
    font-size: 0.85rem;
    color: var(--color-muted);
}

/* ─── Responsive ─────────────────────────────────────────────────────────────── */
@media (max-width: 768px) {
    .search-hero h1 {
        font-size: 1.5rem;
    }

    .search-row {
        flex-direction: column;
    }

    button[type="submit"] {
        width: 100%;
    }

    .pagination {
        flex-wrap: wrap;
        gap: var(--spacing-sm);
    }
}
