/* ═══════════════════════════════════════════
   MF Times — Design System
   "Investing Intelligence" — market news, data & mutual-fund intelligence.
   Editorial / publication feel. Light only (warm paper).

   Palette: Ink black + green on warm paper. Gold is reserved for editorial
   section kickers only; red is reserved for negative market data only.

   Type: Fraunces (masthead/headlines) · Plus Jakarta Sans (body/UI)
         · IBM Plex Mono (prices, NAVs, %, timestamps, ticker).
═══════════════════════════════════════════ */

:root {
  /* ── Typefaces ── */
  --font:        'Plus Jakarta Sans', sans-serif;  /* body / UI */
  --font-head:   'Fraunces', Georgia, serif;        /* headlines / masthead */
  --font-data:   'IBM Plex Mono', ui-monospace, monospace; /* numbers / ticker */

  /* ── Brand tokens (rebrand source of truth) ── */
  --ink:         #111111;
  --green:       #1B7A3E;
  --green-light: #4ECB7D;
  --red-light:   #F09E9E;  /* negative data on ink surfaces */
  --paper:       #F8F4EC;
  --paper-2:     #FFFFFD;
  --mint:        #EBF5EF;
  --muted:       #8C8C8C;

  /* ── Surfaces — warm newspaper stock ──
     The ground is warm paper, not white. An interim "modern serif" direction
     switched --bg to #FFFFFF, which quietly removed the newspaper character
     from every page; restored here as the default.

     Two warm tones, deliberately: --bg is the page stock, --surf sits a shade
     lighter for cards and tables so they lift off it without a border doing all
     the work. Pure white is reserved for input fields, where it signals
     "you can type here". */
  --bg:        #F7F3EA;   /* page ground — warm newsprint */
  --nav-bg:    #FBF8F1;   /* masthead sits slightly above the page */
  --surf:      #FCFAF4;   /* cards, tables, panels */
  --surf2:     #F1EBDE;   /* recessed: table heads, bar tracks, quiet fills */
  --ticker-bg: #0A0A0A;   /* a shade deeper than --ink so it recedes behind the Decode */
  --footer-bg: var(--ink);

  /* Rules are warm too — a cool grey hairline on warm stock reads as dirt. */
  --rule-w:   #E3DCCC;
  --rule:     #E3DCCC;
  --border:   var(--rule-w);
  --border-s: #D5CCB8;

  /* ── Text ── */
  --text:     var(--ink);
  --text2:    #333333;
  --text3:    var(--muted);

  /* ── Primary accent = green (does most of the work) ── */
  --primary:    var(--green);
  --primary-l:  #21924A;
  --primary-d:  #145F30;
  --primary-bg: rgba(27,122,62,0.08);

  /* ── Gold: editorial section kickers ONLY, used sparingly ── */
  --gold:     #C9961A;
  --gold-l:   #A87A0F;
  --gold-d:   #E0AC2C;
  --gold-bg:  rgba(201,150,26,0.10);

  /* Semantic "healthy" signal — shares the brand green. Financial-correctness
     signal (e.g. ROE in healthy range), also the positive market-data colour. */
  --green-bg:     rgba(27,122,62,0.09);
  --green-border: rgba(27,122,62,0.24);

  /* ── Red: negative market data only (losses/declines). Never general UI. ── */
  --red:        #B23B3B;
  --red-bg:     rgba(178,59,59,0.08);
  --red-border: rgba(178,59,59,0.20);

  --amber:        #A87A0F;
  --amber-bg:     rgba(201,150,26,0.10);
  --amber-border: rgba(201,150,26,0.26);

  --shadow:      rgba(17,17,17,0.12);
  --shadow-s:    rgba(17,17,17,0.05);
  --shadow-card: 0 2px 16px rgba(17,17,17,0.07), 0 0 0 1px var(--rule);
}

/* ── Editorial headline treatment ──
   Fraunces carries every headline. Applied globally so the 60+ existing pages
   inherit the publication voice without per-page edits. */
h1, h2, h3, .pub-hero-title, .r-lbl-loud {
  font-family: var(--font-head);
  letter-spacing: -0.015em;
}
h1 { font-weight: 900; }
h2, h3 { font-weight: 800; }

/* ── Data / numerals ──
   Anything that is a live number reads in Plex Mono. */
.mono, .t-price, .t-chg, .num, .data-val {
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
}

/* ── Editorial section kicker — the one sanctioned use of gold ── */
.kicker {
  font-family: var(--font);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold);
}

/* ── Base resets ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
input, button, select, textarea { font-family: inherit; font-size: inherit; }
html { scroll-behavior: smooth; }
body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.7;
}

/* Base link colour. There was none — every link on the site was styled by its
   own component rule, so any link that missed one fell through to the browser
   default and rendered #0000EE blue on warm paper. That is how a mailto in the
   "Write for MF Times" block ended up blue on every page carrying it.
   Green is the house accent and does this work; components that need something
   else still override it, since anything with a class beats a bare element. */
a { color: var(--green); }

/* ── Shared nav ── */
.tbb-nav {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 2rem;
  height: 64px;
  background: var(--nav-bg);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 100;
  gap: 1rem;
  box-shadow: 0 1px 0 var(--border);
}
.tbb-logo {
  display: flex; align-items: center; gap: 0.6rem; text-decoration: none; flex-shrink: 0;
}
/* Nav uses the WORDMARK only (logo-wordmark.png) — the full lockup's
   "INVESTING INTELLIGENCE" tagline renders at ~3px in a 64px nav and is
   illegible. The full masthead with tagline is used in the footer, where
   there is room for it. */
.tbb-logo-img { height: 30px; width: auto; display: block; }
.nav-right { display: flex; align-items: center; gap: 1.2rem; }

/* Stage 67: nav links bumped up — bolder weight, more presence so the
   nav doesn't read as 'small' next to the auth buttons. */
.nav-link {
  color: var(--text);
  text-decoration: none;
  font-size: 0.92rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  transition: color 0.15s;
  white-space: nowrap;
}
.nav-link:hover { color: var(--primary); }

.btn-nav {
  background: transparent;
  color: var(--text);
  border: 1.5px solid var(--border-s);
  border-radius: 8px;
  padding: 0.5rem 1.05rem;
  font-family: var(--font);
  font-size: 0.86rem; font-weight: 700;
  cursor: pointer;
  text-decoration: none;
  transition: all 0.15s;
  white-space: nowrap;
}
.btn-nav:hover { border-color: var(--primary); color: var(--primary); }
.btn-nav.primary { background: var(--primary); color: #fff; border-color: var(--primary); }
.btn-nav.primary:hover { background: var(--primary-l); border-color: var(--primary-l); }

/* ── Shared buttons ── */
.btn {
  background: var(--primary);
  color: #fff;
  border: none;
  border-radius: 10px;
  padding: 0.7rem 1.5rem;
  font-family: var(--font);
  font-size: 0.88rem; font-weight: 700;
  cursor: pointer;
  transition: background 0.15s, transform 0.12s, box-shadow 0.15s;
  text-decoration: none;
  display: inline-flex; align-items: center; gap: 0.4rem;
  box-shadow: 0 2px 12px rgba(10,37,64,0.22);
}
.btn:hover { background: var(--primary-l); transform: translateY(-1px); box-shadow: 0 4px 20px rgba(10,37,64,0.30); }
.btn:active { transform: translateY(0); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; transform: none; box-shadow: none; }

.btn-ghost {
  background: transparent;
  color: var(--text);
  border: 1.5px solid var(--border-s);
  box-shadow: none;
}
.btn-ghost:hover { border-color: var(--primary); color: var(--primary); background: var(--primary-bg); box-shadow: none; }

/* ── Universal CTA button — used across learn, stock, and app pages ── */
/* Any page that loads theme.css gets this for free. Per-page overrides must use var(--primary). */
.cta-btn {
  display: inline-block;
  background: var(--primary);
  color: #fff;
  font-size: 15px;
  font-weight: 700;
  padding: 14px 32px;
  border-radius: 10px;
  text-decoration: none;
  transition: background 0.15s, transform 0.12s;
  cursor: pointer;
  border: none;
}
.cta-btn:hover { background: var(--primary-l); transform: translateY(-1px); }

/* ── Ticker — ink background, paper text, mono, thin green bottom rule ── */
.ticker-bar {
  overflow: hidden;
  background: var(--ticker-bg);
  border-bottom: 2px solid var(--green);
  padding: 0.46rem 0;
  cursor: default;
}
.ticker-bar:hover .ticker-track { animation-play-state: paused; }
.ticker-track {
  display: flex;
  align-items: center;
  white-space: nowrap;
  width: max-content;
  will-change: transform;
}
@keyframes tscroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.t-item {
  font-family: var(--font-data); font-size: 0.72rem; color: rgba(248,244,236,0.72);
  font-variant-numeric: tabular-nums;
  display: inline-flex; align-items: center; gap: 0.3rem;
  padding: 0 1.1rem;
  border-right: 1px solid rgba(248,244,236,0.14);
}
.t-item:last-child { border-right: none; }
.t-sym { color: var(--paper); font-weight: 600; letter-spacing: 0.02em; }
.t-price { color: rgba(248,244,236,0.72); }
/* On the ink ticker, positive uses the lightened green for legibility. */
.t-up  { color: var(--green-light); font-weight: 600; }
.t-dn  { color: var(--red-light);   font-weight: 600; }
.t-nil { font-size: 0.72rem; color: rgba(248,244,236,0.45); padding: 0 1rem; font-family: var(--font-data); }

/* ── Shared inputs ── */
.field {
  width: 100%;
  background: var(--surf2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.7rem 1rem;
  color: var(--text);
  font-family: var(--font);
  font-size: 0.88rem; font-weight: 500;
  outline: none;
  transition: border-color 0.15s;
}
.field:focus { border-color: var(--primary); }
.field::placeholder { color: var(--text3); font-weight: 400; }
.field-err { display: none; font-size: 0.77rem; color: var(--red); margin-top: 0.45rem; font-weight: 600; }

/* ── Toast ── */
.toast {
  position: fixed; bottom: 1.75rem; left: 50%; transform: translateX(-50%);
  background: var(--green-bg); border: 1px solid var(--green-border);
  color: var(--green); padding: 0.72rem 1.3rem; border-radius: 100px;
  font-size: 0.82rem; font-weight: 700; z-index: 999;
  display: none; white-space: nowrap;
  box-shadow: 0 8px 24px var(--shadow);
}

@media (max-width: 768px) {
  .tbb-nav { padding: 0 1.1rem; gap: 0.5rem; }
  .tbb-logo-img { height: 24px; }
  .btn-nav:not(.primary) { display: none; }
  /* "Subscribe — free →" overflows a 390px nav alongside the hamburger.
     Drop the "— free" qualifier; the modal still says it's free. */
  .btn-nav-long { display: none; }
  .btn-nav.primary { padding: 0.45rem 0.8rem; font-size: 0.8rem; }
  .nav-right { gap: 0.6rem; }
}

/* ═══════════════════════════════════════════
   THE DECODE — the signature module.
   One number from the news, and what sits under it. Ink ground, oversized
   mono figure, a verdict line. Recurring and instantly recognisable.
═══════════════════════════════════════════ */
.decode {
  background: var(--ink); color: var(--paper); border-radius: 2px;
  padding: 2.5rem 2.5rem 2.25rem;
  /* Clear air above: without it the ink block runs straight into the ink
     ticker and the two read as one confused mass. */
  margin: 2.75rem 0 3rem;
  position: relative; overflow: hidden;
}
/* Green rule on TOP, so the module announces itself rather than being
   closed off at the bottom. */
.decode::before {
  content: ''; position: absolute; left: 0; right: 0; top: 0;
  height: 3px; background: var(--green);
}
/* A hairline label that ties the block to the page it sits on. */
.decode::after {
  content: ''; position: absolute; left: 2.5rem; right: 2.5rem; bottom: 0;
  height: 1px; background: rgba(248,244,236,0.10);
}
.decode-k {
  font-family: var(--font-data); font-size: 0.68rem; font-weight: 500;
  letter-spacing: 0.22em; text-transform: uppercase; color: var(--green-light);
  margin-bottom: 1.5rem; display: flex; align-items: center; gap: 0.6rem;
}
.decode-k::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%;
  background: var(--green-light); flex-shrink: 0;
  animation: decode-pulse 2.4s ease-in-out infinite;
}
@keyframes decode-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.25; } }
/* Positioning lede — the loudest type on the homepage. This is the block that
   has to say what MF Times is before a reader scrolls. */
.decode-lede {
  font-family: var(--font-head); font-weight: 800;
  font-size: clamp(1.9rem, 4.2vw, 3.15rem); line-height: 1.05;
  letter-spacing: -0.03em; color: var(--paper); margin: 0 0 1.1rem;
}
.decode-lede em { font-style: normal; color: var(--green-light); }
.decode-sub {
  font-size: 0.98rem; line-height: 1.6; color: rgba(248,244,236,0.7);
  max-width: 62ch; margin: 0 0 1.75rem;
}
/* Proof strip: the claim above is only worth making if the numbers back it. */
.decode-stats {
  display: flex; flex-wrap: wrap; gap: 0 2.5rem;
  padding: 1.1rem 0 1.4rem; margin-bottom: 1.75rem;
  border-top: 1px solid rgba(248,244,236,0.14);
  border-bottom: 1px solid rgba(248,244,236,0.14);
}
.decode-st { display: flex; align-items: baseline; gap: 0.5rem; }
.decode-stv {
  font-family: var(--font-data); font-weight: 500; font-size: 1.35rem;
  color: var(--paper); letter-spacing: -0.02em;
}
.decode-stl {
  font-family: var(--font-data); font-size: 0.64rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: rgba(248,244,236,0.5);
}

.decode-grid { display: grid; grid-template-columns: auto 1fr; gap: 2.75rem; align-items: center; }
.decode-fig {
  font-family: var(--font-data); font-size: clamp(3.2rem, 7vw, 5.5rem); font-weight: 600;
  line-height: 0.92; letter-spacing: -0.045em; color: var(--paper);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.decode-fig .u { font-size: 0.4em; color: var(--green-light); margin-left: 0.15em; letter-spacing: 0; }
.decode-cap {
  font-family: var(--font-data); font-size: 0.68rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: rgba(248,244,236,0.5); margin-top: 0.85rem;
}
.decode-body {
  font-family: var(--font-head); font-size: clamp(1.15rem, 1.8vw, 1.5rem); font-weight: 600;
  line-height: 1.35; letter-spacing: -0.015em; color: var(--paper); margin: 0;
}
.decode-body em { color: var(--green-light); font-style: normal; }
.decode-foot {
  display: flex; gap: 1.5rem; flex-wrap: wrap; align-items: baseline;
  margin-top: 1.75rem; padding-top: 1.25rem; border-top: 1px solid rgba(248,244,236,0.15);
  font-family: var(--font-data); font-size: 0.68rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: rgba(248,244,236,0.45);
}
.decode-foot a { color: var(--green-light); text-decoration: none; }
.decode-foot a:hover { text-decoration: underline; }
@media (max-width: 760px) {
  .decode { padding: 1.75rem 1.35rem 1.5rem; }
  .decode-grid { grid-template-columns: 1fr; gap: 1.25rem; }
}

/* ── Pull-stat: an opinionated number inside prose ── */
.pullstat {
  display: grid; grid-template-columns: auto 1fr; gap: 1.5rem; align-items: center;
  margin: 2rem 0; padding: 1.25rem 0; border-block: 1px solid var(--rule);
}
.pullstat-n {
  font-family: var(--font-data); font-size: 2.6rem; font-weight: 600; line-height: 1;
  color: var(--ink); letter-spacing: -0.03em; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.pullstat-n .u { font-size: 0.42em; color: var(--green); margin-left: 0.12em; }
.pullstat-t { font-size: 1rem; line-height: 1.5; color: var(--text2); margin: 0; }
.pullstat-t strong { color: var(--ink); font-weight: 600; }
@media (max-width: 560px) { .pullstat { grid-template-columns: 1fr; gap: 0.6rem; } }

/* ── Live pulse ── */
.pulse-dot {
  display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--green); margin-right: 0.45rem; vertical-align: middle;
  animation: decode-pulse 2.4s ease-in-out infinite;
}
.mkt-state {
  font-family: var(--font-data); font-size: 0.68rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text3);
}
.mkt-state.open { color: var(--green); }

/* Numbers that change get a brief flash so refreshes are visible */
@keyframes tickflash { 0% { background: var(--green-bg); } 100% { background: transparent; } }
.tick { animation: tickflash 1.1s ease-out; }

/* ── "Soon" badge — sections we are not covering yet ─────────────────────── */
/* Amber, not green: green means live data on this site, and a nav badge that
   reads as an endorsement of an empty section is worse than no badge. */
.soon {
  display: inline-block; vertical-align: middle;
  font-family: var(--font-data); font-size: 0.55rem; font-weight: 500;
  letter-spacing: 0.1em; text-transform: uppercase;
  padding: 0.1rem 0.3rem; margin-left: 0.35rem;
  border: 1px solid var(--amber-border); color: var(--amber);
  background: var(--amber-bg); border-radius: 2px;
}

/* Section-level coming-soon banner */
.soon-band {
  background: var(--ink); color: var(--paper);
  padding: 2.25rem 2rem; margin-bottom: 2.5rem;
  border-top: 3px solid var(--gold);
}
.soon-band-k {
  font-family: var(--font-data); font-size: 0.64rem; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--gold-d); margin-bottom: 0.9rem;
}
.soon-band h2 {
  font-family: var(--font-head); font-weight: 800;
  font-size: clamp(1.5rem, 3vw, 2.2rem); line-height: 1.1;
  letter-spacing: -0.025em; color: var(--paper); margin: 0 0 0.8rem;
}
.soon-band p {
  font-size: 0.95rem; line-height: 1.6; color: rgba(248,244,236,0.72);
  max-width: 60ch; margin: 0;
}
.soon-band a { color: var(--green-light); }
.soon-lg { font-size: 0.7rem; vertical-align: middle; margin-left: 0.6rem; }

/* ── Card elevation on warm stock ────────────────────────────────────────── */
/* On a warm ground, a card only 1.06 contrast from the page barely separates.
   The design review solved this with a 14px radius; that reads as an app, and
   MF Times is a publication — the FT and Economist use sharp corners and rules.
   So: keep the 2px newspaper corner, and get the separation from a shadow
   instead. Two layers, both very low alpha — a tight one for the edge and a
   soft one for the lift. Anything heavier looks like a pop-up. */
:root {
  --lift: 0 1px 2px rgba(17,17,17,0.04), 0 2px 8px rgba(17,17,17,0.045);
  --lift-hover: 0 2px 4px rgba(17,17,17,0.05), 0 6px 18px rgba(17,17,17,0.07);
}

/* ── Footer columns ──────────────────────────────────────────────────────── */
.foot-cols {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 2rem; max-width: 900px; margin: 0 auto 2rem; text-align: left;
}
.foot-col h5 {
  font-family: var(--font-data); font-size: 0.6rem; font-weight: 500;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--green-light); margin: 0 0 0.9rem;
}
.foot-col a {
  display: block; font-size: 0.85rem; line-height: 1.5;
  color: rgba(248,244,236,0.62); text-decoration: none;
  margin-bottom: 0.6rem; transition: color .15s;
}
.foot-col a:hover { color: var(--paper); }
.foot-col .soon {
  font-size: 0.5rem; padding: 0.05rem 0.25rem; margin-left: 0.25rem;
  border-color: rgba(224,172,44,0.4); color: var(--gold-d);
  background: rgba(201,150,26,0.12);
}
@media (max-width: 720px) {
  .foot-cols { grid-template-columns: repeat(2, 1fr); gap: 1.5rem; }
}

/* ── Footer CTA band ────────────────────────────────────────────────────────
   Subscribe and Write-for-us on every page. The footer's link columns are
   navigation; these two are the actions. Sits on the ink footer, so the
   colours are fixed to the paper/green pair rather than themed tokens. */
.foot-cta {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 0.7rem 1rem;
  padding: 0 0 1.6rem; margin-bottom: 1.6rem;
  border-bottom: 1px solid rgba(248,244,236,0.12);
}
.foot-cta-b {
  display: inline-block; font-family: var(--font-data); font-size: 0.86rem;
  font-weight: 500; padding: 0.7rem 1.2rem; border-radius: 2px;
  background: var(--green); color: var(--paper);
  border: 1px solid var(--green); cursor: pointer; text-decoration: none;
  transition: background .15s, color .15s;
}
.foot-cta-b:hover { background: var(--green-light); color: var(--ink); border-color: var(--green-light); }
.foot-cta-b.ghost { background: transparent; color: rgba(248,244,236,0.85); border-color: rgba(248,244,236,0.28); }
.foot-cta-b.ghost:hover { background: rgba(248,244,236,0.08); color: var(--paper); border-color: rgba(248,244,236,0.5); }
.foot-cta-n { font-size: 0.8rem; color: rgba(248,244,236,0.5); }
@media (max-width: 560px) { .foot-cta-b { width: 100%; text-align: center; } }

/* ── Scrolling ticker ───────────────────────────────────────────────────────
   nav.js injects .tk on EVERY page, but these rules previously lived only in
   home.html — so everywhere else the ticker rendered unstyled with no
   overflow clipping. It went unnoticed while the content was stock symbols;
   switching to fund names (much longer) pushed the page 9px sideways on every
   article. max-width + overflow:hidden is the load-bearing pair. */
.tk {
  background: var(--ticker-bg); color: var(--paper);
  font-family: var(--font-data); font-size: 0.75rem;
  overflow: hidden; white-space: nowrap;
  max-width: 100%; width: 100%;
}
.tk-track { display: inline-block; padding: 0.55rem 0; animation: tkscroll 40s linear infinite; }
.tk-track:hover { animation-play-state: paused; }
.tk-track span { margin-right: 2.25rem; }
.tk .up { color: var(--green-light); }
.tk .dn { color: var(--red-light); }
.tk .fl { color: rgba(248,244,236,0.55); }
@keyframes tkscroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) { .tk-track { animation: none; } }

/* ── Loading state ───────────────────────────────────────────────────────────
   Lives here rather than in fund.css because every page loads theme.css and
   half the loading states are on pages that never load fund.css.

   A bare "Loading…" reads like a broken page. The masthead plus a moving bar
   reads like the paper is being set — and on a fund page, where we fetch NAV
   history and compute returns before anything can render, the wait is real.

   .fload-sm is for a table cell or a rail block, where a 148px wordmark would
   dominate whatever it is standing in for. */
.fload { display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1.1rem; padding: 5.5rem 1rem; text-align: center; }
.fload-l { width: 148px; max-width: 55%; height: auto; opacity: 0.9; }
.fload-bar { width: 168px; max-width: 60%; height: 2px; background: var(--rule);
  border-radius: 2px; overflow: hidden; }
.fload-bar i { display: block; width: 40%; height: 100%; background: var(--green);
  border-radius: 2px; animation: fload 1.15s ease-in-out infinite; }
@keyframes fload {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(350%); }
}
.fload-t { font-family: var(--font-data); font-size: 0.68rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--text3); }

/* Dropped straight into a .card-grid the loader would occupy one narrow
   column; span every track so it centres against the whole grid. */
.card-grid > .fload, .card-grid-2 > .fload { grid-column: 1 / -1; }
.fload-sm { gap: 0.7rem; padding: 2.2rem 1rem; }
.fload-sm .fload-l { width: 96px; }
.fload-sm .fload-bar { width: 110px; height: 2px; }
.fload-sm .fload-t { font-size: 0.6rem; }

/* Respect a reader who has asked the OS to stop animation. */
@media (prefers-reduced-motion: reduce) {
  .fload-bar i { animation: none; width: 100%; opacity: 0.5; }
}

/* ── Shimmer skeleton ────────────────────────────────────────────────────────
   Used by the sidebar while its payload is in flight. The rail used to be an
   empty <aside> until the fetch resolved, so it looked like it arrived late
   and the content column reflowed when it landed. A skeleton at roughly the
   finished shape reserves the space and reads as loading. */
.sk {
  background: linear-gradient(90deg, var(--surf2) 25%, var(--rule) 37%, var(--surf2) 63%);
  background-size: 400% 100%;
  animation: sk 1.3s ease-in-out infinite;
  border-radius: 2px;
}
@keyframes sk { 0% { background-position: 100% 0; } 100% { background-position: -100% 0; } }
.sk-box { pointer-events: none; }
.sk-h { height: 0.62rem; width: 42%; margin-bottom: 0.95rem; }
.sk-l { height: 0.82rem; width: 100%; margin-bottom: 0.6rem; }
.sk-l.sk-s { width: 68%; margin-bottom: 0; }
@media (prefers-reduced-motion: reduce) {
  .sk { animation: none; background: var(--surf2); }
}

/* ── Subscribe prompt ────────────────────────────────────────────────────────
   Appears once, ~45 seconds in, and stays gone for the session once closed.
   Centred rather than a corner slide-in: a corner toast reads as an ad, and
   this is the one ask the site makes. */
.subpop {
  position: fixed; inset: 0; z-index: 9000;
  display: flex; align-items: center; justify-content: center;
  padding: 1.2rem; background: rgba(17,17,17,0.55);
  animation: subfade .22s ease-out;
}
@keyframes subfade { from { opacity: 0; } to { opacity: 1; } }
.subpop-c {
  position: relative; width: 100%; max-width: 440px;
  background: var(--surf); border: 1px solid var(--rule);
  border-top: 3px solid var(--green); border-radius: 3px;
  padding: 1.9rem 1.7rem 1.5rem; box-shadow: 0 24px 60px rgba(0,0,0,0.28);
}
.subpop-x {
  position: absolute; top: 0.5rem; right: 0.7rem;
  background: none; border: 0; cursor: pointer;
  font-size: 1.5rem; line-height: 1; color: var(--text3); padding: 0.2rem 0.3rem;
}
.subpop-x:hover { color: var(--ink); }
.subpop-k {
  font-family: var(--font-data); font-size: 0.6rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--green); margin-bottom: 0.4rem;
}
.subpop-h {
  font-family: var(--font-head); font-size: 1.4rem; font-weight: 700;
  line-height: 1.2; margin: 0 0 0.55rem; color: var(--ink);
}
.subpop-s { font-size: 0.88rem; line-height: 1.6; color: var(--text2); margin: 0 0 1.1rem; }
.subpop-f { display: flex; flex-direction: column; gap: 0.5rem; }
.subpop-f input[type="email"], .subpop-f input[type="tel"] {
  font-family: var(--font); font-size: 0.92rem; padding: 0.62rem 0.75rem;
  border: 1px solid var(--border-s); border-radius: 2px;
  background: var(--bg); color: var(--ink);
}
.subpop-f input:focus { outline: 2px solid var(--green-bg); border-color: var(--green); }
/* Honeypot — off-screen rather than display:none, which some bots detect. */
#mft-sub-w { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }
.subpop-b {
  font-family: var(--font-data); font-size: 0.82rem; font-weight: 600;
  padding: 0.68rem 1rem; cursor: pointer; margin-top: 0.15rem;
  background: var(--green); color: #fff; border: 1px solid var(--green); border-radius: 2px;
}
.subpop-b:hover:not(:disabled) { background: var(--green-light); color: var(--ink); }
.subpop-b:disabled { opacity: 0.6; cursor: default; }
.subpop-m { font-size: 0.82rem; margin-top: 0.6rem; min-height: 1rem; }
.subpop-m.ok  { color: var(--green); }
.subpop-m.err { color: var(--red); }
.subpop-n { font-size: 0.72rem; line-height: 1.5; color: var(--text3); margin: 0.9rem 0 0; }
@media (prefers-reduced-motion: reduce) { .subpop { animation: none; } }

/* ── Card byline ─────────────────────────────────────────────────────────────
   A face, a name and a role at the foot of every card. Cards carried a date
   and nothing else, which made a grid of headlines read as aggregated copy —
   the opposite of the pitch, which is that named practitioners write here.
   Desk pieces get the MF mark, so no card shows a gap where a face belongs. */
.cby {
  display: flex; align-items: center; gap: 0.5rem;
  margin-top: auto; padding-top: 0.75rem;
  border-top: 1px solid var(--rule);
}
.cby-i {
  width: 30px; height: 30px; border-radius: 50%; object-fit: cover;
  background: var(--surf2); flex: none;
}
/* min-width:0 on BOTH the flex item and the row. A grid track is 1fr, which
   is minmax(auto, 1fr) — it refuses to shrink below its content, so a nowrap
   long role line pushed every trio card
   to 677px and blew the homepage out by 632px. */
.cby { min-width: 0; }
.cby-t { display: flex; flex-direction: column; min-width: 0; line-height: 1.2; }
.cby-n {
  font-family: var(--font); font-size: 0.78rem; font-weight: 700; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cby-r {
  font-family: var(--font-data); font-size: 0.58rem; color: var(--text3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cby-m {
  margin-left: auto; flex: none;
  font-family: var(--font-data); font-size: 0.6rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text3);
}

/* The write-for-us rail block. Bordered like the newsletter box but in the
   accent, because it is an invitation rather than a form. */
.rail-write { border-left: 3px solid var(--gold); }
.rail-write .promo-a {
  display: inline-block; margin-top: 0.15rem; text-decoration: none;
  font-family: var(--font-data); font-size: 0.74rem; font-weight: 600;
  color: var(--green);
}
.rail-write .promo-a:hover { text-decoration: underline; }
/* Nav: the invitation reads as an offer, not another section. */
.nav-write { color: var(--green) !important; }
