/*
 * Web tier design tokens + self-hosted fonts (FND-002 → FE-300/301) — the
 * pipeline entry, linked on every web page.
 *
 * Self-hosts the three brand fonts (latin subset, font-display: swap — no runtime
 * Google Fonts fetch on the critical path; Propshaft fingerprints the font-file
 * refs at build time) and declares the FULL v3 Material-3 tonal palette (light +
 * dark), type scale, spacing/radius, and the always-on layout-shell base. Ported
 * from documents/mockups/web-app-ui-v3.html (:root + .theme-dark); component
 * classes there resolve against these variables unchanged. The editorial
 * cover-art plates live alongside in web/cover_art.css.
 */

/* ── Self-hosted fonts (latin subset, swap) ─────────────────────────────── */
@font-face { font-family: "Fraunces";   font-style: normal; font-weight: 400; font-display: swap; src: url("/assets/fraunces-400-be8bc773.woff2") format("woff2"); }
@font-face { font-family: "Fraunces";   font-style: normal; font-weight: 500; font-display: swap; src: url("/assets/fraunces-500-569a1e75.woff2") format("woff2"); }
@font-face { font-family: "Fraunces";   font-style: normal; font-weight: 600; font-display: swap; src: url("/assets/fraunces-600-ce9d2bc6.woff2") format("woff2"); }
@font-face { font-family: "DM Sans";    font-style: normal; font-weight: 400; font-display: swap; src: url("/assets/dm-sans-400-148a763a.woff2") format("woff2"); }
@font-face { font-family: "DM Sans";    font-style: normal; font-weight: 500; font-display: swap; src: url("/assets/dm-sans-500-ea26c756.woff2") format("woff2"); }
@font-face { font-family: "DM Sans";    font-style: normal; font-weight: 700; font-display: swap; src: url("/assets/dm-sans-700-60f105ba.woff2") format("woff2"); }
@font-face { font-family: "Newsreader"; font-style: normal; font-weight: 400; font-display: swap; src: url("/assets/newsreader-400-f3cfe033.woff2") format("woff2"); }
@font-face { font-family: "Newsreader"; font-style: normal; font-weight: 500; font-display: swap; src: url("/assets/newsreader-500-428cf1c7.woff2") format("woff2"); }

/* ── v3 Material-3 tonal palette · LIGHT (default) ───────────────────────── */
:root {
  /* named M3 tokens (canonical) */
  --primary:              #522DE6;   /* deep indigo-violet — CTAs, active, links, wordmark */
  --primary-bright:       #6B4EFF;   /* hover / tint / verified */
  --primary-container:    #E5DEFF;   /* violet tint surface */
  --on-primary-container: #4109D7;   /* AA-safe violet text on the tint */
  --primary-tint:         #C8BFFF;
  --on-primary:           #FFFFFF;
  --ink:                  #1E1B18;   /* primary text */
  --ink-2:                #474556;   /* secondary text — cool slate-violet */
  --outline:              #787587;   /* strong hairline */
  --outline-variant:      #C9C4D9;   /* subtle hairline */
  --canvas:               #FFF8F4;   /* warm rosy cream */
  --surface-1:            #FAF2ED;
  --surface-2:            #F4ECE7;
  --surface-3:            #EFE7E1;
  --surface-4:            #E9E1DC;
  --surface-hi:           #FFFFFF;   /* highest / elevated */
  --cover:                #0A0A0C;   /* signature cover / scrim base */
  --like:                 #FF3040;   /* like / active heart only */
  --tertiary:             #DD0C2C;   /* editorial crimson — Special Report / edition tag */
  --tertiary-container:   #FFDAD7;

  /* legacy aliases remapped onto the M3 palette (keeps every v3 component class working) */
  --violet-500:      #522DE6;
  --violet-600:      #4109D7;
  --violet-400-warm: #8B7FFF;
  --heart-red:       #FF3040;
  --verified:        #6B4EFF;
  --bg:              #FFF8F4;
  --surface:         #FAF2ED;
  --surface-muted:   #EFE7E1;
  --surface-elevated:#FFFFFF;
  --text:            #1E1B18;
  --text-muted:      #474556;
  --border:          #C9C4D9;
  --accent:          #522DE6;
  --accent-subtle:   #E5DEFF;
  --cover-bg:        #0A0A0C;
  --cover-text:      #F5F5F5;
  --topic-text:      #4109D7;
  --topic-tint:      #E5DEFF;
  --badge-red:       #DD0C2C;

  /* type — Fraunces display / DM Sans UI-body / Newsreader reading. Non-Latin
     display headings degrade to curated serif fallbacks (FE-301; the full
     18-locale switch is FE-336/337). */
  --font-display:   "Fraunces", "Amiri", "Noto Serif JP", "Noto Serif Devanagari", Georgia, "Times New Roman", serif;
  --font-body:      "DM Sans", "Noto Sans Arabic", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-read:      "Newsreader", Georgia, "Times New Roman", serif;
  --font-editorial: var(--font-read);   /* FND-002 back-compat alias */

  /* type scale (derived from the v3 mockup) */
  --fs-display-xl: clamp(40px, 5.4vw, 68px);
  --fs-display:    40px;
  --fs-heading:    34px;
  --fs-title:      25px;
  --fs-subtitle:   20px;
  --fs-body-lg:    19px;
  --fs-body:       16px;
  --fs-body-sm:    15px;
  --fs-caption:    13.5px;
  --fs-eyebrow:    12.5px;

  /* spacing + radius (v3 names) */
  --space-xs: 4px; --space-sm: 8px; --space-md: 12px; --space-lg: 16px;
  --space-xl: 24px; --space-xxl: 32px; --space-xxxl: 48px;
  --r-sm: 6px; --r-md: 10px; --r-lg: 16px; --r-xl: 28px; --r-pill: 999px;

  /* FND-002 back-compat spacing/radius aliases */
  --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px;
  --space-6: 24px; --space-8: 32px;
  --radius: 14px;

  --measure:      600px;   /* the boxed reading column */
  --measure-wide: 640px;

  /* self-contained editorial grain (feTurbulence, data-URI) — no external image */
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='150' height='150'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.4 0'/%3E%3C/filter%3E%3Crect width='150' height='150' filter='url(%23g)'/%3E%3C/svg%3E");
}

/* ── DARK palette ────────────────────────────────────────────────────────
   Two application paths, no JS required:
   1. prefers-color-scheme: dark is the no-JS default (unless the user has
      explicitly forced light via [data-theme="light"] / .theme-light).
   2. An explicit [data-theme="dark"] / .theme-dark on <html> (FE-308's toggle)
      wins regardless of the system setting. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not(.theme-light) {
    --primary:              #8B7FFF;
    --primary-bright:       #C8BFFF;
    --primary-container:    #241A3E;
    --on-primary-container: #C8BFFF;
    --ink:                  #F5F5F5;
    --ink-2:                #9AA4B6;
    --outline:              #4A4E5C;
    --outline-variant:      #393D4A;
    --canvas:               #000000;   /* body base — the dark twin of --bg */
    --surface-1:            #16181C;
    --surface-2:            #1F2228;
    --surface-3:            #23262D;
    --surface-4:            #2A2D38;
    --surface-hi:           #1F2228;
    --cover:                #0A0A0C;

    --violet-500:      #8B7FFF;
    --violet-600:      #C8BFFF;
    --bg:              #000000;
    --surface:         #16181C;
    --surface-muted:   #2A2D38;
    --surface-elevated:#1F2228;
    --text:            #F5F5F5;
    --text-muted:      #9AA4B6;
    --border:          #393D4A;
    --accent:          #8B7FFF;
    --accent-subtle:   #241A3E;
    --topic-text:      #C8BFFF;
    --topic-tint:      #241A3E;
    --badge-red:       #FF5A67;
  }
}

:root[data-theme="dark"],
.theme-dark {
  --primary:              #8B7FFF;
  --primary-bright:       #C8BFFF;
  --primary-container:    #241A3E;
  --on-primary-container: #C8BFFF;
  --ink:                  #F5F5F5;
  --ink-2:                #9AA4B6;
  --outline:              #4A4E5C;
  --outline-variant:      #393D4A;
  --canvas:               #000000;   /* body base — the dark twin of --bg */
  --surface-1:            #16181C;
  --surface-2:            #1F2228;
  --surface-3:            #23262D;
  --surface-4:            #2A2D38;
  --surface-hi:           #1F2228;
  --cover:                #0A0A0C;

  --violet-500:      #8B7FFF;
  --violet-600:      #C8BFFF;
  --bg:              #000000;
  --surface:         #16181C;
  --surface-muted:   #2A2D38;
  --surface-elevated:#1F2228;
  --text:            #F5F5F5;
  --text-muted:      #9AA4B6;
  --border:          #393D4A;
  --accent:          #8B7FFF;
  --accent-subtle:   #241A3E;
  --topic-text:      #C8BFFF;
  --topic-tint:      #241A3E;
  --badge-red:       #FF5A67;
}

/* ── Always-on base + the responsive layout shell (FE-303) ───────────────── */
* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-body-lg);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
}

/* Global visible focus ring (mockup review F12 — WCAG 2.4.7). */
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

/* Skip-link — first focusable element, visually hidden until focused. */
.skip-link {
  position: absolute;
  /* Park OFF the top edge (not left: -9999px): a negative inline offset extends the
     document's scroll width under dir="rtl" (the scroll origin flips), so an RTL
     page would get ~10000px of phantom horizontal scroll. Parking vertically is
     direction-agnostic. inset-inline-start keeps it at the start edge (left in LTR,
     right in RTL) when it slides in on focus. */
  inset-inline-start: 0;
  top: -9999px;
  z-index: 100;
  background: var(--primary);
  color: var(--on-primary);
  font-family: var(--font-body);
  font-weight: 600;
  text-decoration: none;
  padding: var(--space-sm) var(--space-lg);
  border-radius: 0 0 var(--r-md) 0;
}
.skip-link:focus { top: 0; }

/* 3-zone shell: single column (mobile) → nav + content (tablet) → nav + content
   + Newsstand rail (desktop). Pure CSS Grid, zero JS. The nav/rail zone widths
   come from their own components; the shell just places them. */
.web-shell { max-width: 1400px; margin: 0 auto; }
.web-shell__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}
.web-shell__main {
  min-width: 0;
  width: 100%;
  max-width: var(--measure-wide);
  margin: 0 auto;
  padding: var(--space-xl) var(--space-lg) var(--space-xxxl);
}
.web-shell__main:focus { outline: none; }
/* The nav zone is present at EVERY width: it carries the desktop rail (≥768px)
   AND the mobile top bar (<768px), which swap via .rail-full / .mnav
   (web/components.css). The Newsstand rail zone stays desktop-only. */
.web-shell__nav { display: block; }
.web-shell__rail { display: none; }

/* Nav-less surfaces (the pre-auth doors — sign in / join / reset — and the legal
   + marketing doc pages) emit no nav or rail track. Without this, the lone <main>
   auto-places into the FIRST (nav) track and pins hard-left, leaving a huge empty
   right half (worst on the auth cards). Collapse the grid to a single centered
   column for them. Its (0,2,0) specificity beats the (0,1,0) media-query track
   rules below, so it wins at every width with no source-order dependence. */
.web-shell__grid:not(:has(.web-shell__nav)) { grid-template-columns: minmax(0, 1fr); }

@media (min-width: 768px) {
  .web-shell__grid { grid-template-columns: auto minmax(0, 1fr); }
}
@media (min-width: 1100px) {
  .web-shell__grid { grid-template-columns: auto minmax(0, 1fr) auto; }
  .web-shell__rail { display: block; }
}
