/*
 * public-base.css — dependency closure of views/partials/public-nav.ejs +
 * views/partials/public-footer.ejs.
 *
 * Phase 1 of docs/plans/2026-09-03-public-site-visual-unification.md.
 * Every page that includes public-nav or public-footer must load this file
 * (via views/partials/public-head.ejs) BEFORE its own inline <style> block,
 * so that same-specificity source order lets the page's own inline rules
 * win — this is the whole no-op argument, see design doc §2. DO NOT rewrite
 * any selector here (no combining, no added specificity, no reordering of
 * properties beyond what's noted below) — that would break the guarantee.
 *
 * Selectors below were extracted byte-for-byte from the 13 marketing pages'
 * own inline <style> blocks. The extraction rule, the comparison script,
 * and the full candidate/exclusion tables are committed and re-runnable —
 * see docs/plans/2026-09-03-public-marketing-css-extraction-report.md and
 * scripts/public-css-rule-diff.js. Everything below except `:root` (see its
 * own comment) is byte-identical across every marketing page that has it —
 * no per-page value variance, no majority-vote judgment calls.
 */

/* `:root` — Phase 3 status (2026-09-04, Phase 3 of the design doc). This
   comment replaces an earlier one whose safety precondition Phase 3 makes
   false; read this version, not the design doc's Phase 1 row, for how the
   3 pages with a non-default palette (features-gold-silver-ai-quant-
   analysis.ejs, features-realtime-minute-data-coverage.ejs,
   features-python-strategy-backtest.ejs) get their colors today.

   Old mechanism (Phase 1/2, no longer in effect): each of the 3 pages kept
   its own complete, unmodified inline `:root` block, later in source order
   than this file's `<link>`, winning the cascade on identical specificity
   (a WIN-BY-SOURCE-ORDER guarantee). That required Phase 2's dedup-deletion
   criterion to stay "delete an inline rule iff byte-identical to the shared
   file" forever, because a byte-different `:root` would never qualify for
   deletion — brittle by construction, and undocumented by any test (the
   violating script never existed, so a test pinned against it would have
   been unfalsifiable scaffolding).

   Current mechanism (Phase 3): the 3 pages no longer carry an inline
   `:root` at all. The backtest page sets `<body class="theme-mint">` — see
   the `.theme-mint` rule directly below `:root`, which
   overrides exactly the one token the page used to diverge on
   (`--primary`+`--primary-rgb` for gold, `--accent`+`--accent-rgb` for
   mint). This is a WIN-BY-PROXIMITY guarantee, not source order: custom
   properties inherit down the DOM tree, and `body.theme-mint` is a nearer
   ancestor of every element on that page than `html` (where `:root`'s
   declarations apply), so the class's value wins regardless of which
   stylesheet loads first or last. Both mechanisms work, but they are
   different guarantees — anything that depended on "these 3 pages win
   because their inline block comes later in source order" stopped being
   true the moment their inline `:root` was deleted. The genuinely
   falsifiable property this mechanism now has (which the old one never
   did) — a `.theme-mint` body class actually overrides the
   default token value seen by every consuming selector on that page, not
   just at `:root` — is what test/public-css-drift-guard.test.js's
   "theme classes actually override" case pins down; see that test.

   This file must still define `:root`'s full token set (not just the 3
   overridden ones) because it needs to stand alone for consumers that are
   NOT one of the 14 marketing pages and carry no theme class of their own
   (Track C's /marketplace, Phase 4's legal.ejs/user-guide.ejs) — without
   it, every var(--primary)/var(--accent)/etc. reference below resolves to
   nothing, which is the exact defect class /marketplace's "5 undefined
   variables" bug already is.

   `--primary-rgb`/`--accent-rgb` (added Phase 3): RGB-component siblings
   of `--primary`/`--accent`, consumed only inside `rgba(var(--x-rgb),
   alpha)` call sites across all 14 marketing pages' inline <style> blocks
   plus this file and public-marketing.css. Declaring them at `:root`
   (rather than scoped to one component's container) is deliberate, not an
   oversight of the design doc's general "no new tokens" rule — see that
   doc's second 2026-09-04 amendment to §1.1 for why a page-spanning,
   theme-overridable RGB sibling is the one case that requires `:root`
   rather than merely tolerating it there. They are not a new color: each
   is a re-expression of an existing color token's components, kept in
   sync by construction (`.theme-mint` overrides `--accent` and
   `--accent-rgb` together, never one without the other) so a consumer
   can never observe `--primary` and `--primary-rgb` disagreeing. */
:root { --bg:#070b14; --surface:#0d1424; --surface-2:#101a2e; --text:#e8ecf8; --muted:#a4b0ca; --line:#24314d; --primary:#d7a83a; --accent:#9f75ff; --primary-rgb:215,168,58; --accent-rgb:159,117,255; --topbar-h:73px; }

/* `--topbar-h` (added Phase 4b, docs/plans/2026-09-03-public-site-visual-
   unification.md). NOT derived from `.topbar-inner{height:72px}` above —
   `.topbar` itself also carries `border-bottom:1px solid …`, and with the
   sitewide `* { box-sizing:border-box; }` rule this file already declares,
   that border is added to `.topbar`'s own auto height rather than eating
   into `.topbar-inner`'s 72px. Measured directly: a live `/market` page
   (a page that already ships `.topbar`) reported
   `document.querySelector('header.topbar').getBoundingClientRect().height`
   === 73 at both 1440px and 375px viewports (Playwright, Chromium,
   2026-09-05) — 72 + the 1px border, not 72. Any consumer that needs to
   sit below the topbar (Phase 4b's `.guide-toc`/`.toc-toggle-btn`) must
   use this token, not a hand-copied 72. `views/marketplace.ejs` used to
   hardcode `calc(100vh - 72px)` for this same box (#1223: 1px short
   against this measurement) and also never reserved any space for
   partials/trust-banner.ejs's banner (#1228) — fixed by removing the
   hardcoded literal entirely: that page's own `<style>` block now sizes
   `.right-main-content` via a `.mp-viewport-frame` flex column that
   reserves whatever the topbar and banner actually render at, live, with
   no dependency on this token or a hand-copied number. See that page's
   own comment (search `.mp-viewport-frame`) for the full rationale. */

/* `--banner-safe-h` (Phase 4b round 3, LA design 2026-09-05) was removed
   here in round 4 (2026-09-05, same day -- see
   docs/plans/2026-09-03-public-site-visual-unification.md): its sole
   consumer, `.toc-toggle-btn` in views/user-guide.ejs, no longer needs an
   unconditional worst-case offset derived from the trust-banner's height,
   because that button moved from a top-anchored, banner-clearing position
   to a bottom-anchored one (see that rule's own comment for why: the old
   top-anchored design paid its 140px reservation in full even when the
   banner was DISMISSED -- the state nearly every real visitor is in --
   producing a 152px empty void above the page's first heading). A token
   with no CSS consumer is scaffolding, not a fix, and this one was added
   this same phase and never shipped in a released state, so removing it
   is not rework. Its measurement table (the actual banner heights across
   every breakpoint x locale) still has a job: it lives on in
   test/public-css-banner-safe-h-guard.test.js as a hand-written,
   independent product-height regression tripwire on
   `.lg-trust-banner`'s real rendered height -- true regardless of
   whether any CSS token consumes it. #1227/#1228/#1229 are not wired to
   that number in any executable way; anyone working on those tickets
   may simply find it useful to read -- see that test file's own header
   comment for the full table and the current value. Whoever next needs
   a CSS-consumed upper bound on the banner's height should reintroduce
   a token in their own change, not resurrect this one blind. */

/* Theme classes (Phase 3) — put on <body> by the 3 pages that need a
   non-default palette. Each overrides exactly the token(s) that page used
   to diverge on inline, plus that token's RGB sibling (kept together, see
   the `:root` comment above on why they must never disagree). Not mutually
   exclusive by construction (a page could in principle carry both), but no
   current page needs both at once. */
.theme-mint { --accent:#3ee08a;  --accent-rgb:62,224,138; }

* { box-sizing: border-box; }
html,body { margin:0; padding:0; font-family:Inter,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif; background:var(--bg); color:var(--text); }

/* ── Topbar ── */
.topbar { position:sticky; top:0; z-index:30; background:rgba(7,11,20,.72); backdrop-filter:blur(8px); border-bottom:1px solid rgba(255,255,255,.06); }
.topbar-inner { height:72px; display:flex; align-items:center; justify-content:space-between; }
.brand { display:flex; align-items:center; gap:10px; font-weight:800; font-size:1.2rem; }
.brand span { color:var(--primary); }
.brand-logo { width:30px; height:30px; border-radius:8px; object-fit:cover; border:1px solid rgba(255,255,255,.2); background:rgba(255,255,255,.06); }
.top-links { display:flex; gap:20px; color:var(--muted); font-size:.95rem; }
.top-links a { color:inherit; text-decoration:none; transition:.15s; }
.top-links a:hover { color:var(--text); }
.nav-right { display:flex; align-items:center; gap:12px; }
@media (max-width:960px) {
  .top-links { display:none; }
}

/* ── Features dropdown — copied verbatim from public-nav.ejs's own
   <style> block (scoped to .top-links); public-nav.ejs is the single
   source of truth for these, not a page comparison. ── */
.top-links .nav-dropdown { position: relative; }
.top-links .nav-dropdown-toggle { cursor: pointer; display: flex; align-items: center; gap: 4px; }
.top-links .nav-dropdown-toggle::after { content: '▾'; font-size: .7em; opacity: .7; }
.top-links .nav-dropdown-panel {
    display: none;
    position: absolute;
    top: calc(100% + 14px);
    left: 50%;
    transform: translateX(-50%);
    min-width: 240px;
    background: rgba(15,19,31,.96);
    border: 1px solid rgba(255,255,255,.1);
    border-radius: 10px;
    box-shadow: 0 8px 32px rgba(0,0,0,.45);
    padding: 8px 0;
    z-index: 100;
  }
.top-links .nav-dropdown:hover .nav-dropdown-panel,
  .top-links .nav-dropdown:focus-within .nav-dropdown-panel { display: block; }
.top-links .nav-dropdown-panel a {
    display: flex;
    flex-direction: column;
    padding: 10px 18px;
    border-radius: 0;
    color: rgba(255,255,255,.85) !important;
    text-decoration: none;
    transition: background .15s;
  }
.top-links .nav-dropdown-panel a:hover { background: rgba(255,255,255,.07); color: #fff !important; }
.top-links .nav-dropdown-panel .ndp-title { font-size: .92rem; font-weight: 500; }
.top-links .nav-dropdown-panel .ndp-sub { font-size: .78rem; opacity: .55; margin-top: 1px; }
.top-links .nav-dropdown-panel .ndp-badge {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 6px;
    border-radius: 999px;
    border: 1px solid rgba(255,176,80,.45);
    background: rgba(255,176,80,.12);
    color: #ffc785;
    font-size: .68rem;
    font-weight: 600;
    vertical-align: middle;
  }
.top-links .nav-dropdown-divider { height: 1px; background: rgba(255,255,255,.08); margin: 6px 0; }

/* ── Buttons ── (`.cta-primary` deliberately NOT here — see the extraction
   report's "considered, rejected" section: it has a per-page color variant
   on the 2 gold pages and no other file depends on it being present, so
   it stays inline-only rather than adding another item to Phase 2's
   byte-identical-forever list for no structural benefit.) */
.cta { display:inline-flex; align-items:center; justify-content:center; border-radius:12px; font-weight:600; cursor:pointer; text-decoration:none; transition:.18s; border:none; font-size:.95rem; }
.cta:hover { transform:translateY(-1px); }
.cta-ghost { color:var(--text); border:1px solid var(--line); padding:11px 18px; background:rgba(255,255,255,.02); }
.cta-login { color:var(--muted); padding:11px 14px; background:transparent; }
.cta-login:hover { color:var(--text); }

/* ── Skip link — present on 12/13 marketing pages; market.ejs has never
   had one (see the extraction report / design doc §9; not fixed here).
   `.skip-link:focus` deliberately NOT here — see the extraction report:
   it has a per-page color variant on the 2 gold pages and no structural
   need to be in this file, so it stays inline-only. ── */
.skip-link { position:absolute; left:-9999px; top:auto; width:1px; height:1px; overflow:hidden; }

/* ── Footer ── */
footer { border-top:1px solid rgba(255,255,255,.07); padding:28px 0 40px; color:#91a0c5; font-size:.9rem; background:rgba(5,9,16,.92); }
.footer-grid { display:grid; grid-template-columns:1fr; gap:18px; }
.footer-card { background:rgba(255,255,255,.03); border:1px solid rgba(255,255,255,.08); border-radius:14px; padding:18px; }
.footer-card h3 { margin:0 0 10px; font-size:1rem; color:#eef4ff; }
.footer-links { display:flex; flex-wrap:wrap; gap:10px 14px; margin:12px 0; }
.footer-links a { color:#f0dba0; text-decoration:none; }
.footer-links a:hover { color:#fff; }
.footer-meta { color:#a4b0ca; line-height:1.75; }

/* `.footer-risk` deliberately NOT here — same treatment as `.cta-primary`
   and `.skip-link:focus` above, and for the same kind of reason. Found
   2026-09-04 during Phase 2a's dry run (see the design doc's Phase 2
   precondition note): it shares the `<aside class="container footer-risk">`
   element (views/partials/public-footer.ejs) with `.container`, which is
   ALSO deliberately kept inline-only (design doc §11 — `.container`'s value
   diverges per page). Both declare a margin property on that one element at
   EQUAL specificity. `.footer-risk`'s inline text was byte-identical across
   all 13 pages, which made it look like a safe candidate by the Phase 2
   deletion criterion — but "byte-identical" only guarantees THIS selector's
   own value survives extraction, not that some OTHER kept selector's
   relative cascade position against it stays the same. Concretely: inside
   each page's own inline <style>, `.footer-risk` was declared AFTER
   `.container`, so `.footer-risk`'s margin-top:14px used to win. Extracting
   it into this file moves its only surviving copy to BEFORE every page's
   inline <style> (that's the whole Phase 1 no-op argument), which flips the
   winner to `.container`'s margin:0 — silently dropping the footer's
   risk-disclosure top spacing on every page that includes public-footer.ejs.
   Caught live by e2e/visual's build-identity-checked A/B run (9/9 pages
   using this footer regressed identically) before this ever shipped —
   see test/public-css-cascade-collision-guard.test.js, which asserts this
   exact collision shape can never recur silently. No structural upside to
   extraction outweighs this cascade risk, so `.footer-risk` stays
   inline-only, like the other three deliberate exclusions above. */
