/* ChartHorizon — The Weekly Tape
   Cool-newsprint financial-broadsheet theme. Single source of truth for the index and every page.
   Type: Newsreader, self-hosted under /assets/fonts (zero third-party requests). */

/* The weight axis is clipped to 400–700 — the only weights this site sets. Declaring the
   real range stops the browser synthesising a face it can't reach. */
@font-face{
  font-family:'Newsreader'; font-style:normal; font-weight:400 700; font-display:swap;
  src:url('/assets/fonts/newsreader.woff2') format('woff2');
}
@font-face{
  font-family:'Newsreader'; font-style:italic; font-weight:400 700; font-display:swap;
  src:url('/assets/fonts/newsreader-italic.woff2') format('woff2');
}

:root{
  --paper:#f5f4f1; --ink:#17150f; --gold:#c8a24a; --gold-ink:#7d641e;
  --rule:#ddd9d0; --rule-strong:#17150f; --thead:#ecebe6;
  /* Both muted tones clear 4.5:1 on paper, card and quote-bg — muted-2 is the lighter
     step (4.79:1), not a lighter-than-AA one. See the Muted Floor rule in DESIGN.md. */
  --muted:#6b6356; --muted-2:#736b5c;
  --quote-bg:#efede7; --quote-ink:#4a443a; --card:#fbfbf9;
  --bull:#39744b; --bear:#a8503f;
  --serif:'Newsreader',Georgia,'Times New Roman',serif;
  --sans:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
  /* Prose measure: the text column is narrower than the sheet, so figures, boards and
     tables break out past it the way plates do in print. ~75 characters at 19px. */
  --measure:38rem;
  /* Shadow tint as bare channels so the dark theme can swap warm ink for pure black
     without every rule below repeating its own colour. */
  --shadow-tint:23,21,15;
}

/* ---- dark edition ----
   The night press run. Grounds are the dashboard's own dark tokens (--bg/--surface/
   --surface2/--border), so the paper and the app read as one product; the type stays
   Newsreader and the accent stays the newspaper's gold, so this is still the paper.

   Two rules from DESIGN.md carry over and were re-measured against these grounds, not
   assumed (all figures vs. paper / card / quote-bg):
     · Muted Floor — every tone that carries text clears 4.5:1 on all three surfaces.
       muted 5.96/5.32/4.84, muted-2 5.66/5.05/4.59, bull 7.16/6.39/5.81,
       bear 6.97/6.22/5.66, gold-ink 9.25/8.26/7.51.
     · Ink Ring — :focus-visible is `2px solid var(--ink)` and needs no dark branch at
       all: ink inverts to near-white here and measures 17.22:1 on paper.

   The one real inversion is the accent. --gold-ink exists in the light theme only
   because Foil Gold manages 2.19:1 on paper and cannot legally be text there. On this
   ground the same gold measures 7.75:1, so the accent finally carries itself and
   --gold-ink is a *lift* of the gold rather than a darkened stand-in. */
[data-theme="dark"]{
  --paper:#0b131d; --ink:#f3f6fa; --gold:#c8a24a; --gold-ink:#d6b264;
  --rule:#243240; --rule-strong:#6b8099; --thead:#1b2734;
  --muted:#8493a6; --muted-2:#808fa2;
  --quote-bg:#1b2734; --quote-ink:#c3cedb; --card:#141f2b;
  /* Same two hues as the light theme, lifted off the navy — not the dashboard's
     neon #1ec9a0/#f0664f, which would read as trading UI rather than as newsprint. */
  --bull:#6fae83; --bear:#d98a76;
  --shadow-tint:0,0,0;
}

*{box-sizing:border-box}
/* Declared per theme so form controls, scrollbars and the UA's own chrome follow the
   sheet. The light branch also tells Android's auto-dark to keep its hands off the paper. */
html{-webkit-text-size-adjust:100%; color-scheme:light}
html[data-theme="dark"]{color-scheme:dark}
body{
  max-width:760px; margin:0 auto; padding:0 22px;
  background:var(--paper); color:var(--ink);
  font:19px/1.6 var(--serif);
  font-optical-sizing:auto;
  -webkit-font-smoothing:antialiased;
}

/* ---- focus ---- */
/* One ring everywhere. Foil Gold is only 2.19:1 on paper, so it fails 1.4.11 as an
   indicator — ink carries it on light ground, gold only where the ground is ink. */
:focus-visible{outline:2px solid var(--ink); outline-offset:2px; border-radius:2px}

/* ---- a11y utilities ---- */
.visually-hidden{position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip-path:inset(50%); white-space:nowrap; border:0}
.skip-link{position:absolute; left:50%; top:10px; transform:translateX(-50%); z-index:20; padding:10px 16px;
  background:var(--ink); color:var(--paper); font:700 11px/1 var(--sans); letter-spacing:.1em; text-transform:uppercase;
  text-decoration:none; border:none; border-radius:999px; opacity:0; pointer-events:none}
.skip-link:focus-visible{opacity:1; pointer-events:auto; outline:2px solid var(--gold); outline-offset:2px}
/* The global a:hover turns link text to ink, which on this ink pill is ink on ink: a keyboard
   reader who also touched the mouse saw the link go blank. */
.skip-link:hover{color:var(--paper)}

/* ---- article typography ---- */
h1{font:600 clamp(34px,4.6vw,42px)/1.1 var(--serif); letter-spacing:-.6px; margin:.55em 0 .12em; text-wrap:balance}
h2{font:650 25px/1.25 var(--serif); letter-spacing:-.2px; margin:1.6em 0 .4em; padding-top:1.1em; border-top:1px solid var(--rule); text-wrap:balance}
/* broadsheet section opener: a short gold tick sits on the hairline that opens each section */
h2::before{content:""; position:absolute; margin-top:-1.1em; width:34px; border-top:2px solid var(--gold)}
h2{position:relative}
p{margin:.75em 0; text-wrap:pretty}
strong{color:var(--ink)}
.dek{color:var(--muted); font-style:italic; line-height:1.5; margin:.2em 0 1.35em; max-width:var(--measure)}
/* The article head: the headline, the story in one sentence, then when and from what. The
   dateline sits UNDER the dek rather than over the headline, so the headline is the first
   thing on the page and not a label above it; the sources line is the old subtitle, which
   was a provenance note doing a dek's job. */
.post-head{margin:0 0 1.7em}
.post-head .dek{margin-bottom:.75em}
.post-head .post-meta{margin:0}
.post-head h1 + .post-meta{margin-top:.6em}
.post-sources{margin:.3em 0 0; max-width:var(--measure); font:13px/1.5 var(--sans); color:var(--muted-2); text-wrap:pretty}
/* Prose holds the measure; figures, boards and tables break out to the full sheet. */
.post-body>:is(p,ul,ol,dl,blockquote){max-width:var(--measure)}
/* A chart the generator writes as a bare markdown image arrives wrapped in a <p>, and the
   measure above then held it to the text column while every other figure ran the sheet. */
.post-body>p:has(>img:only-child){max-width:none}
/* Posts open each section with `---`, and the h2 already carries a rule and the gold tick,
   so the pair drew two hairlines 40px apart. The h2 keeps its rule; the <hr> before it goes. */
.post-body hr:has(+h2){display:none}
a{color:var(--gold-ink); text-decoration:none; border-bottom:1px solid color-mix(in srgb,var(--gold) 40%,transparent)}
a:hover{color:var(--ink); border-bottom-color:var(--gold)}
img{max-width:100%; height:auto; border-radius:6px; margin:18px 0; box-shadow:0 1px 14px rgba(var(--shadow-tint),.13)}
table{border-collapse:collapse; width:100%; font:14px/1.45 var(--sans); margin:14px 0; font-variant-numeric:tabular-nums lining-nums}
td,th{border:1px solid var(--rule); padding:8px 12px; text-align:left}
th{background:var(--thead); font-weight:600}
/* The Ledger's four-column extremes table needs ~313px at 14px with 12px padding, and a 320px
   phone gives it 276px: the page scrolled sideways by 15px on every Ledger issue. */
@media (max-width:420px){
  .post-body table{font-size:13px}
  .post-body :is(td,th){padding:7px 8px}
}
/* The Ledger's hedging-program table: the markets that crossed the midpoint this
   report. Fixed layout so the market column does not size to whichever name happens
   to be longest that week ("Natural Gas (Henry Hub)" vs "Gold"), which made the
   header row jump between issues. The two right-hand columns both carry a phrase
   ("from above the midpoint" / "▼ below midpoint"), so they take equal, generous
   shares — at 16% the last one wrapped its own heading onto two lines. */
.program-board{table-layout:fixed}
.program-board td:first-child,.program-board th:first-child{width:34%}
.program-board td:last-child,.program-board th:last-child{width:30%}
/* On a phone, auto layout handed the nowrap "▼ below midpoint" its full width and squeezed
   "Turned" to one word per line: ~196px rows at 390px. Fixed shares and tighter padding keep
   each phrase to two lines. The mark may wrap before "midpoint" in this table only, because
   the column cannot hold it whole; "▼ below" still never splits at these widths. */
@media (max-width:560px){
  .program-board :is(td,th){padding:8px 9px}
  .program-board td:first-child,.program-board th:first-child{width:30%}
  .program-board td:last-child,.program-board th:last-child{width:34%}
  .program-board :is(.mark-bull,.mark-bear){white-space:normal}
}
/* read marks for post tables — always paired with a glyph + word, never color alone (Read-Mark Rule) */
.mark-bull{color:var(--bull); font-weight:700}
.mark-bear{color:var(--bear); font-weight:700}
/* one read mark, one line: on a phone the Side column wrapped "▼" and "LOW" apart and
   doubled the height of every row */
.mark-bull,.mark-bear{white-space:nowrap}
hr{border:none; border-top:1px solid var(--rule); margin:34px 0}
/* broadsheet pull quote: tone fill inside a full hairline — no accent side-stripe */
blockquote{border:1px solid var(--rule); background:var(--quote-bg); padding:12px 18px; margin:20px 0; border-radius:4px; color:var(--quote-ink)}
blockquote p{margin:.3em 0}
.post-disclaimer{font:italic 13px/1.55 var(--sans); color:var(--muted); max-width:70ch}

/* ---- broadsheet masthead ---- */
.site-head{padding:38px 0 0; text-align:center}
.site-head .brand{display:inline-flex; align-items:center; gap:13px; text-decoration:none; color:inherit; border:none}
.site-head .mark{flex:none; width:clamp(30px,3.4vw,38px); height:auto}
/* the mark's horizon rides currentColor (see default.html); only the sun is accented */
.site-head .mark .mark-sun{stroke:var(--gold)}
.site-head .word{font:700 clamp(30px,4.4vw,42px)/1 var(--serif); letter-spacing:.1em; text-transform:uppercase}
.masthead-sub{font:11px/1 var(--sans); letter-spacing:.26em; text-transform:uppercase; color:var(--muted); margin-top:12px}
/* classic broadsheet tramline: a thick rule with a hairline riding 3px beneath it */
.masthead-rule{position:relative; border-top:2.5px solid var(--rule-strong); margin-top:15px}
.masthead-rule::after{content:""; position:absolute; left:0; right:0; top:3px; border-top:1px solid var(--rule-strong)}
.masthead-motto{font:italic 400 14px/1 var(--serif); color:var(--muted); text-align:center; padding:11px 0 1px}
/* 12px/13px gaps and .08em tracking, not 16px and .1em: with "Front Page" as the first tab
   (2026-09-13) the row needed 740px of a 716px sheet and pushed Support onto a line of its
   own on every page but the cover. September is the longest month the edition stamp prints. */
.dateline{display:flex; align-items:center; flex-wrap:wrap; gap:8px 12px; padding:10px 0; border-bottom:1px solid var(--rule);
  font:11px/1 var(--sans); letter-spacing:.08em; text-transform:uppercase; font-variant-numeric:tabular-nums}
.dateline .site-nav{display:flex; gap:13px}
/* padding + negative margin keeps the layout identical while lifting tap targets ≥24px (WCAG 2.5.8) */
/* nowrap: a flex row shrinks its items before it wraps, so without this the narrow masthead
   breaks the labels themselves ("THE / TAPE") rather than moving a whole tab to line two.
   It only started showing with the fifth tab (Resources, 2026-09-06); the pair below lets
   the row wrap as tabs instead. */
.dateline .site-nav a{color:var(--muted); text-decoration:none; border:none; padding:9px 4px; margin:-9px -4px; white-space:nowrap}
.dateline .site-nav a:hover{color:var(--ink)}
.dateline .site-nav a.active,.dateline .site-nav a[aria-current="page"]{color:var(--ink); font-weight:600}
.dateline .edition{margin-left:auto; color:var(--muted)}
.dateline .support{display:inline-flex; align-items:center; gap:6px; color:var(--gold-ink); text-decoration:none; border:none; letter-spacing:.06em; padding:9px 4px; margin:-9px -4px}
.dateline .support svg{width:13px; height:13px; fill:currentColor; flex:none}
.dateline .support:hover{color:var(--ink)}
/* edition switch: the light/dark control, set as dateline furniture rather than as a
   widget. Class names, the two child glyphs and the sun-in-light / moon-in-dark
   convention are the dashboard's (app/web/styles.css), so the control means the same
   thing in both products. Padding lifts it to a ≥24px target (WCAG 2.5.8) without
   moving the row. */
.theme-toggle{appearance:none; background:none; border:none; cursor:pointer; color:var(--muted);
  display:inline-flex; align-items:center; padding:9px 5px; margin:-9px -5px; border-radius:4px}
.theme-toggle:hover{color:var(--ink)}
.theme-toggle svg{width:15px; height:15px; flex:none}
.theme-toggle .moon{display:none}
[data-theme="dark"] .theme-toggle .sun{display:none}
[data-theme="dark"] .theme-toggle .moon{display:block}
@media (max-width:560px){
  /* 24px, not 38px: the touch rows below make the dateline 14px taller, and this pays for
     it, so no page's content starts any lower on a phone than it did before them. */
  .site-head{padding-top:24px}
  .site-head .word{font-size:24px}
  .masthead-sub{letter-spacing:.18em}
  /* Touch rows. 7px of padding around an 11px label is a 25px target (WCAG 2.5.8), and a
     14px row gap is exactly the two paddings, so a tab's target meets the one below it
     instead of sliding under it. With 9px padding on 6-8px gaps the rows overlapped. */
  .dateline{justify-content:center; gap:14px}
  .dateline .site-nav{flex-wrap:wrap; justify-content:center; gap:14px}
  .dateline .site-nav a,.dateline .support,.theme-toggle{padding-block:7px; margin-block:-7px}
  .dateline .edition{margin-left:0}
}
/* Five tabs need ~425px on one row (~410px before the first tab became "Front Page"). Below
   that a wrapping row stranded "About" alone under the other four, so the nav becomes a 3 + 2
   grid: six tracks, each tab spanning two, the second row starting on track two so its pair
   sits centred under the three above. The switch sits at 440px rather than at the measured
   fit, so a system sans a few pixels wider than San Francisco cannot bring the orphan back.
   Tracks stop at 52px, so a cell is at most 104px and the tabs stay a set instead of
   spreading to the edges of the sheet; at 320px a cell is 92px. */
@media (max-width:439px){
  .dateline .site-nav{display:grid; grid-template-columns:repeat(6,minmax(0,52px)); justify-content:center; gap:14px 0; width:100%}
  .dateline .site-nav a{grid-column:span 2; justify-self:center}
  .dateline .site-nav a:nth-child(4){grid-column:2 / span 2}
}

.site-foot{margin-top:54px; padding:22px 0 46px; border-top:1px solid var(--rule); font:13px/1.62 var(--sans); color:var(--muted)}
.site-foot strong{color:var(--ink)}
.site-foot .legal-links{margin-top:8px}
/* small print still gets a measure: at 13px across the 760px sheet a line ran ~115 characters */
.site-foot p{max-width:70ch}
.site-foot a{color:var(--muted); text-decoration:none; border-bottom:1px solid var(--rule)}
.site-foot a:hover{color:var(--ink)}

/* ---- index front page ---- */
.index-standfirst{font:italic 400 19px/1.5 var(--serif); color:var(--muted); margin:1.3em 0 1.7em; max-width:62ch; text-wrap:pretty}
/* On a phone it ran four lines of 19px italic between the masthead and the lead, and the lead
   headline started 596px down an 844px screen. */
@media (max-width:560px){ .index-standfirst{font-size:16.5px; margin:1em 0 1.3em} }
/* section rule: a small caps label riding a strong hairline, broadsheet-style (an h2, so it carries the outline) */
.section-rule{display:flex; align-items:center; gap:14px; margin:0; padding-top:0; border-top:none;
  font:700 11px/1 var(--sans); letter-spacing:.16em; text-transform:uppercase; color:var(--muted)}
.section-rule::before{content:none}
.section-rule::after{content:""; flex:1; border-top:2px solid var(--rule-strong)}

/* a real dateline: which edition this is, then when it ran — so seven Ledger entries in a
   row read as a running series rather than as the same note posted seven times.
   Shared by the front page, /archive/, the hubs and the article head (.post-meta).
   Sentence case since 2026-09-13: tracked capitals were fifteen of the thirty-six text runs
   in the cover's first screen, one small voice for every job. They now belong to the
   masthead, the nav and the section rules only. */
.post-dateline,.post-meta{display:block; font:500 12.5px/1.4 var(--sans); font-variant-numeric:tabular-nums lining-nums}
.post-edition{color:var(--gold-ink); font-weight:600}
.post-date{color:var(--muted-2)}
:is(.post-dateline,.post-meta) .sep{color:var(--muted-2)}

/* back issues: the front page is capped, everything else lives on /archive/ */
.more-issues{margin:26px 0 0; padding-top:16px; border-top:2px solid var(--rule-strong); text-align:right;
  font:600 13.5px/1.2 var(--sans)}
.more-issues a{color:var(--gold-ink); border:none; padding:9px 2px; margin:-9px 0}
.more-issues a:hover{color:var(--ink)}
.archive-year{margin:34px 0 0}
.archive-list{list-style:none; padding:0; margin:6px 0 0}
.archive-list li{display:flex; align-items:baseline; gap:4px 16px; flex-wrap:wrap; padding:12px 0; border-top:1px solid var(--rule)}
/* rem, not em: the dateline sets its own size, and the column has to clear the longest
   label ("Hedgers’ Ledger · Aug 30") on one line so the headlines stay in a column */
.archive-list .post-dateline{flex:none; width:11rem; white-space:nowrap}
.archive-list .archive-link{font:600 19px/1.3 var(--serif); color:var(--ink); border:none; flex:1 1 16ch; text-wrap:balance}
.archive-list .archive-link:hover{color:var(--gold-ink)}
@media (max-width:560px){ .archive-list li{display:block} .archive-list .post-dateline{width:auto; margin-bottom:3px} }

/* section hubs (/tape/, /ledger/) reuse the archive list, minus the edition label —
   the page IS the edition — so the dateline column only has to clear "Aug 16". */
/* A hub's standing paragraph: how to read the edition, under the dek. Body ink, not the
   dek's muted italic — the dek says what the edition IS and this says how it works, and
   two muted italic blocks in a row read as one long subtitle nobody finishes. */
.hub-intro{max-width:var(--measure); margin:0 0 1.35em; line-height:1.6}
.hub-intro a{color:var(--gold-ink)}
.hub-list .post-dateline{width:6.5rem}
@media (max-width:560px){ .hub-list .post-dateline{width:auto} }
/* Standing-in for a hub with no run yet: reads as an editorial note, not as an error. */
.hub-empty{margin:30px 0 0; padding-top:18px; border-top:2px solid var(--rule-strong);
  color:var(--muted); line-height:1.55; max-width:var(--measure)}

/* ---- the reading room (/resources/) ----
   Outside material, set as a reference column rather than as cards: the same
   .post-dateline furniture the index and /archive/ use, so a link that leaves the site
   still reads as an entry in this paper. The dateline's gold slot carries the desk's own
   signal (Positioning, Hedging program, …) instead of an edition — that is the whole
   editorial point of the page, so it sits where the eye already looks for a label. */
.res-standing{max-width:var(--measure); color:var(--muted); margin:1.1em 0 0}
/* A promoted section: set as a plate so it reads as its own shelf rather than as the first
   run of an undifferentiated list. Used for the paid section, which is why the disclosure
   chip on each entry is a SEPARATE flag in the data — decoration must never be what carries
   a legal notice. The plate supplies the boundary, so the h2 gives up its own rule and gold
   tick here — the plate edge is the section opener now. */
.res-section--featured{margin:30px 0 0; padding:20px 26px 26px; border:1px solid var(--rule);
  border-radius:12px; background:var(--card)}
.res-section--featured > h2{margin:0; padding-top:0; border-top:none; font-size:27px}
.res-section--featured > h2::before{content:none}
.res-section--featured .res-title{font-size:23px}
.res-section--featured .res-item:first-child{border-top-color:var(--rule-strong)}
/* On a phone the two standing paragraphs ran 547px at body size, and the first entry sat
   1,150px down an 844px screen. They are a notice about the page rather than the page, so
   there they step down to 16px, under the entries' own 17px takes. The wording does not
   change: both paragraphs are load-bearing (see the comment in resources.html). */
@media (max-width:560px){
  .res-standing{font-size:16px; line-height:1.55; margin-top:.9em}
  .res-section--featured{margin-top:24px; padding:18px 16px 20px}
}
.res-standing a{color:var(--gold-ink)}
.res-note{max-width:var(--measure); font:14px/1.55 var(--sans); color:var(--muted); margin:.5em 0 0}
.res-list{list-style:none; padding:0; margin:14px 0 0}
.res-item{padding:16px 0; border-top:1px solid var(--rule)}
/* Paid-link disclosure. Muted and outlined, never gold: gold is the slot the desk's own
   signal sits in, and a disclosure wearing the accent colour reads as a recommendation.
   Sits in the dateline row, so it is AT the link — § 5a Abs. 4 UWG wants the commercial
   purpose recognisable there, not only in the section note above it. */
.res-ad{display:inline-block; padding:2px 7px; border:1px solid var(--rule);
  border-radius:999px; background:var(--quote-bg); color:var(--muted); font-weight:600; font-size:12px}
/* The gap sits on the end of the source before the chip, not on the chip's start: on a phone
   the chip wraps to a line of its own, and a leading margin indented it 9px off the column. */
.res-item .post-date{margin-right:9px}
.res-title{font:600 21px/1.28 var(--serif); letter-spacing:-.15px; margin:5px 0 0; text-wrap:balance}
.res-byline{font:italic 400 16px/1.4 var(--serif); color:var(--muted); margin:3px 0 0}
.res-title a{color:var(--ink); border:none}
.res-title a:hover{color:var(--gold-ink)}
/* Off-site marker on the one link each item has. Decorative and aria-hidden: the arrow is
   a hint, not the destination — the section note says in words that these open on YouTube.
   Non-breaking space so it can never be left alone on a line of its own. */
.res-ext{font-size:.72em; color:var(--muted-2); margin-left:.32em; vertical-align:.18em}
.res-title a:hover .res-ext{color:var(--gold-ink)}
/* The desk's own paragraph on an entry. Full ink, deliberately: every other line in this
   item is borrowed — title, author, series — and the one that is this paper's own work is
   the one that should read as body text rather than as furniture. Sits above the topic
   bullets because it is the argument and they are the index to it. */
.res-take{max-width:var(--measure); font:17px/1.62 var(--serif); color:var(--ink); margin:8px 0 0}
.res-topics{list-style:none; padding:0; margin:9px 0 0}
/* Marker is the h2 opener's gold tick, shrunk — the page's one repeated ornament. */
.res-topics li{position:relative; padding-left:19px; margin:4px 0; max-width:var(--measure);
  font:15px/1.55 var(--sans); color:var(--muted)}
.res-topics li::before{content:""; position:absolute; left:0; top:.63em; width:10px; border-top:2px solid var(--gold)}
.res-close{margin:36px 0 0; padding-top:16px; border-top:2px solid var(--rule-strong)}
.res-close p{max-width:var(--measure); margin:0; font-style:italic; color:var(--muted)}
.res-close a{color:var(--gold-ink)}

/* ---- "Elsewhere in the paper": the links between editions, under every post ----
   Same dateline furniture as the index and /archive/ (see _includes/post-teaser.html),
   set one step down: this is a footer to the piece you just read, not a second front page. */
.post-more{margin:46px 0 0}
.post-more-list{list-style:none; padding:0; margin:6px 0 0}
.post-more-list li{padding:14px 0; border-top:1px solid var(--rule)}
.post-more-list li:first-child{border-top:none}
.post-more-list .post-link{display:inline-block; margin:.14em 0 0; font:600 19px/1.25 var(--serif);
  letter-spacing:-.15px; color:var(--ink); border:none; text-wrap:balance}
.post-more-list .post-link:hover{color:var(--gold-ink)}
/* two links share the foot rule under a post now — the hub, then the whole run */
.post-more .more-issues .sep{margin:0 10px; color:var(--muted-2)}

/* ---- post body: broadsheet drop cap on the first paragraph ---- */
.post-body>p:first-of-type::first-letter{
  float:left; font:600 64px/48px var(--serif); color:var(--gold-ink);
  padding:4px 9px 0 0;
}
/* Not every .post-body opens a read: on /about/ the cap split the brand ("C hartHorizon"). */
.no-dropcap>p:first-of-type::first-letter{float:none; font:inherit; color:inherit; padding:0}

/* ---- legal pages (Impressum / Datenschutz) ---- */
.legal{font-size:16px}
.legal h1{margin:.4em 0 .1em}
.legal h2{font-size:20px; border-top:none; padding-top:0; margin:1.7em 0 .3em}
.legal p,.legal ul{color:var(--muted); margin:.3em 0; max-width:var(--measure)}
.legal strong{color:var(--ink)}
.legal code{font:12.5px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace; background:var(--quote-bg); border:1px solid var(--rule); border-radius:4px; padding:1px 5px; color:var(--ink)}
.legal a.link{color:var(--gold-ink); border-bottom:1px solid color-mix(in srgb,var(--gold) 40%,transparent)}
.legal a.link:hover{color:var(--ink)}
.legal .back{display:inline-block; margin-top:36px}

/* Bilingual since 2026-09-19: one h1 for both languages, then each edition under its own
   label. The old subsection h2s became h3s so the two language blocks sit at one level and
   a heading-by-heading reader meets a boundary instead of sliding from English section 8
   into German section 1 — the level moved, the type did not, so h3 reproduces what .legal h2
   looked like, gold tick included. The edition label is the one head that drops the tick:
   the double rule is its furniture, and gold is the slot the desk's own signal sits in. */
.legal h3{font:650 20px/1.25 var(--serif); letter-spacing:-.2px; margin:1.7em 0 .3em; position:relative; text-wrap:balance}
.legal h3::before{content:""; position:absolute; margin-top:-1.1em; width:34px; border-top:2px solid var(--gold)}
.legal h2.legal-edition{font:650 13px/1.3 var(--sans); letter-spacing:.14em; text-transform:uppercase; color:var(--muted); border-top:3px double var(--rule-strong); padding-top:12px; margin:3em 0 .1em}
.legal h2.legal-edition:first-of-type{margin-top:2em}
.legal h2.legal-edition::before{content:none}
.legal .legal-lang{font-size:14px; margin:.3em 0 0}
.legal .legal-note{font-style:italic; margin:.2em 0 1.2em}

/* ---- /dashboard/ — coming-soon notice (broadsheet, no hero-CTA) ---- */
/* No kicker over the headline (removed 2026-09-13 from /dashboard/, /resources/ and the 404):
   the heading carries its own weight, so it takes the ordinary h1 top margin back. */
.notice-head{text-align:center}
.notice-head h1{margin:.55em 0 .1em}
.notice-head .dek{max-width:36ch; margin-left:auto; margin-right:auto}
.notice-rule{width:54px; border-top:2px solid var(--gold); margin:16px auto 0}
/* Release line — the masthead's own dateline idiom, set directly under the rule so a shipped
   build is visible on arrival instead of 4,800px down the page. Not a hero CTA: no button,
   no panel, just the edition's stand-first for the software. Its one link jumps to #download
   rather than fetching a file, so the reader lands on the buttons with the architecture and
   the first-run notes beside them. */
.dl-top{display:flex; flex-wrap:wrap; align-items:baseline; justify-content:center; gap:4px 15px;
  margin:17px 0 0; font:600 13.5px/1.2 var(--sans);
  font-variant-numeric:tabular-nums lining-nums}
.dl-top-label{color:var(--muted); font-weight:500}
.dl-top a{color:var(--gold-ink); padding:8px 2px; margin:-8px 0;
  border-bottom:1px solid color-mix(in srgb,var(--gold) 45%,transparent)}
.dl-top a:hover{color:var(--ink); border-bottom-color:var(--gold)}
.dash-reads{margin:30px 0; padding:18px 18px 20px; border:1px solid var(--rule); border-radius:12px; background:var(--card); text-align:center}
.dash-reads .label{display:block; font:700 11px/1.3 var(--sans); letter-spacing:.14em; text-transform:uppercase; color:var(--muted-2); margin-bottom:13px}
.dash-reads .fx-chips{justify-content:center}
.dash-close{text-align:center; font-style:italic; color:var(--muted); margin:30px 0 4px; text-wrap:balance}
.notfound{max-width:var(--measure); margin:28px auto 0; text-align:center; text-wrap:pretty}

/* download block — three platform buttons (active link or "Coming soon" state) */
/* scroll-margin: the release line up top jumps here, and without it the section label sits
   flush against the viewport edge on arrival. */
.dl{margin:34px 0 6px; text-align:center; scroll-margin-top:28px}
.dl-label{display:block; font:700 11px/1.3 var(--sans); letter-spacing:.14em; text-transform:uppercase; color:var(--muted-2); margin-bottom:15px}
.dl-grid{display:grid; grid-template-columns:repeat(3,1fr); gap:12px; max-width:440px; margin:0 auto}
.dl-btn{display:flex; flex-direction:column; align-items:center; justify-content:center; gap:9px; padding:18px 10px 15px; border:1px solid var(--rule); border-radius:12px; background:var(--card); color:var(--ink); text-decoration:none; transition:border-color .14s, box-shadow .14s, transform .04s}
.dl-os-ico{width:27px; height:27px; fill:var(--ink); transition:fill .14s, opacity .14s}
.dl-os{font:700 15px/1 var(--sans)}
.dl-sub{font:600 12.5px/1.3 var(--sans); color:var(--muted-2); white-space:nowrap; font-variant-numeric:tabular-nums lining-nums}
/* which build this button actually is. An Intel Mac cannot run the arm64 dmg and a
   32-bit Windows cannot run the x64 setup — that belongs before the click, not after it.
   Deliberately NOT nowrap like .dl-sub: at 320px the column is ~75px wide and a wrapped
   second line is better than a label overflowing its own button. */
.dl-arch,.dl-size{margin-top:-5px; font:500 12px/1.35 var(--sans); color:var(--muted-2); font-variant-numeric:tabular-nums lining-nums}
/* what the click costs, set tight under the architecture so the two read as one group */
.dl-size{margin-top:-8px}
/* active state: real download link */
a.dl-btn:hover{border-color:var(--gold); box-shadow:0 2px 10px rgba(var(--shadow-tint),.09)}
a.dl-btn:hover .dl-os-ico{fill:var(--gold-ink)}
a.dl-btn:hover .dl-sub{color:var(--gold-ink)}
a.dl-btn:hover :is(.dl-arch,.dl-size){color:var(--gold-ink)}
a.dl-btn:active{transform:translateY(1px)}
/* coming-soon state: not yet downloadable */
.dl-btn--soon{background:var(--quote-bg); border-style:dashed; cursor:default}
.dl-btn--soon .dl-os-ico{fill:var(--muted-2); opacity:.6}
/* muted, not muted-2: "Coming soon" sat at exactly 4.50:1 on the quote-bg ground */
.dl-btn--soon .dl-os,.dl-btn--soon .dl-sub{color:var(--muted)}
.dl-note{font:italic 14px/1.5 var(--serif); color:var(--muted); margin:16px auto 0; max-width:42ch; text-wrap:balance}
/* First-run helper for unsigned builds — collapsed by default, launched state only.
   Set as a card at .dl-grid's own 440px so it reads as the fourth element of the download
   block rather than as a footnote under it. It was muted-2 11px on bare paper and got
   missed: a reader who does not open this meets Gatekeeper calling the app damaged, or
   SmartScreen refusing to run it, with no idea the page already answered it. That is the
   most likely moment for a download to be abandoned, so the line carries ink weight and a
   gold marker — still a disclosure, not a second CTA competing with the buttons above. */
.dl-firstrun{max-width:440px; margin:18px auto 0; text-align:left; font:14px/1.55 var(--sans); color:var(--muted);
  border:1px solid var(--rule); border-radius:12px; background:var(--card)}
/* padding lifts the disclosure control well past the ≥24px target (WCAG 2.5.8) */
.dl-firstrun summary{cursor:pointer; text-align:center; font:600 14.5px/1.3 var(--sans); color:var(--ink); list-style:none; padding:13px 15px; border-radius:12px}
.dl-firstrun summary:hover{color:var(--gold-ink)}
.dl-firstrun summary::-webkit-details-marker{display:none}
.dl-firstrun summary::after{content:" ▾"; font-size:15px; line-height:0; vertical-align:-1px; color:var(--gold-ink)}
.dl-firstrun[open] summary{border-bottom:1px solid var(--rule); border-radius:12px 12px 0 0}
.dl-firstrun[open] summary::after{content:" ▴"}
.dl-firstrun p{margin:12px 0 8px; padding:0 15px}
.dl-firstrun ul{margin:0 0 14px; padding:0 15px 0 calc(15px + 1.15em); list-style:disc}
.dl-firstrun li{margin:5px 0}
.dl-firstrun b{color:var(--ink); font-weight:700}
.dl-firstrun code{font:12.5px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace; background:var(--quote-bg); border:1px solid var(--rule); border-radius:4px; padding:1px 5px}
/* The source offer, the block's closing line. Sans and muted, not the italic serif of
   .dl-note: that line carries the one thing a reader must know before clicking, and two
   italic lines under the buttons read as one paragraph nobody finishes. */
.dl-source{font:14px/1.55 var(--sans); color:var(--muted); margin:18px auto 0; max-width:42ch; text-wrap:balance}
/* 11px floor on a phone: the architecture line is what stops an Intel Mac downloading a dmg
   it cannot run, and at 8px it was the smallest text on the site */
@media (max-width:420px){ .dl-grid{gap:8px} .dl-btn{padding:14px 6px 12px} .dl-os{font-size:14px} .dl-sub{font-size:11.5px} .dl-arch,.dl-size{font-size:11px} }

/* dashboard product page — screenshot plates set as plates on the sheet */
.board{margin:30px 0}
.board img{width:100%; margin:0; display:block; border:1px solid var(--rule); border-radius:10px; box-shadow:0 1px 16px rgba(var(--shadow-tint),.10)}
.board figcaption{font:italic 15px/1.5 var(--serif); color:var(--muted); text-align:center; margin-top:11px; text-wrap:balance}
/* hero breaks out wider than the 760px column, bounded so it never causes horizontal scroll */
.board-hero{--bleed:clamp(0px, calc((100vw - 716px)/2 - 16px), 160px); margin:26px calc(-1*var(--bleed)) 32px}
.board-hero img{border-radius:12px}
@media (prefers-reduced-motion:no-preference){
  .board img{transition:box-shadow .25s ease}
  .board img:hover{box-shadow:0 6px 30px rgba(var(--shadow-tint),.13)}
}

/* ---- FX Map page (/fx/) ---- */
.fxmap{margin:18px 0 6px}
/* the board's dateline, set under the dek the way an article's is (see fx.html) */
.dek:has(+ .fxmap-meta){margin-bottom:.7em}
.fxmap-meta{font:500 12.5px/1.4 var(--sans); color:var(--muted); margin:0}
.fx-board,.fx-pairs{display:grid; grid-template-columns:1fr 1fr; gap:14px}
.fx-pairs{margin-top:14px}
.fx-col,.fx-pairshelf{border:1px solid var(--rule); border-radius:10px; padding:14px 16px; background:var(--card)}
.fx-col--bull{border-color:color-mix(in srgb,var(--bull) 40%,transparent)}
.fx-col--bear{border-color:color-mix(in srgb,var(--bear) 40%,transparent)}
.fx-col-head{display:flex; align-items:center; gap:8px; font:700 11.5px/1 var(--sans); letter-spacing:.07em; text-transform:uppercase; margin-bottom:12px}
.fx-col--bull .fx-col-head{color:var(--bull)}
.fx-col--bear .fx-col-head{color:var(--bear)}
.fx-count{font:600 11px/1 var(--sans); color:var(--muted); background:var(--quote-bg); border:1px solid var(--rule); border-radius:999px; padding:3px 7px; letter-spacing:0}
.fx-chips{display:flex; flex-wrap:wrap; gap:7px}
.fx-chip{font:13px/1 var(--sans); padding:8px 11px; border-radius:999px; background:var(--quote-bg); border:1px solid var(--rule); color:var(--ink); white-space:nowrap}
.fx-chip b{font-weight:700; margin-left:2px}
.fx-col--bull .fx-chip b{color:var(--bull)}
.fx-col--bear .fx-chip b{color:var(--bear)}
.fx-neutral-row{display:flex; align-items:center; flex-wrap:wrap; gap:7px; margin-top:12px}
.fx-neutral-label{font:700 11px/1 var(--sans); letter-spacing:.07em; text-transform:uppercase; color:var(--muted); margin-right:2px}
.fx-chip--flat b{color:var(--muted)}
.fx-pairshelf-head{font:700 11.5px/1 var(--sans); letter-spacing:.07em; text-transform:uppercase; margin-bottom:3px}
.fx-pairshelf-head--bull{color:var(--bull)}
.fx-pairshelf-head--bear{color:var(--bear)}
.fx-pairshelf-note{font:12.5px/1.45 var(--sans); color:var(--muted); margin-bottom:11px}
.fx-pairlist{display:grid; grid-template-columns:1fr 1fr; gap:8px}
.fx-pair{display:flex; flex-direction:column; gap:3px; padding:9px 11px; border-radius:8px; background:var(--quote-bg); border:1px solid var(--rule)}
.fx-pair-nm{font:600 13px/1 var(--sans); color:var(--ink)}
/* the pair's score is the data on this board, so it is not the smallest text on the page */
.fx-pair-sp{font:13px/1.1 var(--sans); color:var(--muted)}
.fx-pair--bull .fx-pair-sp{color:var(--bull)}
.fx-pair--bear .fx-pair-sp{color:var(--bear)}
/* clickable pair tiles — open the per-pair chart overlay */
button.fx-pair{margin:0; width:100%; text-align:left; font-family:inherit; cursor:pointer; position:relative; transition:border-color .12s, box-shadow .12s, transform .04s}
button.fx-pair::after{content:"\203A"; position:absolute; top:8px; right:11px; font:600 14px/1 var(--sans); color:var(--muted-2); opacity:.55; transition:opacity .12s, transform .12s}
button.fx-pair:hover{box-shadow:0 1px 6px rgba(var(--shadow-tint),.08)}
button.fx-pair:hover::after{opacity:1; transform:translateX(2px)}
button.fx-pair--bull:hover{border-color:var(--bull)}
button.fx-pair--bull:hover::after{color:var(--bull)}
button.fx-pair--bear:hover{border-color:var(--bear)}
button.fx-pair--bear:hover::after{color:var(--bear)}
button.fx-pair:active{transform:translateY(1px)}
/* an instruction, not a link — the leading glyph keeps it from reading as one */
.fx-pair-hint{color:var(--gold-ink)}
.fx-pair-hint::before{content:"\203A\00a0"}
.fx-empty{font:italic 13px/1.5 var(--sans); color:var(--muted); margin:2px 0 0}
.fx-method{margin:16px 0 0}
/* read, not fine print: it is the one place the page says how a score is made */
.fx-method p{font:13.5px/1.55 var(--sans); color:var(--muted); margin:.4em 0; max-width:64ch}
.fx-method strong{color:var(--ink)}
.fx-rate-wrap{overflow-x:auto}
/* Shown only where the ledger actually has to scroll, so the clipped edge is announced
   rather than discovered. Hidden from AT above the breakpoint via display:none. */
.fx-rate-scroll{display:none; font:italic 13px/1.5 var(--serif); color:var(--muted); margin:9px 0 0}
/* ledger numerals: aligned figures across every FX data surface (font: shorthand resets variant-numeric, so set it per element) */
.fxmap-meta,.fx-count,.fx-chip,.fx-chip b,.fx-pair-sp,.fx-pair-nm,.fx-rate-table{font-variant-numeric:tabular-nums lining-nums}
/* Borders are drawn per cell (right + bottom; the header row and the first column close the top
   and left) because the currency column is sticky, and in a collapsed table the borders belong
   to the table: a stuck cell would slide over the ledger without its own edge. On a phone the
   ledger scrolls sideways, and until 2026-09-14 it took each row's currency with it. */
.fx-rate-table{border-collapse:separate; border-spacing:0; width:100%; font:13px/1.4 var(--sans); margin:0}
.fx-rate-table th,.fx-rate-table td{border:solid var(--rule); border-width:0 1px 1px 0; padding:8px 11px; text-align:left; white-space:nowrap}
.fx-rate-table th{border-top-width:1px}
.fx-rate-table :is(th,td):first-child{position:sticky; left:0; z-index:1; border-left-width:1px; background:var(--paper)}
.fx-rate-table th:first-child{background:var(--thead)}
/* Bank and instrument are the only wide columns; letting the two of them wrap brings the
   whole ledger inside the 760px sheet, so nothing is clipped on a desktop read. */
.fx-rate-table :is(th,td):nth-child(3),.fx-rate-table :is(th,td):nth-child(4){white-space:normal; min-width:9ch}
.fx-rate-table th{background:var(--thead); font:600 11px/1.2 var(--sans); letter-spacing:.05em; text-transform:uppercase; color:var(--muted)}
.fx-rate-cur{font-weight:700}
.fx-rate-value{background:var(--quote-bg); font-weight:600}
.fx-rate-bias{font-weight:700; text-align:right}
.fx-rate-bias--bull{color:var(--bull)}
.fx-rate-bias--bear{color:var(--bear)}
.fx-rate-bias--flat{color:var(--muted)}

/* ---- embedded market widgets (TradingView, /fx/ only — see privacy.html §6) ---- */
.tv-widget{margin:14px 0 8px}
.tv-ticker{margin:6px 0 4px}
.tv-widget .tradingview-widget-container{border:1px solid var(--rule); border-radius:10px; overflow:hidden; background:var(--card)}
/* TradingView injects `.tradingview-widget-copyright a { color:#b2b5be !important }` at
   runtime — 1.86:1 on paper, i.e. an attribution link nobody can read. !important is the
   only thing that outranks !important, and our selector is the more specific of the two.
   This is the one place in the sheet where it is warranted. */
.tv-widget .tradingview-widget-copyright,.fx-modal .tradingview-widget-copyright{font:11px/1.4 var(--sans); color:var(--muted); padding:7px 11px; text-align:right}
.tv-widget .tradingview-widget-copyright a,.fx-modal-foot a{color:var(--muted) !important; border:none; padding:5px 2px; border-radius:3px}
.tv-widget .tradingview-widget-copyright a:hover,.fx-modal-foot a:hover{color:var(--ink) !important}

/* TradingView blocked — privacy extension, DNS filter, corporate proxy. The frames never
   arrive, so hide the empty shells and print a first-party note where the data should be,
   rather than leaving a headed section standing over a gap. Toggled by the script on /fx/. */
.tv-fallback{display:none}
.no-tv .tv-widget{display:none}
.no-tv .fx-pair-hint{display:none}
.no-tv .tv-fallback{display:block; margin:14px 0 8px; padding:15px 18px; border:1px solid var(--rule);
  border-radius:10px; background:var(--quote-bg); font:14px/1.55 var(--sans); color:var(--muted)}
.no-tv .tv-fallback strong{color:var(--ink)}

/* TradingView not asked for yet. The embeds set third-party cookies, so they stay unbuilt
   until the reader clicks — which means this ask, not the frame, is what the page renders
   first. Styled as the fallback note above is: same first-party furniture, so a reader who
   meets both never has to work out which one is the site talking. Toggled pre-paint by the
   bootstrap at the top of fx.html (tv-ask / tv-ok on <html>). */
.tv-consent,.tv-revoke{display:none}
.tv-ask .tv-consent{display:block; margin:14px 0 8px; padding:15px 18px; border:1px solid var(--rule);
  border-radius:10px; background:var(--quote-bg); font:14px/1.55 var(--sans); color:var(--muted)}
.tv-ask .tv-consent p{margin:.55em 0; max-width:60ch}
.tv-ask .tv-consent p:first-child{margin-top:0}
.tv-ask .tv-consent p:last-child{margin-bottom:0}
.tv-ask .tv-consent strong{color:var(--ink)}
.tv-consent-note{font-size:12.5px}
.tv-consent code{font:11.5px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace; background:var(--card); border:1px solid var(--rule); border-radius:4px; padding:1px 5px}
/* The ticker has no ask of its own, at any width. On a phone its bar came to 162px of
   permission copy between the masthead and the board the reader opened the page for; on a
   desktop (until 2026-09-14) its first words, "Live prices are off.", were the first line under
   the masthead, above the page's own h1. Nothing is lost: the dek says live prices come from
   TradingView, and the calendar card further down asks once for all three embeds with the full
   explanation beside its button. Only the unconsented state is hidden, so a reader who has
   said yes still gets the tape at the top of the page. */
.tv-ask .tv-ticker{display:none}
/* attribution for a frame that was never built reads as a credit for nothing */
.tv-ask .tv-widget .tradingview-widget-copyright{display:none}
.tv-ok .tv-revoke{display:block; margin:6px 0 18px; font:12.5px/1.5 var(--sans); color:var(--muted)}

.tv-consent-btn,.tv-revoke-btn{appearance:none; cursor:pointer; font:600 12.5px/1 var(--sans);
  letter-spacing:.06em; color:var(--ink); background:var(--card); border:1px solid var(--rule);
  border-radius:8px; padding:9px 14px; transition:border-color .14s, color .14s}
.tv-consent-btn:hover,.tv-revoke-btn:hover{border-color:var(--gold); color:var(--gold-ink)}
.tv-consent-btn:active,.tv-revoke-btn:active{transform:translateY(1px)}
.tv-revoke-btn{font-size:11.5px; padding:6px 10px; color:var(--muted)}
/* inside the pair overlay the surrounding copy is italic serif; the control is not */
.fx-modal-empty .tv-consent-btn{margin-top:6px}

/* per-pair chart overlay (TradingView Advanced Chart) — a native <dialog>: the platform
   supplies the focus trap, Escape handling and focus restore; ::backdrop dims the sheet */
.fx-modal{flex-direction:column; width:min(960px,calc(100vw - 48px)); height:min(78vh,720px); padding:0;
  background:var(--card); border:1px solid var(--rule); border-radius:12px;
  box-shadow:0 18px 60px rgba(var(--shadow-tint),.35); overflow:hidden; color:inherit}
.fx-modal[open]{display:flex}
.fx-modal::backdrop{background:rgba(var(--shadow-tint),.55); -webkit-backdrop-filter:blur(2px); backdrop-filter:blur(2px)}
.fx-modal-head{display:flex; align-items:center; justify-content:space-between; gap:12px; padding:12px 16px; border-bottom:1px solid var(--rule)}
.fx-modal-title{font:700 15px/1 var(--sans); letter-spacing:.03em; color:var(--ink)}
/* The pair's read in words ("Bull +8/10"), coloured as on the tile it came from. It replaced a
   3px bull/bear stripe along the panel's top edge, which said the direction in colour alone. */
.fx-modal-dir{margin-left:10px; font:600 13px/1 var(--sans); color:var(--muted); font-variant-numeric:tabular-nums lining-nums}
.fx-modal[data-dir="bull"] .fx-modal-dir{color:var(--bull)}
.fx-modal[data-dir="bear"] .fx-modal-dir{color:var(--bear)}
.fx-modal-x{appearance:none; width:30px; height:30px; border-radius:8px; border:1px solid var(--rule); background:var(--quote-bg); color:var(--muted); font:13px/1 var(--sans); cursor:pointer}
.fx-modal-x:hover{color:var(--ink); border-color:var(--gold)}
.fx-modal-body{flex:1; min-height:0}
.fx-modal-body .tradingview-widget-container,.fx-modal-body .tradingview-widget-container__widget{height:100%; width:100%}
.fx-modal-foot{font:11px/1.4 var(--sans); color:var(--muted); padding:6px 14px; text-align:right; border-top:1px solid var(--rule)}
/* No chart in the panel — either the reader has not asked for TradingView yet, or the
   embed was blocked. Either way say so in first-party copy and let the panel shrink to the
   message instead of framing 700px of nothing.
   `fit-content`, not `auto`: a <dialog> is fixed with both block insets at 0, and an auto
   height makes that box STRETCH to the viewport rather than centre — the panel came out
   856px tall for two lines of text, taller than the 702px it caps at with a chart in it.
   A fit-content height is definite enough that the UA's `margin:auto` centres it again. */
.fx-modal:has(.fx-modal-empty){height:fit-content}
.fx-modal-empty{display:flex; flex-direction:column; justify-content:center; padding:26px 30px; text-align:center}
.fx-modal-empty p{font:italic 16px/1.55 var(--serif); color:var(--muted); margin:.35em 0; max-width:44ch; margin-inline:auto; text-wrap:pretty}
.fx-modal-empty strong{font-style:normal; color:var(--ink)}

@media (max-width:560px){
  .fx-board,.fx-pairs{grid-template-columns:1fr}
  .fx-modal{width:calc(100vw - 24px); height:82vh}
  /* below this width the ledger genuinely has to scroll — announce it */
  .fx-rate-scroll{display:block}
}

/* ---- dark edition: the plates ----
   Post cards come out of the dashboard's headless export baked light, one file, no dark
   twin — on navy they arrive as lit panels. A hairline and ~8% off the brightness seats
   them on the sheet the way a plate sits on newsprint; hover returns the file untouched,
   so nothing is permanently dimmed and no image is ever read through a filter that hides
   detail. Deliberately NOT `invert()`: these are candles read by colour, and inverting
   them turns every up-day red.

   `.plate` is exempt because it needs no correction: the /dashboard/ screenshots are shot
   twice, in the app's own light and dark themes, and the rule below picks the right one. */
[data-theme="dark"] :is(.post-body,.board,.lead-figure) img:not(.plate){filter:brightness(.92)}
@media (prefers-reduced-motion:no-preference){
  /* box-shadow is restated because .board img already animates it above and this
     later, more specific rule would otherwise replace that transition outright. */
  [data-theme="dark"] :is(.post-body,.board,.lead-figure) img:not(.plate){transition:filter .2s ease, box-shadow .25s ease}
}
[data-theme="dark"] :is(.post-body,.board,.lead-figure) img:not(.plate):hover{filter:none}

/* Two plates per figure, one per edition (see _includes/board.html). `display:none` is
   load-bearing twice over: it keeps the plate that isn't showing out of the accessibility
   tree, so the shared alt text is never announced twice — and, because a display:none
   image is never in the viewport, it stops `loading="lazy"` from ever fetching it. The
   page therefore still downloads exactly one set of screenshots, as it always did.
   No-JS readers get the light plates, which is right: without JS no data-theme is set
   and the sheet stays light too.

   All three are written through `.board` on purpose: `.board img` already sets
   display:block, and a bare `.plate-dark` loses to it on specificity — which shows up as
   both editions stacked on the light sheet. */
.board .plate-dark{display:none}
[data-theme="dark"] .board .plate-light{display:none}
[data-theme="dark"] .board .plate-dark{display:block}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{transition-duration:.01ms !important; animation-duration:.01ms !important}
}

/* ---- the cover -----------------------------------------------------------
   Only the home page widens. The 760px measure is set on `body` (see the body rule
   at the top of this file), not on a wrapper, so the cap is lifted here and handed
   back to the masthead and the footer: the cover steps out from under a narrow head,
   which is the broadsheet gesture, not an oversight. Every other page renders a
   byte-identical <body> tag and is untouched. */
body.wide-page{max-width:none}
body.wide-page .site-head,
body.wide-page .site-foot{max-width:760px; margin-inline:auto}
body.wide-page main.wide{max-width:1080px; margin-inline:auto}

.front-grid{display:grid; grid-template-columns:minmax(0,1fr) 300px; gap:0 48px; align-items:start; margin-top:8px}
.front-main{min-width:0}

/* lead story */
.lead{padding-bottom:20px; border-bottom:1px solid var(--rule); margin-bottom:20px}
.lead-figure{margin:0 0 13px}
/* 16:9, because a Weekly Tape lead is now a title card with its headline set into the
   lower half of the image — the old 2:1 crop from the top ate exactly that. The Ledger's
   chart cards (1200x1036) crop acceptably at 16:9 too, in fact better than at 2:1, so one
   rule serves both editions and no per-edition branch is needed. */
/* the plate is a link to its story (index.html) — block so the whole picture is the hit
   area, border:none so the global gold underline on <a> does not rule under it */
.lead-figure a{display:block; border:none}
.lead-figure img{display:block; width:100%; aspect-ratio:16/9; object-fit:cover; object-position:top;
  margin:0; border:1px solid var(--rule); border-radius:10px; box-shadow:0 1px 16px rgba(var(--shadow-tint),.10)}
/* A chart card in the lead slot (index.html sets this when the image is a <slug>/cards/
   plate). No 16:9 crop: a chart is read, not framed, and cropping it cuts the data. */
.lead-figure-plate img{aspect-ratio:auto; height:auto; object-fit:contain}
/* an h2 set as a headline — resets the section-opener chrome the global h2 carries */
.lead-head{margin:.1em 0 0; padding-top:0; border-top:none; font-weight:400; letter-spacing:normal}
.lead-head::before{content:none}
.lead-head .post-link{display:inline-block; font:600 clamp(29px,3.2vw,39px)/1.08 var(--serif);
  letter-spacing:-.5px; color:var(--ink); border:none; text-wrap:balance}
.lead-head .post-link:hover{color:var(--gold-ink)}
.lead-dek{margin:.4em 0 0; color:var(--muted); font-style:italic; line-height:1.5; max-width:58ch}
.lead-second{border-bottom:2px solid var(--rule-strong); padding-bottom:22px; margin-bottom:26px}
.lead-second .lead-head .post-link{font-size:clamp(21px,1.9vw,25px); line-height:1.24; letter-spacing:-.2px}
.lead-second .lead-dek{font-size:16px}

/* the two strands */
.strands{display:grid; grid-template-columns:1fr 1fr; gap:34px}
/* Empty-Ledger cover: one strand, full width, rather than a headed empty column. */
.strands-single{grid-template-columns:1fr}
.strand{min-width:0; display:flex; flex-direction:column}
.strand-list{list-style:none; padding:0; margin:4px 0 0}
.strand-list li{padding:13px 0; border-top:1px solid var(--rule)}
.strand-list li:first-child{border-top:none}
/* no dek here on purpose: dropping it is what lets eight entries occupy the height four
   took on the old single ladder */
.strand-list .post-link{display:inline-block; margin:.14em 0 0; font:600 19px/1.24 var(--serif);
  color:var(--ink); border:none; text-wrap:balance}
.strand-list .post-link:hover{color:var(--gold-ink)}
/* The two columns rarely hold the same number of wrapped headlines, so the feet would
   otherwise sit at different heights — on a page whose argument is column discipline,
   that reads as an accident. Flex + auto margin pins both hub links to a shared baseline. */
.strand .more-issues{margin-top:auto; padding-top:12px; border-top-width:1px}
.front-foot{margin-top:34px}

/* the cover folds down before the sheet does: rail under the strands, then one column */
@media (max-width:939px){
  .front-grid{grid-template-columns:minmax(0,1fr); gap:34px}
}
@media (max-width:600px){
  .strands{grid-template-columns:1fr; gap:26px}
}

/* the rail: FX standing + dashboard block */
.rail{min-width:0}
.rail-block + .rail-block{margin-top:30px}
.rail-meta{font:12.5px/1.4 var(--sans); color:var(--muted); margin:9px 0 11px}
.rail .fx-chips + .fx-chips{margin-top:7px}
.rail .fx-chip{font-size:12.5px; padding:7px 10px}
.rail-lede{font:15px/1.5 var(--serif); color:var(--muted); margin:12px 0 0; max-width:none}
.rail-lede strong{color:var(--ink)}
/* the plate is furniture here, not a plate on a product page: no bleed, tighter caption */
.rail .board{margin:12px 0 0}
.rail .board figcaption{font-size:13px; margin-top:8px; text-align:left}
.rail .more-issues{margin-top:14px; padding-top:11px; border-top-width:1px}

/* below the fold-down the rail is a full-width footer band, so its two blocks sit
   side by side instead of stacking into a second long ladder */
@media (max-width:939px) and (min-width:601px){
  .rail{display:grid; grid-template-columns:1fr 1fr; gap:34px; align-items:start}
  .rail-block + .rail-block{margin-top:0}
}

/* "On video" — a linked-out card, never an embed. The whole card is the anchor, so it
   resets the global link chrome; the thumbnail is a committed copy, which is what keeps
   the cover at zero third-party requests. */
.rail-video .video-card{display:block; color:inherit; border:none; margin-top:12px}
.video-shot{position:relative; display:block}
.video-shot img{display:block; width:100%; margin:0; border:1px solid var(--rule); border-radius:10px; filter:grayscale(1)}
/* The still is set in grey and takes its colour back only when the reader reaches for the
   card. It is a thumbnail made for a YouTube feed, and in full colour it was the loudest thing
   on the cover: neon type brighter than the lead story beside it, on a paper whose one accent
   is gold. Grey rather than a gold duotone, because gold is the slot the desk's own signal
   sits in. The dark edition adds the plates' usual dim here, since the plate rule above no
   longer lists .video-shot: one selector cannot carry both filters. */
[data-theme="dark"] .video-shot img{filter:grayscale(1) brightness(.92)}
.video-card:is(:hover,:focus-visible) .video-shot img{filter:none}
.video-play{position:absolute; inset:0; display:flex; align-items:center; justify-content:center}
/* White, not --paper: this sits on a photograph, not on the sheet, so it must stay light
   in both editions — in the dark one --paper is navy and the glyph would vanish. */
.video-play svg{width:54px; height:54px; fill:#fff; filter:drop-shadow(0 1px 7px rgba(0,0,0,.55))}
.rail-video .post-dateline{margin-top:10px}
.video-title{display:block; margin-top:2px; font:600 17px/1.28 var(--serif); color:var(--ink); text-wrap:balance}
.video-card:hover .video-title{color:var(--gold-ink)}
@media (prefers-reduced-motion:no-preference){
  .video-shot img{transition:filter .25s ease}
  .video-play svg{transition:transform .12s ease}
  .video-card:hover .video-play svg{transform:scale(1.08)}
}
