/* ============================================================================
   v3 shell — the site-wide near-white editorial ground.
   Extracted 2026-07-19 from templates/agent/base.html at the one-go flip, so
   the shell is defined ONCE instead of being re-inlined per standalone page.

   Design source of truth: docs/FABLE_WEATHER_REDESIGN_2026-07.md
   Hard rules (docs/V3_PORT_CONTRACT.md): colour = physical demand, never price
   — sienna = demand-supportive, steel = demand-softening, ink for everything
   else. No green/red anywhere. Bold only on values.

   RESPONSIVE CONTRACT (added at the flip; the desks were desktop-only ports and
   five of six scrolled the body horizontally on a 390px phone):
     - the BODY never scrolls horizontally at 320 / 390 / 834 / 1440
     - anything genuinely too wide to wrap (ticker rails, data tables) scrolls
       INSIDE its own container, so the page stays still under the finger
     - the nav never disappears — below 920px it becomes a scrollable rail
       (it used to `display:none`, which left phones with no navigation at all)
   ========================================================================== */

:root{
  /* --ink-3 was #878d94 in the mockups. On paper that measures 3.24:1, which
     fails WCAG AA (4.5:1) for the 11-13px secondary text it is used for
     everywhere — as-of stamps, footnotes, eyebrows, bylines. Darkened to
     #676d73 = 5.04:1 on paper, 4.72:1 on the paper-2 tint. Still reads as the same quiet grey; it is simply
     legible now. This is the ONE token deviation from the approved mockups. */
  --paper:#fbfbfa; --paper-2:#f4f4f3; --ink:#191c20; --ink-2:#4b5057; --ink-3:#676d73;
  --hair:#e2e3e4; --hair-2:#eeeeec;
  --dplus:#a34a17; --dplus-tint:#f6ebe2;
  --dminus:#31708f; --dminus-tint:#e8f0f4;
  --neut:#656b71; --neut-tint:#ededec;
  --serif:"New York","Charter","Iowan Old Style",Georgia,serif;
  --sans:-apple-system,"SF Pro Text","Helvetica Neue",Arial,sans-serif;
  --shell-pad:32px;
}

/* ── wireroom.css dark-palette override ──────────────────────────────────────
   static/css/wireroom.css declares its OWN :root palette built for a dark
   ground (--text:#f1f5f9 near-white, --bone:#c8d1de, --silver:#94a3b8). Those
   are text colours; on paper they measured 1.24-1.54:1 — literally invisible,
   and a screenshot flatters them because the shapes are still there. The
   base.html compat layer remapped the `er-*` Tailwind classes but could not
   reach these, because they are hex values inside a stylesheet, not classes.
   v3-shell.css loads LAST, so redeclaring the same custom properties here
   re-tints every wireroom surface (the article retention rails, the wire feed)
   without touching that file's geometry. */
:root{
  --void:#fbfbfa; --shelf:#ffffff; --surface:#ffffff;
  --border:#e2e3e4; --border-strong:#d6d7d8;
  --ghost:#676d73; --slate:#4b5057; --silver:#676d73;
  --bone:#4b5057; --cream:#4b5057; --text:#191c20;
  --accent:#191c20; --accent-bright:#191c20; --accent-glow:rgba(25,28,32,.08);
  /* Signal colours collapse to the v3 semantics: sienna = demand-supportive /
     attention, steel = demand-softening / settled, ink for everything else.
     No green/red anywhere (hard contract rule) — direction is carried by the
     ▲▼ glyphs, which are present in the markup. */
  --cyan:#31708f; --clear:#676d73; --watch:#a34a17;
  --threat:#a34a17; --critical:#a34a17;
  --green:#4b5057; --red:#4b5057;
}

*{margin:0;padding:0;box-sizing:border-box}
html{font-size:16px;-webkit-text-size-adjust:100%}
body{background:var(--paper);color:var(--ink);font-family:var(--sans);
     -webkit-font-smoothing:antialiased;line-height:1.5;overflow-x:clip}
a{color:inherit;text-decoration:none}
a:hover{color:var(--ink-2)}
img,svg,video{max-width:100%}
.num{font-variant-numeric:tabular-nums lining-nums}
.label{font-size:12px;font-weight:600;color:var(--ink-3);font-variant-caps:all-small-caps;letter-spacing:.035em}
:focus-visible{outline:2px solid var(--ink-2);outline-offset:2px;border-radius:3px}
.shell{max-width:1240px;margin:0 auto;padding:0 var(--shell-pad)}

/* ── collision reset ──────────────────────────────────────────────────────────
   wireroom.css (the OLD dark Wire Room design) and this file share NINETEEN
   class names: brand, navlinks, topbar, topbar-in, card, chip, claim, eyebrow,
   footnote, fresh, freshset, live, on, pill, prevnote, rail-eyebrow, sep,
   stale, d.

   Loading last is NOT enough. Cascade replaces per-PROPERTY, not per-rule, so
   any property wireroom declares that this file does not simply survives —
   which is why the mast rendered MONO UPPERCASE with .12em tracking on
   base.html pages while the v3 desks rendered it as sentence-case serif. The
   site looked like two different products because it partly was.

   So every shared class must restate the full font shorthand set:
   family / size / weight / transform / tracking. Do not delete a line here
   because it "looks redundant" — redundancy is the point. */
.brand,.navlinks,.navlinks a,.eyebrow,.rail-eyebrow,.prevnote,.pill,
.chip,.card,.footnote,.fresh,.freshset,.sep,.stale{
  text-transform:none;
}
.brand{font-family:var(--serif);font-size:18px;font-weight:600;letter-spacing:-.01em;
       display:inline-flex;align-items:baseline;gap:0;color:var(--ink)}
.navlinks{font-family:var(--sans);font-size:13px;letter-spacing:normal;font-weight:400}
.navlinks a{font-family:var(--sans);font-size:13px;letter-spacing:normal}

/* ── type scale ───────────────────────────────────────────────────────────────
   ONE scale for the whole site. Before this, the same element rendered seven
   different ways across page classes (h1 at 30/31/33/34/36px, weight 600 and
   700, four different tracking values) because each surface had been styled in
   isolation. Page-specific CSS may override a size, but it should have a reason
   the reader can see. */
h1.display,h1.read,main h1,.page-h1{
  font-family:var(--serif);font-size:32px;line-height:1.2;font-weight:600;
  letter-spacing:-.014em;color:var(--ink)}
h2.sec,.sec-h h2{font-family:var(--serif);font-size:20px;line-height:1.3;
  font-weight:600;letter-spacing:-.008em}
/* small-caps microlabel — the ONE place tracking is deliberate */
.rail-eyebrow,.eyebrow,.label,.sitefoot h3{
  font-family:var(--sans);font-size:12px;font-weight:600;color:var(--ink-3);
  font-variant-caps:all-small-caps;letter-spacing:.04em;text-transform:none}
.standfirst,.lede{font-family:var(--serif);font-size:17.5px;line-height:1.6;color:var(--ink-2)}

/* "beta" flag — the products are honest about their maturity rather than
   letting a reader hit a rough edge and conclude the site is broken. */
.betaflag{font-family:var(--sans);font-size:9px;font-weight:700;color:var(--dplus);
  background:var(--dplus-tint);border-radius:2px;padding:1px 4px;margin-left:5px;
  vertical-align:2px;letter-spacing:.06em;text-transform:uppercase;white-space:nowrap}

/* ── topbar ───────────────────────────────────────────────────────────────── */
.topbar{position:sticky;top:0;z-index:40;background:rgba(251,251,250,.94);
        backdrop-filter:blur(8px);border-bottom:1px solid var(--hair)}
.topbar-in{max-width:1240px;margin:0 auto;display:flex;align-items:baseline;
           gap:26px;padding:14px var(--shell-pad);flex-wrap:wrap}
.brand{font-family:var(--serif);font-size:18px;font-weight:600;letter-spacing:-.01em;flex:0 0 auto}
.brand span{color:var(--ink-3);font-weight:400}
.navlinks{display:flex;gap:20px;font-size:13px;min-width:0}
.navlinks a{color:var(--ink-3);white-space:nowrap}
.navlinks a:hover{color:var(--ink)}
.navlinks a.on{color:var(--ink);font-weight:600}
.freshset{display:flex;gap:14px;align-items:baseline;margin-left:auto}
.fresh{font-size:11.5px;color:var(--ink-3);display:inline-flex;align-items:center;gap:5px}
.fresh .d{width:6px;height:6px;border-radius:50%;background:var(--ink-3);opacity:.55}

.prevnote{display:flex;align-items:baseline;gap:10px;margin:16px 0 0;font-size:11.5px;color:var(--ink-3)}
.prevnote .pill{border:1px solid var(--hair);border-radius:3px;padding:2px 8px;font-weight:600;
                font-variant-caps:all-small-caps;letter-spacing:.04em;color:var(--ink-2)}

/* ── site footer ──────────────────────────────────────────────────────────── */
.sitefoot{border-top:1px solid var(--hair);margin-top:56px;padding:26px 0 56px;font-size:12px;color:var(--ink-3)}
.sitefoot .cols{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:26px}
.sitefoot h3{font-size:11px;font-weight:600;color:var(--ink-2);font-variant-caps:all-small-caps;
             letter-spacing:.04em;margin-bottom:8px}
.sitefoot a{color:var(--ink-3);display:inline-block;padding:2px 0}
.sitefoot a:hover{color:var(--ink)}
.sitefoot .chips{display:flex;flex-wrap:wrap;gap:4px 12px}
.sitefoot .legal{margin-top:22px;padding-top:14px;border-top:1px solid var(--hair-2);line-height:1.6}

/* ── reusable containment utilities ───────────────────────────────────────────
   Use these instead of letting a wide child push the document. `.xscroll` is
   the workhorse: the RAIL scrolls, the PAGE does not. */
.xscroll{overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;
         overscroll-behavior-x:contain}
.xscroll::-webkit-scrollbar{display:none}
.xscroll>*{min-width:max-content}
/* right-edge fade telling the reader there is more — pure CSS, no JS */
.xfade{position:relative}
.xfade::after{content:"";position:absolute;top:0;right:0;bottom:0;width:26px;pointer-events:none;
              background:linear-gradient(to right,rgba(251,251,250,0),var(--paper))}
.fluid-svg{width:100%;height:auto;max-width:100%;display:block}

/* ── shared editorial primitives ──────────────────────────────────────────────
   Generic pieces that more than one surface needs (podcast transcript, article
   pages, the agent desk). Page-specific CSS stays in each template's
   {% block extra_css %}. */
h1.display{font-family:var(--serif);font-size:36px;line-height:1.18;font-weight:600;letter-spacing:-.014em}
.standfirst{font-family:var(--serif);font-size:17px;line-height:1.6;color:var(--ink-2);margin-top:12px;max-width:64ch}
.eyebrow{font-size:12px;font-weight:600;color:var(--ink-3);font-variant-caps:all-small-caps;letter-spacing:.04em}
.eyebrow b{color:var(--dplus);font-weight:600}
.card{background:#fff;border:1px solid var(--hair);border-radius:6px}
.rail-eyebrow{font-size:12px;font-weight:600;color:var(--ink-3);font-variant-caps:all-small-caps;
              letter-spacing:.04em;margin:0 0 10px}
.rail-eyebrow i{font-style:normal;font-weight:400}
.footnote{margin:40px 0 0;padding:16px 0 0;border-top:1px solid var(--hair);font-size:11.5px;
          color:var(--ink-3);line-height:1.65;max-width:96ch}
.footnote b{color:var(--ink-2);font-weight:600}
.badge{font-size:10.5px;font-weight:700;font-variant-caps:all-small-caps;letter-spacing:.05em;
       border-radius:3px;padding:1px 8px 2px;white-space:nowrap}
.badge.live{background:var(--dminus-tint);color:var(--dminus)}
.badge.edge{background:var(--dplus-tint);color:var(--dplus)}
.badge.art{background:var(--neut-tint);color:var(--ink-2)}
.badge.claim{background:none;border:1px solid var(--hair);color:var(--ink-3)}
/* controlled-vocabulary demand chips — colour is physical demand, never price */
.chip{font-size:11px;font-weight:600;border-radius:3px;padding:2px 8px;white-space:nowrap;
      font-variant-caps:all-small-caps;letter-spacing:.03em}
.chip.dplus{background:var(--dplus-tint);color:var(--dplus)}
.chip.dminus{background:var(--dminus-tint);color:var(--dminus)}
.chip.neut{background:var(--neut-tint);color:var(--ink-2)}
/* stale data is desaturated + stamped, never hidden (contract rule 5) */
.stale{opacity:.62;filter:saturate(.55)}

/* Category tint classes from wireroom.css (.cat-eu-power was #60a5fa = 2.54:1
   on paper, and an off-palette blue besides). Category is carried by the label
   text; it does not need a hue. */
[class^="cat-"],[class*=" cat-"]{color:var(--ink-2)}
/* A separator painted in the hairline colour is invisible as TEXT (1.24:1).
   `text-er-border` is the Tailwind spelling of the same mistake — a BORDER
   token used as a text colour on breadcrumb slashes. */
.sep,.dot-sep{color:var(--ink-3)}
/* !important is deliberate on this shim: base.html's compat layer raises its
   own selectors to (0,2,0) to beat Tailwind's hover variants, so equal-
   specificity overrides here silently lose. These are a handful of colour-only
   corrections over a dark palette, not layout — forcing them is the honest fix
   and keeps the correction in ONE file. */
[class~="text-er-border"]{color:var(--ink-3) !important}
/* Off-palette category badges (violet/amber/cyan washes from the dark theme):
   the wash backgrounds drop the text to ~1.5:1 on paper. Collapse them to the
   v3 chip grammar — quiet tint, ink text. */
[class~="text-er-violet"],[class~="text-er-cyan"],[class~="text-er-amber"],
[class~="text-er-green"],[class~="text-er-red"]{color:var(--ink-2) !important}
[class*="bg-er-violet"],[class*="bg-er-cyan"],[class*="bg-er-amber"],
[class*="bg-er-green"],[class*="bg-er-red"]{background:var(--neut-tint) !important}

/* ── hardcoded dark hexes baked into markup ───────────────────────────────────
   A set of templates carry Tailwind ARBITRARY values (text-[#E5E7EB],
   bg-[#0D1522], ...) chosen for the dark theme. They are in the markup, not in
   any palette, so neither the er-* compat layer nor the wireroom variable
   override can reach them — on paper they measure 1.2-2.2:1. Remapped by value
   here rather than editing a dozen templates, which keeps the correction in one
   reviewable place. Light inks -> ink scale; dark surfaces -> paper/tint;
   status hues -> the v3 semantics (sienna attention, steel settled, no
   green/red).                                                                */
[class*="text-[#F1F5F9]"],[class*="text-[#E5E7EB]"],[class*="text-[#DCE3ED]"],
[class*="text-[#D7DEE9]"]{color:var(--ink) !important}
[class*="text-[#A7B0BF]"],[class*="text-[#9CA3AF]"],[class*="text-[#6F7D91]"]{
  color:var(--ink-3) !important}
/* link blues */
[class*="text-[#58A6FF]"],[class*="text-[#0A66C2]"],[class*="text-[#2DD4FF]"],
[class*="text-[#A7F3FF]"]{color:var(--dminus) !important}
/* status hues: attention -> sienna, everything else -> ink. No green/red. */
[class*="text-[#F5A623]"],[class*="text-[#FFD866]"],[class*="text-[#FF9B5C]"]{
  color:var(--dplus) !important}
[class*="text-[#39D353]"],[class*="text-[#6EE7A0]"],[class*="text-[#F85149]"],
[class*="text-[#A78BFA]"],[class*="text-[#C084FC]"]{color:var(--ink-2) !important}
/* dark surfaces -> quiet tints */
[class*="bg-[#0B111C]"],[class*="bg-[#0D1522]"],[class*="bg-[#101927]"],
[class*="bg-[#172634]"],[class*="bg-[#1F2937]"],[class*="bg-[#1A1A2A]"]{
  background-color:var(--paper-2) !important}
[class*="bg-[#102A4F]"],[class*="bg-[#10234A]"],[class*="bg-[#0B2A33]"]{
  background-color:var(--dminus-tint) !important}
[class*="bg-[#2A1A10]"],[class*="bg-[#302008]"],[class*="bg-[#2A210D]"],
[class*="bg-[#3A1216]"]{background-color:var(--dplus-tint) !important}
[class*="bg-[#102A1C]"],[class*="bg-[#122A1C]"],[class*="bg-[#2D1854]"]{
  background-color:var(--neut-tint) !important}
[class*="border-[#151E2B]"],[class*="border-[#1B2636]"],[class*="border-[#3B4658]"]{
  border-color:var(--hair) !important}

/* Stock Tailwind saturated badges (bg-purple-500/20 + text-purple-400 and
   friends) — chosen for a dark ground, ~1.5:1 on paper. Public surfaces only
   need the tint collapsed; /ops is an internal dashboard and is excluded from
   the palette rules by being noindex + admin-only, but the same correction
   there does no harm. */
[class*="text-purple-4"],[class*="text-violet-4"],[class*="text-indigo-4"],
[class*="text-blue-4"],[class*="text-cyan-4"],[class*="text-teal-4"],
[class*="text-emerald-4"],[class*="text-green-4"],[class*="text-red-4"],
[class*="text-rose-4"],[class*="text-amber-4"],[class*="text-yellow-4"],
[class*="text-orange-4"],[class*="text-pink-4"]{color:var(--ink-2) !important}
[class*="bg-purple-5"],[class*="bg-violet-5"],[class*="bg-indigo-5"],
[class*="bg-blue-5"],[class*="bg-cyan-5"],[class*="bg-teal-5"],
[class*="bg-emerald-5"],[class*="bg-green-5"],[class*="bg-red-5"],
[class*="bg-rose-5"],[class*="bg-amber-5"],[class*="bg-yellow-5"],
[class*="bg-orange-5"],[class*="bg-pink-5"]{background-color:var(--neut-tint) !important}

/* ── responsive ───────────────────────────────────────────────────────────── */
@media(max-width:920px){
  /* The nav used to vanish entirely below this width. Now it scrolls. */
  .navlinks{flex:1 1 100%;order:3;overflow-x:auto;-webkit-overflow-scrolling:touch;
            scrollbar-width:none;gap:16px;padding-bottom:2px;overscroll-behavior-x:contain}
  .navlinks::-webkit-scrollbar{display:none}
  .navlinks a{flex:0 0 auto;padding:6px 0}
  .topbar-in{gap:12px 20px;padding-top:11px;padding-bottom:9px}
  .freshset{margin-left:auto;order:2}
}
@media(max-width:640px){
  :root{--shell-pad:16px}
  .sitefoot .cols{grid-template-columns:minmax(0,1fr);gap:20px}
  .freshset{display:none}          /* build stamps are desk furniture, not reader value */
  .brand{font-size:17px}
  /* touch targets */
  .navlinks a{padding:9px 0;min-height:44px;display:inline-flex;align-items:center}
}
@media(max-width:380px){
  .topbar-in{gap:10px 14px}
}

/* Respect reduced motion for the sticky/blur chrome. */
@media(prefers-reduced-motion:reduce){
  *{animation-duration:.01ms !important;animation-iteration-count:1 !important;
    transition-duration:.01ms !important;scroll-behavior:auto !important}
}
