/* spaces-svc — public stylesheet
   Matches the Niche of One network (os.css / RATION v5):
   warm paper stock, ink text, Oswald display, Space Mono kickers, Lora reading.
   DISCIPLINE: red (--buy) is the MONEY DOOR ONLY — price, unlock, tip. Never décor. */

/* Self-hosted fonts (no Google CDN): woff2 under /fonts/, font-display:swap baked in.
   Latin + latin-ext split by unicode-range so only the needed subset downloads.
   Mirrors the network's /fonts/display.css + reader.css. */
/* Poppins — display/SHOUT (--disp): 500/600/700/800 */
@font-face{font-family:'Poppins';font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/poppins-v24-pxiByp8kv8JHgFVrLGT9Z1JlFc-K.woff2) format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Poppins';font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/poppins-v24-pxiByp8kv8JHgFVrLGT9Z1xlFQ.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Poppins';font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/poppins-v24-pxiByp8kv8JHgFVrLEj6Z1JlFc-K.woff2) format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Poppins';font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/poppins-v24-pxiByp8kv8JHgFVrLEj6Z1xlFQ.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Poppins';font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/poppins-v24-pxiByp8kv8JHgFVrLCz7Z1JlFc-K.woff2) format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Poppins';font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/poppins-v24-pxiByp8kv8JHgFVrLCz7Z1xlFQ.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Poppins';font-style:normal;font-weight:800;font-display:swap;src:url(/fonts/poppins-v24-pxiByp8kv8JHgFVrLDD4Z1JlFc-K.woff2) format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Poppins';font-style:normal;font-weight:800;font-display:swap;src:url(/fonts/poppins-v24-pxiByp8kv8JHgFVrLDD4Z1xlFQ.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
/* Figtree — variable (300..900), body/UI face (--ui) */
@font-face{font-family:'Figtree';font-style:normal;font-weight:300 900;font-display:swap;src:url(/fonts/figtree-variable-latinext.woff2) format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Figtree';font-style:normal;font-weight:300 900;font-display:swap;src:url(/fonts/figtree-variable-latin.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
/* Space Mono — kickers/mono (--mono): 400/700 */
@font-face{font-family:'Space Mono';font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/spacemono-v17-i7dPIFZifjKcF5UAWdDRYE98RWq7.woff2) format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Space Mono';font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/spacemono-v17-i7dPIFZifjKcF5UAWdDRYEF8RQ.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Space Mono';font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/spacemono-v17-i7dMIFZifjKcF5UAWdDRaPpZUFuaHjyV.woff2) format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Space Mono';font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/spacemono-v17-i7dMIFZifjKcF5UAWdDRaPpZUFWaHg.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
/* Lora — reading voice (--read): 400/600 + italic 400 */
@font-face{font-family:'Lora';font-style:italic;font-weight:400;font-display:swap;src:url(/fonts/lora-v37-0QI8MX1D_JOuMw_hLdO6T2wV9KnW-MoFoqF2nOeZ.woff2) format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Lora';font-style:italic;font-weight:400;font-display:swap;src:url(/fonts/lora-v37-0QI8MX1D_JOuMw_hLdO6T2wV9KnW-MoFoq92nA.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Lora';font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/lora-v37-0QIvMX1D_JOuMwT7I-NP.woff2) format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Lora';font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/lora-v37-0QIvMX1D_JOuMwr7Iw.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Lora';font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/lora-v37-0QIvMX1D_JOuMwT7I-NP.woff2) format('woff2');unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Lora';font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/lora-v37-0QIvMX1D_JOuMwr7Iw.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  /* Canonical brand tokens now live in design-tokens.css (loaded first): --paper, --ink, --panel,
     --panel2, --buy, --on-buy, --rule-hard, --lift, --disp, --ui, --read, --mono, --s1..--s6.
     Only genuine per-property overrides stay here. */
  --muted:   #5c5952;   /* reader muted — one step darker than the dashboard's --grey; clears 4.5:1 on --panel (6.5:1) and --panel2 (5.7:1) */
  --rule:    color-mix(in srgb, var(--ink) 20%, var(--paper));
  --yellow:  #ffe000;

  --measure: 700px;
  --gutter:  24px;
}

/* Dark palette. Follow the OS preference by default, but a network-wide theme choice (shared
   noo_theme cookie on .nicheof.one, applied as data-theme in the head) wins: an explicit light
   choice overrides OS-dark, and an explicit dark choice applies even on a light OS. Keeps the
   eZine in sync with the apex theme toggle instead of drifting to the OS default. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    /* Surfaces/ink/buy/rule-hard flip in design-tokens.css; only the reader's local overrides stay. */
    --muted: #9a988f;
    --rule: color-mix(in srgb, var(--ink) 26%, var(--paper));
  }
  :root:not([data-theme="light"]) .net-bar__mark { filter: none; }
  :root:not([data-theme="light"]) .site-footer__dot { filter: invert(1); }
}
:root[data-theme="dark"] {
  --muted: #9a988f;
  --rule: color-mix(in srgb, var(--ink) 26%, var(--paper));
}
:root[data-theme="dark"] .net-bar__mark { filter: none; }
:root[data-theme="dark"] .site-footer__dot { filter: invert(1); }

html { font-size: 16px; -webkit-text-size-adjust: 100%; overflow-x: hidden; }

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--ui);
  font-size: 1rem;
  line-height: 1.6;
  min-height: 100vh;
  max-width: calc(var(--measure) + var(--gutter) * 2);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

/* ── Network bar (shared chrome — every space is a node on nicheof.one) ──────── */
/* Skip link — keyboard users bypass the net-bar straight to the content.
   Visually hidden until :focus (mirrors the network's os.css .skip). */
.skip {
  position: fixed; left: 10px; top: -60px; z-index: 100003;
  background: var(--ink); color: var(--paper); font-family: var(--ui); font-weight: 700;
  padding: 11px 16px; border: 2px solid var(--buy); text-decoration: none; transition: top 0.15s ease;
}
.skip:focus { top: 10px; outline: 3px solid var(--ink); outline-offset: 2px; }
main#main:focus { outline: none; }   /* programmatic focus target only — no ring on the whole main */

.net-bar {
  position: relative; left: 50%; width: 100vw; margin-left: -50vw;
  background: var(--ink);
  border-bottom: 1px solid color-mix(in srgb, var(--paper) 16%, transparent);
}
.net-bar__inner {
  max-width: calc(var(--measure) + var(--gutter) * 2);
  margin: 0 auto; padding: 8px var(--gutter); min-height: 48px;
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
}
.net-bar__brand { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; }
.net-bar__mark { width: 26px; height: 26px; flex: none; background: url('/assets/jf.png') center/contain no-repeat; filter: invert(1); }
.net-bar__name { font-family: var(--disp); font-weight: 800; font-size: 1.06rem; letter-spacing: 0.01em; color: var(--paper); }
.net-bar__cta {
  display: inline-flex; align-items: center; min-height: 24px;   /* interactive-target floor (desktop) */
  font-family: var(--mono); font-size: 0.72rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--paper); opacity: 1; text-decoration: none; white-space: nowrap;
}
.net-bar__cta:hover { opacity: 1; }
.net-bar__right { display: inline-flex; align-items: center; gap: 16px; }
.net-bar__cta--own { opacity: 1; border-bottom: 1.5px solid var(--paper); padding-bottom: 1px; }

/* Reusable kicker — Space Mono, tracked, uppercase. The zero-color tier. */
.kick, .badge, .site-header__links a, .post-list__meta, .post__byline-meta,
.paywall__label, .post__nav, .site-footer {
  font-family: var(--mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

a { color: var(--ink); }

/* Selection = the house yellow highlighter; dark ink text stays readable on it
   in both light and dark themes (matches .post__body mark). */
::selection { background: var(--yellow, #f5d90a); color: #141414; }

/* ── Masthead ──────────────────────────────────────────────────────────────── */
.site-header {
  border-bottom: 3px solid var(--rule-hard);
  padding: var(--s5) 0 var(--s3);
  margin-bottom: var(--s5);
}
.site-header__name {
  font-family: var(--disp);
  font-weight: 800;
  /* Ceiling (--name-max) is stepped down by title length in layout.php so a long space
     name doesn't balloon; the 1.6rem floor + overflow-wrap keep even an unbroken word in bounds. */
  font-size: clamp(1.6rem, 8vw, var(--name-max, 4.4rem));
  line-height: 0.9;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  text-wrap: balance;
  overflow-wrap: anywhere;
  min-width: 0;
}
.site-header__name a { color: var(--ink); text-decoration: none; }
.site-header__name a:hover { text-decoration: underline; }
/* Broadsheet dateline — per-handle furniture (folio + fleuron hashed from the handle) so every
   space reads hand-set, not provisioned. Space Mono caps between hairline rules; fleuron in ink.
   Kept at the 11.5px floor, solid colour, full opacity. */
.site-header__dateline {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  padding: 7px 0;
  margin-top: 14px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 8px;
}
.site-header__dateline .sh-fleuron { color: var(--ink); font-size: 1rem; margin-right: 2px; }
.site-header__bio {
  font-family: var(--ui);
  font-size: 0.9375rem;
  color: var(--muted);
  margin-top: 10px;
  max-width: 52ch;
  line-height: 1.5;
}
/* Link-in-bio block: the member's links as tappable button pills (shop, socials, current work),
   with the network's fill-on-hover + press-down craft. They update whenever the member edits their
   links in the dashboard — a dynamic links section, not decoration. */
.site-header__links { display: flex; flex-wrap: wrap; gap: 8px 10px; margin-top: 18px; }
.site-header__links a {
  font-family: var(--ui);
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--ink);
  text-decoration: none;
  border: 2px solid var(--ink);
  border-radius: var(--btn-radius, 999px);
  padding: 7px 14px;
  background: var(--panel);
  transition: transform .1s ease, box-shadow .1s ease, background .15s ease, color .15s ease;
}
.site-header__links a:hover { background: var(--ink); color: var(--paper); }
.site-header__links a:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--rule-hard); }
@media (max-width: 600px) { .site-header__links a { font-size: 0.86rem; padding: 9px 15px; } }

/* ── Space banner + avatar (Track: personalize — curated layout presets) ─────
   body.layout-{standard|banner|minimal} is the ONLY hook; three fixed looks,
   no free-form CSS. Graceful when a member has no banner/avatar: the header
   renders exactly as the pre-personalize plain text masthead. ────────────── */
.site-banner {
  position: relative; left: 50%; width: 100vw; margin-left: -50vw;
  border-bottom: 1px solid var(--rule);
  overflow: hidden;
}
.site-banner img { display: block; width: 100%; height: 100%; object-fit: cover; }

.site-header__top { display: flex; align-items: center; gap: 16px; }
.site-header__avatar {
  flex: none; width: 56px; height: 56px; border-radius: 50%; overflow: hidden;
  border: 2px solid var(--rule-hard); background: var(--panel);
}
.site-header__avatar img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* standard: the avatar straddles the banner's bottom edge (magazine nameplate), but the
   TITLE sits fully below the banner so display type never bleeds onto the image. Only the
   avatar is lifted, with a transform (visual only) so its straddle is independent of how
   many lines the title wraps to. */
body.layout-standard .site-banner { height: 210px; margin-bottom: 0; }
body.layout-standard .site-header { padding-top: 14px; margin-top: 0; position: relative; }
body.layout-standard .site-header__top { align-items: flex-end; gap: 18px; }
body.layout-standard .site-header__avatar {
  width: 96px; height: 96px; border: 4px solid var(--paper);
  box-shadow: 0 0 0 1px var(--rule-hard); border-radius: 8px;
  transform: translateY(-46px);   /* lift the avatar up to straddle the banner edge */
}
body.layout-standard .site-header__name { padding-bottom: 6px; }
/* no banner: nothing to straddle, so drop the lift and keep an honest top margin */
body.layout-standard:not(:has(.site-banner)) .site-header { padding-top: var(--s5); }
body.layout-standard:not(:has(.site-banner)) .site-header__avatar { transform: none; }

/* banner: big hero, avatar + name centered, straddling the bottom edge */
body.layout-banner .site-banner { height: 320px; }
body.layout-banner .site-header { text-align: center; }
body.layout-banner .site-header__top {
  flex-direction: column; align-items: center; margin-top: -54px;
}
body.layout-banner .site-header__avatar {
  width: 108px; height: 108px; border: 4px solid var(--paper);
  box-shadow: 0 0 0 1px var(--rule-hard); margin-bottom: 14px;
}
body.layout-banner .site-header__bio { margin-left: auto; margin-right: auto; }
body.layout-banner .site-header__links { justify-content: center; }

/* minimal: no banner (suppressed server-side too), tight vertical rhythm */
body.layout-minimal .site-header { padding: 22px 0 12px; margin-bottom: 20px; }
body.layout-minimal .site-header__avatar { width: 40px; height: 40px; }

/* ── Magazine (space home — featured/pinned, up to 5) ────────────────────────
   Lead = first pinned post (big cover + title). mag-grid = next up-to-4 pinned,
   smaller cards. Graceful with no cover_url: text-only, divided by a top rule
   instead of an image. Covers are always object-fit:cover at a fixed 16:9 box
   with a 1px var(--rule) border — never crop-jump, never distort. ───────────── */
.mag { margin-bottom: 44px; }

.mag-lead { margin-bottom: 8px; }
.mag-lead__cover {
  display: block;
  margin-bottom: 18px;
  border: 1px solid var(--rule);
}
.mag-lead__cover img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}
.mag-lead__title {
  font-family: var(--disp);
  font-weight: 800;
  font-size: clamp(2.3rem, 5vw, 3rem);
  line-height: 0.98;
  text-transform: uppercase;
  letter-spacing: -0.02em;
}
.mag-lead__title a { color: var(--ink); text-decoration: none; }
.mag-lead__title a:hover { text-decoration: underline; }
.mag-lead__excerpt {
  font-family: var(--read);
  font-size: 1.0625rem;
  color: var(--ink);
  margin-top: 12px;
  max-width: 62ch;
  line-height: 1.55;
}
.mag-lead__meta {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 14px;
}

.mag-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 28px;
  margin-top: 34px;
}
.mag-card {
  border-top: 1px solid var(--rule);
  padding-top: 16px;
}
.mag-card__cover {
  display: block;
  margin-bottom: 12px;
  border: 1px solid var(--rule);
}
.mag-card__cover img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}
.mag-card__title {
  font-family: var(--disp);
  font-weight: 600;
  font-size: 1.1875rem;
  line-height: 1.15;
  text-transform: uppercase;
  letter-spacing: -0.01em;
}
.mag-card__title a { color: var(--ink); text-decoration: none; }
.mag-card__title a:hover { text-decoration: underline; }
.mag-card__meta {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 8px;
}

/* ── Feed (space home — chronological, below the magazine) ───────────────────── */
.feed__kicker {
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  border-bottom: 1px solid var(--rule);
  padding-bottom: 10px;
  margin-bottom: 4px;
}

/* Desktop: 2-col grid for the secondary featured cards */
@media (min-width: 601px) {
  .mag-grid { grid-template-columns: repeat(2, 1fr); gap: 30px 26px; }
}

/* ── Post list (home) — Medium-style rows: text left, square cover right ────
   .post-list__item is a flex row (text block + optional 112px thumb) with a
   clean divider between items. Falls back to a plain text row when a post
   has no cover_url. Stacks to thumb-below on mobile (see @media below). ──── */
.post-list { list-style: none; }
.post-list__item {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
  border-bottom: 1px solid var(--rule);
  padding: 26px 0;
}
.post-list__item:first-child { border-top: 1px solid var(--rule); }
.post-list__text { flex: 1 1 auto; min-width: 0; }
.post-list__thumb {
  display: block;
  flex: none;
  width: 112px;
  height: 112px;
  border: 1px solid var(--rule);
}
.post-list__thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.post-list__title {
  font-family: var(--disp);
  font-weight: 600;
  font-size: 1.3rem;
  line-height: 1.12;
  text-transform: uppercase;
  letter-spacing: -0.01em;
}
.post-list__title a { color: var(--ink); text-decoration: none; }
.post-list__title a:hover { text-decoration: underline; }
.post-list__excerpt {
  font-family: var(--read);
  font-size: 1rem;
  color: var(--ink);
  margin-top: 8px;
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.post-list__meta { font-size: 0.72rem; color: var(--muted); margin-top: 10px; }

/* ── Tags — the category nav (organizational, NOT money — ink, never red) ────
   .tag-row  = quiet chip row under the space-home header (only renders when a
   published post carries a tag). .post__tags = same chips under a post. Both
   link to /t/{tag}. font-size floors at 11.5px (network readability floor). */
.tag-row { display: flex; flex-wrap: wrap; gap: 8px; margin: -14px 0 30px; }
.post__tags { display: flex; flex-wrap: wrap; gap: 8px; margin: 30px 0 4px; }
.tag-chip {
  display: inline-block;
  font-family: var(--mono);
  font-size: max(0.75rem, 11.5px);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  border: 1px solid var(--ink);
  padding: 4px 10px;
}
.tag-chip:hover { background: var(--ink); color: var(--paper); }
.tag-page__title { font-size: max(0.75rem, 11.5px); color: var(--ink); }

/* ── Price badge (money → red) ─────────────────────────────────────────────── */
.badge {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 700;
  padding: 2px 7px;
  vertical-align: 0.14em;
  margin-left: 8px;
  letter-spacing: 0.06em;
}
.badge--gated { background: var(--buy); color: var(--on-buy); }
/* Discovery paid indicator — INK chip, never red. Discovery has no money door
   of its own (red is reserved for the actual checkout on the origin post); this
   only flags that the piece is paid, then links out. Floored at 11.5px. */
.badge--paid {
  background: transparent; color: var(--ink);
  border: 1px solid var(--ink);
  font-size: max(0.625rem, 11.5px);
}

/* ── Discovery (discover.{apex}) — network-wide "a real find" ─────────────────
   Reuses the crafted .post-list rows; only the masthead + author link are new.
   Ink/accent only — Discovery surfaces work, it never sells, so no red chrome. */
.discover__masthead {
  border-bottom: 3px solid var(--rule-hard);
  padding: var(--s5) 0 var(--s3);
  margin-bottom: var(--s4);
}
.discover__kicker {
  font-family: var(--mono);
  font-size: max(0.75rem, 11.5px);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 12px;
}
.discover__title {
  font-family: var(--disp);
  font-weight: 800;
  font-size: clamp(2.6rem, 7vw, 3.6rem);
  line-height: 0.92;
  letter-spacing: -0.02em;
  text-transform: uppercase;
}
.discover__lede {
  font-family: var(--read);
  font-size: 1.0625rem;
  color: var(--muted);
  margin-top: 14px;
  max-width: 54ch;
  line-height: 1.5;
}
/* Author credit on each card — ink link, never red. Sits inside .post-list__meta
   so it inherits the mono/uppercase/tracked meta styling. */
.discover__by { color: var(--ink); text-decoration: none; font-weight: 700; }
.discover__by:hover { text-decoration: underline; text-underline-offset: 2px; }
.discover__empty-cta { margin-top: 14px; }
.discover__empty-cta a { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; }
.discover__empty-cta a:hover { opacity: 0.7; }

/* ── Article ───────────────────────────────────────────────────────────────── */
.post__cover, .post__body img.post__cover {
  width: 100%; height: auto; max-height: 480px; object-fit: cover;
  display: block; margin: 0 0 32px; border: 1px solid var(--rule);
}
.post__header { margin-bottom: 8px; }
.post__title {
  font-family: var(--disp);
  font-weight: 700;
  font-size: clamp(2.1rem, 4.6vw, 3.05rem);
  line-height: 1.08;
  letter-spacing: -0.01em;
  text-transform: none;
  text-wrap: balance;
  margin-bottom: 16px;
}
.post__subtitle {
  font-family: var(--read);
  font-weight: 400;
  font-style: normal;
  font-size: 1.375rem;
  line-height: 1.45;
  color: var(--muted);
  margin-bottom: 26px;
}

/* Byline row — Medium's signature: monogram avatar + name + "N min read · date" */
.post__byline {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-bottom: 20px;
  border-bottom: 1px solid var(--rule);
}
.post__avatar {
  flex: none;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--ui);
  font-weight: 700;
  font-size: 1.0625rem;
  display: flex;
  align-items: center;
  justify-content: center;
}
.post__byline-text { flex: 1 1 auto; min-width: 0; }
.post__byline-name {
  font-family: var(--ui);
  font-weight: 600;
  font-size: 0.9375rem;
  color: var(--ink);
  line-height: 1.3;
}
.post__byline-meta {
  font-size: 0.72rem;
  color: var(--muted);
  margin-top: 3px;
}
.post__byline-badge { flex: none; margin-left: auto; }

/* Co-author byline (Collaboration Phase A) — attribution only, never money → never red. */
.post__byline-name .post__author { color: var(--ink); }
.post__byline-name a.post__author { text-decoration: none; }
.post__byline-name a.post__author:hover { text-decoration: underline; text-underline-offset: 2px; }
.post__byline-sep { color: var(--muted); font-weight: 400; }

/* Inline paywall teaser — the free above-the-marker portion, fading into the
   paper just before the paywall block to signal there's more below. */
.post__body--teaser { position: relative; margin-bottom: 0; }
.post__body--teaser::after {
  content: ""; display: block; height: 2.6em; margin-top: -2.6em;
  background: linear-gradient(to bottom, transparent, var(--paper));
  pointer-events: none;
}

/* Draft preview flag — a quiet note, never money → never red. */
.preview-flag {
  font-family: var(--ui); font-size: 0.75rem; font-weight: 600;
  border: 1px dashed var(--rule-hard); padding: 8px 12px;
  margin-bottom: var(--s3); color: var(--muted);
}

/* Cross-post indicator on the feed — a piece co-authored on another space,
   linking out to its origin. Muted, never red. */
.post-list__cross { color: var(--muted); font-size: 0.85em; }

/* Body prose — Lora, the reading voice. Medium-scale: ~21px/1.62, airy paragraphs. */
.post__body { font-family: var(--read); font-size: 1.3rem; line-height: 1.62; }
.post__body h1, .post__body h2, .post__body h3 {
  font-family: var(--disp); font-weight: 600; line-height: 1.15;
  text-transform: uppercase; letter-spacing: -0.01em; margin: 44px 0 14px;
}
/* OWNER SIGN-OFF (single, easily-reverted rule): mid-article headings read in
   sentence case, not the ALL-CAPS used for furniture/kickers. Delete this one
   rule to restore uppercase in-body headings. */
.post__body h1, .post__body h2, .post__body h3 { text-transform: none; }
.post__body h1 { font-size: 1.8rem; }
.post__body h2 { font-size: 1.45rem; }
.post__body h3 { font-size: 1.2rem; }
.post__body p { margin-bottom: 1.4em; text-wrap: pretty; }
.post__body a { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; text-decoration-thickness: 1px; }
.post__body a:hover { opacity: 0.7; }
.post__body strong { font-weight: 600; }
.post__body em { font-style: italic; }
.post__body blockquote {
  border-left: 3px solid var(--ink); margin: 30px 0; padding: 2px 0 2px 22px;
  color: var(--muted); font-style: italic;
}
.post__body blockquote p:last-child { margin-bottom: 0; }
.post__body code { font-family: var(--mono); font-size: 0.8em; background: var(--panel2); padding: 1px 5px; }
.post__body pre { background: var(--ink); color: var(--paper); padding: 20px; overflow-x: auto; margin: 30px 0; font-size: 0.85rem; }
.post__body pre code { background: transparent; padding: 0; color: inherit; }
.post__body ul, .post__body ol { padding-left: 28px; margin-bottom: 1.4em; }
.post__body li { margin-bottom: 9px; }
.post__body hr { border: none; border-top: 2px solid var(--rule); margin: 46px 0; }
.post__body img { max-width: 100%; height: auto; display: block; margin: 30px 0; }
.post__body mark { background: var(--yellow); color: #141414; padding: 0 3px; }

/* ── Inline body figures (Markdown ![alt](url) images) ─────────────────────────
   figure + italic Lora caption in --muted. Width tiers reuse the .net-bar
   full-bleed breakout: --wide centers a bounded band on the viewport, --full
   spans edge to edge. Default (--regular) stays inside the reading measure. */
.post-fig { margin: 34px 0; }
.post-fig img { width: 100%; max-width: 100%; height: auto; display: block; margin: 0; border: 1px solid var(--rule); }
.post-fig figcaption {
  font-family: var(--read); font-style: italic; font-size: 0.9375rem;
  color: var(--muted); line-height: 1.5; margin-top: 10px; text-align: center;
}
.post-fig--wide {
  position: relative; left: 50%;
  width: min(100vw, 1000px); margin-left: calc(min(100vw, 1000px) / -2);
}
.post-fig--full { position: relative; left: 50%; width: 100vw; margin-left: -50vw; }
.post-fig--full img { border-left: none; border-right: none; }
/* Keep the caption readable — re-constrain it to the reading measure when the
   figure itself has broken out of the column. */
.post-fig--wide figcaption, .post-fig--full figcaption {
  max-width: var(--measure); margin-left: auto; margin-right: auto; padding: 0 var(--gutter);
}

/* ── Block media embeds (YouTube/Vimeo/Spotify/SoundCloud/Bandcamp iframes) ────
   Same vertical rhythm as .post-fig. Video hosts get a responsive 16:9 box via
   padding-top; audio hosts get a fixed player height. */
.post-embed { margin: 34px 0; }
.post-embed iframe { display: block; width: 100%; max-width: 100%; border: 1px solid var(--rule); }

/* Responsive 16:9 for video (YouTube, Vimeo). */
.post-embed--video { position: relative; width: 100%; padding-top: 56.25%; }
.post-embed--video iframe { position: absolute; inset: 0; height: 100%; border: 0; }

/* Fixed height for audio players (Spotify, SoundCloud, Bandcamp). */
.post-embed--audio iframe { height: 166px; }
.post-embed--audio-tall iframe { height: 352px; }

/* ── Bookmark cards (link previews) ────────────────────────────────────────────
   A lone non-embed URL whose OG metadata the cron (src/resolve_bookmarks.php)
   resolved into url_cards renders as this card — see _md_bookmark_card() in
   render.php (pure DB read, zero network). Same border + --lift + panel as
   .post-fig / .author-card so a preview sits in the post's craft language, NOT
   the money-door red. Nodes: figure.bookmark-card > a.bmc-link >
   (img.bmc-img?) + span.bmc-host + span.bmc-title + span.bmc-desc. */
.bookmark-card { margin: 34px 0; }
.bookmark-card .bmc-link {
  display: grid; grid-template-columns: 1fr; align-items: start;
  border: 2px solid var(--ink); background: var(--panel); box-shadow: var(--lift);
  text-decoration: none; color: var(--ink); overflow: hidden;
}
.bookmark-card .bmc-link:hover { background: var(--panel2); }
.bookmark-card .bmc-img {
  display: block; width: 100%; height: 180px; object-fit: cover;
  background: var(--panel2); border-bottom: 2px solid var(--ink);
}
.bookmark-card .bmc-host {
  font-family: var(--mono); font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted);
  padding: 16px 18px 0;
}
.bookmark-card .bmc-title {
  font-family: var(--disp); font-weight: 700; font-size: 1.15rem; line-height: 1.2;
  letter-spacing: -0.01em; color: var(--ink); padding: 5px 18px 0;
}
.bookmark-card .bmc-desc {
  font-family: var(--read); font-size: 0.95rem; line-height: 1.5; color: var(--muted);
  padding: 8px 18px 18px;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
/* Image left on wider viewports. :has() lets a broken/absent image collapse the
   column cleanly — onerror="this.remove()" drops the <img>, the selector stops
   matching, and the grid reverts to a single text column. */
@media (min-width: 560px) {
  .bookmark-card .bmc-link:has(.bmc-img) { grid-template-columns: 220px 1fr; }
  .bookmark-card .bmc-link:has(.bmc-img) .bmc-img {
    grid-column: 1; grid-row: 1 / span 3; height: 100%; min-height: 150px;
    border-bottom: none; border-right: 2px solid var(--ink);
  }
  .bookmark-card .bmc-link:has(.bmc-img) .bmc-host,
  .bookmark-card .bmc-link:has(.bmc-img) .bmc-title,
  .bookmark-card .bmc-link:has(.bmc-img) .bmc-desc { grid-column: 2; }
  .bookmark-card .bmc-link:has(.bmc-img) .bmc-host { padding-top: 18px; }
}

/* Gumroad button (their JS restyles, but give it a sane base) */
.post__body a.gumroad-button {
  display: inline-block; text-decoration: none; color: var(--on-buy);
  background: var(--buy); font-family: var(--ui); font-weight: 700;
  padding: 11px 22px; margin: 4px 0;
}
.post__body a.gumroad-button:hover { color: var(--on-buy); opacity: 0.9; }

/* ── Download PDF — ghost button (NOT money, so ink not red) ────────────────── */
.post__pdf-link { margin: 28px 0 4px; }
.post__pdf-link a {
  display: inline-block;
  font-family: var(--ui); font-size: 0.8125rem; font-weight: 600;
  color: var(--ink); text-decoration: none;
  border: 1.5px solid var(--ink); padding: 8px 16px;
}
.post__pdf-link a:hover { background: var(--ink); color: var(--paper); }

/* ── Paywall (money → red) ─────────────────────────────────────────────────── */
.paywall { border: 2px solid var(--ink); background: var(--panel); box-shadow: var(--lift); margin-top: var(--s5); }
.paywall__inner { padding: var(--s4) var(--s3); text-align: center; }
.paywall__label { font-size: 0.72rem; font-weight: 700; color: var(--muted); margin-bottom: 10px; }
.paywall__price { font-family: var(--disp); font-size: 2.6rem; font-weight: 700; color: var(--buy); line-height: 1; margin-bottom: 10px; }
.paywall__desc { font-family: var(--read); font-size: 1rem; color: var(--ink); margin-bottom: 24px; }
.paywall__form { display: flex; flex-direction: column; align-items: center; gap: 14px; max-width: 340px; margin: 0 auto; }
.paywall__email-label { font-family: var(--ui); font-size: 0.8125rem; font-weight: 600; text-align: left; width: 100%; }
.paywall__email-note { font-weight: 400; color: var(--muted); display: block; font-size: 0.75rem; margin-top: 3px; }
.paywall__email-input, .tip-widget__email-input, .tip-widget__custom {
  border: 1.5px solid var(--ink); padding: 10px 12px; font-family: var(--ui);
  font-size: 0.9375rem; outline: none; background: var(--paper); color: var(--ink);
}
.paywall__email-input { width: 100%; }
.paywall__email-input:focus, .tip-widget__email-input:focus, .tip-widget__custom:focus { border-color: var(--ink); box-shadow: 0 0 0 2px color-mix(in srgb, var(--ink) 28%, transparent); }
.paywall__notice { font-family: var(--ui); font-size: 0.75rem; text-transform: none; letter-spacing: 0; color: var(--muted); margin-top: 16px; }

/* ── Money button ──────────────────────────────────────────────────────────── */
.btn-unlock {
  display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box;
  background: var(--buy); color: var(--on-buy); border: 2px solid var(--buy);
  font-family: var(--ui); font-size: 0.86rem; font-weight: 700; letter-spacing: normal;
  text-transform: none; border-radius: var(--btn-radius, 3px);
  min-height: 44px; padding: 13px 28px; cursor: pointer; width: 100%;
}
.btn-unlock:hover { opacity: 0.92; }
.btn-unlock:active { opacity: 1; }

/* ── Free-Stories member pool (NOT money — ink, never --buy) ────────────────── */
.paywall__comp { margin-top: 22px; padding-top: 20px; border-top: 1px solid var(--rule); }
.btn-comp {
  display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box;
  background: transparent; color: var(--ink);
  border: 2px solid var(--ink); border-radius: var(--btn-radius, 3px); font-family: var(--ui); font-size: 0.9375rem;
  font-weight: 700; letter-spacing: normal; min-height: 44px; padding: 11px 26px; cursor: pointer;
  width: 100%; margin-top: 10px;
}
.btn-comp:hover { background: var(--ink); color: var(--paper); }
.btn-comp:active { opacity: 0.85; }

/* ── Spark — members-only appreciation tap (NOT money, so ink not red) ─────── */
.spark-wrap { margin: 30px 0 4px; }
.spark-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; box-sizing: border-box;
  font-family: var(--ui); font-size: 0.8125rem; font-weight: 700;
  background: transparent; color: var(--ink);
  border: 2px solid var(--ink); border-radius: var(--btn-radius, 3px); min-height: 36px; padding: 8px 16px; cursor: pointer;
}
.spark-btn:hover { background: var(--panel2); }
.spark-btn:disabled { opacity: 0.6; cursor: default; }
/* Sparked = subtle filled state — ink, never --buy (red is the money door). */
.spark-btn.is-sparked { background: var(--ink); color: var(--paper); }
.spark-btn.is-sparked:hover { opacity: 0.9; }

/* ── Tip widget ────────────────────────────────────────────────────────────── */
.tip-widget { border: 2px solid var(--ink); background: var(--panel); box-shadow: var(--lift); margin-top: var(--s5); }
.tip-widget__inner { padding: var(--s3); text-align: center; }
.tip-widget__label { font-family: var(--ui); font-size: 0.9375rem; color: var(--ink); margin-bottom: 16px; }
.tip-widget__amounts { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 8px; margin-bottom: 16px; }
.tip-amt {
  font-family: var(--ui); font-size: 0.9375rem; font-weight: 700;
  background: var(--paper); border: 1.5px solid var(--ink); color: var(--ink);
  padding: 9px 18px; cursor: pointer;
}
.tip-amt:hover { background: var(--panel2); }
.tip-amt.is-active { background: var(--buy); border-color: var(--buy); color: var(--on-buy); }
.tip-widget__custom { width: 108px; }
.tip-widget__email-label { font-family: var(--ui); font-size: 0.8125rem; font-weight: 600; display: block; text-align: left; max-width: 320px; margin: 0 auto 6px; }
.tip-widget__email-note { font-weight: 400; color: var(--muted); }
.tip-widget__email-input { width: 100%; max-width: 320px; margin: 0 auto 16px; display: block; }
.tip-widget .btn-unlock { max-width: 320px; margin: 0 auto; }

/* ── Subscribe (reader email capture — free, so ink not red; --buy is money-only) ── */
.subscribe { border: 2px solid var(--ink); background: var(--panel); box-shadow: var(--lift); margin-top: var(--s5); }
.subscribe__inner { padding: var(--s4) var(--s3); text-align: center; }
.subscribe__label { font-family: var(--disp); font-weight: 700; font-size: 1.15rem; color: var(--ink); margin-bottom: var(--s2); letter-spacing: -0.01em; }
.subscribe__form { display: flex; flex-direction: column; align-items: center; gap: 12px; max-width: 320px; margin: 0 auto; }
.subscribe__email-label { font-family: var(--ui); font-size: 0.8125rem; font-weight: 600; text-align: left; width: 100%; }
.subscribe__email-input { width: 100%; border: 1.5px solid var(--ink); padding: 10px 12px; font-family: var(--ui); font-size: 0.9375rem; outline: none; background: var(--paper); color: var(--ink); }
.subscribe__email-input:focus { border-color: var(--ink); box-shadow: 0 0 0 2px color-mix(in srgb, var(--ink) 28%, transparent); }
.subscribe__submit {
  display: block; width: 100%; background: var(--ink); color: var(--paper); border: none;
  font-family: var(--disp); font-size: 0.8rem; font-weight: 600; letter-spacing: 0.06em;
  text-transform: uppercase; border-radius: var(--btn-radius, 999px);
  padding: 13px 22px; cursor: pointer;
}
.subscribe__submit:hover { opacity: 0.88; }
.subscribe__notice { font-family: var(--ui); font-size: 0.75rem; text-transform: none; letter-spacing: 0; color: var(--muted); margin-top: 12px; min-height: 1em; }
.subscribe__privacy { font-family: var(--ui); font-size: 0.72rem; text-transform: none; letter-spacing: 0; color: var(--muted); margin-top: 14px; line-height: 1.5; }

/* ── "Written by" author end card (premium finish, NOT money → ink, never red) ── */
.author-card {
  border: 2px solid var(--ink); background: var(--panel); box-shadow: var(--lift);
  margin-top: var(--s5); padding: var(--s3);
}
.author-card__head { display: flex; align-items: center; gap: 14px; }
.author-card__avatar {
  flex: none; width: 56px; height: 56px; border-radius: 50%; overflow: hidden;
  border: 2px solid var(--rule-hard); background: var(--panel);
}
.author-card__avatar img { display: block; width: 100%; height: 100%; object-fit: cover; }
.author-card__avatar--mono {
  display: flex; align-items: center; justify-content: center;
  background: var(--ink); color: var(--paper); border-color: var(--ink);
  font-family: var(--ui); font-weight: 700; font-size: 1.375rem;
}
.author-card__id { flex: 1 1 auto; min-width: 0; }
.author-card__kicker {
  display: block; font-family: var(--mono); font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted);
}
.author-card__name {
  display: block; font-family: var(--disp); font-weight: 700; font-size: 1.35rem;
  line-height: 1.1; letter-spacing: -0.01em; color: var(--ink); margin-top: 2px;
}
.author-card__follow {
  flex: none; align-self: center;
  font-family: var(--mono); font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--ink); text-decoration: none;
  border: 1.5px solid var(--ink); padding: 7px 14px;
}
.author-card__follow:hover { background: var(--ink); color: var(--paper); }
.author-card__bio {
  font-family: var(--read); font-size: 1rem; line-height: 1.55;
  color: var(--ink); margin-top: 16px; max-width: 60ch;
}

/* ── Recommended reading (blogroll — curation, NOT money → ink, never red) ─────
   Same craft language as .author-card / .subscribe: 2px ink border + panel fill +
   --lift offset shadow. Light/dark + mobile all ride the shared vars/query. ──── */
.blogroll {
  border: 2px solid var(--ink); background: var(--panel); box-shadow: var(--lift);
  margin-top: var(--s5); padding: var(--s3);
}
.blogroll__kicker {
  font-family: var(--mono); font-size: max(0.72rem, 11.5px); font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted);
  margin-bottom: var(--s2);
}
.blogroll__list { list-style: none; margin: 0; padding: 0; }
.blogroll__item {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px 18px;
  padding: 14px 0; border-top: 1px solid var(--rule);
}
.blogroll__item:first-child { border-top: 0; padding-top: 4px; }
.blogroll__text { flex: 1 1 auto; min-width: 0; }
.blogroll__space {
  font-family: var(--disp); font-weight: 700; font-size: 1.1rem; line-height: 1.15;
  color: var(--ink); text-decoration: none;
}
.blogroll__space:hover { text-decoration: underline; text-underline-offset: 3px; }
.blogroll__note {
  font-family: var(--read); font-size: 0.95rem; line-height: 1.5;
  color: var(--muted); margin-top: 4px; max-width: 60ch;
}
.blogroll__follow {
  flex: none; align-self: center;
  font-family: var(--mono); font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--ink); text-decoration: none;
  border: 1.5px solid var(--ink); padding: 7px 14px; white-space: nowrap;
}
.blogroll__follow:hover { background: var(--ink); color: var(--paper); }
@media (max-width: 600px) {
  .blogroll__item { flex-wrap: wrap; }
  .blogroll__follow { align-self: flex-start; }
}

/* ── Nav / footer ──────────────────────────────────────────────────────────── */
.post__nav { margin-top: 52px; padding-top: 18px; border-top: 1px solid var(--rule); font-size: 0.72rem; }
.post__nav a { color: var(--muted); text-decoration: none; }
.post__nav a:hover { color: var(--ink); text-decoration: underline; }
.empty-state { font-family: var(--ui); font-size: 1rem; color: var(--muted); padding: 56px 0; text-align: center; }
.not-found { text-align: center; padding: 80px 0; }
.not-found__code { font-family: var(--disp); font-size: 5.5rem; font-weight: 700; color: var(--ink); line-height: 1; }
.not-found__msg { font-family: var(--read); font-size: 1.15rem; color: var(--ink); margin-top: 14px; }
.not-found__note { font-family: var(--ui); font-size: 0.875rem; color: var(--muted); margin-top: 14px; }
.not-found__note a { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; }
.not-found__note a:hover { opacity: 0.7; }
.not-found__links { display: flex; flex-wrap: wrap; justify-content: center; gap: 14px 26px; margin-top: 26px; }
.not-found__back { display: inline-block; font-family: var(--mono); font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink); text-decoration: none; border-bottom: 2px solid var(--ink); padding-bottom: 2px; }
.not-found__back:hover { opacity: 0.65; }
.site-footer { position: relative; left: 50%; width: 100vw; margin-left: -50vw; background: var(--panel2); border-top: 3px solid var(--rule); margin-top: var(--s6); padding: var(--s4) var(--gutter) var(--s5); font-size: 0.72rem; color: var(--muted); }
.site-footer > * { max-width: var(--measure); margin-left: auto; margin-right: auto; }
.site-footer a { color: var(--muted); text-decoration: underline; }
.site-footer a:hover { color: var(--ink); }
.site-footer__brand { display: inline-flex; align-items: center; gap: 9px; font-family: var(--disp); font-weight: 800; font-size: 1.05rem; letter-spacing: 0; text-transform: none; color: var(--ink); text-decoration: none; margin-bottom: 10px; }
.site-footer__brand:hover { text-decoration: underline; }
.site-footer__dot { width: 18px; height: 18px; flex: none; background: url('/assets/jf.png') center/contain no-repeat; }
.site-footer > span { display: block; text-transform: none; letter-spacing: 0; font-family: var(--ui); font-size: 0.75rem; }

/* ── Responsive ────────────────────────────────────────────────────────────── */

/* Tablet: ease the banner presets down from full desktop scale before the
   phone breakpoint takes over — a 320px hero banner is fine at 1200px wide
   but overpowers a 768px screen. */
@media (max-width: 900px) and (min-width: 601px) {
  body.layout-standard .site-banner { height: 130px; }
  body.layout-banner .site-banner { height: 250px; }
  body.layout-banner .site-header__avatar { width: 92px; height: 92px; }
}

@media (max-width: 600px) {
  :root { --gutter: 16px; }
  html { font-size: 15px; }
  .site-header { padding: 28px 0 14px; }
  /* Stack avatar above the title so the nameplate gets full width instead of being
     squeezed into a narrow column beside the avatar (which forced ugly mid-word breaks).
     No straddle lift here — the avatar leads the stack, fully below the banner. */
  body.layout-standard .site-header__top { flex-direction: column; align-items: flex-start; gap: 12px; }
  body.layout-standard .site-header__avatar { transform: none; }
  .site-header__name { font-size: clamp(1.7rem, 9vw, var(--name-max, 2.8rem)); }
  .post__title { font-size: 2rem; line-height: 1.12; }
  .post__subtitle { font-size: 1.125rem; }
  .post-list__title { font-size: 1.25rem; }
  .post-list__item { flex-direction: column; gap: 14px; }
  .post-list__thumb { width: 100%; height: auto; aspect-ratio: 1 / 1; }
  .post__body { font-size: 1.18rem; line-height: 1.58; }
  .author-card__head { flex-wrap: wrap; }
  .author-card__follow { margin-top: 4px; }
  .paywall__inner { padding: 24px 18px; }
  .paywall__price { font-size: 2.1rem; }
  .mag-lead__title { font-size: 1.7rem; }
  .mag-grid { gap: 22px; }
  .discover__masthead { padding: 28px 0 16px; }
  .discover__title { font-size: 2.2rem; }
  body.layout-standard .site-banner { height: 110px; }
  body.layout-banner .site-banner { height: 200px; }
  body.layout-banner .site-header__avatar { width: 84px; height: 84px; }

  /* Net bar: brand + CTAs never fit on one nowrap row at phone widths —
     let the two clusters wrap onto their own line instead of clipping or
     forcing "NICHE OF ONE" to break mid-word. */
  .net-bar__inner { flex-wrap: wrap; row-gap: 8px; }
  .net-bar__right { gap: 10px 16px; }
  .net-bar__cta { padding: 4px 0; }

  /* Tappable ghost-button on mobile (was ~35px tall). */
  .post__pdf-link a { padding: 12px 18px; }
}

/* Follow — a reading relationship, not a status. Ink outline, never red. */
.follow-btn { display: inline-flex; align-items: center; justify-content: center; min-height: 36px; margin-left: 14px; padding: 6px 14px; border: 2px solid var(--ink); border-radius: var(--btn-radius, 3px); font-family: var(--ui); font-size: var(--min); font-weight: 700; letter-spacing: normal; text-transform: none; color: var(--ink); text-decoration: none; vertical-align: middle; }

/* Coarse-pointer (touch) bump: 44px comfortable tap target for the two space CTAs. */
@media (pointer: coarse) {
  .follow-btn, .net-bar__cta { min-height: 44px; }
}
.follow-btn:hover { background: var(--ink); color: var(--paper); }
.follow-btn.is-following { background: var(--ink); color: var(--paper); pointer-events: none; }

/* ── Reading-progress bar (calm reading) ─────────────────────────────────────
   A thin line pinned to the very top that fills as the article scrolls. INK,
   never red — it tracks reading, it is not a money door. Pure CSS via a scroll
   timeline where supported; the tiny fallback JS in post.php drives it otherwise;
   with neither it stays scaleX(0) (invisible) and nothing breaks. Removed wholesale
   under prefers-reduced-motion. */
.reading-progress {
  position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 200;
  background: transparent; pointer-events: none;
}
.reading-progress__bar {
  display: block; height: 100%; width: 100%;
  background: var(--ink); transform: scaleX(0); transform-origin: 0 50%;
}
@supports (animation-timeline: scroll()) {
  .reading-progress__bar {
    animation: reading-progress-fill linear both;
    animation-timeline: scroll(root block);
  }
}
@keyframes reading-progress-fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@media (prefers-reduced-motion: reduce) { .reading-progress { display: none; } }

/* ── Heading anchors + Contents TOC ──────────────────────────────────────────
   Anchor: a subtle '#' that fades in on heading hover — INK, never red (an
   affordance, not a money door). It's aria-hidden + tabindex=-1 in the markup,
   so screen readers and keyboard tabbing skip it. TOC: a slim fixed rail in the
   left margin on wide screens, a collapsible <details> at the top otherwise.
   Pure anchor links — fully functional with zero JS (native jump + scroll-margin);
   JS only adds the active-section highlight. Floors at the 11.5px readability min. */

/* Land an anchored heading clear of the top chrome, never jammed to the edge. */
.post__body h1, .post__body h2, .post__body h3 { scroll-margin-top: 84px; }

/* The hover '#' affordance. */
.heading-anchor {
  margin-left: 0.4em; color: var(--muted); text-decoration: none;
  font-family: var(--mono); font-weight: 400;
  opacity: 0; transition: opacity .12s ease;
}
.post__body h1:hover .heading-anchor,
.post__body h2:hover .heading-anchor,
.post__body h3:hover .heading-anchor { opacity: .5; }
.heading-anchor:hover { opacity: 1; color: var(--ink); }
/* Touch / no-hover pointers can't reveal-on-hover, so keep it faintly present. */
@media (hover: none) { .heading-anchor { opacity: .3; } }

/* Contents nav — default (mobile / tablet): collapsible card at the top. */
.post-toc { margin: 0 0 var(--s4); }
.post-toc__wrap { border: 1.5px solid var(--rule); background: var(--panel); }
.post-toc__summary {
  font-family: var(--mono); font-size: max(0.72rem, 11.5px); font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted);
  padding: 12px 16px; cursor: pointer; list-style: none;
}
.post-toc__summary::-webkit-details-marker { display: none; }
.post-toc__summary::after { content: '+'; float: right; font-family: var(--mono); font-weight: 400; }
.post-toc__wrap[open] .post-toc__summary::after { content: '\2013'; }
.post-toc__list { list-style: none; margin: 0; padding: 4px 16px 14px; font-family: var(--ui); }
.post-toc__item { margin: 0; }
.post-toc__link {
  display: block; padding: 5px 0 5px 12px; margin-left: -1px;
  font-size: max(0.82rem, 11.5px); line-height: 1.3;
  color: var(--muted); text-decoration: none;
  border-left: 2px solid transparent;
}
.post-toc__item--h3 .post-toc__link { padding-left: 26px; }
.post-toc__link:hover { color: var(--ink); }
.post-toc__link.is-active { color: var(--ink); border-left-color: var(--ink); font-weight: 600; }

/* Wide screens: lift Contents into the left margin as a slim fixed rail, left of
   the centred reading column. The <details> is forced open (summary hidden) so it
   reads as a plain rail — it's rendered with the `open` attribute, so no JS is
   needed to keep it expanded. */
@media (min-width: 1240px) {
  .post-toc {
    position: fixed; top: 96px; margin: 0; z-index: 50;
    left: max(var(--gutter), calc((100vw - var(--measure) - var(--gutter) * 2) / 2 - 228px));
    width: 200px; max-height: calc(100vh - 140px); overflow-y: auto;
  }
  .post-toc__wrap { border: none; background: transparent; }
  .post-toc__summary { display: none; }
  .post-toc__list { padding: 0; border-left: 1px solid var(--rule); }
  .post-toc__link { padding-left: 14px; }
  .post-toc__item--h3 .post-toc__link { padding-left: 28px; }
}

/* Smooth-scroll to anchors — progressive: only when a Contents nav is present and
   the reader hasn't asked for reduced motion. Unsupported (:has) or no-JS → the
   native anchor jump still works; this only softens the landing. */
@media (prefers-reduced-motion: no-preference) {
  html:has(.post-toc) { scroll-behavior: smooth; }
}

/* ── Prev / Next within the space (post foot) ────────────────────────────────
   The chronologically adjacent posts by this writer — a calm two-up. Same craft
   language as .author-card (2px ink border + --lift + panel). Ink, never red:
   navigation, not a money door. Server-rendered links — fully functional no-JS. */
.post-neighbors {
  display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: var(--s5);
}
.post-neighbors__link {
  display: flex; flex-direction: column; gap: 6px;
  border: 2px solid var(--ink); background: var(--panel); box-shadow: var(--lift);
  padding: 16px 18px; text-decoration: none; color: var(--ink);
  transition: background .15s ease;
}
.post-neighbors__link:hover { background: var(--panel2); }
.post-neighbors__link--next { text-align: right; }
.post-neighbors__link--empty { border: none; background: none; box-shadow: none; }
.post-neighbors__dir {
  font-family: var(--mono); font-size: max(0.72rem, 11.5px); font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted);
}
.post-neighbors__title {
  font-family: var(--disp); font-weight: 600; font-size: 1.05rem; line-height: 1.15;
  letter-spacing: -0.01em; color: var(--ink);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* ── "More from {writer}" strip — reuses .post-list rows; chronological, not
   ranked. Only the kicker is new (mirrors .feed__kicker). Ink, never red. */
.more-from { margin-top: var(--s5); }
.more-from__kicker {
  font-family: var(--mono); font-size: 0.75rem; font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted);
  border-bottom: 1px solid var(--rule); padding-bottom: 10px; margin-bottom: 4px;
}

/* ── Reader-controlled Follow block (the anti-feed) ──────────────────────────
   The reader chooses HOW the space reaches them — RSS, Email, or The Underground.
   Card in the house craft language (2px ink border + --lift + panel), matching
   .author-card / .subscribe. Ink, never red: following is a reading relationship,
   not a money door. Choices floor at 11.5px. */
.follow-block { border: 2px solid var(--ink); background: var(--panel); box-shadow: var(--lift); margin-top: var(--s5); }
.follow-block__inner { padding: var(--s4) var(--s3); }
.follow-block__kicker {
  font-family: var(--disp); font-weight: 700; font-size: 1.15rem;
  letter-spacing: -0.01em; color: var(--ink); margin-bottom: 8px;
}
.follow-block__lede {
  font-family: var(--read); font-size: 0.95rem; line-height: 1.5;
  color: var(--muted); margin-bottom: var(--s3); max-width: 54ch;
}
.follow-block__choices { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.follow-block__choice {
  display: flex; flex-direction: column; gap: 4px;
  border: 1.5px solid var(--ink); background: var(--paper);
  padding: 14px 16px; text-decoration: none; color: var(--ink);
  transition: transform .1s ease, box-shadow .1s ease, background .15s ease, color .15s ease;
}
.follow-block__choice:hover { background: var(--ink); color: var(--paper); }
.follow-block__choice:hover .follow-block__choice-note { color: var(--paper); }
.follow-block__choice:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--rule-hard); }
.follow-block__choice-name {
  font-family: var(--mono); font-size: max(0.78rem, 11.5px); font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase;
}
.follow-block__choice-note {
  font-family: var(--ui); font-size: max(0.72rem, 11.5px); color: var(--muted); line-height: 1.35;
}

/* Mobile: single-column stacks for the two-up neighbours and the follow choices. */
@media (max-width: 600px) {
  .post-neighbors { grid-template-columns: 1fr; }
  .post-neighbors__link--next { text-align: left; }
  .post-neighbors__link--empty { display: none; }
  .follow-block__choices { grid-template-columns: 1fr; }
}

/* ── Cmd+K search: net-bar trigger + overlay ──────────────────────────────────
   ACCENT DISCIPLINE: search is INK, never --buy. Red stays the money door only.
   The trigger sits in the dark net-bar (paper-on-ink); the panel is paper stock
   with the zine offset --lift, Space Mono labels, and the 11.5px readability floor. */

/* Trigger — a quiet paper-outlined chip in the net-bar */
.net-bar__search {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--mono); font-size: 0.72rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--paper); background: transparent; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--paper) 45%, transparent);
  border-radius: 2px; padding: 5px 9px; line-height: 1;
  transition: border-color .12s ease, background .12s ease;
}
.net-bar__search:hover { border-color: var(--paper); background: color-mix(in srgb, var(--paper) 12%, transparent); }
.net-bar__search:focus-visible { outline: 2px solid var(--paper); outline-offset: 2px; }
.net-bar__search-icon { flex: none; opacity: .9; }
.net-bar__search-kbd {
  font-family: var(--mono); font-size: 0.62rem; font-weight: 700;
  border: 1px solid color-mix(in srgb, var(--paper) 40%, transparent);
  border-radius: 2px; padding: 1px 4px; opacity: .85;
}
/* On narrow screens keep just the icon — the word + kbd are the first to go */
@media (max-width: 560px) {
  .net-bar__search-label, .net-bar__search-kbd { display: none; }
  .net-bar__search { padding: 6px; }
}

/* Overlay — native <dialog> */
.nf-search {
  width: min(640px, calc(100vw - 28px));
  max-height: min(70vh, 620px);
  margin: 12vh auto auto;              /* sit high, spotlight-style */
  padding: 0; border: 2px solid var(--ink);
  background: var(--panel); color: var(--ink);
  box-shadow: var(--lift);
  overflow: hidden;                    /* results list owns the scroll */
  display: flex; flex-direction: column;
}
.nf-search::backdrop { background: color-mix(in srgb, var(--ink) 42%, transparent); backdrop-filter: blur(1.5px); }
.nf-search[open] { animation: nfSearchIn .12s ease-out; }
@keyframes nfSearchIn { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .nf-search[open] { animation: none; } }

.nf-search__form { margin: 0; }
.nf-search__bar {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 16px; border-bottom: 2px solid var(--ink); background: var(--paper);
}
.nf-search__bar-icon { flex: none; color: var(--muted); }
.nf-search__input {
  flex: 1 1 auto; min-width: 0;
  font-family: var(--ui); font-size: max(1rem, 16px);   /* 16px min: no iOS zoom-on-focus */
  color: var(--ink); background: transparent; border: 0; outline: 0; padding: 2px 0;
}
.nf-search__input::placeholder { color: var(--muted); }
.nf-search__esc {
  flex: none; font-family: var(--mono); font-size: 0.62rem; font-weight: 700;
  color: var(--muted); border: 1px solid var(--rule); border-radius: 2px; padding: 2px 5px;
}

.nf-search__results { list-style: none; margin: 0; padding: 4px; overflow-y: auto; }
.nf-search__row { margin: 0; }
.nf-search__hit {
  display: block; text-decoration: none; color: var(--ink);
  padding: 10px 12px; border-radius: 2px; border: 1px solid transparent;
}
/* keyboard/mouse highlight — INK wash, not red */
.nf-search__hit.is-active, .nf-search__hit:focus-visible {
  background: color-mix(in srgb, var(--ink) 9%, var(--panel));
  border-color: var(--rule); outline: none;
}
.nf-search__hit-title {
  display: block; font-family: var(--disp); font-weight: 700;
  font-size: max(0.98rem, 15px); line-height: 1.25; letter-spacing: -0.01em;
}
.nf-search__hit-excerpt {
  display: block; margin-top: 3px;
  font-family: var(--ui); font-size: max(0.82rem, 11.5px); color: var(--muted); line-height: 1.4;
  overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.nf-search__hit-meta {
  display: block; margin-top: 5px;
  font-family: var(--mono); font-size: max(0.66rem, 11.5px); letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
}
/* Gated badge — a lock affordance, NOT the money door. Neutral ink chip, never red. */
.nf-search__badge {
  display: inline-block; vertical-align: 2px;
  font-family: var(--mono); font-size: max(0.6rem, 11.5px); font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--paper); background: var(--ink);
  border-radius: 2px; padding: 1px 5px; margin-left: 2px;
}

.nf-search__note {
  padding: 12px 16px; border-top: 1px solid var(--rule);
  font-family: var(--mono); font-size: max(0.68rem, 11.5px); letter-spacing: 0.04em;
  color: var(--muted); text-transform: uppercase;
}
.nf-search__note[hidden] { display: none; }
.nf-search__keys { opacity: .8; }

@media (max-width: 560px) {
  .nf-search { width: calc(100vw - 16px); margin-top: 6vh; max-height: 82vh; }
  .nf-search__keys { display: none; }
}

/* ── Reader home / library — you.{apex} ──────────────────────────────────────
   A NETWORK page (no member masthead). Reuses the paper/ink tokens, the mono
   labels, the --lift zine offset-shadow and the 11.5px readability floor.
   Accent is INK — this page has no money door of its own, so it carries NO red
   (--buy) anywhere. */
.lib { max-width: var(--measure); margin: 0 auto; padding: 0 var(--gutter); }

.lib__masthead {
  border-bottom: 3px solid var(--rule-hard);
  padding: var(--s5) 0 var(--s3);
  margin-bottom: var(--s4);
}
.lib__kicker {
  font-family: var(--mono); font-size: max(0.75rem, 11.5px); font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted);
  margin-bottom: 12px;
}
.lib__title {
  font-family: var(--disp); font-weight: 800;
  font-size: clamp(2.2rem, 6vw, 3.2rem); line-height: 0.94;
  letter-spacing: -0.02em; text-transform: uppercase;
}

/* Signed-in identity + sign-out, on the masthead */
.lib__whoami {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px;
  margin-top: 16px;
}
.lib__email {
  font-family: var(--mono); font-size: max(0.72rem, 11.5px);
  letter-spacing: 0.04em; color: var(--muted);
}
.lib__email strong { color: var(--ink); font-weight: 700; }
.lib__signout { margin: 0; }
.lib__signout-btn {
  background: transparent; color: var(--ink); border: 1.5px solid var(--ink);
  font-family: var(--mono); font-size: max(0.66rem, 11.5px); font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  border-radius: var(--btn-radius, 999px); padding: 5px 12px; cursor: pointer;
}
.lib__signout-btn:hover { background: var(--ink); color: var(--paper); }

/* Panel (sign-in / expired states) */
.lib__panel {
  border: 2px solid var(--rule-hard); box-shadow: var(--lift);
  background: var(--panel); padding: var(--s4) var(--s3);
  max-width: 460px; margin: 0 auto var(--s5);
}
.lib__lede {
  font-family: var(--read); font-size: 1.0625rem; line-height: 1.55;
  color: var(--ink); margin-bottom: 22px;
}
.lib__form { display: flex; flex-direction: column; gap: 14px; }
.lib__label {
  font-family: var(--ui); font-size: 0.8125rem; font-weight: 600; color: var(--ink);
}
.lib__label-note { font-weight: 400; color: var(--muted); display: block; font-size: 0.75rem; margin-top: 3px; }
.lib__input {
  border: 1.5px solid var(--ink); padding: 11px 12px; font-family: var(--ui);
  font-size: 0.9375rem; outline: none; background: var(--paper); color: var(--ink); width: 100%;
}
.lib__input:focus { box-shadow: 0 0 0 2px color-mix(in srgb, var(--ink) 28%, transparent); }
/* Sign-in is an INK action, never the red money door */
.lib__submit {
  display: inline-block; background: var(--ink); color: var(--paper); border: none;
  font-family: var(--disp); font-size: 0.86rem; font-weight: 600; letter-spacing: 0.06em;
  text-transform: uppercase; border-radius: var(--btn-radius, 999px); padding: 13px 24px; cursor: pointer; width: 100%;
}
.lib__submit:hover { opacity: 0.9; }
.lib__submit:active { opacity: 1; }
.lib__fineprint {
  font-family: var(--ui); font-size: max(0.75rem, 11.5px); color: var(--muted); margin-top: 16px;
}
.lib__fineprint a, .lib__empty-cta a { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; }

/* Library list — crafted rows, mono metadata */
.lib__list { list-style: none; margin: 0; padding: 0; }
.lib__item {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: 6px 18px; padding: 18px 0; border-bottom: 1px solid var(--rule);
}
.lib__item:first-child { border-top: 1px solid var(--rule); }
.lib__item-link { text-decoration: none; color: var(--ink); flex: 1 1 60%; min-width: 0; }
.lib__item-title {
  display: block; font-family: var(--disp); font-weight: 700;
  font-size: clamp(1.15rem, 2.6vw, 1.4rem); line-height: 1.15;
}
.lib__item-link:hover .lib__item-title { text-decoration: underline; text-underline-offset: 3px; }
.lib__item-space {
  display: block; margin-top: 4px;
  font-family: var(--mono); font-size: max(0.68rem, 11.5px); font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted);
}
.lib__item-when {
  flex: none; font-family: var(--mono); font-size: max(0.66rem, 11.5px);
  letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); white-space: nowrap;
}

/* Empty state — designed, not a bare line */
.lib__empty {
  border: 2px dashed var(--rule-hard); background: var(--panel);
  padding: var(--s5) var(--s3); text-align: center; max-width: 460px; margin: 0 auto var(--s5);
}
.lib__empty-head {
  font-family: var(--disp); font-weight: 800; font-size: 1.5rem;
  text-transform: uppercase; letter-spacing: -0.01em; margin-bottom: 10px;
}
.lib__empty-sub { font-family: var(--read); font-size: 1rem; line-height: 1.55; color: var(--muted); margin-bottom: 18px; }
.lib__empty-cta { font-family: var(--ui); font-size: var(--min); font-weight: 700; letter-spacing: normal; text-transform: none; }

/* Library sections (Purchased / Saved), the add-a-link form + per-card remove.
   INK, never red — the library is a reading surface, not a money door. */
.lib__section { margin: 0 0 var(--s4); }
.lib__section-title {
  font-family: var(--disp); font-weight: 800; font-size: 1.15rem;
  text-transform: uppercase; letter-spacing: 0.03em; color: var(--ink);
  margin: 0 0 var(--s2); padding-bottom: 8px; border-bottom: 2px solid var(--ink);
}
.lib__section-empty {
  font-family: var(--read); font-size: 1rem; line-height: 1.55; color: var(--muted); margin: 0 0 18px;
}
/* Saved rows carry an optional thumbnail + a remove control; center-align them. */
.lib__item--saved { align-items: center; }
.lib__item-thumb {
  flex: none; width: 56px; height: 56px; object-fit: cover;
  border: 1px solid var(--rule); background: var(--panel);
}
.lib__remove { margin: 0; flex: none; }
.lib__remove-btn {
  background: transparent; color: var(--muted); border: 2px solid var(--rule-hard);
  font-family: var(--ui); font-size: var(--min); font-weight: 700;
  letter-spacing: normal; text-transform: none;
  border-radius: var(--btn-radius, 3px); min-height: 36px; padding: 5px 10px; cursor: pointer;
}
.lib__remove-btn:hover { border-color: var(--ink); color: var(--ink); }
/* Add-a-link: inline row of url + optional title + submit, wrapping on narrow. */
.lib__addlink {
  display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end;
  margin-top: var(--s3); padding-top: var(--s3); border-top: 1px solid var(--rule);
}
.lib__addlink .lib__label { flex-basis: 100%; }
.lib__addlink .lib__input { flex: 1 1 220px; width: auto; }
.lib__addlink .lib__submit { flex: none; width: auto; }

@media (max-width: 560px) {
  .lib__masthead { padding: var(--s4) 0 var(--s3); }
  .lib__panel, .lib__empty { padding: var(--s3) var(--s2); }
  .lib__item-when { flex-basis: 100%; }
  .lib__addlink .lib__input, .lib__addlink .lib__submit { flex-basis: 100%; width: 100%; }
}

/* ── Series ───────────────────────────────────────────────────────────────────
   The on-post series strip (post.php) + the public series index (/c/{slug},
   collection.php). Reuses the same tokens as .post-neighbors / .post-list —
   INK, never red: series navigation is a reading relationship, not a money door.
   The only red on the series pages is the gated price BADGE (.badge--gated),
   which is the shared money-door token. Fully functional with zero JS. */

/* On-post strip: prev · "Part N of {Series}" (opens the index) · next */
.series-strip {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: stretch; gap: 8px;
  margin: var(--s3) 0 var(--s4);
  border: 2px solid var(--ink); background: var(--panel); box-shadow: var(--lift);
}
.series-strip__side {
  display: flex; align-items: center; gap: 6px; padding: 12px 14px;
  font-family: var(--mono); font-size: max(0.72rem, 11.5px); font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink);
  text-decoration: none; white-space: nowrap;
}
.series-strip__side--next { justify-content: flex-end; }
.series-strip__side:hover { background: var(--panel2); }
.series-strip__side--empty { pointer-events: none; }
.series-strip__mid {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 10px 16px; text-align: center; text-decoration: none; color: var(--ink);
  border-left: 1px solid var(--rule); border-right: 1px solid var(--rule);
}
.series-strip__mid:hover { background: var(--panel2); }
.series-strip__part {
  font-family: var(--mono); font-size: max(0.72rem, 11.5px); font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted);
}
.series-strip__name {
  font-family: var(--disp); font-weight: 700; font-size: 0.98rem; line-height: 1.1;
  letter-spacing: -0.01em; color: var(--ink);
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden;
}
@media (max-width: 560px) {
  .series-strip { grid-template-columns: 1fr; }
  .series-strip__side { justify-content: center; }
  .series-strip__mid { border-left: none; border-right: none;
    border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule); order: -1; }
}

/* Public series index page (collection.php) */
.series-index__head { margin: var(--s4) 0 var(--s3); }
.series-index__kicker {
  font-family: var(--mono); font-size: max(0.72rem, 11.5px); font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); margin-bottom: 6px;
}
.series-index__title {
  font-family: var(--disp); font-weight: 800; font-size: clamp(1.7rem, 5vw, 2.6rem);
  line-height: 1.05; letter-spacing: -0.02em; color: var(--ink);
}
.series-index__blurb {
  font-family: var(--read); font-size: 1.06rem; line-height: 1.55; color: var(--ink);
  margin-top: 12px; max-width: var(--measure);
}
.series-index__by {
  font-family: var(--mono); font-size: max(0.72rem, 11.5px); color: var(--muted);
  margin-top: 10px; text-transform: uppercase; letter-spacing: 0.06em;
}
.series-list { list-style: none; margin-top: var(--s3); }
.series-list__item {
  display: flex; align-items: flex-start; gap: 14px;
  padding: 18px 0; border-bottom: 1px solid var(--rule);
}
.series-list__item:first-child { border-top: 1px solid var(--rule); }
.series-list__num {
  flex: none; width: 34px; height: 34px; display: grid; place-items: center;
  border: 2px solid var(--ink); background: var(--panel);
  font-family: var(--disp); font-weight: 800; font-size: 1rem; color: var(--ink);
}
.series-list__text { flex: 1 1 auto; min-width: 0; }
.series-list__title {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  font-family: var(--disp); font-weight: 700; font-size: 1.2rem; line-height: 1.2;
  letter-spacing: -0.01em;
}
.series-list__title a { color: var(--ink); text-decoration: none; }
.series-list__title a:hover { text-decoration: underline; }
.series-list__excerpt {
  font-family: var(--read); font-size: 0.98rem; line-height: 1.5; color: var(--ink);
  margin-top: 6px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.series-list__meta { font-size: 0.72rem; color: var(--muted); margin-top: 10px;
  font-family: var(--mono); letter-spacing: 0.04em; }
.series-list__meta-part { text-transform: uppercase; }
.series-list__thumb {
  flex: none; width: 112px; height: 84px; overflow: hidden; border: 1px solid var(--rule);
}
.series-list__thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
@media (max-width: 560px) {
  .series-list__thumb { width: 84px; height: 64px; }
  .series-list__num { width: 28px; height: 28px; font-size: 0.86rem; }
}
