@import url('https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,600;9..144,700;9..144,900&family=Bricolage+Grotesque:opsz,wght@12..96,400;12..96,500;12..96,600;12..96,700;12..96,800&family=JetBrains+Mono:wght@400;500&display=swap');
:root{
  --serif:'Fraunces',Georgia,serif; --sans:'Bricolage Grotesque',system-ui,sans-serif; --mono:'JetBrains Mono',ui-monospace,monospace;
  /* ⚠️ --ink-4 was #a39c91 — 2.48:1 on the paper, which is unreadable rather
     than merely quiet. It carries every date, byline and section label, so it
     is darkened to clear 4.5:1. Same story for the dark theme below. */
  --ink:#141310; --ink-2:#3b3831; --ink-3:#6d6860; --ink-4:#6f6961;
  --paper:#f7f4ed; --paper-2:#efeade; --card:#fffdf8;
  --rule:#e2dccd; --rule-2:#d3ccb9;
  --hot:#ff4d17; --deep:#1b3a5c; --moss:#41693f; --plum:#6b2f5e; --sun:#e8a300;
}
:root[data-theme="dark"]{
  --ink:#f4f1e8; --ink-2:#d2ccbe; --ink-3:#9b948a; --ink-4:#948d82;
  --paper:#12110f; --paper-2:#191713; --card:#1c1a16; --rule:#2c2924; --rule-2:#3b3730;
  --hot:#ff6a3d; --deep:#7fb0dd; --moss:#7fae7c; --plum:#c98bb9; --sun:#ffc44d;
}
*{box-sizing:border-box;}
html{scroll-behavior:smooth;}
body{margin:0;background:var(--paper);color:var(--ink);font-family:var(--sans);-webkit-font-smoothing:antialiased;}
a{color:inherit;text-decoration:none;}
h1,h2,h3,h4{margin:0;font-family:var(--serif);font-weight:700;letter-spacing:-.025em;line-height:1.05;}
p{margin:0;}
.mono{font-family:var(--mono);}
body::before{content:'';position:fixed;inset:0;pointer-events:none;z-index:9999;opacity:.03;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='4'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)'/%3E%3C/svg%3E");}
.wrap{width:100%;margin:0;padding:0 clamp(24px,3.2vw,56px);}

/* ticker */
.ticker{background:var(--ink);overflow:hidden;height:34px;display:flex;align-items:center;}
.ticker-track{display:flex;white-space:nowrap;animation:slide 44s linear infinite;}
.ticker-track span{font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;padding:0 26px;color:var(--paper);opacity:.8;}
.ticker-track span b{color:var(--hot);opacity:1;}
@keyframes slide{from{transform:translateX(0)}to{transform:translateX(-50%)}}

/* masthead */
.mast{border-bottom:2px solid var(--ink);position:sticky;top:0;background:var(--paper);z-index:50;}
.mast-in{display:flex;align-items:flex-end;justify-content:space-between;gap:24px;padding:22px 0 16px;}
.logo{display:flex;align-items:baseline;gap:12px;}
.logo .word{font-family:var(--serif);font-weight:900;font-size:42px;letter-spacing:-.045em;line-height:.85;}
.logo .word i{font-style:normal;color:var(--hot);}
.logo .est{font-family:var(--mono);font-size:9.5px;letter-spacing:.22em;text-transform:uppercase;color:var(--ink-4);padding-bottom:4px;}
.mast-r{display:flex;align-items:center;gap:9px;padding-bottom:4px;}
.icobtn{width:34px;height:34px;border:1px solid var(--rule-2);border-radius:50%;background:transparent;color:var(--ink-2);display:grid;place-items:center;cursor:pointer;transition:.18s;}
.icobtn:hover{background:var(--ink);color:var(--paper);border-color:var(--ink);}
.sub-btn{height:34px;padding:0 17px;border-radius:20px;background:var(--ink);color:var(--paper);border:none;font-family:var(--sans);font-weight:600;font-size:12.5px;cursor:pointer;transition:.18s;}
.sub-btn:hover{background:var(--hot);}
nav.cats{display:flex;border-top:1px solid var(--rule);overflow-x:auto;}
nav.cats a{font-weight:600;font-size:12.5px;padding:10px 0;margin-right:28px;white-space:nowrap;border-bottom:2px solid transparent;color:var(--ink-2);}
nav.cats a.on{border-bottom-color:var(--hot);color:var(--ink);}
nav.cats a:hover{color:var(--hot);}

/* ---------- hero mosaic ---------- */
.mosaic{display:grid;grid-template-columns:1.85fr 1fr 1fr;grid-template-rows:1fr 1fr;gap:14px;height:min(66vh,560px);margin:26px 0 18px;}
.mtile{position:relative;overflow:hidden;background:var(--paper-2);border:1px solid var(--rule-2);display:block;}
.mtile:first-child{grid-row:span 2;}
.mtile .slot{position:absolute;inset:0;}
.mtile .scrim{position:absolute;inset:0;pointer-events:none;background:linear-gradient(180deg,rgba(10,9,7,0) 30%,rgba(10,9,7,.28) 55%,rgba(10,9,7,.86) 100%);}
.mtile .over{position:absolute;left:0;right:0;bottom:0;padding:20px;pointer-events:none;}
.mtile:first-child .over{padding:28px;}
.badge{display:inline-block;font-family:var(--mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;padding:4px 9px;color:#fff;margin-bottom:10px;}
.mtile h3{color:#fff;font-size:19px;font-weight:700;line-height:1.2;text-wrap:pretty;}
.mtile:first-child h2{color:#fff;font-size:clamp(26px,2.9vw,42px);font-weight:900;letter-spacing:-.04em;line-height:1.06;text-wrap:pretty;}
.mby{display:flex;align-items:center;gap:9px;margin-top:14px;}
.mby .av{width:26px;height:26px;border-radius:50%;background:rgba(255,255,255,.2);border:1px solid rgba(255,255,255,.4);color:#fff;display:grid;place-items:center;font-family:var(--serif);font-weight:700;font-size:11px;}
.mby span{font-family:var(--mono);font-size:10.5px;color:rgba(255,255,255,.82);letter-spacing:.05em;}
.mtile:hover h3,.mtile:hover h2{text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:3px;}

/* tag bar */
.tagbar{display:flex;align-items:center;gap:14px;flex-wrap:wrap;border:1px solid var(--rule-2);padding:14px 18px;margin-bottom:12px;background:var(--card);}
.tagbar .lb{font-family:var(--mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-4);white-space:nowrap;}
.tagbar .chips{display:flex;gap:7px;flex-wrap:wrap;}
.chip{font-family:var(--mono);font-size:11.5px;color:var(--ink-2);border:1px solid var(--rule);padding:4px 10px;border-radius:20px;transition:.16s;cursor:pointer;}
.chip:hover{background:var(--ink);color:var(--paper);border-color:var(--ink);}

/* section head */
.sh{display:flex;align-items:baseline;gap:16px;margin:52px 0 22px;}
.sh h2{font-size:32px;font-weight:800;letter-spacing:-.035em;}
.sh .line{flex:1;height:1px;background:var(--rule-2);}
.sh a{font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);border:1px solid var(--rule-2);padding:6px 13px;border-radius:20px;white-space:nowrap;transition:.16s;}
.sh a:hover{background:var(--ink);color:var(--paper);border-color:var(--ink);}

/* trending row */
.trend{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;}
.tcard{position:relative;aspect-ratio:4/5;overflow:hidden;background:var(--paper-2);border:1px solid var(--rule-2);}
.tcard .slot{position:absolute;inset:0;}
.tcard .scrim{position:absolute;inset:0;pointer-events:none;background:linear-gradient(180deg,rgba(10,9,7,0) 40%,rgba(10,9,7,.85) 100%);}
.tcard .over{position:absolute;left:0;right:0;bottom:0;padding:18px;pointer-events:none;}
.tcard h3{color:#fff;font-size:18px;line-height:1.2;font-weight:700;}
.tcard .m{font-family:var(--mono);font-size:10px;color:rgba(255,255,255,.75);margin-top:8px;letter-spacing:.06em;}

/* editor pick — thumb rows */
.picks{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--rule);border:1px solid var(--rule);}
.pick{display:flex;gap:14px;padding:14px;background:var(--card);align-items:center;transition:.18s;}
.pick:hover{background:var(--paper-2);}
.pick .th{width:86px;height:66px;flex-shrink:0;overflow:hidden;background:var(--paper-2);position:relative;border:1px solid var(--rule);}
.pick .th .slot{position:absolute;inset:0;}
.pick h4{font-family:var(--sans);font-weight:600;font-size:14px;line-height:1.35;letter-spacing:-.005em;}
.pick .d{font-family:var(--mono);font-size:10px;color:var(--ink-4);margin-top:6px;letter-spacing:.06em;}
.pick:hover h4{color:var(--hot);}

/* weekly best + sidebar */
.wbgrid{display:grid;grid-template-columns:1.9fr 1fr;gap:32px;align-items:start;}
.wbmain{display:grid;gap:14px;}
.wbhero{position:relative;aspect-ratio:16/9;overflow:hidden;border:1px solid var(--rule-2);background:var(--paper-2);}
.wbhero .slot{position:absolute;inset:0;}
.wbhero .scrim{position:absolute;inset:0;pointer-events:none;background:linear-gradient(180deg,rgba(10,9,7,0) 45%,rgba(10,9,7,.88) 100%);}
.wbhero .over{position:absolute;left:0;right:0;bottom:0;padding:26px;pointer-events:none;}
.wbhero h2{color:#fff;font-size:clamp(22px,2.4vw,34px);font-weight:800;letter-spacing:-.035em;line-height:1.1;}
.wbsub{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;}
.side-h{font-family:var(--mono);font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--ink-4);padding-bottom:12px;border-bottom:2px solid var(--ink);margin-bottom:4px;}
.pop{display:flex;gap:13px;padding:14px 0;border-bottom:1px solid var(--rule);align-items:center;}
.pop .th{width:64px;height:54px;flex-shrink:0;position:relative;overflow:hidden;background:var(--paper-2);border:1px solid var(--rule);}
.pop .th .slot{position:absolute;inset:0;}
.pop h4{font-family:var(--sans);font-weight:600;font-size:13.5px;line-height:1.35;}
.pop .d{font-family:var(--mono);font-size:10px;color:var(--ink-4);margin-top:5px;}
.pop:hover h4{color:var(--hot);}
.catlist{margin-top:34px;}
.catrow{display:flex;align-items:center;gap:10px;padding:11px 0;border-bottom:1px solid var(--rule);font-size:14px;font-weight:500;cursor:pointer;}
.catrow .sw{width:9px;height:9px;border-radius:2px;flex-shrink:0;}
.catrow .n{margin-left:auto;font-family:var(--mono);font-size:11px;color:var(--ink-4);border:1px solid var(--rule);border-radius:20px;padding:2px 9px;}
.catrow:hover{color:var(--hot);}
.promo{margin-top:34px;border:1.5px dashed var(--rule-2);padding:26px 20px;text-align:center;background:var(--card);}
.promo .k{font-family:var(--mono);font-size:9.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--ink-4);}
.promo h4{font-family:var(--serif);font-size:21px;font-weight:700;margin:10px 0 8px;letter-spacing:-.02em;}
.promo p{font-size:12.5px;color:var(--ink-3);line-height:1.55;}
.promo button{margin-top:14px;width:100%;height:38px;border:none;background:var(--ink);color:var(--paper);font-family:var(--sans);font-weight:600;font-size:13px;cursor:pointer;transition:.18s;}
.promo button:hover{background:var(--hot);}

/* latest list */
.latest{display:grid;grid-template-columns:1.9fr 1fr;gap:32px;align-items:start;}
/* No rail worth the column (one author, no products) — blog.php says so and
   the cards take the whole width, three up instead of two. Same cards, same
   classes; the only thing removed is the empty third. */
.latest.full{grid-template-columns:1fr;}
.latest.full .lgrid{grid-template-columns:repeat(3,1fr);}
/* ⚠️ These two are NOT optional. `.latest.full .lgrid` is specificity (0,3,0);
   the responsive rules further down that collapse `.lgrid` are (0,1,0), so
   without an override at the same specificity the three-up grid would win on
   a phone and put three cards across a 390px screen. */
@media(max-width:1100px){ .latest.full .lgrid{grid-template-columns:1fr 1fr;} }
@media(max-width:640px){  .latest.full .lgrid{grid-template-columns:1fr;} }
.lgrid{display:grid;grid-template-columns:repeat(2,1fr);gap:14px;}
.lcard{border:1px solid var(--rule-2);background:var(--card);display:flex;flex-direction:column;transition:.18s;}
.lcard:hover{background:var(--paper-2);}
.lcard .im{position:relative;aspect-ratio:16/9;overflow:hidden;background:var(--paper-2);border-bottom:1px solid var(--rule);}
.lcard .im .slot{position:absolute;inset:0;}
.lcard .bd{padding:18px;display:flex;flex-direction:column;flex:1;}
.lcard h3{font-size:20px;font-weight:700;line-height:1.22;margin-bottom:9px;}
.lcard p{font-size:13.5px;color:var(--ink-3);line-height:1.6;flex:1;}
.lcard .ft{display:flex;align-items:center;gap:9px;margin-top:16px;padding-top:14px;border-top:1px solid var(--rule);font-family:var(--mono);font-size:10px;color:var(--ink-4);text-transform:uppercase;letter-spacing:.07em;}
.lcard .ft .rm{margin-left:auto;color:var(--ink);border-bottom:1px solid var(--hot);}

/* dark strip */
.strip{background:var(--ink);margin-top:64px;padding:60px 0;}
:root[data-theme="dark"] .strip{background:#000;}
.strip .wrap{display:grid;grid-template-columns:1fr 1fr;gap:52px;align-items:center;}
.kicker{display:inline-flex;align-items:center;gap:8px;font-family:var(--mono);font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--hot);margin-bottom:16px;}
.kicker::before{content:'';width:26px;height:1px;background:currentColor;}
.strip .kicker{color:var(--sun);}
.strip h2{font-size:clamp(28px,3.4vw,44px);font-weight:800;letter-spacing:-.04em;color:#fff;}
.strip p{color:#b9b3a7;font-size:16px;line-height:1.65;margin-top:15px;}
.codewin{background:#0b0a08;border:1px solid #2a2722;border-radius:8px;overflow:hidden;}
.codewin .bar{display:flex;align-items:center;gap:6px;padding:10px 13px;border-bottom:1px solid #2a2722;}
.codewin .bar i{width:9px;height:9px;border-radius:50%;display:block;}
.codewin .bar span{font-family:var(--mono);font-size:10.5px;color:#6a655d;margin-left:8px;}
.codewin pre{margin:0;padding:18px;font-family:var(--mono);font-size:12.5px;line-height:1.75;color:#c9c3b6;overflow-x:auto;}
.kw{color:#ff9d7a;}.st{color:#9ad67f;}.cm{color:#5f5a52;}.fn{color:#ffd479;}.nb{color:#8fc7ff;}

/* pull quote */
.pull{margin:64px 0;padding:52px 0;border-top:2px solid var(--ink);border-bottom:2px solid var(--ink);text-align:center;}
.pull blockquote{margin:0 auto;max-width:22ch;font-family:var(--serif);font-weight:600;font-size:clamp(28px,4vw,50px);line-height:1.1;letter-spacing:-.035em;font-style:italic;}
.pull blockquote span{color:var(--hot);}
.pull cite{display:block;margin-top:22px;font-family:var(--mono);font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-4);font-style:normal;}

/* numbers */
.nums{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--rule);border:1px solid var(--rule);}
.nm-c{background:var(--card);padding:28px 24px;}
.nm-c .v{font-family:var(--serif);font-weight:900;font-size:42px;letter-spacing:-.045em;line-height:1;}
.nm-c .l{font-family:var(--mono);font-size:10.5px;text-transform:uppercase;letter-spacing:.12em;color:var(--ink-4);margin-top:9px;}

/* podcast + links */
.split{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:var(--rule);border:1px solid var(--rule);}
.pane{background:var(--card);padding:30px;}
.pane h3{font-size:24px;font-weight:800;letter-spacing:-.03em;margin-bottom:5px;}
.pod{display:grid;grid-template-columns:auto 1fr auto;gap:18px;align-items:center;padding:16px 0;border-bottom:1px solid var(--rule);}
.pod .play{width:42px;height:42px;border-radius:50%;border:1.5px solid var(--ink);display:grid;place-items:center;flex-shrink:0;transition:.18s;}
.pod:hover .play{background:var(--hot);border-color:var(--hot);color:#fff;}
.pod h4{font-family:var(--serif);font-size:18px;font-weight:600;line-height:1.25;}
.pod .g{font-family:var(--mono);font-size:10px;color:var(--ink-4);text-transform:uppercase;letter-spacing:.08em;margin-top:5px;}
.wave{display:flex;align-items:flex-end;gap:2px;height:24px;}
.wave i{width:3px;background:var(--rule-2);border-radius:2px;display:block;}
.rl{display:flex;gap:12px;padding:13px 0;border-bottom:1px solid var(--rule);align-items:baseline;}
.rl .dot{width:7px;height:7px;border-radius:50%;flex-shrink:0;margin-top:6px;}
.rl h4{font-family:var(--sans);font-weight:600;font-size:14px;line-height:1.4;}
.rl .src{font-family:var(--mono);font-size:10px;color:var(--ink-4);margin-top:4px;}

/* authors */
.authors{display:grid;grid-template-columns:repeat(4,1fr);gap:22px;}
.auth .ring{width:66px;height:66px;border-radius:50%;display:grid;place-items:center;font-family:var(--serif);font-weight:700;font-size:24px;color:#fff;margin-bottom:13px;}
.auth h4{font-family:var(--sans);font-weight:700;font-size:15px;}
.auth .role{font-family:var(--mono);font-size:10px;text-transform:uppercase;letter-spacing:.1em;color:var(--hot);margin-top:5px;}
.auth p{font-size:13px;line-height:1.6;color:var(--ink-3);margin-top:9px;}
.auth .cnt{font-family:var(--mono);font-size:10px;color:var(--ink-4);margin-top:8px;}

/* newsletter */
.news{margin:64px 0;border:2px solid var(--ink);padding:48px 40px;display:grid;grid-template-columns:1fr auto;gap:38px;align-items:center;background:var(--card);position:relative;overflow:hidden;}
.news::after{content:'✦';position:absolute;right:-26px;bottom:-66px;font-size:210px;color:var(--paper-2);z-index:0;line-height:1;}
.news>*{position:relative;z-index:1;}
.news h2{font-size:35px;font-weight:800;letter-spacing:-.04em;}
.news p{color:var(--ink-3);font-size:15px;margin-top:11px;max-width:48ch;line-height:1.6;}
.form{display:flex;border:1.5px solid var(--ink);overflow:hidden;min-width:370px;}
.form input{flex:1;border:none;outline:none;background:transparent;padding:13px 15px;font-family:var(--sans);font-size:14px;color:var(--ink);}
.form input::placeholder{color:var(--ink-4);}
.form button{border:none;background:var(--ink);color:var(--paper);padding:0 21px;font-family:var(--sans);font-weight:700;font-size:13.5px;cursor:pointer;transition:.18s;}
.form button:hover{background:var(--hot);}
.fine{font-family:var(--mono);font-size:10.5px;color:var(--ink-4);margin-top:10px;letter-spacing:.04em;}

footer{border-top:2px solid var(--ink);padding:44px 0 30px;}
.fgrid{display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:38px;}
.fh{font-family:var(--mono);font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:var(--ink-4);margin-bottom:13px;}
.fl{display:flex;flex-direction:column;gap:9px;font-size:14px;color:var(--ink-2);}
.fl a:hover{color:var(--hot);}
.fbot{display:flex;justify-content:space-between;align-items:center;margin-top:40px;padding-top:20px;border-top:1px solid var(--rule);font-family:var(--mono);font-size:10.5px;color:var(--ink-4);letter-spacing:.06em;}

@media(max-width:1100px){
  .mosaic{grid-template-columns:1fr 1fr;grid-template-rows:auto;height:auto;}
  .mosaic .mtile{aspect-ratio:16/10;}
  .mosaic .mtile:first-child{grid-row:auto;grid-column:span 2;aspect-ratio:16/8;}
  .trend,.picks,.wbsub,.lgrid,.authors,.nums{grid-template-columns:1fr 1fr;}
  .wbgrid,.latest,.split,.strip .wrap,.news{grid-template-columns:1fr;}
  .fgrid{grid-template-columns:1fr 1fr;}
  .form{min-width:0;width:100%;}
}
@media(max-width:640px){
  /* ⚠️ .nums is NOT in this list: a figure and a three-word label do not need a
     whole phone width, and four of them stacked ran 492px for 20 characters of
     information. It goes 2-up and compact instead — see the .nums block below. */
  .mosaic,.trend,.picks,.wbsub,.lgrid,.authors{grid-template-columns:1fr;}
  .mosaic .mtile:first-child{grid-column:auto;}
  .art-grid{grid-template-columns:1fr !important;}
}

/* ============================================================
   TWEAK VARIANTS — paper stock · voice · rhythm
   ============================================================ */
:root{--grain:.03;--ruleW:1px;--tCase:none;--tTrack:-.025em;--tWeight:900;--air:1;}
body::before{opacity:var(--grain);}

/* ---- paper stock ---- */
:root[data-stock="news"]{
  --paper:#ebeced;--paper-2:#e1e3e5;--card:#f9fafa;
  --ink:#15171a;--ink-2:#393e43;--ink-3:#646b72;--ink-4:#666d74;
  --rule:#d4d7da;--rule-2:#bfc4c8;
  --hot:#c3330f;--deep:#1f4b6e;--moss:#3a6340;--plum:#5f2c56;--sun:#a8780b;
  --grain:.07;--ruleW:1.5px;
}
:root[data-stock="midnight"]{
  --ink:#f4f1e8;--ink-2:#d2ccbe;--ink-3:#9b948a;--ink-4:#948d82;
  --paper:#0e0d0b;--paper-2:#161512;--card:#1a1815;--rule:#292620;--rule-2:#3a362e;
  --hot:#ff6a3d;--deep:#7fb0dd;--moss:#7fae7c;--plum:#c98bb9;--sun:#ffc44d;
  --grain:.05;
}
:root[data-stock="news"] .mast,:root[data-stock="news"] footer,
:root[data-stock="news"] .pull,:root[data-stock="news"] .news,
:root[data-stock="news"] .side-h{border-width:var(--ruleW);}
:root[data-stock="news"] .badge{border-radius:0;}
:root[data-stock="news"] .chip,:root[data-stock="news"] .sh a,
:root[data-stock="news"] .catrow .n,:root[data-stock="news"] .backb{border-radius:0;}
:root[data-stock="news"] .sub-btn{border-radius:0;}

/* ---- typographic voice ---- */
:root[data-voice="brutalist"]{--serif:'Bricolage Grotesque',system-ui,sans-serif;--tTrack:-.05em;--tWeight:800;}
:root[data-voice="brutalist"] h1,:root[data-voice="brutalist"] h2,
:root[data-voice="brutalist"] h3,:root[data-voice="brutalist"] h4{letter-spacing:var(--tTrack);font-weight:var(--tWeight);}
:root[data-voice="brutalist"] .sh h2,:root[data-voice="brutalist"] .pane h3{text-transform:uppercase;letter-spacing:-.02em;}
:root[data-voice="brutalist"] .logo .word{letter-spacing:-.06em;font-weight:800;}
:root[data-voice="brutalist"] .pull blockquote{font-style:normal;text-transform:uppercase;font-size:clamp(24px,3.2vw,42px);}
:root[data-voice="brutalist"] .art .lede{font-family:var(--sans);font-size:19px;}
:root[data-voice="brutalist"] .art p.drop::first-letter{font-family:var(--sans);}
:root[data-voice="brutalist"] .badge{font-weight:700;}

:root[data-voice="classic"]{--tTrack:-.005em;--tWeight:400;--air:1.35;}
:root[data-voice="classic"] h1,:root[data-voice="classic"] h2,
:root[data-voice="classic"] h3,:root[data-voice="classic"] h4{font-weight:400;letter-spacing:var(--tTrack);line-height:1.14;}
:root[data-voice="classic"] .logo .word{font-weight:400;letter-spacing:-.01em;}
:root[data-voice="classic"] .mtile:first-child h2,:root[data-voice="classic"] .nm-c .v,
:root[data-voice="classic"] .art .h1{font-weight:600;}
:root[data-voice="classic"] .sh h2{font-weight:400;}
:root[data-voice="classic"] .sh,:root[data-voice="classic"] .art h3{letter-spacing:.01em;}
:root[data-voice="classic"] .art p{font-size:18.5px;line-height:1.85;}
:root[data-voice="classic"] .art .lede{font-style:italic;font-size:23px;}
:root[data-voice="classic"] .badge{letter-spacing:.2em;}

/* ---- layout rhythm ---- */
/* ---- layout rhythm (desktop only — breakpoints below own the collapse) ---- */
@media(min-width:1101px){
:root[data-rhythm="newspaper"] .mosaic{grid-template-columns:1.4fr 1fr 1fr;grid-template-rows:1fr 1fr;height:min(52vh,440px);gap:9px;}
:root[data-rhythm="newspaper"] .mtile:first-child h2{font-size:clamp(22px,2.2vw,32px);}
:root[data-rhythm="newspaper"] .mtile h3{font-size:16px;}
:root[data-rhythm="newspaper"] .trend{grid-template-columns:repeat(6,1fr);gap:9px;}
:root[data-rhythm="newspaper"] .tcard{aspect-ratio:3/4;}
:root[data-rhythm="newspaper"] .tcard h3{font-size:14px;}
:root[data-rhythm="newspaper"] .tcard .m{display:none;}
:root[data-rhythm="newspaper"] .picks{grid-template-columns:repeat(4,1fr);}
:root[data-rhythm="newspaper"] .pick{padding:11px;gap:11px;}
:root[data-rhythm="newspaper"] .pick .th{width:62px;height:50px;}
:root[data-rhythm="newspaper"] .pick h4{font-size:13px;}
:root[data-rhythm="newspaper"] .lgrid{grid-template-columns:repeat(3,1fr);gap:9px;}
:root[data-rhythm="newspaper"] .lcard .bd{padding:14px;}
:root[data-rhythm="newspaper"] .lcard h3{font-size:17px;}
:root[data-rhythm="newspaper"] .lcard p{font-size:12.5px;line-height:1.55;}
:root[data-rhythm="newspaper"] .sh{margin:36px 0 16px;}
:root[data-rhythm="newspaper"] .sh h2{font-size:26px;}
:root[data-rhythm="newspaper"] .wbgrid,:root[data-rhythm="newspaper"] .latest{gap:24px;}
:root[data-rhythm="newspaper"] .art-grid{gap:34px;}
:root[data-rhythm="newspaper"] .art{max-width:66ch;}
:root[data-rhythm="newspaper"] .art p{font-size:16px;line-height:1.65;}
:root[data-rhythm="newspaper"] .rhero{aspect-ratio:24/7;}

:root[data-rhythm="gallery"] .mosaic{grid-template-columns:1fr 1fr;grid-template-rows:1.5fr 1fr;height:min(86vh,760px);gap:20px;}
:root[data-rhythm="gallery"] .mtile:first-child{grid-row:span 1;grid-column:span 2;}
:root[data-rhythm="gallery"] .mtile:nth-child(5){display:none;}
:root[data-rhythm="gallery"] .mtile:first-child h2{font-size:clamp(34px,4.4vw,64px);}
:root[data-rhythm="gallery"] .mtile:first-child .over{padding:40px;}
:root[data-rhythm="gallery"] .mtile h3{font-size:23px;}
:root[data-rhythm="gallery"] .trend{grid-template-columns:repeat(3,1fr);gap:20px;}
:root[data-rhythm="gallery"] .trend a:nth-child(4){display:none;}
:root[data-rhythm="gallery"] .tcard{aspect-ratio:1/1;}
:root[data-rhythm="gallery"] .tcard h3{font-size:22px;}
:root[data-rhythm="gallery"] .tcard .over{padding:24px;}
:root[data-rhythm="gallery"] .picks{grid-template-columns:repeat(2,1fr);}
:root[data-rhythm="gallery"] .pick{padding:20px;gap:18px;}
:root[data-rhythm="gallery"] .pick .th{width:120px;height:88px;}
:root[data-rhythm="gallery"] .pick h4{font-size:16px;}
:root[data-rhythm="gallery"] .lgrid{grid-template-columns:1fr;gap:20px;}
:root[data-rhythm="gallery"] .lcard{display:grid;grid-template-columns:1.1fr 1fr;}
:root[data-rhythm="gallery"] .lcard .im{aspect-ratio:auto;height:100%;border-bottom:none;border-right:1px solid var(--rule);}
:root[data-rhythm="gallery"] .lcard .bd{padding:26px;}
:root[data-rhythm="gallery"] .lcard h3{font-size:25px;}
:root[data-rhythm="gallery"] .sh{margin:70px 0 28px;}
:root[data-rhythm="gallery"] .sh h2{font-size:38px;}
:root[data-rhythm="gallery"] .tagbar,:root[data-rhythm="gallery"] .nums{display:none;}
:root[data-rhythm="gallery"] .rhero{aspect-ratio:16/9;}
:root[data-rhythm="gallery"] .art{max-width:76ch;}
:root[data-rhythm="gallery"] .art p{font-size:19px;line-height:1.85;}
}

/* ---- tweaks panel ---- */
.reader{position:fixed;inset:0;z-index:200;background:var(--paper);overflow-y:auto;display:none;}
.reader.on{display:block;}
.rbar{position:sticky;top:0;z-index:5;background:var(--paper);border-bottom:1px solid var(--rule);}
.rbar-in{display:flex;align-items:center;gap:16px;padding:14px 0;}
.backb{display:inline-flex;align-items:center;gap:8px;border:1px solid var(--rule-2);border-radius:20px;padding:7px 15px;font-size:12.5px;font-weight:600;background:transparent;color:var(--ink-2);cursor:pointer;transition:.16s;font-family:var(--sans);}
.backb:hover{background:var(--ink);color:var(--paper);border-color:var(--ink);}
.rprog{position:absolute;left:0;bottom:-1px;height:2px;background:var(--hot);width:0;}
.rhero{position:relative;aspect-ratio:21/8;overflow:hidden;border:1px solid var(--rule-2);background:var(--paper-2);margin:24px auto 0;max-width:1160px;}
.rhero .slot{position:absolute;inset:0;}
/* ⚠️ The reading column is 60% wider than it was (1160 → 1856), clamped to the
   viewport so it never forces a horizontal scrollbar on a laptop. The article
   itself is centred inside its own column rather than left-aligned against the
   sidebar — at this width, hugging the left edge leaves a canyon of nothing. */
/* The rail carries contents, next-up, the dispatch box and a product card, so
   it earns real width on a laptop rather than the 280px it started with. */
.art-grid{display:grid;grid-template-columns:minmax(0,1fr) 380px;gap:56px;align-items:start;
  padding:36px 0 0;max-width:min(1856px,96vw);margin:0 auto;}
@media(max-width:1500px){.art-grid{grid-template-columns:minmax(0,1fr) 330px;gap:44px;}}
/* ⚠️ `width:100%` is load-bearing, not decoration. Auto side margins turn OFF
   a grid item's default stretch, so the box falls back to fit-content — whose
   floor is its MIN-CONTENT. On a phone that made the article 410px wide inside
   a 358px column and the overflow guard silently clipped the text. An explicit
   width restores stretch; the max-width still caps it and the margins still
   centre it on a wide screen. */
.art{width:100%;max-width:96ch;margin-left:auto;margin-right:auto;}
.art .h1{font-family:var(--serif);font-weight:900;font-size:clamp(32px,4.4vw,58px);letter-spacing:-.045em;line-height:1.03;text-wrap:pretty;}
.art .lede{font-family:var(--serif);font-size:21px;line-height:1.5;color:var(--ink-2);margin-top:20px;font-weight:400;}
.artby{display:flex;align-items:center;gap:14px;margin:26px 0;padding:18px 0;border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);flex-wrap:wrap;}
.artby .av{width:46px;height:46px;border-radius:50%;background:var(--deep);color:#fff;display:grid;place-items:center;font-family:var(--serif);font-weight:700;font-size:18px;}
.artby .who{font-size:14.5px;font-weight:700;}
.artby .meta{font-family:var(--mono);font-size:11px;color:var(--ink-4);margin-top:3px;}
.shares{margin-left:auto;display:flex;gap:7px;}
.shares button{width:34px;height:34px;border:1px solid var(--rule-2);border-radius:50%;background:transparent;color:var(--ink-3);display:grid;place-items:center;cursor:pointer;transition:.16s;}
.shares button:hover{background:var(--hot);color:#fff;border-color:var(--hot);}
/* The rail is icon-only, so a copied link has no label to change to "Copied" — the button itself has to say so. */
.shares button.is-done{background:var(--ink);color:#fff;border-color:var(--ink);}
.art p{font-size:17.5px;line-height:1.75;color:var(--ink-2);margin:0 0 22px;}
.art p.drop::first-letter{float:left;font-family:var(--serif);font-weight:900;font-size:74px;line-height:.78;padding:6px 12px 0 0;color:var(--hot);}
.art h3{font-size:27px;font-weight:800;letter-spacing:-.03em;margin:38px 0 14px;}
.art blockquote{margin:32px 0;padding:4px 0 4px 26px;border-left:3px solid var(--hot);font-family:var(--serif);font-style:italic;font-size:22px;line-height:1.45;color:var(--ink);}
.art ul{margin:0 0 22px;padding-left:22px;}
.art li{font-size:17px;line-height:1.7;color:var(--ink-2);margin-bottom:9px;}
.art .figure{margin:32px 0;}
.art .figure .box{position:relative;aspect-ratio:16/9;overflow:hidden;border:1px solid var(--rule-2);background:var(--paper-2);}
.art .figure .box .slot{position:absolute;inset:0;}
.art .figure figcaption{font-family:var(--mono);font-size:11px;color:var(--ink-4);margin-top:9px;letter-spacing:.03em;}
.art .cw{margin:30px 0;}
.callout{margin:30px 0;border:1.5px solid var(--ink);background:var(--card);padding:22px 24px;}
.callout .k{font-family:var(--mono);font-size:9.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--hot);margin-bottom:9px;}
.callout p{font-size:15.5px;margin:0;line-height:1.65;}
.arttags{display:flex;gap:7px;flex-wrap:wrap;margin:36px 0;padding-top:26px;border-top:1px solid var(--rule);}
.abox{display:flex;gap:18px;padding:26px;border:1.5px solid var(--ink);background:var(--card);margin-bottom:36px;}
.abox .ring{width:62px;height:62px;border-radius:50%;display:grid;place-items:center;font-family:var(--serif);font-weight:700;font-size:23px;color:#fff;flex-shrink:0;}
.abox h4{font-family:var(--sans);font-weight:700;font-size:16px;}
.abox .role{font-family:var(--mono);font-size:10px;text-transform:uppercase;letter-spacing:.1em;color:var(--hot);margin:4px 0 8px;}
.abox p{font-size:13.5px;line-height:1.6;color:var(--ink-3);margin:0;}
/* article sidebar
   ⚠️ `position:sticky` alone does NOT hold a rail that is taller than the
   viewport: it scrolls with the page until its own bottom arrives, which is
   exactly the "it moves" complaint. Capping its height and letting it scroll
   INSIDE itself is what makes it stay put no matter how long the essay is. */
.asb{position:sticky;top:70px;max-height:calc(100vh - 88px);overflow-y:auto;overscroll-behavior:contain;
  /* The rail scrolls, but its scrollbar is hidden — it sits beside an article
     and a permanent second bar reads as a broken frame. */
  scrollbar-width:none;-ms-overflow-style:none;}
.asb::-webkit-scrollbar{width:0;height:0;}
.toc{border-left:2px solid var(--rule);padding-left:16px;}
.toc a{display:block;font-size:13px;color:var(--ink-3);padding:6px 0;line-height:1.4;}
.toc a:hover,.toc a.on{color:var(--hot);}
.nextup{display:flex;gap:12px;padding:13px 0;border-bottom:1px solid var(--rule);align-items:center;}
.nextup .th{width:58px;height:50px;flex-shrink:0;position:relative;overflow:hidden;background:var(--paper-2);border:1px solid var(--rule);}
.nextup .th .slot{position:absolute;inset:0;}
.nextup h4{font-family:var(--sans);font-weight:600;font-size:13px;line-height:1.35;}
.nextup .d{font-family:var(--mono);font-size:9.5px;color:var(--ink-4);margin-top:4px;}
.nextup:hover h4{color:var(--hot);}
/* comments */
.cmts{border-top:2px solid var(--ink);padding-top:32px;margin-top:8px;}
.cmt{display:flex;gap:14px;padding:20px 0;border-bottom:1px solid var(--rule);}
.cmt .av{width:38px;height:38px;border-radius:50%;display:grid;place-items:center;font-family:var(--serif);font-weight:700;font-size:15px;color:#fff;flex-shrink:0;}
.cmt .nm{font-size:13.5px;font-weight:700;}
.cmt .tm{font-family:var(--mono);font-size:10px;color:var(--ink-4);}
.cmt p{font-size:14.5px;line-height:1.65;color:var(--ink-2);margin:8px 0 0;}
.cmt .acts{display:flex;gap:14px;margin-top:10px;font-family:var(--mono);font-size:10.5px;color:var(--ink-4);text-transform:uppercase;letter-spacing:.07em;}
.cmt .acts span{cursor:pointer;}
.cmt .acts span:hover{color:var(--hot);}
.cmtbox{display:flex;gap:14px;padding:22px 0 0;}
.cmtbox textarea{flex:1;min-height:80px;resize:vertical;border:1px solid var(--rule-2);background:var(--card);padding:13px 15px;font-family:var(--sans);font-size:14.5px;color:var(--ink);outline:none;}
.cmtbox textarea:focus{border-color:var(--ink);}

/* ============================================================
   Production addendum — added when the design was ported to the
   live blog. The design used <image-slot>, a drag-and-drop
   placeholder from the design canvas; real posts carry a real
   featured image, or none at all.
   ============================================================ */
.slot{display:block;position:relative;overflow:hidden;background:var(--paper-2);}
.slot img{width:100%;height:100%;object-fit:cover;display:block;}
/* No featured image: a quiet lettered plate rather than a broken frame or a
   stock photo nobody chose. Uses the post's own category colour. */
.slot.empty{display:grid;place-items:center;background:
  linear-gradient(135deg,color-mix(in oklab,var(--sl,#6d6860) 22%,var(--paper-2)),var(--paper-2));}
.slot.empty span{font-family:var(--serif);font-weight:900;font-size:clamp(28px,6vw,64px);
  color:color-mix(in oklab,var(--sl,#6d6860) 55%,transparent);letter-spacing:-.04em;user-select:none;}
.mtile .slot,.tcard .slot,.wbhero .slot,.rhero .slot{position:absolute;inset:0;}
.lcard .im .slot,.pick .th .slot,.pop .th .slot,.nextup .th .slot{position:absolute;inset:0;}

/* Empty-state for a blog with nothing published yet. */
.blank{padding:90px 0;text-align:center;}
.blank h2{font-size:clamp(24px,3vw,34px);margin-bottom:10px;}
.blank p{color:var(--ink-3);font-size:15px;max-width:44ch;margin:0 auto;line-height:1.65;}

/* Pagination, which the static design had no need for. */
.pager{display:flex;gap:9px;justify-content:center;padding:10px 0 70px;}
.pager a,.pager span{font-family:var(--mono);font-size:12px;padding:9px 15px;border:1px solid var(--rule-2);
  background:var(--card);color:var(--ink-2);}
.pager .cur{background:var(--ink);color:var(--paper);border-color:var(--ink);}
.pager a:hover{border-color:var(--ink-3);}

/* The reader is a full page here, not an overlay — posts have their own URL so
   they can be linked, shared and indexed. */
.reader.page{position:static;transform:none;opacity:1;visibility:visible;height:auto;overflow:visible;background:var(--paper);}

/* The design's drop cap applied to the real first paragraph. The source marked
   it by hand (<p class="drop">); a post's body is generated from blocks or
   Markdown, so it is selected structurally instead — the first paragraph of
   the article, whichever renderer produced it. */
/* ⚠️ `.art > p:first-of-type` also matched the LEDE, so the page got two drop
   caps. The design puts the cap on the paragraph immediately after the byline,
   which is exactly what this selects. */
.art .artby + p::first-letter,
.art .pb-inarticle .pb-b:first-of-type p:first-of-type::first-letter{
  float:left;font-family:var(--serif);font-weight:900;font-size:74px;line-height:.78;
  padding:6px 12px 0 0;color:var(--hot);
}
@media(max-width:640px){
  .art .artby + p::first-letter,
  .art .pb-inarticle .pb-b:first-of-type p:first-of-type::first-letter{font-size:56px;}
}
/* A partly-filled Editor's pick row showed an empty bordered cell; size the
   grid to what is actually there. */
.picks[data-n="1"]{grid-template-columns:1fr;}
.picks[data-n="2"]{grid-template-columns:1fr 1fr;}

/* ============================================================
   CODE BLOCKS INSIDE AN ARTICLE
   ------------------------------------------------------------
   ⚠️ These were rendering and completely invisible. The builder's own
   stylesheet gives .pb-code a dark surface (--pb-sf, #11141b), while the
   article wrapper sets `color:inherit` so the page's near-black ink applies —
   dark text on a dark box. The markup was correct, the CSS was correct, and
   nothing was readable.

   Rather than lightening the box, match the design's own .codewin terminal:
   dark panel, warm light text. That is what the source design uses for code
   inside an essay, so this is the intended look rather than a patch.
   ============================================================ */
.pb-inarticle .pb-code{
  background:#0b0a08;border:1px solid #2a2722;border-radius:8px;
  padding:18px 20px;margin:0 0 26px;overflow-x:auto;
  -webkit-overflow-scrolling:touch;
}
.pb-inarticle .pb-code code{
  font-family:var(--mono);font-size:12.5px;line-height:1.75;
  color:#c9c3b6;background:none;border:none;padding:0;white-space:pre;
}
/* Inline `code` in a paragraph stays light-on-paper — it sits in running text. */
.pb-inarticle p code,.pb-inarticle li code{
  background:var(--paper-2);border:1px solid var(--rule);border-radius:5px;
  padding:1px 6px;font-family:var(--mono);font-size:.88em;color:var(--ink);
}
.pb-inarticle .pb-list{margin:0 0 1.3em;padding-left:1.35em;}
.pb-inarticle .pb-list li{margin:0 0 .6em;color:var(--ink-2);}
.pb-inarticle .pb-alert{
  border-left:3px solid var(--hot);border-top:none;border-right:none;border-bottom:none;
  background:var(--paper-2);border-radius:0 8px 8px 0;padding:16px 20px;margin:0 0 26px;
  color:var(--ink-2);font-size:15px;line-height:1.65;
}
.pb-inarticle h2{font-family:var(--serif);font-size:clamp(22px,3vw,30px);
  letter-spacing:-.025em;margin:1.6em 0 .5em;color:var(--ink);}
.pb-inarticle .pb-quote{border-left:3px solid var(--ink);background:transparent;
  padding:6px 0 6px 22px;border-radius:0;font-family:var(--serif);font-size:1.15em;}

/* ============================================================
   RESPONSIVE LAYER
   ------------------------------------------------------------
   ⚠️ max-width queries ONLY, so the desktop rendering stays byte-identical to
   the imported design. The source shipped grid-stacking at 1100/640 and
   nothing else — the masthead, reader bar, article header, buttons and footer
   had no mobile rules at all, which is why the pill buttons ("Back to blog",
   "Subscribe") wrapped their labels inside a fixed 34px height and looked
   broken.
   ============================================================ */

/* --- the pills, everywhere ---
   ⚠️ `.sub-btn` is a <button> in the source design, where the browser centres
   the label vertically for free. Rendered as an <a> (so it can be a real link
   to the dispatch section) it does not: measured at above=0 / below=19 in a
   34px pill — the text sat on the baseline, 9.5px above centre. A fixed height
   needs explicit centring on anything that is not a <button>.
   Harmless on the real <button>s that also use this class. */
.sub-btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;text-decoration:none;}
.sub-btn,.backb{white-space:nowrap;flex-shrink:0;}
.icobtn{flex-shrink:0;}

/* Mobile contents drawer — the sidebar's list, in the one place it helps on a
   phone. Hidden on desktop; the rail carries it there. */
.tocm{display:none;margin:0 0 26px;border:1px solid var(--rule-2);background:var(--card);}
.tocm>summary{list-style:none;cursor:pointer;padding:13px 16px;font-family:var(--mono);
  font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--ink-2);
  display:flex;align-items:center;justify-content:space-between;gap:10px;}
.tocm>summary::-webkit-details-marker{display:none;}
.tocm>summary::after{content:"+";font-family:var(--sans);font-size:16px;letter-spacing:0;color:var(--hot);}
.tocm[open]>summary::after{content:"−";}
.tocm .tocm-n{font-size:9.5px;letter-spacing:.1em;color:var(--ink-4);margin-left:auto;margin-right:4px;}
.tocm .toc{border-left:none;padding:0 16px 12px;}
.tocm .toc a{padding:8px 0;font-size:14px;border-bottom:1px solid var(--rule);}
.tocm .toc a:last-child{border-bottom:none;}

@media(max-width:1100px){
  .wrap{padding:0 20px;}
  /* ⚠️ minmax(0,1fr), NOT 1fr. A bare `1fr` track is `minmax(auto,1fr)`, whose
     automatic minimum grows to the widest thing inside it — so one long code
     line or a wide table stretched the whole article past the phone screen,
     and body's overflow guard then CLIPPED the text rather than scrolling it.
     Zeroing the track minimum is what lets the column actually fit. */
  .art-grid{grid-template-columns:minmax(0,1fr);}   /* the sidebar is unusable narrow */
  /* ⚠️ Undo the desktop rail's internal scroll. A capped, separately
     scrolling box makes sense beside an article; stacked under one on a phone
     it is a scroll trap inside a scroll. */
  .asb{position:static;max-height:none;overflow:visible;padding-right:0;margin-top:38px;}
  #toc-desk{display:none;}                   /* the drawer above replaces it */
  .tocm{display:block;}
  .news{padding:38px 30px;}
  .abox{padding:22px;}
}

@media(max-width:860px){
  .mast-in{flex-wrap:wrap;align-items:center;gap:14px;padding:16px 0 12px;}
  .mast-r{padding-bottom:0;margin-left:auto;}
  .rbar-in{gap:10px;padding:10px 0;}
  .rhero{margin-top:18px;}
  .art .h1,.art h1{font-size:clamp(27px,6vw,40px);}
  .news{grid-template-columns:1fr;padding:34px 26px;gap:24px;}
  .fgrid{gap:26px;}
}

@media(max-width:640px){
  .wrap{padding:0 16px;}

  /* masthead */
  .ticker{height:28px;}
  .ticker-track span{font-size:10px;padding:0 18px;}
  .logo .word{font-size:26px;}
  .logo .est{display:none;}                  /* secondary, and it crowds the row */
  .mast-in{padding:13px 0 10px;}
  .mast-r{gap:7px;}
  .sub-btn{height:32px;padding:0 13px;font-size:12px;}
  .icobtn{width:32px;height:32px;}
  .cats{gap:0;}
  .cats a{padding:11px 13px;font-size:12px;}

  /* hero mosaic + cards */
  .mosaic{gap:10px;margin:16px 0 14px;}
  .mosaic .mtile{aspect-ratio:16/11;}
  .mosaic .mtile:first-child{aspect-ratio:16/11;}
  .mtile:first-child h2{font-size:23px;}
  .mtile h3{font-size:17px;}
  .mtile .over,.mtile:first-child .over{padding:15px;}
  .tagbar{flex-direction:column;align-items:flex-start;gap:9px;padding:14px 16px;}
  .sh{margin:34px 0 16px;}
  .sh h2{font-size:23px;}
  .wbhero{aspect-ratio:16/11;}
  .wbsub{gap:10px;}
  .lcard .bd{padding:16px;}
  .pick,.pop,.nextup{padding:11px 12px;}

  /* the reading bar: keep back + theme + subscribe, drop the metadata */
  .rbar-in{gap:8px;padding:9px 0;}
  .rbar-in .mono{display:none;}
  .backb{padding:6px 12px;font-size:12px;}

  /* article */
  /* ⚠️ 21:8 is a desktop banner ratio. At 358px wide that is a 136px letterbox
     that crops the artwork to a strip — the image is there and unreadable.
     A phone gets a shape the picture actually survives. */
  .rhero{margin-top:14px;aspect-ratio:16/10;}
  .art{padding-top:22px;}
  /* Nothing inside an article may exceed the column, whatever it is. */
  .art img,.art video,.art iframe,.art figure,.art table,
  .pb-inarticle img,.pb-inarticle video,.pb-inarticle iframe{max-width:100%;height:auto;}
  .pb-inarticle .pb-embed{max-width:100%;}
  /* "By the numbers" from the builder: two 169px columns cannot hold a label
     like "limits we have not tested by exceeding". One per row, value and
     label side by side, reads at any width. */
  .pb-inarticle .pb-stats{grid-template-columns:1fr!important;gap:10px;text-align:left;}
  .pb-inarticle .pb-stat{display:flex;align-items:baseline;gap:12px;padding:11px 13px;
    border:1px solid var(--rule);border-radius:10px;background:var(--card);}
  .pb-inarticle .pb-stat strong{font-size:26px;line-height:1;flex-shrink:0;min-width:2.2em;}
  .pb-inarticle .pb-stat span{font-size:13px;line-height:1.4;}
  /* The pull-quote board: it was inheriting desktop padding and a 1.06em size
     on top of the larger body type, which pushed it past the screen. */
  .pb-inarticle .pb-quote{padding:12px 14px;font-size:1em;}
  .art blockquote{margin:24px 0;padding-left:16px;font-size:19px;}
  .art .lede{font-size:16px;}
  .artby{gap:11px;margin:20px 0;padding:14px 0;}
  .artby .shares{margin-left:auto;}
  .abox{flex-direction:column;gap:14px;padding:20px;}
  .abox .ring{width:52px;height:52px;font-size:20px;}
  .arttags{gap:6px;}
  .pb-inarticle .pb-code{padding:14px;margin:0 0 20px;}
  .pb-inarticle .pb-code code{font-size:11.5px;}

  /* blocks that were still two-up at this width */
  /* "By the numbers" stays 2×2 and shrinks — 4 full-width cards were 492px of
     scrolling for four short figures, the tallest cheap thing on the page. */
  .nums{grid-template-columns:1fr 1fr;}
  .nm-c{padding:14px 15px;}
  .nm-c .v{font-size:27px;}
  .nm-c .l{font-size:9px;letter-spacing:.1em;margin-top:5px;}
  .fgrid{grid-template-columns:1fr;gap:22px;}
  .fbot{flex-direction:column;gap:8px;text-align:left;}
  .news{padding:28px 20px;}
  .news h2{font-size:26px;}
  .form{flex-direction:column;}
  .form input,.form button{width:100%;}
  .pager{flex-wrap:wrap;}
  .promo{padding:20px;}
  .pull blockquote{font-size:22px;}
  .blank{padding:60px 0;}

  /* anything wide inside an article must scroll, not overflow the page */
  .art table,.pb-inarticle table{display:block;overflow-x:auto;}
}

@media(max-width:420px){
  .logo .word{font-size:22px;}
  .sub-btn{padding:0 11px;}
  .mosaic .mtile{aspect-ratio:4/3;}
  .mtile:first-child h2{font-size:20px;}
  .nm-c{padding:12px 12px;}
  .nm-c .v{font-size:24px;}
  .sh h2{font-size:20px;}
}

/* ============================================================
   THE min-width:auto TRAP
   ------------------------------------------------------------
   ⚠️ A grid or flex ITEM defaults to `min-width:auto`, which means it refuses
   to shrink below its content's min-content width. A <pre> with white-space:pre
   has a min-content width of its longest line — so one long shell command made
   the article track wider than the phone, and every line of the page was clipped
   on the right.

   `overflow-x:hidden` on the body HIDES that; it does not fix it, and it is why
   the page measured "no overflow" while the text was visibly cut off. The real
   fix is min-width:0 down the containing chain, so the track can shrink and the
   <pre> scrolls inside itself instead. */
.art-grid > *,.art,.asb,
.latest > *,.wbgrid > *,.wbmain,.split > *,.news > *{min-width:0;}
.pb-inarticle,.pb-inarticle .pb-b,.pb-inarticle .pb-w{min-width:0;max-width:100%;}

/* Belt and braces, after the real fix above.
   ⚠️ `clip`, NOT `hidden`. Per spec, an `overflow-x:hidden` on <body> forces
   the OTHER axis to compute to `auto` — which turns the body into a scroll
   container and silently breaks `position:sticky` on every descendant. That is
   what stopped the article sidebar sticking. `clip` guards against horizontal
   overflow without creating a scroll container. */
html,body{max-width:100%;overflow-x:clip;}
img,svg,iframe,table{max-width:100%;}
pre{max-width:100%;}

/* ============================================================
   SHARE ROW
   The block used to emit four unstyled <a> tags, which rendered as a run-on
   line of link text under every article. Real buttons, with each network's
   own mark, in the publication's own visual language rather than brand colours
   — they only take the brand colour on hover, so the row stays quiet.
   ============================================================ */
/* ⚠️ Top rule ONLY. .arttags below already opens with its own border and 36px
   of margin, so a bottom rule here left two hairlines with 92px of nothing
   between them — it read as a broken empty section, not as breathing room. */
.pb-share{display:flex;align-items:center;gap:16px;flex-wrap:wrap;
  padding:20px 0 0;border-top:1px solid var(--rule);margin:8px 0 0;}
.pb-share-l{font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink-4);flex-shrink:0;}
.pb-share-row{display:flex;gap:8px;flex-wrap:wrap;}
.pb-sh{display:inline-flex;align-items:center;justify-content:center;gap:8px;
  height:36px;padding:0 14px;border:1px solid var(--rule-2);border-radius:20px;
  background:transparent;color:var(--ink-2);cursor:pointer;font-family:var(--sans);
  font-size:12.5px;font-weight:600;white-space:nowrap;transition:.16s;}
.pb-sh svg{width:15px;height:15px;flex-shrink:0;}
.pb-sh:hover{border-color:var(--ink);background:var(--ink);color:var(--paper);}
/* Icon-only variant: a circle, same as the byline actions. */
.pb-share-icon .pb-sh{width:36px;padding:0;border-radius:50%;}
.pb-share-icon .pb-sh span{display:none;}
/* Labels-only: the mark comes off, otherwise this setting is indistinguishable
   from "Icon + label" and one of the three choices does nothing. */
.pb-share-label .pb-sh svg{display:none;}
.pb-share-label .pb-sh{padding:0 16px;}
/* Each network claims its own colour on hover — recognisable, never shouty. */
.pb-sh-x:hover{background:#000;border-color:#000;}
.pb-sh-facebook:hover{background:#1877f2;border-color:#1877f2;}
.pb-sh-linkedin:hover{background:#0a66c2;border-color:#0a66c2;}
.pb-sh-reddit:hover{background:#ff4500;border-color:#ff4500;}
.pb-sh-whatsapp:hover{background:#25d366;border-color:#25d366;}
.pb-sh-telegram:hover{background:#229ed9;border-color:#229ed9;}
.pb-sh-email:hover{background:var(--deep);border-color:var(--deep);}
.pb-sh-copy.is-done{background:var(--moss);border-color:var(--moss);color:#fff;}
@media(max-width:640px){
  .pb-share{gap:10px;padding:16px 0;}
  .pb-share-l{width:100%;}
  .pb-sh{height:34px;padding:0 12px;font-size:12px;}
  .pb-share-icon .pb-sh{width:34px;padding:0;}
}

/* ============================================================
   NEWSLETTER FORM
   ------------------------------------------------------------
   The design shipped a bare .form with a fixed 370px min-width and no states
   at all — no busy, no success, no error. It also had nowhere to say anything
   back, so a submit either navigated away or appeared to do nothing.
   ============================================================ */
.nlwrap{display:block;}
.nlwrap .form{min-width:0;width:100%;}
.nlwrap .form button{position:relative;display:inline-flex;align-items:center;justify-content:center;min-width:104px;}
.nlfine{margin-top:9px;font-family:var(--mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-4);}
.nlmsg{margin-top:10px;font-size:13px;line-height:1.5;padding:9px 12px;border-radius:7px;}
.nlmsg.ok{background:var(--paper-2);border-left:3px solid var(--moss);color:var(--ink-2);}
.nlmsg.bad{background:var(--paper-2);border-left:3px solid var(--hot);color:var(--ink-2);}
.nlwrap.is-busy .form button{opacity:.62;cursor:progress;}
/* Once it has worked, the input is no longer the point. */
.nlwrap.is-done .form{border-color:var(--moss);}
.nlwrap.is-done .form input{color:var(--ink-4);}

/* Compact variant — the footer column and anywhere narrow. */
.form-sm{min-width:0;border-width:1.5px;}
.form-sm input{padding:10px 12px;font-size:13px;}
.form-sm button{padding:0 15px;font-size:12.5px;}
.nlwrap-sm .nlfine{display:none;}          /* the big box already said it */
.nlwrap-sm .nlmsg{font-size:12px;padding:7px 10px;}

/* ============================================================
   FOOTER — the extra columns
   ============================================================ */
.fstat{display:flex;gap:18px;flex-wrap:wrap;margin-top:16px;font-family:var(--mono);font-size:10.5px;
  letter-spacing:.08em;text-transform:uppercase;color:var(--ink-4);}
.fstat strong{color:var(--ink);font-size:13px;font-weight:700;letter-spacing:0;}
.fsub{margin-top:26px;max-width:330px;}
.frecent{display:flex;flex-direction:column;gap:14px;}
.frecent a{display:block;}
.frecent .ft{display:block;font-size:14px;line-height:1.35;color:var(--ink-2);font-weight:500;}
.frecent a:hover .ft{color:var(--hot);}
.frecent .fm{display:block;margin-top:3px;font-family:var(--mono);font-size:10px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--ink-4);}
.fnum{margin-left:5px;font-family:var(--mono);font-size:10.5px;color:var(--ink-4);}
.ftags{display:flex;flex-wrap:wrap;gap:6px;}
.ftags a{font-family:var(--mono);font-size:11px;padding:4px 9px;border:1px solid var(--rule-2);
  border-radius:999px;color:var(--ink-3);transition:.15s;}
.ftags a:hover{border-color:var(--ink);background:var(--ink);color:var(--paper);}
.ftop{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--rule-2);background:transparent;
  border-radius:999px;padding:6px 13px;font-family:var(--mono);font-size:10px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink-3);cursor:pointer;transition:.16s;}
.ftop:hover{border-color:var(--ink);background:var(--ink);color:var(--paper);}

@media(max-width:960px){
  .fgrid{grid-template-columns:1fr 1fr;gap:32px 26px;}
  .news{grid-template-columns:1fr;gap:26px;padding:36px 26px;}
  .news h2{font-size:28px;}
}
@media(max-width:640px){
  .fsub{max-width:none;}
  .news{padding:28px 20px;margin:44px 0;}
  .news h2{font-size:24px;}
  /* A fixed-height pill row cannot survive a 320px screen side by side. */
  .nlwrap .form{flex-direction:column;border:none;gap:8px;}
  .nlwrap .form input{border:1.5px solid var(--ink);padding:12px 14px;}
  .nlwrap .form button{padding:12px 18px;width:100%;}
}

/* ============================================================
   THE SHOP — products from the panel's Content ▸ Marketplace tab.

   Same vocabulary as everything else on this page: hairline rules, a mono
   kicker, the serif for names, --hot for the one thing you click. Nothing new
   is invented; a product card is a .lcard that happens to carry a price.
   ============================================================ */
.shoprail{margin-top:34px;}
.shopintro{font-size:12.5px;color:var(--ink-3);line-height:1.55;margin:-2px 0 14px;}
.shoplede{font-size:14.5px;color:var(--ink-3);line-height:1.6;max-width:60ch;margin:-6px 0 20px;}

.shopcard{border:1px solid var(--rule-2);background:var(--card);margin-bottom:13px;transition:.18s;}
.shopcard:hover{border-color:var(--ink-4);}
.shopcard .bd{padding:13px 14px 14px;}
.shopcard h4{font-family:var(--serif);font-size:16.5px;font-weight:700;line-height:1.25;letter-spacing:-.02em;margin-bottom:5px;}
.shopcard p{font-size:12.5px;color:var(--ink-3);line-height:1.5;}
.shopcard .row{display:flex;align-items:center;gap:9px;margin-top:12px;padding-top:11px;border-top:1px solid var(--rule);}

.shopgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;}
.shopitem{border:1px solid var(--rule-2);background:var(--card);display:flex;flex-direction:column;transition:.18s;}
.shopitem:hover{background:var(--paper-2);}
/* A featured product gets the accent edge, not a bigger cell — the grid must
   stay a grid or one flagged item reflows the whole row. */
.shopitem.feat{border-color:var(--hot);}
.shopitem .bd{padding:16px;display:flex;flex-direction:column;flex:1;}
.shopitem h3{font-size:19px;font-weight:700;line-height:1.22;letter-spacing:-.02em;margin-bottom:7px;}
.shopitem p{font-size:13px;color:var(--ink-3);line-height:1.55;}
.shopitem .row{display:flex;align-items:center;gap:10px;margin-top:auto;padding-top:13px;border-top:1px solid var(--rule);}

/* the kicker line: kind · version · badge */
.shopcard .k,.shopitem .k{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin-bottom:7px;
  font-family:var(--mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-4);}
.shopcard .k em,.shopitem .k em{font-style:normal;color:var(--hot);border:1px solid currentColor;border-radius:20px;padding:1px 7px;letter-spacing:.1em;}
.shopcard .k i,.shopitem .k i{font-style:normal;}

.shopfeat{list-style:none;margin:11px 0 0;padding:0;display:flex;flex-direction:column;gap:5px;}
.shopfeat li{position:relative;padding-left:15px;font-size:12.5px;color:var(--ink-3);line-height:1.45;}
.shopfeat li::before{content:'';position:absolute;left:0;top:7px;width:5px;height:5px;background:var(--hot);}

.shopprice{display:flex;align-items:baseline;gap:7px;margin-right:auto;}
.shopprice b{font-family:var(--serif);font-size:19px;font-weight:800;letter-spacing:-.02em;}
.shopprice s{font-family:var(--mono);font-size:11px;color:var(--ink-4);}

.shopbuy{display:inline-flex;align-items:center;gap:6px;height:34px;padding:0 14px;flex-shrink:0;
  background:var(--ink);color:var(--paper);font-family:var(--sans);font-weight:600;font-size:13px;transition:.18s;}
.shopbuy:hover{background:var(--hot);color:#fff;}
.shopbuy.sm{height:30px;padding:0 11px;font-size:12px;}
.shopalt{font-family:var(--mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3);
  border-bottom:1px solid var(--rule-2);flex-shrink:0;}
.shopalt:hover{color:var(--hot);border-color:currentColor;}
.shopmore{display:inline-block;margin-top:2px;font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-3);border-bottom:1px solid var(--hot);}
.shopmore:hover{color:var(--hot);}

/* ---- the carousel ----
   Every frame is stacked in the same box and cross-faded. ⚠️ Opacity, not
   display: a display:none image is not decoded until it is shown, so the first
   advance flashed empty. They are all painted, only one is visible. */
.shopshots{position:relative;display:block;overflow:hidden;background:var(--paper-2);
  border-bottom:1px solid var(--rule);aspect-ratio:16/10;}
.shopshots.wide{aspect-ratio:16/9;}
.shopshots .ss{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:0;transition:opacity .7s ease;}
.shopshots .ss.on{opacity:1;}
.shopshots.empty{display:grid;place-items:center;}
.shopshots.empty span{font-family:var(--serif);font-size:38px;font-weight:800;color:var(--ink-4);opacity:.5;}
.ssdots{position:absolute;left:0;right:0;bottom:7px;display:flex;justify-content:center;gap:5px;}
.ssdots i{width:5px;height:5px;border-radius:50%;background:rgba(255,255,255,.45);
  box-shadow:0 0 0 1px rgba(0,0,0,.25);transition:background .3s;}
.ssdots i.on{background:#fff;}
@media(prefers-reduced-motion:reduce){.shopshots .ss{transition:none;}}

@media(max-width:1100px){
  .shopgrid{grid-template-columns:1fr 1fr;}
  /* ⚠️ 1100, NOT 640. `.dup` marks a rail that has the full-width section
     under it, and the duplication starts the moment `.latest` stops being two
     columns — which is exactly this breakpoint, not the phone one. Hiding it
     only on phones left a tablet printing 1,765px of rail directly above the
     same three products. An article page's rail carries no .dup and stays. */
  .shoprail.dup{display:none;}
}
@media(max-width:640px){
  .shopgrid{grid-template-columns:1fr;gap:12px;}
  .shoplede{font-size:13.5px;margin-bottom:15px;}
  .shoprail{margin-top:26px;}
  .shopintro{display:none;}

  /* The section is what a phone actually gets, so it earns its height back:
     shorter art, tighter card, three bullets. Six products still fit inside a
     reasonable scroll instead of running a screen each. */
  .shopitem .bd{padding:13px;}
  .shopitem h3{font-size:17px;}
  .shopitem p{font-size:12.5px;}
  .shopitem .row{padding-top:11px;}
  .shopitem .shopshots{aspect-ratio:16/9;}
  .shopfeat{margin-top:9px;gap:4px;}
  .shopfeat li{font-size:12px;}
  .shopfeat li:nth-child(n+4){display:none;}
}

/* ============================================================
   THE FOOTER ON A PHONE — measured, then cut
   ------------------------------------------------------------
   At 390×844 the tail after the last post ran 1,616px: a 323px dispatch
   section plus a 1,293px footer. Nearly two full screens of scrolling on a
   page whose entire point is the article above it.

   The height was not four columns' worth of information — it was four columns
   stacked into ONE at 640px, carrying duplicates:

     · the intro <p> in the brand block prints the SAME sentence that
       #dispatch prints ~200px higher up
     · .fsub is a SECOND subscribe form, directly under the big one

   So the phone rules cut duplication and go back to two columns; they do not
   invent a different footer. Latest and Topics are trimmed (not removed) —
   the full set is one tap away on /blog. Nothing here applies above 640px:
   max-width only, so the desktop footer is byte-for-byte what it was.
   ============================================================ */
@media(max-width:640px){
  footer{padding:26px 0 20px;}

  /* Two columns. One stacked column is what made it 1,293px tall. */
  .fgrid{grid-template-columns:1fr 1fr;gap:24px 18px;}
  .fgrid > :first-child{grid-column:1 / -1;}   /* brand block keeps the full width */
  /* Three blocks in two columns leaves the last cell empty, so the Topics block
     takes the whole row instead of talking to a hole — and its link list can
     then run across rather than down. */
  .fgrid > :last-child{grid-column:1 / -1;}
  .fgrid > :last-child .fl{flex-direction:row;flex-wrap:wrap;gap:8px 17px;}

  /* ⚠️ these three carry inline styles from blog-foot.php — a plain rule loses. */
  .fgrid .logo{margin-bottom:8px !important;}
  .fgrid .logo .word{font-size:23px !important;}
  .fl[style]{margin-bottom:15px !important;}   /* Sections list: inline 22px */
  .ftags + .fh{margin-top:15px !important;}    /* "Elsewhere" heading: inline 22px */

  .fgrid > :first-child > p{display:none;}     /* #dispatch already said this */
  .fsub{display:none;}                         /* ...and already has this form */
  .fstat{margin-top:12px;gap:14px;}

  .fh{margin-bottom:8px;}
  .fl{gap:7px;font-size:13.5px;}
  .fl > a:nth-child(n+5){display:none;}        /* Sections 6 → 4 (the nav has 4, so it is untouched) */

  .frecent{gap:11px;}
  .frecent > a:nth-child(n+4){display:none;}   /* Latest 4 → 3 */
  .frecent .ft{font-size:13.5px;
    /* In a 170px column a headline can run five lines and blow the row height. */
    display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;}

  .ftags{gap:5px;}
  .ftags a{font-size:10.5px;padding:3px 8px;}
  .ftags a:nth-child(n+7){display:none;}       /* Topics 12 → 6 */

  /* © and Top on one row, the colophon wrapping under them — 2 lines, not 3. */
  .fbot{flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:space-between;
    gap:7px 12px;text-align:left;margin-top:22px;padding-top:14px;}
  .fbot-mid{order:3;flex-basis:100%;}
  .ftop{padding:5px 11px;}
}

/* ⚠️ 380, not 420 — 390px is a current iPhone, i.e. the MAINSTREAM phone, not a
   narrow edge case. Trimming Latest to two posts there costs the most common
   visitor a link for no reason. This pass is for the genuinely small screen. */
@media(max-width:380px){
  .fgrid{gap:20px 14px;}
  .frecent > a:nth-child(n+3){display:none;}   /* Latest 3 → 2 */
  .ftags a:nth-child(n+5){display:none;}       /* Topics 6 → 4 */
}

/* ============================================================
   DARK-MODE CHIP CONTRAST
   The category colours are LIGHTENED for the dark theme (plum goes #6b2f5e →
   #c98bb9), and white text on a pastel is 2.7:1 — worse than the light theme
   it was designed for. On dark, these chips take dark ink instead; the colour
   still identifies the section, it just stops fighting the label.
   ============================================================ */
:root[data-theme="dark"] .badge,
:root[data-theme="dark"] .artby .av,
:root[data-theme="dark"] .abox .ring,
:root[data-stock="midnight"] .badge,
:root[data-stock="midnight"] .artby .av,
:root[data-stock="midnight"] .abox .ring{color:#12110f;}
