/* RELATIVE URL WARNING — these stylesheets live in site/css/, so every url() must be written
   ../assets/... , not assets/... . The rules were extracted from index.html on 2026-08-14 where
   assets/ resolved against the PAGE; in a stylesheet it resolves against the STYLESHEET, which
   silently 404'd all eight platform icons. If you move this file, re-check every url(). */

/* ============================================================================================
   ITG PRIMITIVES — the reusable pieces: buttons, eyebrow, cards, pills, icons, media.
   Depends on tokens.css. Load AFTER it, BEFORE blocks.css.
   Extracted from index.html 2026-08-14 verbatim, so the home renders identically.
   ============================================================================================ */

*{box-sizing:border-box;}

html,body{margin:0;padding:0;background:#04060a;}

::selection{background:#96ff00;color:#04060a;}

@keyframes itgGlowPulse{0%,100%{opacity:.55;}50%{opacity:.85;}}

@keyframes itgFloat{0%,100%{transform:translateY(0);}50%{transform:translateY(-10px);}}

@keyframes itgVideoWipe{0%{transform:translateX(-200%) scaleX(0.7);}50%{transform:translateX(230%) scaleX(2);}100%{transform:translateX(680%) scaleX(0.7);}}

@keyframes itgHoloGlitch{
    0%,88%,100%{transform:translateY(-50%) translateX(0);clip-path:none;border-color:rgba(150,255,0,0.9);}
    89%{transform:translateY(-50%) translateX(-2px);clip-path:inset(0 0 55% 0);border-color:rgba(54,236,255,0.9);}
    90%{transform:translateY(-50%) translateX(2px);clip-path:inset(55% 0 0 0);}
    91%{transform:translateY(-50%) translateX(-1px);clip-path:none;border-color:rgba(150,255,0,0.9);}
    93%{transform:translateY(-50%) translateX(1px);}
    94%{transform:translateY(-50%) translateX(0);}
  }

@keyframes itgSolidFlick{0%,100%{box-shadow:0 0 22px rgba(150,255,0,0.55);}92%{box-shadow:0 0 22px rgba(150,255,0,0.55);}94%{box-shadow:0 0 10px rgba(54,236,255,0.7);filter:hue-rotate(40deg);}96%{box-shadow:0 0 22px rgba(150,255,0,0.55);filter:none;}}

@keyframes itgScan{0%,100%{opacity:1;transform:scaleX(1);}50%{opacity:.7;transform:scaleX(0.97);}90%{opacity:1;}92%{opacity:.4;transform:translateX(2px);}94%{opacity:1;transform:translateX(0);}}

@keyframes itgTextGlitch{
    0%{text-shadow:-3px 0 #36ecff,3px 0 #ff2e6e;transform:translate(-2px,0) skewX(-6deg);clip-path:inset(0 0 60% 0);}
    25%{text-shadow:3px 0 #36ecff,-3px 0 #ff2e6e;transform:translate(2px,1px);clip-path:inset(50% 0 0 0);}
    50%{text-shadow:-3px 0 #96ff00,3px 0 #36ecff;transform:translate(-1px,-1px) skewX(4deg);clip-path:inset(20% 0 30% 0);}
    75%{text-shadow:2px 0 #ff2e6e,-2px 0 #36ecff;transform:translate(1px,0);clip-path:none;}
    100%{text-shadow:none;transform:translate(0,0);clip-path:none;}
  }

/* episode card: no border, no cyan glow — soft shadow lifts it on hover (2026-08-13, Nico)
   `.epcard` shares this SELECTOR rather than copying the values (2026-08-17): the home's dc markup
   carries .glowcard, episodes.html carries .epcard, and a copied shadow is how the two drifted
   apart in the first place. One rule, two entry points. Navy shadow, not black: these lift off the
   white band. */
  .glowcard,.epcard{position:relative;box-shadow:none;transition:transform .25s,box-shadow .3s cubic-bezier(.22,1,.36,1);}

.glowcard:hover,.epcard:hover{box-shadow:0 16px 38px rgba(15,53,87,0.22),0 4px 12px rgba(15,53,87,0.12);}

@keyframes cmIn{from{clip-path:inset(0 100% 0 0);}to{clip-path:inset(0 0 0 0);}}

@keyframes cmOut{from{clip-path:inset(0 0 0 0);}to{clip-path:inset(0 0 0 100%);}}

/* hover was 700 -> 900 (Black): +7.8px width jump and closed counters at 16px inverted.
     Both states now 700 + matched tracking, so the wipe is purely chromatic. (2026-08-13, Nico) */
  .cmeta{position:relative;display:inline-block;color:#96ff00;font-weight:700;letter-spacing:.015em;padding:2px 6px;margin-left:-6px;white-space:nowrap;}

.cmeta::after{content:attr(data-meta);position:absolute;left:0;top:0;padding:2px 6px;background:#96ff00;color:#04060a;font-weight:700;letter-spacing:.015em;white-space:nowrap;clip-path:inset(0 100% 0 0);pointer-events:none;}

.cmeta.cm-in::after{animation:cmIn .26s cubic-bezier(.22,1,.36,1) forwards;}

.cmeta.cm-out::after{animation:cmOut .26s cubic-bezier(.22,1,.36,1) forwards;}

/* ── platform icons ── */
    .plt-link{display:flex;flex-direction:column;align-items:center;gap:14px;text-decoration:none;width:132px;}

/* ══ MASKED MARK, shared plumbing ══ (2026-08-14, audit) ════════════════════════════════
   This eight-line block was written THREE times: .plt-icon here, .host-ico-i in blocks.css and
   .ft-soc-i in footer.css. Every mark on the site is drawn the same way — a solid box masked by
   an SVG, so the colour is exact at rest and on hover — so the plumbing belongs in one rule and
   each mark keeps only its own mask-image, box and colour.
   It must stay ABOVE the per-mark rules below: several override mask-size (auto 46px, 46px 46px,
   auto 38px) and rely on source order to beat this `contain`. No url() here on purpose, which is
   also why this rule can safely serve .ft-soc-i, whose masks are root-relative in footer.css. */
    .plt-icon,.host-ico-i,.ft-soc-i{
      display:block;
      -webkit-mask-position:center;mask-position:center;
      -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
      -webkit-mask-size:contain;mask-size:contain;
    }

/* all icon boxes same height (52px) so labels align; width varies per brand.
       background-* stays here, not in the shared rule: only .plt-icon swaps its mask for a real
       background-image on hover. */
    .plt-icon{width:52px;height:52px;background-color:rgba(255,255,255,0.8);background-repeat:no-repeat;background-position:center;background-size:contain;transition:filter .28s ease;}

.plt-label{font-family:var(--font);font-weight:var(--w-body);font-size:var(--t-label);letter-spacing:.06em;text-transform:uppercase;color:rgba(255,255,255,0.8);white-space:nowrap;text-align:center;transition:color .25s;}

/* default masks — optical sizes: YouTube ~36px tall, Spotify/Apple ~46px (circle/square need more area), Amazon/iHeart ~38px */
    .plt-youtube .plt-icon{-webkit-mask-image:url('../assets/icon-youtube.svg');mask-image:url('../assets/icon-youtube.svg');}

.plt-spotify .plt-icon{-webkit-mask-image:url('../assets/icon-spotify.svg');mask-image:url('../assets/icon-spotify.svg');-webkit-mask-size:auto 46px;mask-size:auto 46px;}

.plt-apple   .plt-icon{-webkit-mask-image:url('../assets/icon-apple-podcasts.svg');mask-image:url('../assets/icon-apple-podcasts.svg');-webkit-mask-size:46px 46px;mask-size:46px 46px;}

.plt-amazon  .plt-icon{width:64px;-webkit-mask-image:url('../assets/icon-amazon-music.svg');mask-image:url('../assets/icon-amazon-music.svg');}

.plt-iheart  .plt-icon{-webkit-mask-image:url('../assets/icon-iheart.svg');mask-image:url('../assets/icon-iheart.svg');-webkit-mask-size:auto 38px;mask-size:auto 38px;}

/* label hover — instant, no transition on icon (avoids white-box flash when switching mask→bg-image) */
    .plt-link:hover .plt-label{color:rgba(255,255,255,1);}

/* ── LIGHT CONTEXT ── the strip was dark-only until subscribe.html put it on the white band
   (2026-08-14, Nico). REST STATE ONLY is needed: the hover swaps each mask for that platform's
   real brand SVG, and all five carry their own colour — YouTube red, Spotify green, Apple
   gradient, iHeart #c6002b, Amazon gradients (checked in the files, not assumed). Those read
   correctly on white, so no hover override exists here on purpose.
   The `.plt-<brand>:hover .plt-icon` rules are (0,3,0) and still beat this (0,2,0), which is what
   lets the icon go transparent for the brand image even inside a light band. */
    .itg-light .plt-icon,.ctx-light .plt-icon{background-color:rgba(27,36,42,.8);}

.itg-light .plt-label,.ctx-light .plt-label{color:rgba(27,36,42,.8);}

.itg-light .plt-link:hover .plt-label,.ctx-light .plt-link:hover .plt-label{color:var(--itg-near-black);}

/* hover per icon: mask off, show fill or brand SVG directly as bg-image, plus that platform's own
   soft glow (2026-08-17, Nico).
   WHY drop-shadow AND NOT box-shadow / --glow: the mark is an SVG, so the box is a 52px square with
   transparent corners. box-shadow would ring the SQUARE; drop-shadow reads the alpha and hugs the
   real silhouette. And the glow must be the PLATFORM's colour, not ITG lime — a lime halo under a
   red YouTube mark reads as a rendering error — so --glow cannot serve here and each rule carries
   its own. Colours are the actual fills inside each SVG (grepped, not guessed): YouTube #ff0000,
   Spotify #1db954, Apple's gradient midpoint, iHeart #c6002b, Amazon's cyan #4cc0ef.
   TWO shadows per mark: a tight 8px core at .5 for presence and a wide 22px at .26 for falloff.
   One wide shadow alone reads as fog, one tight one as a hard outline.
   `transition:filter` REPLACES the old `transition:none` — the reason that was there was the
   white-box flash when background-color goes transparent, and naming only `filter` still leaves
   background-color instant, so the flash cannot come back while the glow fades in. */
    .plt-youtube:hover .plt-icon{transition:filter .28s ease;background-color:transparent;background-image:url('../assets/icon-youtube-fill.svg');background-size:contain;-webkit-mask-image:none;mask-image:none;filter:drop-shadow(0 0 8px rgba(255,0,0,.5)) drop-shadow(0 0 22px rgba(255,0,0,.26));}

.plt-spotify:hover .plt-icon{transition:filter .28s ease;background-color:transparent;background-image:url('../assets/icon-spotify-fill.svg');background-size:auto 46px;-webkit-mask-image:none;mask-image:none;filter:drop-shadow(0 0 8px rgba(29,185,84,.5)) drop-shadow(0 0 22px rgba(29,185,84,.26));}

.plt-apple:hover   .plt-icon{transition:filter .28s ease;background-color:transparent;background-image:url('../assets/icon-apple-fill.svg');background-size:46px 46px;-webkit-mask-image:none;mask-image:none;filter:drop-shadow(0 0 8px rgba(187,62,224,.5)) drop-shadow(0 0 22px rgba(187,62,224,.26));}

.plt-iheart:hover  .plt-icon{transition:filter .28s ease;background-color:transparent;background-image:url('../assets/icon-iheart.svg');background-size:auto 38px;-webkit-mask-image:none;mask-image:none;filter:drop-shadow(0 0 8px rgba(198,0,43,.55)) drop-shadow(0 0 22px rgba(198,0,43,.3));}

.plt-amazon:hover  .plt-icon{transition:filter .28s ease;background-color:transparent;background-image:url('../assets/icon-amazon-music.svg');background-size:contain;-webkit-mask-image:none;mask-image:none;filter:drop-shadow(0 0 8px rgba(76,192,239,.5)) drop-shadow(0 0 22px rgba(76,192,239,.26));}

/* NO GLOW ON LIGHT — same rule the system already states in tokens.css (`--glow:none` on
   .ctx-light): white is already at maximum luminance, so a spread reads as a blurry halo rather
   than as light. On subscribe.html this strip sits on the white band, so the glow is killed there
   and the colourised mark carries the hover alone. (0,3,0) like the brand rules above, and later in
   source order, which is what lets it win. */
    .itg-light .plt-link:hover .plt-icon,.ctx-light .plt-link:hover .plt-icon{filter:none;}

/* ── play-button ripple: expanding wave on hover (ITG green; mirrors Terra's pipelineGlow box-shadow spread) ── */
    [data-vplay]::before,[data-vplay]::after{content:'';position:absolute;inset:0;border-radius:50%;opacity:0;pointer-events:none;}

[data-yt-embed] button:hover [data-vplay]::before,[data-yt-embed] button:hover [data-vplay]::after{animation:itgPlayRipple 4s ease-out infinite;}

[data-yt-embed] button:hover [data-vplay]::after{animation-delay:2s;}

@keyframes itgPlayRipple{0%{opacity:.8;box-shadow:0 0 0 0 rgba(150,255,0,0.8);}55%{opacity:0;box-shadow:0 0 0 120px rgba(150,255,0,0);}100%{opacity:0;box-shadow:0 0 0 120px rgba(150,255,0,0);}}

/* eyebrow live-dot: slow, small expanding ripple (mirrors the video play ripple) */
    .eyebrow-dot{position:relative;}

.eyebrow-dot::after{content:'';position:absolute;inset:0;border-radius:50%;opacity:0;pointer-events:none;animation:eyebrowRipple 3.6s ease-out infinite;}

@keyframes eyebrowRipple{0%{opacity:.7;box-shadow:0 0 0 0 rgba(150,255,0,0.7);}70%{opacity:0;box-shadow:0 0 0 8px rgba(150,255,0,0);}100%{opacity:0;box-shadow:0 0 0 8px rgba(150,255,0,0);}}

/* ══ EYEBROW ══ real module definition (2026-08-13). Until now the class only carried the
       light-context colour and every instance repeated the type inline. Phase 3 strips those. */
/* TOKENISED 2026-08-14 (audit). Every value below was a literal that happened to equal a token,
       including `color:#36ecff` — which is why blocks.css still needs
       `.itg-light .eyebrow{color:#0661aa !important}`: the base bypassed --eyebrow, so the light
       context could not simply redefine it. --t-eyebrow existed as an ORPHAN at the same 20px.
       This is the most-used module on the site (19 instances across the four pages), so it was
       also the most expensive place to hold a hardcoded colour. The !important stays until the
       home stops writing its eyebrow colours inline — it is fighting those, not this rule. */
    .eyebrow{font-family:var(--font);font-weight:var(--w-strong);font-style:italic;font-size:var(--t-eyebrow);letter-spacing:normal;text-transform:none;color:var(--eyebrow);}

/* rounded-rect badges, same card language as the episode cards (2026-08-13, Nico) */
    .ab-host{margin:0;width:212px;background:var(--surface);border:1px solid rgba(255,255,255,0.10);border-radius:var(--r-badge);overflow:hidden;transition:transform .28s cubic-bezier(.22,1,.36,1),border-color .28s;}

.ab-host:hover{transform:translateY(-3px);border-color:rgba(150,255,0,0.45);}

/* Portrait frame, matching the original host slots' 200x240. Both portraits are cropped
       from the SAME ep170 studio frame and exported at 2x (424x480), so they share camera,
       lighting and background, and neither is upscaled. */
    .ab-host img{width:100%;height:240px;object-fit:cover;object-position:center;display:block;}

.ab-host figcaption{padding:16px 18px 20px;}

.ab-host .h-name{font-family:var(--font);font-weight:var(--w-strong);font-size:var(--t-small);line-height:1.1;letter-spacing:var(--track-tight);text-transform:uppercase;color:var(--fg);margin-bottom:6px;}

.ab-host .h-role{font-family:var(--font);font-weight:var(--w-strong);font-style:italic;font-size:var(--t-meta);line-height:1.3;color:var(--accent-text);margin-bottom:10px;}

.ab-host .h-info{font-family:var(--font);font-weight:var(--w-body);font-size:var(--t-meta);line-height:1.45;color:rgba(255,255,255,0.62);}

.ab-host .h-info em{font-style:italic;}

/* ══ GHOST BUTTON — one component (2026-08-13, Nico) ══════════════════════════════
       Geometry is IDENTICAL everywhere: 1px solid border, 16px/700, .06em, 11px 22px, 48px tall.
       The ONLY thing that changes per context is the resting colour (white on dark, ink on
       white). Hover behaves the same in both: lime wipes in, text goes ink.
       Was: 3 hero buttons at 16px/opaque-white vs the section button at 20px/35%-dark — the
       section CTA outweighed the hero CTA. Now one size, one border treatment. */
    .btn-ghost{
      position:relative;overflow:hidden;display:inline-flex;align-items:center;
      font-family:var(--font);font-size:var(--t-ui);letter-spacing:.06em;text-transform:uppercase;
      padding:11px 22px;border:1px solid;border-radius:0;background:transparent;text-decoration:none;
      transition:color .28s,border-color .28s,box-shadow .28s;
      /* cursor is explicit because this class is also worn by <button> (episodes.html Load more),
         and a button's UA cursor is `default`, not `pointer`. Harmless on <a>. (2026-08-17) */
      cursor:pointer;
    }

/* resting colour — the one contextual difference */
    .btn-ghost{color:var(--fg);border-color:var(--fg);}

/* on white */
    /* hover — identical treatment; lime differs only because brand forbids #96ff00 on light */
    .btn-ghost:hover{color:var(--itg-ink);border-color:var(--accent);box-shadow:var(--glow);}

/* The wipe is pure CSS (2026-08-14): it used to be driven by the dc runtime's btnFillIn /
   btnFillOut handlers, which meant the button silently lost its hover on any page that is plain
   HTML rather than a dc document — i.e. every page except the home.
   transform-origin flips right -> left on hover, so it enters from the left and retreats to the
   right on mouse-out instead of rewinding leftwards. Same trick as .btn-sub. */
.btn-ghost [data-fill]{
  position:absolute;inset:0;background:var(--accent);
  transform:scaleX(0);transform-origin:right center;
  transition:transform .3s var(--ease);
  z-index:1;pointer-events:none;
}
.btn-ghost:hover [data-fill]{transform:scaleX(1);transform-origin:left center;}

.btn-ghost .btn-label{position:relative;z-index:2;display:inline-grid;}

.btn-ghost .btn-label > span{grid-area:1/1;font-weight:700;}

.btn-ghost .btn-arrow{margin-left:9px;}

/* same body spec as the Sponsor section's copy (20px / 1.65); the light-context colour
       comes from the band, so only the size and leading had to be reconciled. */
    /* --w-body-ctx, not --w-body (2026-08-17): this note first landed on a light band on the episode
       page and rendered at 400, visibly thinner than the copy around it. The contextual token is
       identical (400) on dark, so the home does not move, and steps to 600 on white where
       dark-on-light type contracts optically. */
    .vid-note{font-family:var(--font);font-weight:var(--w-body-ctx);font-size:var(--t-body);line-height:var(--lh-body);margin:0;}

@media (max-width:900px){
      .vid-row{grid-template-columns:1fr;}
      .vid-copy,.vid-frame{grid-column:1;}
    }

/* ── PRIMARY variant ── the commercial CTA. A COLOUR variant ONLY: fill, text colour, border and
       glow change; GEOMETRY DOES NOT. It also used to set font-size:18px / padding:16px 34px, which
       contradicted the one-geometry rule the base declares above and made a primary button visibly
       taller and wider than the ghost standing next to it in the same .btn-row — two buttons on one
       line at two different sizes (books.html, caught by Nico 2026-08-17).
       Hierarchy comes from the lime fill and the glow, which is already emphatic against a 1px
       outline; it does not need size on top. Ghost stays for secondary actions (episode guide,
       start here, view all, read more). The wipe inverts to ink so the mechanic still reads on a
       lime ground. (2026-08-13, Nico · geometry unified 2026-08-17) */
    .btn-ghost--primary{color:var(--itg-ink) !important;background:var(--accent);border-color:var(--accent) !important;box-shadow:var(--glow);}

.btn-ghost--primary [data-fill]{background:var(--itg-ink);}

.btn-ghost--primary:hover{color:var(--accent) !important;border-color:var(--accent) !important;box-shadow:var(--glow);}

.sp-copy{flex:1 1 560px;}

/* the gap above the sponsors must equal the gap below them, i.e. the white band's own
       bottom clearance. Both read the same token so they cannot drift. (2026-08-14, Nico) */
    .sp-current{padding:var(--zone-pad) 0 0;}

/* now lives on the WHITE band -> ITG Blue, since cyan is unreadable there */
    .sp-current-label{margin:0;white-space:nowrap;}

/* single row: label, then the logos to its right, whole group centred */
    /* one gap governs the whole row: label->Terra must equal Terra->JBK (2026-08-14, Nico) */
    /* THE MIDDLE ITEM SITS AT THE PAGE CENTRE. (Nico, 2026-08-14 — third attempt, and the right
       one.) Two earlier tries both failed the same way: centring the whole group, and centring
       the logo pair, each left the middle item off centre.
       Here every item is a direct grid child of `1fr auto 1fr`, so the auto column — the middle
       item — is pinned to the true centre, and its neighbours hang off it symmetrically at
       exactly one gap each. Works whatever the label says, on every page.
       `display:contents` on .sp-logos flattens its children into the grid, so the markup keeps
       its wrapper and no page has to change. */
    .sp-current--center{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;column-gap:96px;}
    .sp-current--center .sp-current-label{justify-self:end;}
    .sp-current--center .sp-logos{display:contents;}
    .sp-current--center .sp-logo:last-child{justify-self:start;}
    @media (max-width:760px){
      .sp-current--center{grid-template-columns:1fr;row-gap:26px;justify-items:center;}
      .sp-current--center .sp-current-label,.sp-current--center .sp-logo:last-child{justify-self:center;}
    }

.sp-logos{display:flex;align-items:center;flex-wrap:wrap;gap:36px 96px;}

/* full opacity — no transparency on partner marks. Cap the HEIGHT, let width follow. */
    .sp-logo{display:inline-flex;align-items:center;transition:transform .28s cubic-bezier(.22,1,.36,1);}

.sp-logo:hover{transform:scale(1.06);}

.sp-logo img{width:auto;display:block;}

/* OPTICAL BALANCE, not equal box heights. Measured on the artwork: the TERRA wordmark fills
       only 56.1% of its viewBox height (the box is set by the tall aperture symbol) while JBK's
       fills 83.3% (set by its own caps). Matching box heights therefore makes JBK's letters ~48%
       bigger, which is why Terra looked small at an equal 38px.
       Terra is scaled x1.16 = matching INK MASS. The cap-height match (x1.48, i.e. 68px) and the
       geometric mean (x1.31, 60px) both read as Terra dominating, because its wider 3.69 aspect
       makes footprint outweigh cap height here. (2026-08-13, Nico) */
    /* Rebalanced for the LIGHT artwork, which is a different asset from the dark pair: the
       light Terra PNG carries ~11% internal padding and its wordmark fills 51.2% of the box
       against JBK's 83.2%, so ink-mass matching needs x1.26 here (the dark pair needed x1.16). */
    .sp-logo--jbk img{height:46px;}

.sp-logo--terra img{height:58px;}

/* ══════════════════════════════════════════════════════════════════════════════════════════════
   ADDED 2026-08-14 while building sponsor.html — the three pieces the system was missing.
   Every value comes from tokens; no literals.
   ══════════════════════════════════════════════════════════════════════════════════════════════ */

/* ── STAT ROW ── big number + label. Reach figures, audience counts, anything countable. */
.stat-row{display:flex;flex-wrap:wrap;gap:32px 72px;}
.stat{display:flex;flex-direction:column;gap:6px;}
.stat-n{font-family:var(--font);font-weight:var(--w-display);font-size:56px;line-height:1;
        letter-spacing:var(--track-tight);color:var(--fg);}
.stat-n small{font-size:26px;}
.stat-l{font-family:var(--font);font-weight:var(--w-strong);font-size:var(--t-label);
        letter-spacing:.1em;text-transform:uppercase;color:var(--eyebrow);}

/* ── DEF LIST ── label + description pairs, rendered as a marked list.
   Audience segments, spec sheets, FAQ-ish content.
   The term uses --accent-text, NOT --accent: the brand's light lime measures 1.75:1 on white
   and is unreadable as type. See tokens.css. (2026-08-14, Nico) */
.deflist{display:grid;gap:30px;margin:0;}
.deflist--2col{grid-template-columns:1fr 1fr;gap:34px 56px;}
.deflist dt{
  position:relative;padding-left:22px;
  font-family:var(--font);font-weight:var(--w-strong);font-size:var(--t-term);line-height:1.2;
  letter-spacing:var(--track-tight);color:var(--accent-text);margin:0 0 8px;
}
/* list marker — a solid square. It is a graphic element, but it still reads --accent-text so it
   stays visible on white; a lime square there would sit at the same 1.75:1 as the type did. */
.deflist dt::before{
  content:'';position:absolute;left:0;top:.52em;
  width:9px;height:9px;background:var(--accent-text);
}
.deflist dd{font-family:var(--font);font-weight:var(--w-body-ctx);font-size:var(--t-small);
            line-height:1.55;color:var(--fg-muted);margin:0;padding-left:22px;}

/* ── SECTION LIST ── a real <ul> for facts that are one line each. (2026-08-14, Nico)
   The format rows on about.html were a .deflist--2col, which turned five one-liners into a
   two-column table and put each label on its own line above its value; the source renders them as
   a plain list of "<strong>Label:</strong> value". Use .deflist when the description needs its own
   paragraph, .sec-list when the whole item fits on a line.
   Same 9px square marker and the same --accent-text label colour as .deflist dt, so the two read
   as one family — and the square stays visible on white, where a lime one would sit at 1.75:1. */
.sec-list{margin:0;padding-left:22px;list-style:none;}
.sec-list li{position:relative;font-family:var(--font);font-weight:var(--w-body-ctx);
             font-size:var(--t-body);line-height:1.7;color:var(--fg);margin:0 0 16px;}
.sec-list li:last-child{margin-bottom:0;}
.sec-list li::before{content:'';position:absolute;left:-22px;top:.62em;
                     width:9px;height:9px;background:var(--accent-text);}
.sec-list strong{font-weight:var(--w-strong);color:var(--accent-text);}

/* ── FEATURE CARD ── titled card in a grid. Ad formats, plans, module summaries.
   Same surface/radius/hover language as the episode card, so the site reads as one system. */
/* NOT interactive. No hover, no lift, no transition: a hover state signals "you can click this"
   and these cards are not links. A permanent accent border was tried and dropped — six lime
   outlines competed with the lime headings inside them. (2026-08-14, Nico) */
.fcard{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-card);
       padding:26px 24px;}
/* same size and accent as a def-list term, from the same token — they are the same kind of
   heading, so they must not drift apart. (2026-08-14, Nico) */
.fcard-t{font-family:var(--font);font-weight:var(--w-strong);font-size:var(--t-term);line-height:1.2;
         letter-spacing:var(--track-tight);color:var(--accent-text);margin:0 0 12px;}
.fcard-d{font-family:var(--font);font-weight:var(--w-body);font-size:var(--t-ui);line-height:1.55;
         color:var(--fg-muted);margin:0;}

/* ── FORM FIELD ── input / textarea, both contexts. */
.field{display:flex;flex-direction:column;gap:8px;}
.field-l{font-family:var(--font);font-weight:var(--w-strong);font-size:var(--t-meta);letter-spacing:.1em;
         text-transform:uppercase;color:var(--fg-muted);}
.input,.textarea{
  font-family:var(--font);font-weight:var(--w-body);font-size:var(--t-ui);color:var(--fg);
  background:rgba(4,6,10,.55);border:1px solid var(--line);border-radius:0;
  padding:13px 16px;outline:none;transition:border-color var(--dur),box-shadow var(--dur);
}
.ctx-light .input,.ctx-light .textarea,.itg-light .input,.itg-light .textarea{
  background:var(--itg-white);border-color:rgba(27,36,42,.35);
}
.input:focus,.textarea:focus{border-color:var(--accent);box-shadow:var(--glow);}
.textarea{min-height:118px;resize:vertical;}
.input::placeholder,.textarea::placeholder{color:rgba(255,255,255,.38);}

/* The light-context override above covers background and border but NOT the placeholder, which
   was left at white .38 — invisible on a white field. Found 2026-08-14 when subscribe.html's form
   moved onto the white band. That form has no placeholders (the source uses labels only), so this
   never rendered wrong; sponsor.html and contact.html do have them and would have broken the day
   either moved bands. */
.ctx-light .input::placeholder,.ctx-light .textarea::placeholder,
.itg-light .input::placeholder,.itg-light .textarea::placeholder{color:rgba(27,36,42,.45);}
.ctx-light .input::placeholder,.itg-light .input::placeholder{color:rgba(27,36,42,.45);}

/* ── INLINE LINK ── accented link inside body copy. Added 2026-08-14 for contact.html, where
   emails and cross-links appear mid-sentence; sponsor.html had been styling one inline.
   Uses --accent-text (it is type), so it is lime on dark and ITG Blue on white — never the
   brand's light lime, which sits at 1.75:1 on white. */
.link-accent{
  color:var(--accent-text);text-decoration:none;
  border-bottom:1px solid currentColor;
  transition:opacity var(--dur);
}
.link-accent:hover{opacity:.7;}

/* ── PILL ── the outlined chip from the home's hero ("180+ EPISODES · SINCE 2019"), promoted to a
   module so tag rows and social links read as the same object. (2026-08-14, Nico)
   Edge and fill come from --pill-edge / --pill-bg, so it survives a move onto the white band;
   type is --accent-text, never --accent (lime type on white is 1.75:1).
   14px, not the hero's 18px: the hero chip is a page-level badge and these sit inside body copy.
   Works as <a> (hover fills) and as <span> (a static tag, no hover — same rule as .fcard). */
.pill{
  display:inline-flex;align-items:center;gap:8px;
  padding:6px 15px;border-radius:var(--r-pill);
  border:1px solid var(--pill-edge);background:var(--pill-bg);
  font-family:var(--font);font-weight:var(--w-strong);font-size:var(--t-label);
  letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--accent-text);text-decoration:none;white-space:nowrap;
  transition:border-color var(--dur) var(--ease),background var(--dur) var(--ease),
             color var(--dur) var(--ease);
}

/* Fill on hover, in both contexts: ink type on a lime ground is high-contrast either way, which
   is why this one hover rule needs no per-context override. No glow — a chip is not a button. */
a.pill:hover{border-color:var(--accent);background:var(--accent);color:var(--itg-ink);}

/* Rows wrap; the gap is the row's, so no margins on the pills themselves. */
.pill-row{display:flex;flex-wrap:wrap;align-items:center;gap:10px;}

/* SCOPE — pills are for LINKS (social handles, downloadable assets), not for prose fragments.
   A `.pill-row-l` label class existed here for one turn to head a row of "Geeks out on" tags;
   Nico rejected pills for those (2026-08-14) and it was deleted rather than left as dead CSS.
   Interest lists and similar read as inline text with middots, the way the source writes them. */
