/* ============================================================
   The Ormstown Observer — shared design system
   ------------------------------------------------------------
   SINGLE SOURCE OF TRUTH for design tokens, the spacing scale
   and base typography. Historically every page re-declared its
   own :root block, which drifted (--muted was #666 on the home
   page and #555 in the header). Pages that link this file MUST
   NOT re-declare :root tokens.

   PROVENANCE — token values are maintained in the Claude Design
   project "Ormstown Observer Design System"
   (7100bbed-cc8c-49af-8e4c-1188988a3d67), files tokens/*.css.
   Design is authoritative for visual decisions; this repo is
   authoritative for shipped code. When you carry a change
   across, update that project's github.md "Last sync".

   DISPLAY FACE — migrated to Libre Baskerville on 2026-07-31,
   matching the Design project. Playfair Display is gone from the
   repo. Because Libre Baskerville stops at 700 (and its italic
   exists at 400 only), every display weight was moved 900 -> 700
   across 55 files, and all 54 pages' Google Fonts URLs now request
   Libre+Baskerville:ital,wght@0,400;0,700;1,400. NEVER set a
   display heading above 700: the browser will synthesise a smeared
   faux-bold instead of refusing.

   ONE DELIBERATE DIVERGENCE remains — do not "fix" it by syncing
   blindly: the type scale. Design's --size-body is 17.5px; body
   here is still 16px. Adopting the scale changes reading size on
   every page and wants a proof page first.

   Opting a page in:
     1. <link rel="stylesheet" href="/observer.css">  (in <head>,
        BEFORE the page's own inline <style> so page rules win)
     2. add the pre-paint theme script (see below)
     3. delete the page's inline :root token block
     4. replace hardcoded colours with tokens — #fff card grounds
        become var(--surface-card), greys become var(--ink-soft) —
        or they will not adapt in dark mode

   Pages that do NOT link this file keep their inline tokens and
   stay light-only. That is deliberate: it makes the rollout safe
   one page at a time.

   Pre-paint theme script — paste into <head> BEFORE this link so
   a saved dark preference doesn't flash light on load:

     <script>(function(){try{var t=localStorage.getItem('observerTheme');
     if(t==='dark'||t==='light')document.documentElement.setAttribute('data-theme',t);}catch(e){}})();</script>

   The palette is the paper's own house system — ink #1a1a1a,
   paper #faf8f4, accent #b5161b, rule #c8b97a. Dark mode lifts
   the accent to #e8686c so the red stays legible on dark ground.
   ============================================================ */

:root {
  /* Sentinel — observer-header.js checks this to decide whether to
     render the theme toggle. Never remove it. */
  --obs-css: 1;

  color-scheme: light;

  /* ── Ink & paper ── */
  --ink:         #1a1a1a;
  --ink-soft:    #575048;   /* warm secondary text */
  --paper:       #faf8f4;
  --paper-dark:  #f0ece4;
  --accent:      #b5161b;
  --accent-bg:   #f5e8e8;
  --accent-press:#8f1115;   /* accent hover/active */
  --rule:        #c8b97a;   /* gold editorial rule */
  --hair:        #ddd7ca;   /* light divider */
  --border-warm: #d4c9b8;   /* the older, heavier border */

  /* ── Back-compat aliases ──
     Older page rules still reference these names. Keeping them as
     aliases means a converted page's existing CSS keeps working
     and picks up dark mode for free. Prefer the names above in
     anything new. */
  --ink-light:    var(--ink-soft);
  --muted:        var(--ink-soft);
  --accent-light: var(--accent-bg);
  --border:       var(--hair);

  /* ── Chrome ──
     For deliberately dark strips (the Community Compass banner, tool bars).
     These must NOT be built from --ink/--paper: those invert in dark
     mode, which would turn a dark banner light and hide its white text.
     Chrome stays dark in both themes, only deepening at night. */
  --chrome-bg:   #2a2723;
  --chrome-text: #f3efe6;
  --chrome-soft: #a49a88;

  /* ── Status ── */
  --confirm:      #155724;
  --warn:         #721c24;
  --pending:      #856404;
  --confirm-bg:   #e6f4ea;
  --confirm-hair: #a8d5b5;
  --pending-bg:   #fff3cd;
  --pending-hair: #ffd680;
  --beta:         #c9a227;

  /* ── Notice categories ── */
  --cat-consultation: #b5161b;
  --cat-bylaw:        #2f6b4f;
  --cat-tender:       #8a6d1f;
  --cat-other:        #555555;

  /* ── Semantic aliases ──
     --surface-card is the one to reach for instead of a bare #fff:
     it is white on paper and near-black in dark mode. */
  --text-body:      var(--ink);
  --text-muted:     var(--ink-soft);
  --text-on-accent: #ffffff;
  --surface-page:   var(--paper);
  --surface-sunk:   var(--paper-dark);
  --surface-card:   #ffffff;
  --link:           var(--accent);
  --link-hover:     var(--ink);
  --divider:        var(--hair);
  --divider-strong: var(--ink);
  --scrim:          rgba(0,0,0,.35);
  --hero-gradient:  linear-gradient(to top, rgba(0,0,0,.92) 0%, rgba(0,0,0,.5) 45%, rgba(0,0,0,.15) 100%);

  /* ── Spacing scale ── */
  --s1: 6px;
  --s2: 10px;
  --s3: 16px;
  --s4: 24px;
  --s5: 36px;
  --s6: 56px;

  /* ── Rules & borders ── */
  --rule-hair:     1px;
  --rule-strong:   2px;
  --rule-heavy:    3px;
  --border-accent: 3px;
  --border-fact:   4px;
  --masthead-top:  5px;

  /* ── Radii — the Observer is a newspaper: square by default.
     Only chips, expandable panels and beta tags round at all. ── */
  --radius-0:    0;
  --radius-1:    2px;
  --radius-2:    3px;
  --radius-3:    4px;
  --radius-pill: 50%;

  /* ── Elevation — one shadow in the whole system (the nav drawer). ── */
  --shadow-drawer: -4px 0 24px rgba(0,0,0,.15);

  /* ── Motion ── */
  --dur-fast:    .12s;
  --dur-base:    .15s;
  --dur-drawer:  .25s;
  --ease-drawer: cubic-bezier(.4,0,.2,1);

  /* ── Type: families ──
     Libre Baskerville is a sturdier, lower-contrast broadsheet face than
     the Playfair Display it replaced. It runs wider and has a larger
     x-height, so it reads bigger at the same px size. */
  --serif-display: 'Libre Baskerville', Georgia, 'Times New Roman', serif;
  --serif-body:    'Source Serif 4', Georgia, 'Times New Roman', serif;
  --sans:          ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;

  --font-display: var(--serif-display);
  --font-body:    var(--serif-body);
  --font-label:   var(--sans);

  /* ── Type: display sizes (fluid) ── */
  --size-masthead:      clamp(32px, 6vw, 60px);
  --size-headline:      clamp(28px, 5vw, 46px);
  --size-page-title:    clamp(28px, 4.5vw, 44px);
  --size-section-title: clamp(24px, 4vw, 36px);
  --size-section-head:  22px;
  --size-pull-quote:    22px;

  /* ── Type: body ── */
  --size-deck:    19px;
  --size-lede:    19.5px;
  --size-body:    17.5px;
  --size-body-sm: 15.5px;
  --size-caption: 13.5px;
  --size-fine:    12.5px;

  /* ── Type: sans labels — the Observer's "kicker" register ── */
  --size-label:    10px;
  --size-label-sm: 9px;
  --size-label-lg: 11px;

  /* ── Type: weights ──
     Libre Baskerville tops out at 700, so "black" IS 700 here. Do not
     raise this to 900: the browser will synthesise a smeared faux-bold
     rather than fall back cleanly. Italic exists at 400 only. */
  --weight-black: 700;
  --weight-bold:  700;
  --weight-semi:  600;
  --weight-light: 300;

  /* ── Type: line heights ── */
  --leading-tight: 1.12;
  --leading-hed:   1.28;
  --leading-body:  1.7;
  --leading-loose: 2;

  /* ── Type: tracking — the paper's uppercase micro-labels ── */
  --track-label:      .1em;
  --track-label-wide: .14em;
  --track-kicker:     .22em;
  --track-flag:       .26em;
  --track-masthead:   .03em;

  /* ── Layout ── */
  --measure:       68ch;    /* comfortable reading measure */
  --container:     1180px;  /* full-width page shell */
  --column:        680px;   /* article column */
  --wrap-wide:     1100px;  /* index pages (notices, masthead inner) */
  --wrap-mid:      900px;   /* council watch */
  --wrap-narrow:   760px;   /* Community Compass */
  --hero-ratio:    21 / 9;
  --hero-min:      320px;
  --hero-max:      540px;
  --rail-thumb:    118px;
  --rail-icon:     80px;
  --story-thumb-h: 160px;
}

/* ── Dark palette ──
   Applied when the reader's system asks for dark, unless they have
   explicitly chosen light via the header toggle. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --ink:         #ece7dc;
    --ink-soft:    #a9a294;
    --paper:       #16150f;
    --paper-dark:  #201e18;
    --accent:      #e8686c;
    --accent-bg:   #2e1c1c;
    --rule:        #8a7c48;
    --hair:        #35322a;
    --border-warm: #35322a;
    --confirm:     #7dc98f;
    --warn:        #f0908f;
    --pending:     #e0bd6a;
    --chrome-bg:   #0e0d0a;
    --chrome-text: #ece7dc;
    --chrome-soft: #8c8474;
    --surface-card:#201e18;
  }
}

/* Explicit choice from the header toggle always wins. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --ink:         #ece7dc;
  --ink-soft:    #a9a294;
  --paper:       #16150f;
  --paper-dark:  #201e18;
  --accent:      #e8686c;
  --accent-bg:   #2e1c1c;
  --rule:        #8a7c48;
  --hair:        #35322a;
  --border-warm: #35322a;
  --confirm:     #7dc98f;
  --warn:        #f0908f;
  --pending:     #e0bd6a;
  --chrome-bg:   #0e0d0a;
  --chrome-text: #ece7dc;
  --chrome-soft: #8c8474;
  --surface-card:#201e18;
}

:root[data-theme="light"] {
  color-scheme: light;
  --ink:         #1a1a1a;
  --ink-soft:    #575048;
  --paper:       #faf8f4;
  --paper-dark:  #f0ece4;
  --accent:      #b5161b;
  --accent-bg:   #f5e8e8;
  --rule:        #c8b97a;
  --hair:        #ddd7ca;
  --border-warm: #d4c9b8;
  --confirm:     #155724;
  --warn:        #721c24;
  --pending:     #856404;
  --chrome-bg:   #2a2723;
  --chrome-text: #f3efe6;
  --chrome-soft: #a49a88;
  --surface-card:#ffffff;
}

/* ── Base ── */
* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif-body);
  font-size: 16px;   /* Design's --size-body is 17.5px — see divergence note */
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4 {
  font-family: var(--serif-display);
  color: var(--ink);
  text-wrap: balance;
}

a { color: inherit; }

img { max-width: 100%; }

hr {
  border: 0;
  border-top: var(--rule-hair) solid var(--hair);
  margin: var(--s4) 0;
}

::selection { background: var(--accent); color: var(--text-on-accent); }

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

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}
