/* ==========================================================================
   newsletter.css - self-contained stylesheet for the light-ground newsletter
   surfaces (archive index and issue article). Ported from the approved
   design mockup, docs/design/2026-08-27-newsletter-surfaces/direction-chosen.html
   (the "Said and Unsaid" chosen blend). Does not @import or otherwise depend
   on site.css - site.css is dark-only (color-scheme: dark at :root) and its
   own header records light mode as a dropped design call; these routes are a
   scoped light-ground amendment carried in their own sheet instead. See the
   SCOPE note in site.css's header comment.

   Deviations from the mockup, all deliberate:
     - Harness chrome (.harness*, .h-btn) dropped - mockup furniture only.
     - @font-face block added at the top (mockup loaded fonts via Google
       Fonts CDN + Tailwind CDN; this site self-hosts, per site.css's form).
     - color-scheme: light added to :root - the scoped amendment itself.
     - Tailwind utility classes in the footer markup (flex, flex-col, gap-4,
       flex-wrap, gap-6) replaced with real rules on .footer-light .wrap and
       .fnav - the Tailwind CDN does not ship here.
     - .empty-light code added - the mockup set the Weekly Tool <code> font
       with an inline style= attribute, which verify.py C13 forbids.
     - .sources-block summary given an explicit min-height:44px alongside
       its existing padding, per decision.md section 8's 44px tap-target
       floor.
   ========================================================================== */

/* --- Faces. Self-hosted; no external runtime dependency. ------------------ */
@font-face { font-family:'Inter Tight'; font-weight:600; font-display:swap; src:url('fonts/InterTight-600.woff2') format('woff2'); }
@font-face { font-family:'Inter Tight'; font-weight:700; font-display:swap; src:url('fonts/InterTight-700.woff2') format('woff2'); }
@font-face { font-family:'Inter Tight'; font-weight:800; font-display:swap; src:url('fonts/InterTight-800.woff2') format('woff2'); }
@font-face { font-family:'Inter';       font-weight:400; font-display:swap; src:url('fonts/Inter-400.woff2') format('woff2'); }
@font-face { font-family:'Inter';       font-weight:600; font-display:swap; src:url('fonts/Inter-600.woff2') format('woff2'); }
@font-face { font-family:'IBM Plex Mono'; font-weight:400; font-display:swap; src:url('fonts/IBMPlexMono-400.woff2') format('woff2'); }
@font-face { font-family:'IBM Plex Mono'; font-weight:500; font-display:swap; src:url('fonts/IBMPlexMono-500.woff2') format('woff2'); }
@font-face { font-family:'Newsreader'; font-style:normal; font-weight:400; font-display:swap; src:url('fonts/Newsreader-400.woff2') format('woff2'); }
@font-face { font-family:'Newsreader'; font-style:normal; font-weight:500; font-display:swap; src:url('fonts/Newsreader-500.woff2') format('woff2'); }
@font-face { font-family:'Newsreader'; font-style:italic; font-weight:400; font-display:swap; src:url('fonts/Newsreader-400i.woff2') format('woff2'); }
@font-face { font-family:'Newsreader'; font-style:italic; font-weight:500; font-display:swap; src:url('fonts/Newsreader-500i.woff2') format('woff2'); }


/* ==========================================================================
   TOKENS - copied VERBATIM from direction-c.html, which itself derives them
   from site/site.css tier-1 primitives. No new hues invented anywhere in
   this file; every color below traces to one of these variables.
   ========================================================================== */
:root{
  /* Scoped amendment, decision.md section 10: these routes are a light
     ground by approved design. site.css sets color-scheme: dark at its own
     :root for the rest of the (dark-only) site; this sheet is self-contained
     and does not touch that - it sets its own color-scheme here instead. */
  color-scheme: light;

  /* --- Dark-island primitives, copied verbatim from site.css tier 1. --- */
  --d-bg:#05080F;
  --d-ink:#F0F4FA;
  --d-dim:#9AAAC4;
  --d-line: rgba(255,255,255,.11);
  --d-line-2: rgba(255,255,255,.16);
  --d-primary:#60D8EE;
  --d-accent:#A78BFF;
  --d-badge-bg: rgba(96,216,238,.12);
  --d-badge-border: rgba(96,216,238,.35);

  /* --- Light-ground tokens, re-derived by Direction C, reused unchanged. --- */
  --paper: #F2F6FB;
  --paper-deep: #E7ECF5;
  --ink: #0C1629;
  --ink-body: #464E5E;
  --ink-dim: #5D6780; /* DESIGN REVIEW FIX: was #6E7890 (3.7-4.1:1 on paper/paper-deep,
    fails WCAG AA 4.5:1 for the small meta/mono text it's used on - dates, source
    urls, footer fine print). Darkened within the same hue to 5.2:1 on --paper and
    4.8:1 on --paper-deep. */
  --cyan: #60D8EE;
  --violet: #A78BFF;
  --violet-ink: #6B4FD8;

  --hairline: rgba(12,22,41,.13);
  --hairline-strong: rgba(12,22,41,.24);

  /* REVISION 2: the third section ground, per revision.md 3.3. Derived by
     mixing site.css's own --cy-navy (#0C1629, aliased as --ink above) with
     --cy-cyan (#60D8EE) at 80/20 - a tint of navy toward cyan, no new hue.
     Checked with a script (not by eye) against the text colors it actually
     carries: --d-ink 10.36:1, --d-dim 4.86:1, --cyan-as-accent 6.84:1 - all
     clear of WCAG AA. Luminance is ~17x the dark block's (#05080F), so the
     two read as distinct grounds rather than "two dark sections". */
  --blue-bg: #1D3D50;

  /* REVISION 4: the Tool section's ground, changed from a light lavender to
     a DEEP BLUE on Chris's instruction. Derived by mixing --cy-navy (#0C1629)
     with --cy-cyan (#60D8EE) at 90/10 - the same "known token tinted toward a
     known accent" recipe as --blue-bg, so it invents no new hue; it is simply
     a deeper stop on the same navy-to-cyan line that produced the money blue.
     Chosen from four candidates by computed luminance so it reads as its OWN
     ground rather than collapsing into either neighbour: 1.30:1 against the
     money blue (#1D3D50) and 1.35:1 against the dark block (#05080F), which
     is about equidistant. #0C1629 was rejected at 1.11:1 against the dark
     block - too close to read as different. Carries --paper text at 13.68:1,
     far clear of AA. */
  --tool-bg: #14293D;

  --s-2:8px; --s-3:12px; --s-4:16px; --s-5:24px; --s-6:40px; --s-7:64px; --s-8:96px;
  --ease: cubic-bezier(.16,1,.3,1);

  /* DESIGN REVIEW FIX: shared reading measure, used to center the article's
     body-copy column (prose, numbered sections, pullquote, empty state) AND
     its kicker as one aligned unit, instead of a left-flush column stranded
     in a wide wrap. See .section-light:not(.arc-list) rules below. */
  --measure: 44rem;

  /* REVISION 2: "ground tokens" - the text/rule colors every section-level
     component (.kicker, .prose-light, .prose-numbered, .signal) reads
     through, rather than hardcoding var(--ink) etc. directly. Default here
     is the light-ground reading; .section-dark and .section-blue override
     these three custom properties so the SAME markup and the SAME classes
     work on all three grounds without a parallel "-dark" class for every
     text rule. */
  --gk-ink: var(--ink);
  --gk-body: var(--ink-body);
  --gk-dim: var(--ink-dim);
  --gk-accent: var(--violet-ink);
  --gk-hairline: var(--hairline);
  --gk-hairline-strong: var(--hairline-strong);
}

*,*::before,*::after{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; }
body{
  margin:0; background:var(--paper); color:var(--ink-body);
  font:400 16px/1.6 'Inter', system-ui, sans-serif;
  -webkit-font-smoothing:antialiased; text-wrap:pretty; overflow-x:hidden;
}
img{ display:block; max-width:100%; height:auto; }
h1,h2,h3{ margin:0; text-wrap:balance; }
p{ margin:0; }
ul,ol{ margin:0; padding:0; list-style:none; }
a{ color:inherit; }
:focus-visible{ outline:2px solid var(--violet-ink); outline-offset:3px; }

/* Hotfix 2026-08-28: article.py's head() emits a `.skip` link on every
   newsletter page (same accessibility pattern as site.css's own .skip),
   but this sheet never carried a matching rule - site.css is dark-only and
   deliberately not loaded here (see this file's header note), so the link
   rendered as a plain, permanently visible line of text at the very top of
   the page. Same hide-until-focus treatment as site.css's .skip, re-derived
   against this sheet's light-ground tokens. */
.skip{
  position:absolute; left:var(--s-4); top:-100px; z-index:20;
  background:var(--paper); color:var(--ink); border:1px solid var(--hairline-strong);
  padding:var(--s-2) var(--s-3); text-decoration:none;
  font:400 13px/1 'Inter', sans-serif;
  transition:top .15s var(--ease);
}
.skip:focus{ top:var(--s-4); }

.mono{ font:500 12px/1 'IBM Plex Mono', ui-monospace, monospace; letter-spacing:.14em; text-transform:uppercase; }
.wrap{ width:100%; max-width:1120px; margin-inline:auto; padding-inline:32px; }
@media (max-width:720px){ .wrap{ padding-inline:20px; } }


/* ==========================================================================
   DARK ISLAND - masthead. Values copied verbatim from site.css's .masthead /
   .brand / .badge / .nav rules, exactly as Direction C transplanted them.
   Shared chrome: it sits above both surfaces in this single mockup file,
   which is also where the first appearance of "Tronny" happens on each real
   page this represents.
   ========================================================================== */
.masthead{ position:relative; background:var(--d-bg); border-bottom:1px solid var(--d-line); }
.masthead .wrap{ display:flex; align-items:center; justify-content:space-between; gap:24px; min-height:76px; max-width:1120px; }
.brand{
  display:inline-flex; align-items:center; gap:10px;
  font:700 19px/1 'Inter Tight', sans-serif; letter-spacing:-.02em;
  color:var(--d-ink); text-decoration:none; flex:none;
}
.brand .mark{ width:24px; height:24px; border-radius:6px; flex:none; }
.badge{
  display:inline-flex; align-items:center; gap:6px; white-space:nowrap;
  font:600 11px/1 'Inter', system-ui, sans-serif;
  padding:5px 11px 5px 9px; border-radius:999px;
  background:var(--d-badge-bg); color:var(--d-primary);
  border:1px solid var(--d-badge-border);
}
.badge svg{ width:12px; height:12px; flex:none; stroke-width:1.8; }

/* REVISION 4: the badge's default cyan-on-transparent treatment is built for
   the dark masthead. In the byline block it sits on --paper, where cyan text
   measures 1.54:1 - illegible, and a truthfulness-rule element is the last
   thing that may be hard to read. On light grounds it becomes a SOLID dark
   blue pill with --paper text: 13.68:1, and it echoes the dark masthead
   island that already bridges this light page back to the site. */
.byline-block .badge{
  background:var(--tool-bg); color:var(--paper);
  border-color:transparent;
}
.nav{ display:flex; gap:28px; }
.nav a{
  font:400 14px/1 'Inter', sans-serif; color:var(--d-dim); text-decoration:none;
  padding-block:6px; border-bottom:1px solid transparent; white-space:nowrap;
  transition:color .15s var(--ease), border-color .15s var(--ease);
}
.nav a:hover{ color:var(--d-ink); }
.nav a[aria-current="page"]{ color:var(--d-ink); font-weight:600; border-bottom-color:var(--d-primary); }
.nav-toggle{ display:none; }
@media (max-width:859px){
  .masthead .wrap{ flex-direction:row; align-items:center; justify-content:space-between; gap:12px; min-height:0; padding-block:14px; }
  .nav-toggle{
    display:inline-flex; align-items:center; justify-content:center; width:44px; height:44px;
    padding:0; background:transparent; border:1px solid var(--d-line-2); color:var(--d-ink);
    cursor:pointer; flex:none;
  }
  .nav-toggle .bars{ position:relative; width:18px; height:12px; }
  .nav-toggle .bars span{ position:absolute; left:0; width:18px; height:1.5px; background:currentColor; transition:transform .2s var(--ease), opacity .2s var(--ease), top .2s var(--ease); }
  .nav-toggle .bars span:nth-child(1){ top:0; }
  .nav-toggle .bars span:nth-child(2){ top:5px; }
  .nav-toggle .bars span:nth-child(3){ top:10px; }
  .nav-toggle[aria-expanded="true"] .bars span:nth-child(1){ top:5px; transform:rotate(45deg); }
  .nav-toggle[aria-expanded="true"] .bars span:nth-child(2){ opacity:0; }
  .nav-toggle[aria-expanded="true"] .bars span:nth-child(3){ top:5px; transform:rotate(-45deg); }
  .nav{ display:none; position:absolute; top:100%; left:0; right:0; flex-direction:column; gap:0; padding-block:4px 12px; padding-inline:20px; border-top:1px solid var(--d-line); background:var(--d-bg); z-index:9; }
  #nav-toggle[aria-expanded="true"] ~ #primary-nav{ display:flex; }
  .nav a{ display:flex; align-items:center; min-height:44px; border-bottom:1px solid var(--d-line); font-size:15px; }
  .nav a:last-child{ border-bottom:none; }
}

/* ==========================================================================
   SECTION GROUNDS - light (paper), dark (#05080F, "the dark block"), and
   blue (--blue-bg). All three share the same structural rules and the same
   text/rule classes below; only the --gk-* custom properties change per
   ground. REVISION 2: spacing tightened hard here per 3.2 - Chris's
   complaint was "broken sections of text", and the fix is background
   contrast doing the separating job that whitespace used to do.
   ========================================================================== */
.kicker{
  display:inline-block; color:var(--gk-ink); margin-bottom:12px;
  padding-bottom:8px; border-bottom:2px solid var(--cyan);
}
.section-light, .section-dark, .section-blue, .section-deepblue{ border-top:1px solid var(--gk-hairline); }
.section-light:first-of-type, .section-dark:first-of-type, .section-blue:first-of-type, .section-deepblue:first-of-type{ border-top:none; }
.section-light .wrap, .section-dark .wrap, .section-blue .wrap, .section-deepblue .wrap{ padding-block:clamp(30px,4.5vh,52px); }

.section-dark{
  --gk-ink: var(--d-ink);
  --gk-body: var(--d-dim);
  --gk-dim: var(--d-dim);
  --gk-accent: var(--d-primary); /* cyan reads clearly on both grounds - see --blue-bg comment */
  --gk-hairline: var(--d-line);
  --gk-hairline-strong: var(--d-line-2);
}
.section-dark{ background:var(--d-bg); }
/* REVISION 4: both blue grounds carry --paper as their text color - the same
   white used as a BACKGROUND on the light sections - on Chris's instruction.
   This applies to heading AND body, not just the heading: body copy on blue
   was previously --d-dim (#9AAAC4), a blue-grey that read as washed out
   against the ground. Measured on the real grounds: --paper is 10.54:1 on
   --blue-bg and 13.68:1 on --tool-bg, both far clear of AA. --gk-dim stays
   the dimmer value for genuine metadata (dates, source lines), which should
   still recede. */
.section-blue, .section-deepblue{
  --gk-ink: var(--paper);
  --gk-body: var(--paper);
  --gk-dim: var(--d-dim);
  --gk-accent: var(--d-primary);
  --gk-hairline: var(--d-line);
  --gk-hairline-strong: var(--d-line-2);
}
.section-blue{ background:var(--blue-bg); }
.section-deepblue{ background:var(--tool-bg); }

/* DESIGN REVIEW FIX: at 1440 the article's body-copy column (.prose-light,
   .prose-numbered, .pullquote, .empty-light - all set to --measure below)
   was left-flush in the 1120px wrap, leaving a bare field down the right
   side of the page; the same left-flush-in-a-wide-container pattern left an
   awkward gap under the index's single remaining row (fixed separately,
   see .remaining-col). Centring the reading column - kicker included, so it
   still sits flush with the paragraph text below it rather than stranded at
   the far left - reads as a deliberate margin either side, the way a press
   column sits in a page, rather than an accident. Scoped to
   :not(.arc-list) so the index's featured-row grid (which needs the full
   1120px to hold image + divider + remaining column) is untouched, and
   extended to the dark/blue grounds added in revision 2. */
:is(.section-light:not(.arc-list), .section-dark, .section-blue, .section-deepblue, .hitl-block) > .wrap > .kicker{
  display:block; max-width:var(--measure); margin-inline:auto;
}
.hl-serif{ font-family:'Newsreader', ui-serif, Georgia, serif; }

.tlink-light{
  color:var(--gk-ink); text-decoration:none;
  border-bottom:1px solid var(--gk-hairline-strong);
  transition:border-color .15s var(--ease), color .15s var(--ease);
}
.tlink-light:hover{ border-bottom-color:var(--gk-ink); }

/* REVISION 4: on the two blue grounds a link must not be the same --paper as
   the body copy around it, or it stops reading as a link at all. Cyan carries
   it: 8.88:1 on --tool-bg, well clear of AA, and it is the accent already
   doing link duty on the dark ground. This is the fix for the build-log link
   in the Tool section, which was rendering navy-on-deep-blue at 1.22:1. */
:is(.section-blue, .section-deepblue) .tlink-light{
  color:var(--d-primary);
  border-bottom-color:rgba(96,216,238,.4);
}
:is(.section-blue, .section-deepblue) .tlink-light:hover{ border-bottom-color:var(--d-primary); }

.byline-line{ font:400 15px/1.5 'Inter', sans-serif; color:var(--ink-body); margin-top:14px; }
.byline-line b{ color:var(--ink); font-weight:600; }

/* Signal-id mechanic: accent-colored superscript numeral, reading through
   --gk-accent so it stays legible on all three grounds. Every mark points
   down to the ONE consolidated sources block at the article's foot, not to
   a per-section list. */
.signal{
  font:500 11px/1 'IBM Plex Mono', ui-monospace, monospace;
  vertical-align:super; font-size:.62em; line-height:0;
  color:var(--gk-accent); text-decoration:none; margin-left:1px;
  border-bottom:1px solid transparent;
}
.signal:hover, .signal:focus-visible{ border-bottom-color:var(--gk-accent); }

.prose-light{ color:var(--gk-body); max-width:var(--measure); margin-inline:auto; display:grid; gap:var(--s-4); font-size:16px; line-height:1.7; }
.prose-light b, .prose-light strong{ color:var(--gk-ink); font-weight:600; }

/* Task 11 fix: the numbered/list section kinds (article.py's _section())
   emit any markdown body text ahead of their structured list as bare <p>
   tags, direct children of .wrap - never wrapped in .prose-light the way
   the "prose" kind wraps its body. On the light ground that bare <p> still
   read correctly by accident (the unscoped `body{color:var(--ink-body)}`
   default happens to equal the light-ground reading), which is exactly why
   this went unnoticed until the fixture's dark-ground "What people are
   discussing" paragraph was checked against real painted pixels for the
   first time here: 2.40:1 on --d-bg. Scoped to a direct-child selector so
   it only ever touches this exact unwrapped-paragraph shape, matching
   .prose-light's own color and measure rather than inventing a new look. */
.section-dark .wrap > p, .section-blue .wrap > p, .section-deepblue .wrap > p, .section-light .wrap > p{
  color:var(--gk-body); max-width:var(--measure); margin-inline:auto; font-size:16px; line-height:1.7; margin-bottom:var(--s-4);
}

/* Sections 2 and 3: prose paragraphs with the numbering kept as a lead-in,
   replacing the one-line numbered list. Counts are still derived, not
   fixed - 3 items and 5 items both sit correctly in this structure.
   REVISION 2: li padding-block tightened from 24px to 18px per 3.2. */
.prose-numbered{ display:grid; gap:0; margin-top:var(--s-5); border-top:1px solid var(--gk-hairline); max-width:var(--measure); margin-inline:auto; }
.prose-numbered li{
  display:grid; grid-template-columns:34px 1fr; gap:16px;
  padding-block:18px; border-bottom:1px solid var(--gk-hairline);
}
.prose-numbered .n{ font:500 13px/1.7 'IBM Plex Mono', monospace; color:var(--gk-accent); }
.prose-numbered p{ color:var(--gk-body); font-size:15.5px; line-height:1.7; }

/* REVISION 3, per 3.2: per-item reaction pills on "What people are
   discussing" - a platform pill (text name, no logo) and a comment-count
   pill (comment emoji + count). Quiet metadata, not buttons: no fill, a
   hairline border, and the same --gk-dim / --gk-hairline-strong tokens
   every other ground-aware component reads through, so the pair reads
   correctly wherever prose-numbered is used. Checked against the actual
   dark ground (#05080F) they sit on today: --d-dim text is 8.51:1, clear
   of WCAG AA (4.5:1) with room to spare even at 11px. */
.prose-numbered .reaction-pills{ grid-column:2; display:flex; flex-wrap:wrap; gap:8px; margin-top:10px; }
.pill{
  display:inline-flex; align-items:center; gap:5px;
  font:500 11px/1 'IBM Plex Mono', monospace; letter-spacing:.04em;
  color:var(--gk-dim); padding:5px 10px; border-radius:999px;
  border:1px solid var(--gk-hairline-strong); background:transparent;
}
.pill-comments{ font-variant-numeric:tabular-nums; }
.pill-comments span{ font-size:11px; line-height:1; }

/* Pull-quote: italic serif, deep navy, single cyan underline beneath the
   attributed name only. "Its own treatment" per revision.md 3.3 - sits
   under the story, distinct from the light/dark/blue alternation.
   REVISION 2: margin-block tightened from --s-6 (40px) to --s-5 (24px). */
.pullquote{ max-width:56ch; margin-block:var(--s-5); margin-inline:auto; }
.pullquote p{
  font:italic 500 clamp(24px,3vw,32px)/1.35 'Newsreader', ui-serif, Georgia, serif;
  color:var(--ink); letter-spacing:-.01em;
}
.pullquote cite{
  display:inline-block; margin-top:16px; font:400 13px/1 'Inter', sans-serif;
  font-style:normal; color:var(--ink-dim);
  padding-bottom:6px; border-bottom:2px solid var(--cyan);
}

/* Empty state - Tool section. Narrower measure, more air, no border/box. */
/* REVISION 4: was max-width:46ch centered, which put its left edge inboard of
   the section kicker above it - visible now that Tool and Disconnecting both
   use it. Now it spans --measure like every other body component so the left
   edge lines up, and the 46ch reading limit moves to the paragraphs. */
.empty-light{ max-width:var(--measure); margin-inline:auto; padding-block:var(--s-4) var(--s-3); }
.empty-light p{ max-width:52ch; }
/* REVISION 4: reads the ground token rather than the hardcoded light-ground
   value, so it follows the Tool section onto the deep-blue ground instead of
   staying dark-on-dark. Same fix the other body components already had. */
.empty-light p{ color:var(--gk-body); font-size:15.5px; line-height:1.7; }
.empty-light p + p{ margin-top:14px; }
/* DEVIATION: the mockup sets this on the Weekly Tool <code> element with an
   inline style= attribute ("font-family:'IBM Plex Mono',monospace;
   font-size:.92em;"). Inline styles are forbidden - verify.py C13 fails on
   them - so the same declaration is a real rule here instead. */
.empty-light code{ font-family:'IBM Plex Mono', ui-monospace, monospace; font-size:.92em; }

/* REVISION 2 - Human in the Loop: "its own treatment" per 3.3, meaning
   neither the light/dark/blue rotation nor a bare .section-light. Uses
   --paper-deep, the SAME token already carrying the featured-media inset
   and the light-mode "deeper paper" reading elsewhere in this file - no
   new color introduced. This is also the grey-ground block the reference
   capture (shots/ref-riftdispatch-article.png) calibrates against. */
.hitl-block{ background:var(--paper-deep); border-top:1px solid var(--hairline); }
/* REVISION 3, per 4.1: header spacing now matches every other section - the
   same padding-block the .section-light/.section-dark/.section-blue wraps
   get, applied here explicitly since .hitl-block isn't part of that
   selector group (it deliberately opts out of the light/dark/blue rotation
   per revision.md 3.3, but the space above and below its header should not
   opt out along with it). */
.hitl-block .wrap{ padding-block:clamp(30px,4.5vh,52px); }
/* REVISION 3: reads through --gk-body (was hardcoded var(--ink-body)) so
   the same class works as the Microsoft-news lead (light ground) and the
   new "What people are discussing" lead (dark ground) without a second
   class. */
.section-lead{ color:var(--gk-body); max-width:var(--measure); margin-inline:auto; margin-bottom:var(--s-5); font-size:15.5px; line-height:1.7; }
.hitl-live-line{
  display:block; max-width:var(--measure); margin-inline:auto; margin-top:-14px; margin-bottom:var(--s-5);
  font:500 12px/1 'IBM Plex Mono', monospace; letter-spacing:.1em; text-transform:uppercase; color:var(--ink-dim);
}
.hitl-episode{
  max-width:var(--measure); margin-inline:auto; padding:var(--s-4) var(--s-5);
  background:var(--paper); border:1px solid var(--hairline-strong); border-left:3px solid var(--cyan);
}
.hitl-eyebrow{ display:block; font:500 12px/1 'IBM Plex Mono', monospace; letter-spacing:.1em; text-transform:uppercase; color:var(--ink-dim); margin-bottom:10px; }
.hitl-episode h3{ font:700 20px/1.3 'Inter Tight', sans-serif; letter-spacing:-.015em; color:var(--ink); margin-bottom:8px; }
.hitl-episode p{ color:var(--ink-body); font-size:15px; line-height:1.6; }
.hitl-links{ margin-top:14px; display:flex; gap:16px; flex-wrap:wrap; }
.hitl-links a{ color:var(--violet-ink); font:600 14px/1 'Inter', sans-serif; text-decoration:none; border-bottom:1px solid transparent; }
.hitl-links a:hover{ border-bottom-color:var(--violet-ink); }

/* REVISION 2 - Microsoft news this past week (4.4). Deliberately denser and
   more list-like than the prose sections - "a sweep rather than an
   argument", per revision.md. */
.ms-news-list{ display:grid; gap:0; margin-top:var(--s-4); border-top:1px solid var(--hairline); max-width:var(--measure); margin-inline:auto; }
.ms-news-list li{ display:grid; grid-template-columns:100px 1fr; gap:16px; padding-block:14px; border-bottom:1px solid var(--hairline); }
@media (max-width:560px){
  .ms-news-list li{ grid-template-columns:1fr; gap:4px; }
}
.ms-news-list time{ font:500 12px/1.5 'IBM Plex Mono', monospace; color:var(--ink-dim); padding-top:2px; }
.ms-news-list h3{ font:600 15.5px/1.4 'Inter', sans-serif; color:var(--ink); margin-bottom:4px; }
.ms-news-list h3 a{ text-decoration:none; border-bottom:1px solid transparent; }
.ms-news-list h3 a:hover{ color:var(--violet-ink); border-bottom-color:var(--violet-ink); }
.ms-news-list p{ color:var(--ink-body); font-size:14px; line-height:1.55; }

/* Consolidated sources block - one <details>, closed on load, at the foot
   of the article. Sources are URLs, never signal ids, in this block. */
.sources-block{ border-top:1px solid var(--hairline-strong); padding-block:var(--s-5); }
.sources-block summary{
  cursor:pointer; list-style:none; display:flex; align-items:center; gap:10px;
  font:500 12px/1 'IBM Plex Mono', monospace; letter-spacing:.14em; text-transform:uppercase;
  color:var(--ink);
  /* DESIGN REVIEW FIX: was a 14px-tall hit target (line-height:1, no
     padding) - the only tap-to-expand control on the article page. Padding
     brings the tappable row to 44px; the small margin pull-up keeps the
     block's visual position close to unchanged rather than pushing the
     source list further down the page. */
  padding-block:15px; margin-top:-9px; margin-bottom:-6px;
  /* DEVIATION, decision.md section 8: the mockup's own comment above states
     the padding brings this row to 44px, but does not assert it as a floor.
     Stated explicitly here so the tap target cannot drift below 44px if the
     font or padding above is ever edited without checking the math again. */
  min-height:44px;
}
.sources-block summary::-webkit-details-marker{ display:none; }
.sources-block summary::before{ content:'+'; font-size:14px; color:var(--violet-ink); width:1em; }
.sources-block[open] summary::before{ content:'-'; }
.sources-block summary:hover{ color:var(--violet-ink); }
.source-list{ margin-top:var(--s-5); display:grid; gap:14px; max-width:78ch; }
.source-list li{ font-size:13.5px; line-height:1.6; color:var(--ink-dim); padding-top:14px; border-top:1px solid var(--hairline); }
.source-list li:first-child{ border-top:none; padding-top:0; }
.source-list .src-pub{ color:var(--ink); font-weight:600; }
.source-list a{ color:var(--violet-ink); text-decoration:none; border-bottom:1px solid transparent; }
.source-list a:hover{ border-bottom-color:var(--violet-ink); }
.source-list .src-url{ display:block; margin-top:3px; font:400 11.5px/1.4 'IBM Plex Mono', monospace; color:var(--ink-dim); word-break:break-all; }

/* ==========================================================================
   ARCHIVE INDEX - header per blend.md: kicker "The archive", headline
   "Said and Unsaid". The publication name is the large element.
   ========================================================================== */
.arc-head .wrap{ padding-block:clamp(40px,6vh,72px) clamp(28px,4vh,44px); }
.arc-head h1{
  font:800 clamp(42px,7vw,80px)/0.98 'Inter Tight', sans-serif; letter-spacing:-.035em;
  color:var(--ink); margin-bottom:12px;
}
/* REVISION 2, per 2: the subtitle no longer carries the disclosure
   sentence or a literal cadence timestamp. .cadence is now the
   publication's proposition (what the newsletter is); .cadence-human is
   the human-shaped cadence line that replaces "Tuesdays, 5am ET". */
.arc-head .cadence{ font:400 15px/1.6 'Inter', sans-serif; color:var(--ink-body); max-width:56ch; }
.arc-head .cadence-human{
  font:italic 500 15px/1.5 'Newsreader', ui-serif, Georgia, serif;
  color:var(--ink-dim); max-width:56ch; margin-top:10px;
}

.arc-list{ border-top:none; }
.arc-list .wrap{ padding-top:clamp(8px,1.5vh,20px); }

/* --------------------------------------------------------------------
   Featured story block, modelled on riftdispatch.substack.com's home
   page (shots/ref-riftdispatch-home.png): large media on the left at
   roughly 45% of the content width, headline/dek/meta centered beneath
   it, a vertical hairline, then a stacked column of remaining issues to
   the right (headline, one-line dek, small-caps meta, small square
   thumbnail on the row's far right).
   -------------------------------------------------------------------- */
.featured-row{ display:grid; gap:var(--s-6); align-items:start; }
@media (min-width:860px){
  .featured-row{ grid-template-columns:45% 1px 1fr; gap:0; align-items:stretch; }
}

.featured-media{
  display:block; position:relative; aspect-ratio:4/3; background:var(--ink);
  overflow:hidden; text-decoration:none; margin-bottom:22px;
  box-shadow: inset 3px 0 0 0 var(--cyan);
}
.featured-media svg{ position:absolute; inset:0; margin:auto; opacity:.92; }

/* The 4/3 ratio above was drawn around the centered SVG placeholder, which
   was the only thing this card could hold when the design was approved -
   real hero images were a DEFER at that point. A generated hero is 16:9
   (/newsletter-image emits 1600x896, the nearest 16-divisible 16:9 the API
   accepts), so a hero dropped into a 4/3 box letterboxes against --ink and
   reads as a rendering fault. Give the card the image's own ratio only when
   it actually holds one, so cover crops nothing and the placeholder case is
   untouched. */
.featured-media:has(img){ aspect-ratio:16/9; }
.featured-media img{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
}
@media (min-width:860px){ .featured-media{ margin-right:var(--s-7); } }

.featured-title{
  text-align:center; font:700 clamp(24px,3.2vw,36px)/1.18 'Inter Tight', sans-serif;
  letter-spacing:-.02em; color:var(--ink); margin-bottom:12px;
}
.featured-title a{ text-decoration:none; }
.featured-title a:hover{ color:var(--violet-ink); }
.featured-dek{
  text-align:center; color:var(--ink-body); font-size:15.5px; line-height:1.6;
  max-width:46ch; margin-inline:auto; margin-bottom:16px;
}
/* RULING AL, 2026-08-27, superseding RULING AK: Chris chose reorder over
   shrink - "bring the headshot, Tronny, and the card under the title and
   above the image" - so the fold is bought by moving content up the card,
   not by shrinking the approved artwork (that shrink is reverted above).
   Mirrors the issue page's .author-line (.author-avatar + .author-name +
   badge, see article.py _byline) rather than the old text-only
   .featured-meta line, with the date appended - a new shape for this
   surface since the issue page carries its date in .issue-head instead. */
.featured-byline{
  display:flex; align-items:center; justify-content:center; gap:10px;
  margin-bottom:16px;
}
.featured-byline .author-avatar{ width:36px; height:36px; }
.featured-date{
  font:500 12px/1 'IBM Plex Mono', monospace; letter-spacing:.1em;
  text-transform:uppercase; color:var(--ink-dim);
}
@media (min-width:860px){
  .featured-title, .featured-dek, .featured-byline{ padding-right:var(--s-7); }
}

.featured-divider{ display:none; }
@media (min-width:860px){
  .featured-divider{ display:block; background:var(--hairline-strong); }
}

.remaining-col{ }
@media (max-width:859px){
  .remaining-col{ margin-top:8px; padding-top:var(--s-6); border-top:1px solid var(--hairline-strong); }
}
@media (min-width:860px){
  /* DESIGN REVIEW FIX: .featured-row uses align-items:stretch at this
     breakpoint so the vertical divider spans the full row height, but that
     also stretched .remaining-col to match the taller featured-media
     column, leaving all the leftover height as dead space under the single
     real row + cadence stub. Centring this column's own content within its
     stretched height turns that into a balanced margin above and below,
     instead of one large gap at the bottom. */
  .remaining-col{ padding-left:var(--s-7); display:flex; flex-direction:column; justify-content:center; }
}
.remaining-kicker{
  display:block; font:500 12px/1 'IBM Plex Mono', monospace; letter-spacing:.14em;
  text-transform:uppercase; color:var(--ink-dim); margin-bottom:var(--s-5);
}
.remaining-row{
  display:grid; grid-template-columns:1fr auto; gap:var(--s-5); align-items:start;
  padding-block:var(--s-5); border-top:1px solid var(--hairline);
}
.remaining-row:first-of-type{ border-top:none; padding-top:0; }
.remaining-row h3{
  font:700 clamp(18px,2.2vw,22px)/1.3 'Inter Tight', sans-serif; letter-spacing:-.015em;
  color:var(--ink); margin-bottom:8px;
}
.remaining-row h3 a{ text-decoration:none; }
.remaining-row h3 a:hover{ color:var(--violet-ink); }
.remaining-row .remaining-dek{ color:var(--ink-body); font-size:14.5px; line-height:1.55; margin-bottom:10px; max-width:44ch; }
.remaining-row .remaining-meta{ font:500 11.5px/1 'IBM Plex Mono', monospace; letter-spacing:.08em; text-transform:uppercase; color:var(--ink-dim); }
.remaining-thumb{
  width:56px; height:56px; flex:none; position:relative; background:var(--ink);
  overflow:hidden; box-shadow: inset 2px 0 0 0 var(--cyan);
}
.remaining-thumb svg{ position:absolute; inset:0; margin:auto; width:30px; height:auto; }

/* The honest n=2 line: one real row, then a stated cadence rather than a
   fabricated extra issue. Same tick-and-mute-label idiom Direction B used
   for its continuation stub, re-grounded for paper. */
.cadence-stub{
  display:flex; align-items:center; gap:10px; margin-top:0; padding-top:var(--s-5);
  border-top:1px solid var(--hairline);
}
.cadence-stub .stub-mark{ width:7px; height:7px; border-radius:1px; background:var(--paper-deep); border:1px solid var(--hairline-strong); flex:none; }
.cadence-stub .stub-text{ font:400 12.5px/1.4 'IBM Plex Mono', monospace; color:var(--ink-dim); letter-spacing:.02em; }

.closing-line{
  font:italic 400 17px/1.6 'Newsreader', ui-serif, Georgia, serif;
  color:var(--ink-dim); margin-top:var(--s-7); border-top:1px solid var(--hairline-strong); padding-top:var(--s-5);
  max-width:60ch;
}

/* ==========================================================================
   ISSUE ARTICLE
   ========================================================================== */

/* REVISION 2, per 3.1: the 100vh title screen is gone. Compact kicker,
   headline and dek, calibrated against shots/ref-riftdispatch-article.png
   - "into the story quickly", not a full-viewport hold. The image now
   follows immediately below (see .hero-image-section), with the byline
   row sitting between dek and image as a thin strip, matching the
   reference's kicker -> title -> dek -> byline -> image order. */
.issue-head{
  padding-block:clamp(36px,6vh,56px) 0;
  border-bottom:none;
}
/* Hotfix 2026-08-28: the title/dek block had no measure-column treatment at
   all, so it sat flush against .wrap's own 32px padding while every body
   section below centers its kicker/prose to the narrower --measure column
   (see the "DESIGN REVIEW FIX" rule further down) - two different left
   edges on the same page. .head-col is the same centered column, sized to
   --measure; h1 and .hero-dek keep their own tighter max-width for line
   wrapping, and (being plain block children with no margin of their own)
   render flush against head-col's left edge - the same edge the body
   copy's measure column resolves to. */
.head-col{ max-width:var(--measure); margin-inline:auto; }
.issue-head h1{
  font:800 clamp(34px,5.5vw,58px)/1.04 'Inter Tight', sans-serif; letter-spacing:-.03em;
  color:var(--ink); margin-bottom:16px; max-width:19ch;
}
/* REVISION 4: roman, not italic, to match the subtitle treatment on the
   archive index - they are the same voice and should not read as two
   different registers. Bottom margin added so the dek is not pressed against
   the hero image below it. */
.issue-head .hero-dek{
  font:500 clamp(17px,1.6vw,20px)/1.5 'Newsreader', ui-serif, Georgia, serif;
  color:var(--ink-body); max-width:58ch; margin-bottom:var(--s-6);
}

/* The hero image, right after the byline row now, not discovered on
   scroll. Full-bleed, dark navy panel standing in for a photograph shot
   for a light frame - cyan rim-light as a single crisp inset line, no
   blur, no radial glow (dark-ground-only device per the brief, does not
   survive the flip). REVISION 2: min-height trimmed - this was sized for
   a below-the-fold reveal, and reads as excessive immediately under a
   compact header. */
.hero-image-section{ border-bottom:1px solid var(--hairline); }
.hero-image-frame{
  position:relative; width:100%; min-height:220px; background:var(--ink);
  overflow:hidden; box-shadow: inset 3px 0 0 0 var(--cyan);
}
@media (min-width:760px){ .hero-image-frame{ min-height:360px; } }
.hero-image-frame svg{ position:absolute; inset:0; margin:auto; }
/* Task 11 fix round 1 (Ruling AL): the frame was only ever styled for the
   mockup's decorative placeholder SVG (position:absolute + margin:auto, a
   centering trick that assumes intrinsically-small art). A real per-issue
   <img> (article.py's _hero()) was unstyled here entirely, so it rendered at
   its own natural size - confirmed against site/assets/tronny-figure-cut-1024.png
   (502x916): with no constraint, that pushed the whole page down by its full
   916px height, burying the disclosure badge below the fold on every
   viewport (C8). object-fit:cover fills the frame's own min-height the same
   full-bleed way the comment above already describes for a real photograph,
   instead of the frame taking its height from whatever image happens to be
   dropped in. */
.hero-image-frame img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }

/* Author line: avatar + "Tronny" + the disclosure badge. The long
   "an AI agent directed and reviewed by Chris Shanku" sentence comes out
   of this line per blend.md - the badge itself is what stays structural,
   and the footer link (below) carries the rest. REVISION 2: this is now
   the "thin byline row" of 3.1, sitting between the dek and the hero
   image rather than after the image - padding trimmed accordingly. */
/* Hotfix 2026-08-28: this used to carry the .wrap class directly (1120px),
   its own flush-left edge one more mismatch against the --measure column
   below it. Now nested in a plain .wrap by article.py's _byline(), with
   its own width narrowed to match the same centered column as .head-col
   and the body sections' kicker/prose. */
.byline-block{
  max-width:var(--measure); margin-inline:auto;
  padding-block:var(--s-4); border-top:1px solid var(--hairline); border-bottom:1px solid var(--hairline);
  display:flex; align-items:center; justify-content:space-between; gap:var(--s-4); flex-wrap:wrap;
}
.author-line{ display:flex; align-items:center; gap:12px; }
.author-avatar{ width:44px; height:44px; border-radius:999px; flex:none; object-fit:contain; }
.author-name{ font:700 16px/1 'Inter Tight', sans-serif; color:var(--ink); }
/* REVISION 4: the two hosts, centered side by side under the episode card. */
/* REVISION 4: the index has no byline row, so after the masthead pill was
   removed this is where the AI-agent badge lives - beside the first
   appearance of the name in content, on the featured story's meta line.
   Same solid dark-blue treatment as the byline badge, scaled down to sit in
   a meta line without shouting. Keeps CLAUDE.md truthfulness rule 3 intact
   on this surface. */
.badge-sm{
  background:var(--tool-bg); color:var(--paper); border-color:transparent;
  font-size:10px; padding:3px 8px 3px 7px; margin-left:8px;
  vertical-align:middle; position:relative; top:-1px;
}
.badge-sm svg{ width:10px; height:10px; }

.hitl-hosts{
  display:flex; justify-content:center; gap:var(--s-6);
  margin-top:var(--s-5); max-width:var(--measure); margin-inline:auto;
}
.hitl-hosts figure{ margin:0; text-align:center; width:88px; }
.hitl-hosts img{ width:88px; height:88px; border-radius:999px; display:block; }
.hitl-hosts figcaption{
  margin-top:8px; font:500 12px/1.3 'IBM Plex Mono', monospace;
  letter-spacing:.06em; color:var(--ink-dim);
}
@media (max-width:420px){ .hitl-hosts{ gap:var(--s-5); } }

.issue-chip{ font:500 12px/1 'IBM Plex Mono', monospace; letter-spacing:.08em; text-transform:uppercase; color:var(--ink-dim); }

.footer-light{ border-top:1px solid var(--hairline-strong); background:var(--paper); }
/* DEVIATION: the mockup declares display:grid here, then overrides it in
   markup with Tailwind utilities (class="wrap flex flex-col gap-4") - the
   CDN utilities always won, so the effective rendered layout was a flex
   column with a 16px gap. The Tailwind CDN does not ship on this site, so
   that effective layout is written here directly instead: --s-4 is the same
   16px gap-4 supplied. .fnav below already carries real flex/flex-wrap/gap
   rules whose --s-5 (24px) matches the mockup's gap-6 utility, so no change
   was needed there. */
.footer-light .wrap{ padding-block:var(--s-6); display:flex; flex-direction:column; gap:var(--s-4); }
.footer-light .fbrand{ display:flex; align-items:center; gap:10px; font:700 17px/1 'Inter Tight', sans-serif; color:var(--ink); margin-bottom:6px; }
.footer-light .fbrand .mark{ width:22px; height:22px; border-radius:5px; }
.footer-light p{ font-size:14px; color:var(--ink-body); max-width:70ch; }
.footer-light .fine{ color:var(--ink-dim); font-size:13px; }
.footer-light .fnav{ display:flex; gap:var(--s-5); flex-wrap:wrap; padding-top:var(--s-4); border-top:1px solid var(--hairline); }
.footer-light .fnav a{ font-size:14px; color:var(--ink-body); text-decoration:none; }
.footer-light .fnav a:hover{ color:var(--ink); }

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

[hidden]{ display:none!important; }
