/* ==========================================================================
   legal-pages.css — the shared shell for the long-form document pages
   ==========================================================================

   WHAT THIS REPLACES
   Four pages (terms-of-service, privacy-policy, cookie-policy, dmca) each
   carried a private inline <style> block. Measured 2026-09-09: 45 selectors
   appeared in ALL FOUR, of which 31 were byte-identical and 14 differed.

   The 14 were NOT drift. Every single difference was the same rule with a
   different accent hue — terms is blue, privacy is purple, cookie is orange,
   dmca is red. The geometry, spacing and sizing were identical everywhere.
   So this is a deliberate per-page accent that had been implemented by
   copy-pasting the whole stylesheet four times and hand-editing the colour.

   That distinction decides the design of this file: there is ONE shell, and a
   page selects its accent with a single modifier class. Nothing else varies.

   HOW A PAGE USES IT
       <link rel="stylesheet" href="/css/legal-pages.css?v=...">
       <main class="legal-page legal-page--privacy"> … </main>

   ⚠ THE ACCENT IS SCOPED TO .legal-page, NOT :root — DELIBERATELY.
   desktop-navigation.ftlh re-links design-tokens.css IN THE BODY, so a
   page-level `:root` override of any canonical token is outranked and
   silently dead (CLAUDE.md #74; 62 templates carry dead overrides this way).
   A class selector on the page wrapper is immune to that, so the accent
   system cannot be killed by the nav. Do not "tidy" these into :root.

   ⚠ TINTS USE THE CHANNEL TOKEN, NOT THE COLOUR TOKEN.
   `rgba(var(--x), .06)` needs `--x` to be `52, 152, 219`, not `#3498db`. If
   the channel variable is missing the whole declaration computes to the empty
   string and is dropped silently — not partially, completely (CLAUDE.md #94).
   That is why every accent has both a `--legal-accent` and a
   `--legal-accent-rgb`, and why they must be kept in step.
   ========================================================================== */


/* --------------------------------------------------------------------------
   0. Document reset
   --------------------------------------------------------------------------
   ⚠ CARRIED OVER VERBATIM, NOT INTRODUCED HERE. All four pages already ran
   this exact global reset from their own inline <style>, so the nav and
   footer on these pages have always rendered with it. Scoping it down to
   .legal-page would be the tidier-looking change and would silently give the
   shared chrome its default margins back — a visible regression on four
   pages, in the name of neatness. It stays global and identical.

   The body rule is load-bearing for the same reason getting-started.css says
   so: no shared stylesheet in this project sets a body background, so
   dropping it leaves body WHITE behind a dark page (CLAUDE.md #82). */

/* Exactly `*`, not `*, *::before, *::after`. The pages reset only elements;
   broadening it to pseudo-elements here would hand every ::before and ::after
   on four pages a box-sizing they did not have, which is a real change of
   behaviour wearing the costume of a tidier selector. */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    margin: 0;
    min-height: 100vh;
    overflow-x: hidden;
    font-family: "Poppins", system-ui, -apple-system, "Segoe UI", sans-serif;
    line-height: var(--leading-relaxed);
    color: var(--text);
    background: var(--bg);
}


/* --------------------------------------------------------------------------
   1. Accent system
   -------------------------------------------------------------------------- */

.legal-page {
    /* Defaults to the house blue/purple so a page that forgets its modifier
       class still renders on-brand rather than falling back to nothing. */
    --legal-accent: var(--brand-blue);
    --legal-accent-rgb: var(--brand-blue-rgb);
    --legal-accent-2: var(--brand-purple);
    --legal-accent-2-rgb: var(--brand-purple-rgb);

    /* Elevated hover ground. Was defined four times in four page :root
       blocks, with two different values. One value, one place. */
    --legal-hover: var(--surface-hover);

    /* Everything that used to be a hardcoded pixel guess at the nav height
       now derives from the one measured number (CLAUDE.md #85). */
    --legal-hero-top: calc(var(--chrome-bottom, 80px) + 80px);
    --legal-sticky-top: calc(var(--chrome-bottom, 80px) + 10px);
    --legal-scroll-margin: calc(var(--chrome-bottom, 80px) + 20px);
}

.legal-page--terms {
    --legal-accent: var(--brand-blue);
    --legal-accent-rgb: var(--brand-blue-rgb);
    --legal-accent-2: var(--brand-purple);
    --legal-accent-2-rgb: var(--brand-purple-rgb);
}

.legal-page--privacy {
    --legal-accent: var(--brand-purple);
    --legal-accent-rgb: var(--brand-purple-rgb);
    --legal-accent-2: var(--brand-blue);
    --legal-accent-2-rgb: var(--brand-blue-rgb);
}

/* The cookie page's orange was a hardcoded #f39c12 defined as a page-local
   --cookie-color. It is not a brand token and has no channel form, so it is
   spelled out here once, with its channels, rather than in four places. */
.legal-page--cookie {
    --legal-accent: #f39c12;
    --legal-accent-rgb: 243, 156, 18;
    --legal-accent-2: var(--warning);
    --legal-accent-2-rgb: var(--warning-rgb);
}

.legal-page--dmca {
    --legal-accent: var(--danger);
    --legal-accent-rgb: var(--danger-rgb);
    --legal-accent-2: var(--danger-dark);
    --legal-accent-2-rgb: var(--danger-rgb);
}


/* --------------------------------------------------------------------------
   2. Entrance reveal
   -------------------------------------------------------------------------- */

/* ⚠ VISIBLE BY DEFAULT. THIS IS THE WHOLE POINT OF THIS BLOCK.
   The four pages previously shipped `.animate-on-scroll { opacity: 0 }` and
   restored it ONLY from an IntersectionObserver callback. That makes the
   observer a precondition for the document existing: any throw earlier in the
   same <script>, a failed CSP nonce, or an observer that never fires leaves a
   fully-rendered page at opacity 0 with no console error (CLAUDE.md #58).
   On a terms-of-service or privacy-policy page that is a blank legal document.

   Measured exposure at the time of writing: faq ran 164 lines of unguarded JS
   in the same block before the observe() call, api-access 114, and these four
   about 14 — no try/catch on any of them.

   So the content is visible with no JS at all, and script OPTS IN to the
   animation by setting .js-reveal on the root. Nothing script does can
   subtract the content; it can only add the motion. */
.legal-page .animate-on-scroll {
    opacity: 1;
    transform: none;
}

.js-reveal .legal-page .animate-on-scroll {
    opacity: 0;
    transform: translateY(25px);
    transition: opacity var(--dur-slow, 0.6s) var(--ease-out),
                transform var(--dur-slow, 0.6s) var(--ease-out);
}

.js-reveal .legal-page .animate-on-scroll.visible {
    opacity: 1;
    transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
    .js-reveal .legal-page .animate-on-scroll {
        opacity: 1;
        transform: none;
        transition: none;
    }

    .legal-hero-icon {
        animation: none;
    }

    /* ⚠ CARRIED OVER, NOT AUTHORED HERE. All four pages shipped this blanket
       damper and it covers the nav, the footer and anything else on the page
       that animates. Dropping it during the extraction would have let every
       animation OUTSIDE this stylesheet run at full speed for a
       reduced-motion user — a regression invisible to anyone not using the
       setting. The design language prefers gentler over zero, so this is a
       candidate to soften later; that is a motion-policy decision for the
       whole site, not something to change silently while moving files. */
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
    }
}


/* --------------------------------------------------------------------------
   3. Hero
   -------------------------------------------------------------------------- */

.legal-hero {
    position: relative;
    padding: var(--legal-hero-top) var(--container-pad) 80px;
    text-align: center;
    overflow: hidden;
}

.legal-hero::before {
    content: '';
    position: absolute;
    top: -10%;
    left: 50%;
    transform: translateX(-50%);
    width: 800px;
    max-width: 100%;
    height: 500px;
    background: radial-gradient(ellipse,
        rgba(var(--legal-accent-rgb), 0.06) 0%,
        rgba(var(--legal-accent-2-rgb), 0.03) 40%,
        transparent 70%);
    pointer-events: none;
}

.legal-hero-icon {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 72px;
    height: 72px;
    margin: 0 auto 24px;
    font-size: 28px;
    color: var(--legal-accent);
    background: linear-gradient(135deg,
        rgba(var(--legal-accent-rgb), 0.12),
        rgba(var(--legal-accent-2-rgb), 0.12));
    border: 1px solid rgba(var(--legal-accent-rgb), 0.18);
    border-radius: var(--radius-xl);
    animation: legal-float 5s ease-in-out infinite;
}

/* ⚠ NAMESPACED DELIBERATELY. `@keyframes float` is defined 20 separate times
   across this codebase (three error pages, seven footer pages, home, and
   more). Keyframe names are document-global and the LAST definition parsed
   wins, so a shared stylesheet claiming the bare name `float` would be a
   20-way collision whose winner depends on link order. See CLAUDE.md #31 —
   a shared component needs a unique prefix. */
@keyframes legal-float {
    0%,
    100% {
        transform: translateY(0);
    }

    50% {
        transform: translateY(-8px);
    }
}

.legal-hero h1 {
    position: relative;
    z-index: 1;
    margin-bottom: 14px;
    font-size: clamp(1.8rem, 4vw, 2.8rem);
    font-weight: var(--weight-bold);
    line-height: 1.15;
    letter-spacing: -0.02em;
}

.legal-hero h1 span {
    background: linear-gradient(135deg, var(--legal-accent), var(--legal-accent-2));
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.legal-hero-meta {
    position: relative;
    z-index: 1;
    font-size: 0.875rem;
    color: var(--text-muted);
}

.legal-hero-meta strong {
    color: var(--text);
}


/* --------------------------------------------------------------------------
   4. Layout
   -------------------------------------------------------------------------- */

.legal-layout {
    display: grid;
    grid-template-columns: 240px 1fr;
    gap: 40px;
    align-items: start;
    max-width: 1100px;
    margin: 0 auto;
    /* bottom clears the mobile bottom nav (the token is 0 on desktop and when
       the nav is minimised); the footer is out of flow */
    padding: 0 var(--container-pad) calc(80px + var(--mh-bottom-nav-space, 0px));
}

.legal-sidebar {
    position: sticky;
    top: var(--legal-sticky-top);
}

.legal-content {
    /* Without this a long <pre>, table or unbroken URL blows the grid track
       out and takes the whole page into horizontal scroll. */
    min-width: 0;
}


/* --------------------------------------------------------------------------
   5. Table of contents
   -------------------------------------------------------------------------- */

.legal-toc {
    padding: 24px 20px;
    background: var(--surface-grad);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
}

.legal-toc-title {
    margin-bottom: 16px;
    padding-bottom: 12px;
    font-size: 0.75rem;
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--text-muted);
    border-bottom: 1px solid var(--border-subtle);
}

.legal-toc-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
    list-style: none;
    margin: 0;
    padding: 0;
}

.legal-toc-link {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 12px;
    font-size: 0.8125rem;
    line-height: var(--leading-base);
    color: var(--text-muted);
    text-decoration: none;
    border-radius: var(--radius-sm);
    transition: background var(--dur-base) ease, color var(--dur-base) ease;
}

.legal-toc-link:hover {
    background: var(--legal-hover);
    color: var(--text);
}

.legal-toc-link:focus-visible {
    outline: 2px solid var(--legal-accent);
    outline-offset: 2px;
}

.legal-toc-link.active {
    background: rgba(var(--legal-accent-rgb), 0.1);
    color: var(--legal-accent);
    font-weight: var(--weight-medium);
}

.legal-toc-link .toc-num {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 22px;
    height: 22px;
    font-size: 10px;
    font-weight: var(--weight-semibold);
    font-variant-numeric: tabular-nums;
    background: var(--glass-bg);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    transition: background var(--dur-base) ease,
                border-color var(--dur-base) ease,
                color var(--dur-base) ease;
}

.legal-toc-link.active .toc-num {
    background: rgba(var(--legal-accent-rgb), 0.2);
    border-color: rgba(var(--legal-accent-rgb), 0.3);
    color: var(--legal-accent);
}


/* --------------------------------------------------------------------------
   6. Sections and prose
   -------------------------------------------------------------------------- */

.legal-section {
    margin-bottom: 48px;
    scroll-margin-top: var(--legal-scroll-margin);
}

.legal-section-header {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 20px;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--border-subtle);
}

.legal-section-num {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 36px;
    height: 36px;
    font-size: 14px;
    font-weight: var(--weight-bold);
    font-variant-numeric: tabular-nums;
    color: var(--legal-accent);
    background: linear-gradient(135deg,
        rgba(var(--legal-accent-rgb), 0.12),
        rgba(var(--legal-accent-2-rgb), 0.12));
    border: 1px solid rgba(var(--legal-accent-rgb), 0.18);
    border-radius: var(--radius-md);
}

.legal-section-header h2 {
    font-size: 1.2rem;
    font-weight: var(--weight-semibold);
    line-height: var(--leading-snug);
}

.legal-text {
    font-size: 0.875rem;
    line-height: 1.9;
    color: var(--text-muted);
}

.legal-text p {
    margin-bottom: 16px;
}

.legal-text strong {
    color: var(--text);
    font-weight: var(--weight-medium);
}

.legal-text a {
    color: var(--legal-accent);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    transition: border-color var(--transition-normal);
}

.legal-text a:hover {
    border-bottom-color: var(--legal-accent);
}

.legal-text a:focus-visible {
    outline: 2px solid var(--legal-accent);
    outline-offset: 2px;
    border-radius: var(--radius-xxs);
}

.legal-text ul {
    list-style: none;
    margin: 12px 0 20px;
    padding: 0;
}

.legal-text ul li {
    position: relative;
    padding-left: 20px;
    margin-bottom: 8px;
}

.legal-text ul li::before {
    content: '\203A';
    position: absolute;
    left: 0;
    font-size: 1rem;
    font-weight: var(--weight-semibold);
    color: var(--legal-accent);
}

.legal-highlight {
    margin: 20px 0;
    padding: 20px 24px;
    font-size: 0.875rem;
    line-height: 1.8;
    color: var(--text-muted);
    background: rgba(var(--legal-accent-rgb), 0.05);
    border: 1px solid rgba(var(--legal-accent-rgb), 0.12);
    border-radius: var(--radius-md);
}

.legal-highlight i {
    margin-right: 8px;
    color: var(--legal-accent);
}

/* The informational variant deliberately does NOT follow the page accent.
   It exists so a neutral aside can be told apart from the page's own voice —
   on the DMCA page the accent is red, and an ordinary "here is how this
   works" note rendered in red reads as a warning it is not. Fixed to the
   informational semantic instead. */
.legal-highlight.info {
    background: rgba(var(--info-rgb), 0.05);
    border-color: rgba(var(--info-rgb), 0.12);
}

.legal-highlight.info i {
    color: var(--info);
}

/* Numbered procedure lists (the DMCA counter-notice steps). Shares the list
   geometry above; only the marker differs. The counter is namespaced because
   CSS counters are inherited by name and a generic one would be reset by any
   other counter on the page. */
.legal-text ol {
    list-style: none;
    margin: 12px 0 20px;
    padding: 0;
    counter-reset: legal-counter;
}

.legal-text ol li {
    position: relative;
    padding-left: 20px;
    margin-bottom: 8px;
    counter-increment: legal-counter;
}

.legal-text ol li::before {
    content: counter(legal-counter) '.';
    position: absolute;
    left: 0;
    font-size: 0.8125rem;
    font-weight: var(--weight-semibold);
    font-variant-numeric: tabular-nums;
    color: var(--legal-accent);
}


/* --------------------------------------------------------------------------
   6b. Data tables
   --------------------------------------------------------------------------
   Used by privacy-policy (the data-collection matrix) and cookie-policy (the
   cookie inventory). A table is the one thing on these pages that genuinely
   cannot reflow to 375px, so it gets its own scroll container rather than
   being squeezed — min-width keeps the columns readable and the wrapper
   scrolls instead of the document. */

.legal-table-scroll {
    width: 100%;
    max-width: 100%;
    margin: 20px 0;
    overflow-x: auto;
    scrollbar-width: thin;
    -webkit-overflow-scrolling: touch;
    border-radius: var(--radius-md);
}

.legal-data-table {
    width: 100%;
    min-width: 460px;
    margin: 0;
    border-collapse: collapse;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    overflow: hidden;
}

.legal-data-table th,
.legal-data-table td {
    padding: 14px 18px;
    text-align: left;
    font-size: 0.8125rem;
    border-bottom: 1px solid var(--border-subtle);
}

.legal-data-table th {
    font-size: 0.75rem;
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text);
    background: rgba(var(--legal-accent-rgb), 0.08);
}

.legal-data-table td {
    color: var(--text-muted);
    background: var(--glass-bg);
}

.legal-data-table tr:last-child td {
    border-bottom: none;
}

.legal-data-table code {
    padding: 2px 6px;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.75rem;
    color: var(--text);
    background: var(--surface-2);
    border-radius: var(--radius-xs);
}


/* --------------------------------------------------------------------------
   7. Contact footer
   -------------------------------------------------------------------------- */

.legal-contact {
    margin-top: 60px;
    padding: 36px;
    text-align: center;
    background: linear-gradient(135deg,
        rgba(var(--legal-accent-rgb), 0.05),
        rgba(var(--legal-accent-2-rgb), 0.05));
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
}

.legal-contact h3 {
    margin-bottom: 8px;
    font-size: 1.1rem;
    font-weight: var(--weight-semibold);
}

.legal-contact p {
    margin-bottom: 20px;
    font-size: 0.875rem;
    color: var(--text-muted);
}

/* The button itself is the shared .btn.btn-gradient — .legal-contact-btn was
   a hand-rolled duplicate of it on all four pages and is gone. This rule only
   tints the shared component to the page accent. */
.legal-contact .btn-gradient {
    background: linear-gradient(135deg, var(--legal-accent), var(--legal-accent-2));
}


/* --------------------------------------------------------------------------
   8. Responsive
   --------------------------------------------------------------------------
   The pages this replaces stopped at 768px, so a phone got a layout designed
   for a small laptop. There is now a real 375px story. */

@media (max-width: 900px) {
    .legal-layout {
        grid-template-columns: 1fr;
        gap: 28px;
    }

    /* min-width: 0 is load-bearing. As a grid item the sidebar's automatic
       minimum is its min-content width, and that includes the full nowrap
       width of the contents row below - so without it the single 1fr track
       grows to fit the whole row, the row never overflows its own box, and it
       cannot scroll. .legal-content carries the same fix for the same reason. */
    .legal-sidebar {
        position: relative;
        top: 0;
        min-width: 0;
    }

    .legal-toc {
        padding: 16px;
    }

    .legal-toc-title {
        margin-bottom: 10px;
    }

    /* ⚠ SCROLLS, DOES NOT WRAP. The previous rule was `flex-wrap: wrap`,
       which stacked a 12-entry contents list into a block that pushed the
       document itself off the first screen. The design language is explicit:
       pill rows scroll horizontally on small screens, never wrap. */
    .legal-toc-list {
        flex-direction: row;
        flex-wrap: nowrap;
        gap: 6px;
        overflow-x: auto;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
    }

    .legal-toc-list::-webkit-scrollbar {
        display: none;
    }

    .legal-toc-link {
        flex-shrink: 0;
        padding: 8px 12px;
        font-size: 0.75rem;
        white-space: nowrap;
    }
}

@media (max-width: 768px) {
    .legal-hero {
        padding-top: calc(var(--chrome-bottom, 80px) + 50px);
        padding-bottom: 60px;
    }

    .legal-section {
        margin-bottom: 40px;
    }

    .legal-contact {
        margin-top: 48px;
        padding: 28px 20px;
    }
}

@media (max-width: 480px) {
    .legal-hero {
        padding-bottom: 44px;
    }

    .legal-hero-icon {
        width: 60px;
        height: 60px;
        margin-bottom: 18px;
        font-size: 24px;
    }

    .legal-layout {
        padding-bottom: calc(56px + var(--mh-bottom-nav-space, 0px));
    }

    .legal-section-header {
        gap: 10px;
    }

    .legal-section-num {
        width: 30px;
        height: 30px;
        font-size: 12px;
    }

    .legal-section-header h2 {
        font-size: 1.05rem;
    }

    /* Long documents are read, not skimmed, so the body text does not shrink
       below this. Only the chrome around it gets tighter. */
    .legal-text {
        font-size: 0.875rem;
        line-height: 1.85;
    }

    .legal-highlight {
        padding: 16px 18px;
    }

    .legal-contact {
        padding: 24px 16px;
    }

    /* 44px minimum touch target — the 6px-gap pill row is the one place on
       these pages where a thumb has to hit something small. */
    .legal-toc-link {
        min-height: 44px;
    }
}
