/* ──────────────────────────────────────────────────────────────────────────
   Literary reading theme — WHITE background, refined SERIF.
   Per reader-ux.md §5: the HTML reading view is ALWAYS white; the typeface
   reflects the title's character — serif for classical/literary magazines
   (e.g. LRB, Granta), sans for modern titles.
   Type: Source Serif 4 (modern, screen-legible serif). Clean, contemporary,
   literary — no sepia, no fust.  Styles every class the converted HTML emits.
   ────────────────────────────────────────────────────────────────────────── */
@import url('https://fonts.googleapis.com/css2?family=Source+Serif+4:ital,opsz,wght@0,8..60,400;0,8..60,500;0,8..60,600;0,8..60,700;1,8..60,400;1,8..60,500;1,8..60,600&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
/* Google Fonts removed — Teal Signal v2.0 uses system fonts only (Inter, Georgia) */

:root {
  --bg: #ffffff;
  --ink: #18181b;
  --ink-soft: #3f3f46;
  --muted: #71717a;
  --faint: #fafafa;
  --rule: #e5e5e5;
  --accent: #18181b;
  --serif: 'Source Serif 4', Georgia, 'Times New Roman', serif;

  /* Reader action colour (co-zinup#12633 AC 9). The reader is publisher-
     branded (brand-guide.md §2a), so its actions use the PUBLISHER's accent
     — never ZinUp teal. `--rd-accent*` are set from issue.brandColors.accent
     by functions/_middleware.ts and src/lib/reader-accent.ts; unset, every
     token falls back to neutral zinc. Components read the `--rd-action*`
     tokens only (see RD in src/lib/reader-accent.ts). */
  --rd-action: var(--rd-accent, #18181b);
  --rd-action-ink: var(--rd-accent-ink, #ffffff);
  --rd-action-text: var(--rd-accent-text-light, #18181b);
  --rd-action-on-dark: var(--rd-accent, #E4E4E7);
  --rd-action-on-dark-ink: var(--rd-accent-ink, #18181b);
  --rd-action-on-dark-text: var(--rd-accent-text-dark, #E4E4E7);
}

* { box-sizing: border-box; }

/* ──────────────────────────────────────────────────────────────────────────
   GLOBAL archetype font. The whole reader (feed chrome, Discover/contents,
   cards, archive, reading view) inherits ONE font per active issue archetype,
   set via data-archetype on the App root:
     editorial-literary → Source Serif 4 (serif)
     industrial-trade   → Inter (sans)
   Components no longer hardcode a family; they inherit this and only pin
   weight/size. Monospace meta tags opt back out explicitly below.
   ────────────────────────────────────────────────────────────────────────── */
[data-archetype="editorial-literary"] {
  font-family: Georgia, 'Times New Roman', serif;  /* Teal Signal v2.0 */
}
[data-archetype="news-weekly"] {
  font-family: Inter, system-ui, -apple-system, sans-serif;  /* Teal Signal v2.0 */
}
[data-archetype="industrial-trade"] {
  font-family: Inter, system-ui, -apple-system, sans-serif;  /* Teal Signal v2.0 */
}
[data-archetype="fashion-glossy"] {
  font-family: Georgia, serif;  /* Teal Signal v2.0 */
}
[data-archetype="lifestyle-travel"],
[data-archetype="house-home"] {
  font-family: Georgia, serif;  /* Teal Signal v2.0 */
}
[data-archetype="sport"] {
  font-family: Inter, system-ui, -apple-system, sans-serif;  /* Teal Signal v2.0 */
}
[data-archetype="tabloid-pop"] {
  font-family: Inter, system-ui, -apple-system, sans-serif;  /* Teal Signal v2.0 */
}
[data-archetype="photography-art"] {
  font-family: Inter, system-ui, -apple-system, sans-serif;  /* Teal Signal v2.0 */
}

/* Named reader STYLES (genre-agnostic) — root sets the BODY font; heading
   overrides below give each its heading font. Keep in sync with archetypes.ts.
   Teal Signal v2.0: collapsed to Inter (sans) + Georgia (serif) system fonts. */
[data-archetype="style-classic"] { font-family: Georgia, serif; }
[data-archetype="style-modern"] { font-family: Inter, system-ui, -apple-system, sans-serif; }
[data-archetype="style-elegant"] { font-family: Inter, system-ui, -apple-system, sans-serif; }
[data-archetype="style-warm"] { font-family: Inter, system-ui, -apple-system, sans-serif; }
[data-archetype="style-bold"] { font-family: Inter, system-ui, -apple-system, sans-serif; }
[data-archetype="style-condensed"] { font-family: Inter, system-ui, -apple-system, sans-serif; }

/* Headings, body, chrome inherit the archetype font from the root. */
[data-archetype] h1,
[data-archetype] h2,
[data-archetype] h3,
[data-archetype] h4,
[data-archetype] p,
[data-archetype] span,
[data-archetype] button,
[data-archetype] input,
[data-archetype] li,
[data-archetype] .card-headline,
[data-archetype] .card-quote-text,
[data-archetype] .card-stat-number,
[data-archetype] .article-body-text {
  font-family: inherit;
}
/* Per-style HEADING fonts (override the inherited body font above). Classic and
   Modern use one font throughout, so they need no override. */
[data-archetype="style-elegant"] h1,
[data-archetype="style-elegant"] h2,
[data-archetype="style-elegant"] h3,
[data-archetype="style-elegant"] .card-headline {
  font-family: 'Instrument Serif', Georgia, serif;
}
[data-archetype="style-warm"] h1,
[data-archetype="style-warm"] h2,
[data-archetype="style-warm"] h3,
[data-archetype="style-warm"] .card-headline {
  font-family: 'Fraunces', Georgia, serif;
}
[data-archetype="style-bold"] h1,
[data-archetype="style-bold"] h2,
[data-archetype="style-bold"] h3,
[data-archetype="style-bold"] .card-headline {
  font-family: 'Archivo', system-ui, -apple-system, sans-serif;
  font-weight: 800;
}
[data-archetype="style-condensed"] h1,
[data-archetype="style-condensed"] h2,
[data-archetype="style-condensed"] h3,
[data-archetype="style-condensed"] .card-headline {
  font-family: 'Oswald', system-ui, -apple-system, sans-serif;
}

/* Monospace meta tags keep their typewriter face regardless of archetype. */
[data-archetype] .meta-tag {
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
}

html, body {
  margin: 0; padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--serif);
  font-size: 19px;
  line-height: 1.66;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

article {
  max-width: 38rem;
  margin: 0 auto;
  padding: 2.5rem 1.5rem 5rem;
  /* Pin font/bg so the design holds when injected into the app shell */
  font-family: var(--serif);
  background: var(--bg);
  color: var(--ink);
}
article, article p, article li, article dd, article dt, article span,
article h1, article h2, article h3, article h4, article blockquote,
article figcaption, article cite, article .kicker, article .byline {
  font-family: var(--serif);
}

/* ── Header block ────────────────────────────────────────────────────────── */
.kicker, .sidebar-kicker, h3, .toc-section, .cover-label, .capsule-meta, .pb-key {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  font-feature-settings: "smcp" 0;
}
.kicker { margin: 0 0 0.85rem; }

h1 {
  font-size: clamp(2.1rem, 8.5vw, 2.9rem);
  line-height: 1.1;
  font-weight: 600;
  letter-spacing: -0.012em;
  margin: 0 0 1rem;
  color: var(--ink);
}
h1 em { font-style: italic; font-weight: 600; }

.standfirst, .lede {
  font-size: 1.3rem;
  line-height: 1.5;
  font-weight: 400;
  font-style: italic;
  color: var(--ink-soft);
  margin: 0 0 1.6rem;
}

.byline, .meta, .issue-meta {
  font-size: 0.9rem;
  font-weight: 500;
  font-style: normal;
  color: var(--muted);
  letter-spacing: 0;
  text-transform: none;
}
.byline {
  margin: 0 0 2.25rem;
  padding-bottom: 1.4rem;
  border-bottom: 1px solid var(--rule);
}
/* co-zinup#12834 — a closing author bio ends the article (where the
   extraction reads it): a rule ABOVE it, italic, no rule below. */
.byline.byline-closing {
  margin: 2rem 0 0;
  padding: 1.2rem 0 0;
  border-bottom: none;
  border-top: 1px solid var(--rule);
  font-style: italic;
}

/* co-zinup#12873 — the closing author bio, rendered at its reading-order
   position in the body (a {kind:"bio"} block from the extraction). */
.reading-bio {
  margin: 2rem 0 1.25rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--rule);
  font-size: 0.95rem;
  font-style: italic;
  color: var(--ink-soft);
}

/* ── Body ────────────────────────────────────────────────────────────────── */
p { margin: 0 0 1.25rem; }
em { font-style: italic; }
strong { font-weight: 700; }

h2 {
  font-size: 1.55rem;
  font-weight: 600;
  letter-spacing: -0.008em;
  line-height: 1.24;
  margin: 2.75rem 0 0.7rem;
  color: var(--ink);
}
h3 { margin: 2.25rem 0 0.55rem; }
h4 {
  font-size: 1.05rem; font-weight: 700;
  margin: 1.6rem 0 0.45rem; color: var(--ink);
}

a { color: var(--accent); text-underline-offset: 2px; }

section { margin: 2.5rem 0 0; }
section + section { border-top: 1px solid var(--rule); padding-top: 2rem; }

/* ── Pull quotes — Georgia italic, 3px left rule in the publisher accent ─ */
blockquote.pullquote {
  margin: 2.5rem 0;
  padding: 0.2rem 0 0.2rem 1.2rem;
  border: 0;
  border-left: 3px solid var(--rd-action);
  font-family: Georgia, 'Times New Roman', serif;
  font-style: italic;
  font-size: 1.6rem;
  line-height: 1.36;
  font-weight: 500;
  letter-spacing: -0.008em;
  color: var(--ink);
}
blockquote.pullquote cite, cite {
  display: block;
  margin-top: 0.9rem;
  font-style: normal;
  font-size: 0.9rem;
  font-weight: 500;
  letter-spacing: 0;
  color: var(--muted);
}

/* ── Images / placeholders ──────────────────────────────────────────────── */
figure.image-placeholder, figure.cover-placeholder, figure.cover-feature-image {
  margin: 2.25rem 0;
  padding: 0;
  background: var(--faint);
  border: 1px solid var(--rule);
  border-radius: 10px;
  aspect-ratio: 3 / 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  color: var(--muted);
  overflow: hidden;
}
figure.image-placeholder::before {
  content: "Image";
  font-size: 0.72rem; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
  color: #bcbcc2;
}
figure.image-placeholder figcaption, figure.cover-placeholder figcaption {
  margin: 0.7rem 1.25rem 0;
  font-size: 0.95rem; line-height: 1.4; font-style: italic; color: var(--muted);
}

/* ── Sidebars ────────────────────────────────────────────────────────────── */
aside.sidebar, aside.operator-bio, .press-quotes {
  margin: 2.5rem 0;
  padding: 1.4rem 1.5rem 1.5rem;
  background: var(--faint);
  border: 1px solid var(--rule);
  border-radius: 12px;
}
.sidebar-kicker { display: block; margin: 0 0 0.45rem; color: var(--muted); }
.sidebar-title { font-size: 1.2rem; font-weight: 600; margin: 0 0 0.3rem; color: var(--ink); }
.sidebar-meta, .pb-meta, .capsule-meta, .item-desc { font-size: 0.9rem; font-style: italic; color: var(--muted); margin: 0 0 0.7rem; }
aside.operator-bio .name { font-weight: 700; font-size: 1.05rem; margin: 0 0 0.2rem; }
aside.operator-bio .role { color: var(--muted); margin: 0; }

/* ── Paperback / capsule list patterns ──────────────────────────────────── */
dl.pb-pattern { margin: 1.4rem 0; padding: 0; }
dl.pb-pattern dt, .paperback dt {
  font-weight: 700; font-size: 1.1rem; margin: 1.4rem 0 0.1rem; color: var(--ink);
}
dl.pb-pattern dd, .paperback dd { margin: 0 0 0.35rem; }
.pb-meta, .pb-key { display: block; }
.paperback, .capsule {
  margin: 1.6rem 0; padding: 1.4rem 0 0; border-top: 1px solid var(--rule);
}
.capsule-num, .page-num, .capsule-meta { color: var(--muted); }
.capsule-num, .page-num { font-size: 0.85rem; font-weight: 700; }
.item-title { font-weight: 600; color: var(--ink); }
.item-body { margin: 0.3rem 0 0; }

/* ── Contents / TOC ─────────────────────────────────────────────────────── */
.toc-section { display: block; margin: 1.9rem 0 0.7rem; color: var(--muted); }
.toc-item {
  display: flex; gap: 0.75rem; align-items: baseline;
  padding: 0.65rem 0; border-bottom: 1px solid var(--rule);
}
.toc-page, .toc-item .page-num { color: var(--muted); font-variant-numeric: tabular-nums; min-width: 2ch; }

/* ── Cover article bits ─────────────────────────────────────────────────── */
.cover-hero, .cover { text-align: left; }
.cover-edition, .issue-meta { color: var(--muted); }
.sell { font-size: 1.3rem; font-style: italic; line-height: 1.4; color: var(--ink-soft); }
.delon { font-size: clamp(2.6rem, 12vw, 4.2rem); font-weight: 600; letter-spacing: -0.02em; margin: 0.4rem 0; }
.promise { font-size: 1.15rem; font-style: italic; color: var(--ink-soft); border-top: 1px solid var(--rule); padding-top: 1rem; margin-top: 1.4rem; }
.cover-label { display: block; margin-bottom: 0.4rem; }

/* ── Misc ────────────────────────────────────────────────────────────────── */
.section-break { text-align: center; margin: 2.4rem 0; color: #cfcfd4; letter-spacing: 0.6em; }

footer.article-foot {
  margin-top: 3.25rem; padding-top: 1.4rem;
  border-top: 1px solid var(--rule);
  font-size: 0.85rem; font-style: italic; color: var(--muted);
}

/* ──────────────────────────────────────────────────────────────────────────
   In-app reading-view shell. The <article class="reading-view"> rendered by
   ArticleSlideUp carries data-archetype; the WHITE background is always on,
   only the typeface + accents change per genre.
   ────────────────────────────────────────────────────────────────────────── */
article.reading-view {
  max-width: 38rem;
  margin: 0 auto;
  background: #ffffff;        /* WHITE — both archetypes */
  color: var(--ink);
  /* co-zinup#10986 AC4 — the bare `article` rule above sets a bottom padding
     of 5rem (80px), sized for "nothing follows the article" (the Original
     PDF view, which never renders the end-of-article rails). In the reading
     view, ReadNextRail/RelatedArticlesRail (rendered as SIBLINGS right after
     this element, not inside it — ArticleSlideUp.tsx) each add their own
     1.5rem (24px) top padding, so the two stacked unconditionally produced
     a measured ~117px gap even when a rail follows immediately, before this
     ticket's diagnosis. Reduced here rather than to zero: when BOTH rails
     are suppressed (sparse-catalogue / no-onOpenCitation), this padding is
     the ONLY bottom spacing the reading view has — collapsing it to zero
     would leave the article's last line flush against the app shell edge. */
  padding-bottom: 2rem;
}
article.reading-view .reading-body { margin-top: 1.5rem; }
/* Part of the same AC4 fix: a trailing block's own default bottom margin
   (e.g. a <p>'s UA-agent ~1em) stacked on TOP of the padding above,
   contributing to the measured gap independently of it. */
article.reading-view .reading-body > *:last-child { margin-bottom: 0; }

/* co-zinup#9916 AC4 — the sentence currently being read aloud (device-voice
   playback only — see ReadAloud.tsx's onSentenceChange doc comment). Idle
   markup is completely unaffected (no wrapping span exists until playback is
   active), so this rule never paints on a static screenshot — the ArticleSlideUp
   Reader/Archive no-diff requirement (AC8) holds regardless of viewport. */
.reading-sentence-active {
  background: rgba(255, 200, 0, 0.35);
  border-radius: 0.15em;
  transition: background 0.15s ease;
}

/* Title — high specificity so it beats Tailwind's preflight reset (which sets
   h1 font-size/weight to inherit, leaving the title smaller than the italic
   standfirst). The headline must read as the dominant element: bold and clearly
   larger than the standfirst beneath it (owner, 2026-06-10). */
article.reading-view h1 {
  font-size: clamp(2.05rem, 7.6vw, 2.7rem);
  line-height: 1.12;
  font-weight: 700;
  letter-spacing: -0.015em;
  margin: 0 0 1rem;
  color: var(--ink);
}
article.reading-view h1 em { font-style: italic; font-weight: 700; }

/* Reading-view rhythm — high-specificity so it beats Tailwind's preflight reset
   (which zeroes h2/p margins, making subheadings run into the body). */
article.reading-view .reading-body p { margin: 0 0 1.15rem; }
article.reading-view .reading-body h2 {
  margin: 2.4rem 0 0.6rem;
  font-size: 1.4rem;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: 0.02em;
}
article.reading-view .reading-body h3 { margin: 1.9rem 0 0.5rem; }
article.reading-view .reading-body > :first-child { margin-top: 0; }

/* Quote-only columns (short quote round-ups, testimonials): each
   verbatim quote renders as a body block. Neutral palette — grey rule, no
   brand colour; imagery (none here) is the only source of colour. */
article.reading-view .reading-body blockquote.reading-pullquote {
  margin: 0 0 1.9rem;
  padding: 0 0 0 1.1rem;
  border: 0;
  border-left: 3px solid #d4d4d8;
  color: var(--ink);
}
article.reading-view .reading-body blockquote.reading-pullquote p {
  margin: 0;
  font-size: 1.3rem;
  line-height: 1.4;
  font-weight: 500;
  letter-spacing: -0.005em;
}
article.reading-view .reading-body blockquote.reading-pullquote cite {
  display: block;
  margin-top: 0.55rem;
  font-style: normal;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--muted);
}

/* Neutral in-body article image — full content width, white reading view,
   no coloured borders. Applies to both archetypes. */
article.reading-view .reading-image {
  width: 100%;
  margin: 1.75rem 0;
  border-radius: 10px;
  background: #ffffff;
}
article.reading-view .reading-image img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: 10px;
}

/* Full-width / edge-to-edge variant — default for every main image
   (co-zinup#12747), publisher- and per-image-overridable. Breaks out of the
   article's own horizontal padding (1.5rem each side, set on `article` above)
   rather than the viewport, so it reaches the true edge on a phone (where the
   column IS the viewport) and the reading column's edge on desktop (where the
   column is capped at 38rem/608px, co-zinup#11918) with the SAME rule and no
   media query. A `vw`-anchored rule is wrong on desktop by construction — see
   co-zinup#12747's build brief for why `100vw`/`calc(-50vw+50%)` (the v1 rule
   this replaces) only happened to look right on mobile. Gallery images stay
   inset (v1 decision; galleries scroll horizontally and edge-to-edge would
   conflict with their overflow) — galleries have no `display` field at all,
   so they never reach this rule. */
article.reading-view .reading-image-full {
  width: calc(100% + 3rem); /* 2 × the parent's own 1.5rem horizontal padding */
  margin-left: -1.5rem;
  margin-right: -1.5rem;
  border-radius: 0;
}
article.reading-view .reading-image-full img {
  border-radius: 0;
}
/* Caption on a full-width image: re-inset the text so it stays legible. */
article.reading-view .reading-image-full figcaption {
  padding-left: 1.5rem;
  padding-right: 1.5rem;
}

/* ──────────────────────────────────────────────────────────────────────────
   ARCHETYPE: industrial-trade — WHITE background + crisp modern SANS (Inter).
   Steel-blue / amber accents. Mirrors every class the literary theme styles
   (kicker, standfirst, byline, h1/h2, pullquote, image-placeholder,
   article-foot, etc.) but sans-serif.
   ────────────────────────────────────────────────────────────────────────── */
:root {
  --ind-sans: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  /* Neutral grey only — the ONLY difference between archetypes is the font. */
  --ind-steel: #71717a;
  --ind-amber: #71717a;
  --ind-slate: #71717a;
  --ind-ink: #18181b;
  --ind-ink-soft: #3f3f46;
  --ind-muted: #71717a;
}

[data-archetype="industrial-trade"] {
  background: #ffffff;        /* WHITE — never sepia */
  color: var(--ind-ink);
}

[data-archetype="industrial-trade"],
[data-archetype="industrial-trade"] p,
[data-archetype="industrial-trade"] li,
[data-archetype="industrial-trade"] span,
[data-archetype="industrial-trade"] h1,
[data-archetype="industrial-trade"] h2,
[data-archetype="industrial-trade"] h3,
[data-archetype="industrial-trade"] h4,
[data-archetype="industrial-trade"] blockquote,
[data-archetype="industrial-trade"] figcaption,
[data-archetype="industrial-trade"] cite,
[data-archetype="industrial-trade"] .kicker,
[data-archetype="industrial-trade"] .standfirst,
[data-archetype="industrial-trade"] .byline {
  font-family: var(--ind-sans);
}

[data-archetype="industrial-trade"] .kicker {
  color: var(--ind-steel);
  font-weight: 700;
  letter-spacing: 0.12em;
}

[data-archetype="industrial-trade"] h1 {
  color: var(--ind-ink);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.08;
}
[data-archetype="industrial-trade"] h1 em { font-style: normal; }

[data-archetype="industrial-trade"] .standfirst,
[data-archetype="industrial-trade"] .lede {
  font-style: normal;          /* sans standfirst reads cleaner upright */
  font-weight: 400;
  color: var(--ind-ink-soft);
  font-size: 1.2rem;
  line-height: 1.5;
}

[data-archetype="industrial-trade"] .byline {
  color: var(--ind-muted);
  font-weight: 500;
}

[data-archetype="industrial-trade"] h2,
[data-archetype="industrial-trade"] h3,
[data-archetype="industrial-trade"] h4 {
  color: var(--ind-ink);
  font-weight: 700;
  letter-spacing: -0.01em;
}

[data-archetype="industrial-trade"] p { color: var(--ind-ink-soft); }

[data-archetype="industrial-trade"] blockquote.pullquote {
  font-style: italic;
  font-weight: 600;
  border-left: 3px solid var(--rd-action);
  color: var(--ind-ink);
}
[data-archetype="industrial-trade"] blockquote.pullquote cite,
[data-archetype="industrial-trade"] cite {
  color: var(--ind-muted);
}

[data-archetype="industrial-trade"] a { color: var(--ind-steel); }

[data-archetype="industrial-trade"] figure.image-placeholder,
[data-archetype="industrial-trade"] figure.cover-placeholder {
  background: #f3f5f8;
  border-color: #d9dee6;
}
[data-archetype="industrial-trade"] figure.image-placeholder figcaption,
[data-archetype="industrial-trade"] figure.cover-placeholder figcaption {
  font-style: normal;
  color: var(--ind-muted);
}

[data-archetype="industrial-trade"] aside.operator-bio,
[data-archetype="industrial-trade"] aside.sidebar {
  background: #f3f5f8;
  border-color: #d9dee6;
}

[data-archetype="industrial-trade"] .section-break { color: var(--ind-amber); }

[data-archetype="industrial-trade"] footer.article-foot {
  font-style: normal;
  color: var(--ind-muted);
}

/* ── Read | Original toggle (neutral pill, two segments) ────────────────── */
/* co-zinup#10865 commit 4 — square, not a bubble (architect brief AC4:
   "No rounded corners, no bubbles" — Jason). */
.orig-toggle {
  display: inline-flex;
  background: #f1f1f3;
  border-radius: 0;
  padding: 2px;
  gap: 2px;
}
.orig-toggle button {
  appearance: none;
  border: none;
  background: transparent;
  color: #71717a;
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: 600;
  font-size: 13px;
  line-height: 1;
  padding: 6px 14px;
  border-radius: 0;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.orig-toggle button.active {
  background: #18181b;
  color: #ffffff;
}

/* ── Archive-only header segmented control (co-zinup#9916 AC5, co-zinup#9927) ──
   Desktop/tablet: absolute-centered over the header row (same math as the
   inline style this replaced — anchored to the row's `position: relative`). */
.archive-segmented-row {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}
/* Narrow viewports — co-zinup#9927 used to wrap `.archive-segmented-row` onto
   its own row here (below Back/Listen) because at 390px Back, the segmented
   control AND the header Listen pill were competing for one row. That header
   Listen pill was deleted in co-zinup#10865 commit 2/3 (Listen now lives only
   in the rail, gated on `view === "read"` — never shown here at all), so the
   crowding #9927 fixed no longer exists in this row. co-zinup#11616 Defect E
   (owner, 2026-09-18, on a real phone: "the header... has two levels... same
   when you go to the printed page" — the header must be a SINGLE row) reverts
   #9927's wrap and instead keeps the control in normal flow, shrunk to fit
   alongside Close and (on the printed-page view) the Scroll/Swipe toggle. */
@media (max-width: 480px) {
  .archive-header-row {
    flex-wrap: nowrap;
  }
  .archive-segmented-row {
    position: static;
    transform: none;
    display: flex;
    justify-content: center;
  }
  /* Both segmented pills (Article text/Printed page AND Scroll/Swipe) shrink
     at this width so Close + both toggles fit on one line at 390px — the
     "fold" the ticket calls out as the candidate when space is genuinely
     tight, rather than dropping either toggle. */
  .archive-header-row .orig-toggle button {
    padding: 5px 8px;
    font-size: 11px;
    white-space: nowrap;
  }
}

/* ── Prev / next article chevrons (Read view, desktop/tablet) ───────────── */
.article-nav-chevron {
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  z-index: 5;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  /* co-zinup#10865 commit 4 — square (architect brief AC4). */
  border-radius: 0;
  background: rgba(24, 24, 27, 0.55);
  color: #ffffff;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  opacity: 0.55;
  transition: opacity 0.15s, background 0.15s;
}
.article-nav-chevron:hover {
  opacity: 1;
  background: rgba(24, 24, 27, 0.78);
}
/* co-zinup#14421 — light theme (desktop only: the attribute is written by
   useReaderShell at >= 1024px, never on a phone). Dark/phone keep the rules above
   byte for byte; this only re-points the chevron chrome at the --rt-* tokens. The
   article body behind it stays white in both themes. */
[data-reader-theme="light"] .article-nav-chevron {
  background: var(--rt-bar-bg);
  color: var(--rt-fg);
  border: 1px solid var(--rt-line2);
}
[data-reader-theme="light"] .article-nav-chevron:hover {
  background: var(--rt-surface);
}
.article-nav-chevron.prev { left: 10px; }
.article-nav-chevron.next { right: 10px; }
/* Touch devices use swipe instead — hide the chevrons there. */
@media (hover: none) and (pointer: coarse) {
  .article-nav-chevron { display: none; }
}

/* ── co-zinup#11379: desktop/tablet — the "next" chevron collides with the
   Listen rail, the mirror image of #11035's mobile-only overlap ─────────
   The comment below (co-zinup#11035) claims "above ~1024px … nothing ever
   reaches them there" — that reasoning only checked the chevrons against
   the ARTICLE COLUMN's clearance, never against `.reading-tools-rail-float`
   itself, and was wrong for that case. Both `.article-nav-chevron` (this
   file, above) and the rail (inline style, `ArticleSlideUp.tsx`'s
   `ReadingToolsRail`) are `position: fixed; top: 50%;
   transform: translateY(-50%)` with NEITHER inside a media query, so at
   every viewport width >=1024px they sit on the exact same vertical
   centre line. The rail is right-anchored at 12px and the "next" chevron
   at 10px (`.article-nav-chevron.next` above) — nearly identical
   horizontal offsets — so on desktop the chevron lands entirely inside
   the rail's box and the rail's DOM subtree (it is on top, later in
   paint order) swallows the click. Below 1024px this doesn't happen only
   because the #11035 media query below overrides both with `!important`
   and separates them by anchoring from the tab bar instead of centring —
   an unrelated fix that happened to also avoid this collision as a side
   effect, not by design.

   Fix: give the "next" chevron alone (the "prev" chevron has no rail on
   its side, so it never collided) a fixed vertical offset from centre,
   above the rail, at every desktop/tablet width — mirrors the mobile
   fix's "stack with a gap" strategy but vertically-relative instead of
   tab-bar-relative, since desktop has no tab bar to anchor from.

   90px is sized against the WORST case, not the measured case: the rail
   is the same `ReadingToolsRail` component at every breakpoint (column
   orientation, co-zinup#10865 commit 3), and the #11035 mobile fix's own
   arithmetic documents it can grow to ~113px tall when Listen AND
   Translate both render (2 buttons + gap + padding + border) — taller
   than the ~63px (Listen only) measured live on the ticket's fixture.
   Half of the worst-case 113px is ~56.5px; the chevron's own half-height
   is 20px; 90 - 56.5 - 20 = 13.5px of real margin even in that case,
   vs. ~38.5px margin in the common (Listen-only) case. Because both
   controls' offsets are computed from the same `50%` anchor, this gap is
   the same at every viewport height. */
@media (min-width: 1024px) {
  .article-nav-chevron.next {
    top: calc(50% - 90px);
  }
}

/* ── co-zinup#11035: keep the reading-tools rail and prev/next chevrons
   off the "Read next" rail on phones ──────────────────────────────────
   Both are `position: fixed`, vertically centred on the viewport, at
   every breakpoint (co-zinup#10865 commit 3). Above ~1024px the article
   column's own centring (`article { max-width: 38rem; margin: 0 auto }`)
   leaves far more clearance than either control's width, so nothing ever
   reaches them there (AC2 — untouched, no query below fires above
   1023px). Below that, the column runs close to the viewport edge, and
   scrolled to the foot of the article, the vertical centre of the
   viewport is exactly where the "Read next" grid (#10991) sits — so the
   rail/chevrons land on a card.

   The fix is NOT to narrow #10991's grid (`.read-next-rail`) — that
   would reintroduce the single-column "cut off" layout it exists to
   avoid — and NOT to hide either control (co-zinup#11035 AC4: both must
   stay reachable). Instead, move them off centre entirely: anchor them
   just above the persistent tab bar (`.zn-tabbar`, fixed, 56px +
   safe-area) instead of viewport-centre, stacked (chevrons above the
   rail, with a gap — both anchor bottom-right/bottom-left otherwise and
   a naive identical offset makes them cover EACH OTHER instead of a
   card), and reserve enough EXTRA bottom padding below the article's
   scrollable content (`.article-reader-scroll`, below) that no card can
   ever reach down into that reserved band — regardless of how many rows
   "Read next" renders or how long the article is. At maximum scroll the
   reserved band is provably empty (it IS the padding), so neither
   control, even stacked with room to spare, can ever land on real
   content. */
@media (max-width: 1023px) {
  /* Chevrons sit ABOVE the rail (rail: up to ~113px tall with Listen +
     Translate both shown, spanning 80px-193px above the tab bar) with a
     27px gap, so a fully-loaded rail and a chevron never touch. */
  .article-nav-chevron {
    top: auto !important;
    bottom: calc(220px + env(safe-area-inset-bottom)) !important;
    transform: none !important;
  }
  .reading-tools-rail-float {
    top: auto !important;
    bottom: calc(80px + env(safe-area-inset-bottom)) !important;
    transform: none !important;
  }
  /* co-zinup#10865's original reserve (4.25rem) only cleared the tab bar
     itself. This replaces (not adds to) it with enough room for the tab
     bar (56px + safe-area) + the rail (up to ~113px) + the chevron stack
     above it (40px) + gaps/margin — see the arithmetic above. */
  .article-reader-scroll {
    padding-bottom: calc(280px + env(safe-area-inset-bottom)) !important;
  }
  /* co-zinup#12034 — while ReadAloud's player bar or its no-voice message
     strip is open (both fixed, full width, directly above the tab bar, up
     to ~100px tall), ReadAloud puts `readaloud-strip-open` on <body>.
     Lift the rail, the chevrons and the scroll reserve by 90px so the
     strip never covers Listen/Translate. Offsets are relative to the
     shared --reader-bottom-chrome (styles/tabbar.css). */
  body.readaloud-strip-open .reading-tools-rail-float {
    bottom: calc(var(--reader-bottom-chrome, calc(56px + env(safe-area-inset-bottom, 0px))) + 114px) !important;
  }
  body.readaloud-strip-open .article-nav-chevron {
    bottom: calc(var(--reader-bottom-chrome, calc(56px + env(safe-area-inset-bottom, 0px))) + 254px) !important;
  }
  body.readaloud-strip-open .article-reader-scroll {
    padding-bottom: calc(var(--reader-bottom-chrome, calc(56px + env(safe-area-inset-bottom, 0px))) + 314px) !important;
  }

  /* co-zinup#11938 (epic #11481 AC5) — the modifier-class suppression rule that used
     to combine with `.reading-tools-rail-float` here (co-zinup#11484, epic #11481
     Fault B) is deleted, not just its explanatory comment trimmed. co-zinup#11616
     (owner decision 2026-09-18, "If people want to read next, they can use the left
     and right") removed the `<ReadNext>` component and its Read-next sentinel
     entirely, and with them the only code path that ever applied that modifier
     class (`readNextNear` in `ArticleSlideUp.tsx`). A CSS rule nothing can ever
     apply is dead weight at best and a false guarantee at worst — this repo's own
     revert-proof gate caught the matching vitest test and mutation declaration as
     stale for the same reason (`check-revert-proof-tests.mjs`: "declared test title
     not found by vitest"). The collision this rule existed to suppress (floating
     rail vs. a Read-next card) is now structurally impossible: there is no
     Read-next rail left to collide with. */
}

/* Subtle fade when swiping/navigating between articles in Read view. */
@keyframes articleFadeIn {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* Entrance for the full-page article reader — a gentle rise + fade (no transform
   lingers, so the sticky header works once it settles). */
@keyframes articleEnter {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: none; }
}

/* ── Original magazine page images (lazy, full content width) ───────────── */
.original-pages {
  background: #ffffff;
  padding: 12px 16px 32px;
}
.original-pages figure {
  margin: 0 0 16px;
}
.original-pages img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: 8px;
  background: #ffffff;
}
.original-pages figcaption {
  margin-top: 6px;
  font-family: 'Inter', system-ui, sans-serif;
  font-size: 12px;
  color: #80838c;
  text-align: center;
}

/* ── In-feed ad card — show the WHOLE advert, never cropped ──────────────── */
.ad-card-contain {
  background: #18181b; /* neutral charcoal letterbox */
}
.ad-card-contain img {
  object-fit: contain; /* the entire advert is visible, letterboxed as needed */
  width: 100%;
  height: 100%;
  display: block;
}

/* SPONSORED disclosure pill (ASA UK) — neutral, used in feed + full-screen */
.ad-sponsored-pill {
  display: inline-block;
  padding: 4px 12px;
  border-radius: 9999px;
  background: rgba(255, 255, 255, 0.12);
  color: #fafafa;
  border: 1px solid rgba(255, 255, 255, 0.20);
  font-family: 'IBM Plex Mono', ui-monospace, monospace;
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

/* ── Full-screen advert view — fit-to-width, scroll to read it all ──────── */
.ad-view {
  position: absolute;
  top: 6%;
  left: 0;
  right: 0;
  bottom: 0;
  background: #18181b;
  border-radius: 20px 20px 0 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.ad-view-header {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 16px;
  background: #18181b;
  border-bottom: 1px solid #27272a;
}
.ad-view-back {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: 'Inter', system-ui, sans-serif;
  font-size: 14px;
  font-weight: 600;
  color: #fafafa;
}
.ad-view-body {
  background: #ffffff; /* neutral white reading surface for the creative */
}
.ad-view-body img {
  width: 100%;
  height: auto;
  display: block; /* full advert, fit to width, taller-than-screen = scroll */
}
.ad-view-placeholder {
  min-height: 60vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  background: #18181b;
  padding: 0 24px;
  text-align: center;
}
.ad-view-placeholder-name {
  color: #fafafa;
  font-size: 1.5rem;
  font-weight: 700;
  max-width: 20ch;
}
.ad-view-footer {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  padding: 16px;
  background: #18181b;
  border-top: 1px solid #27272a;
}
.ad-view-advertiser {
  font-family: 'Inter', system-ui, sans-serif;
  font-size: 14px;
  color: #a1a1aa;
}
.ad-view-visit {
  display: inline-block;
  padding: 10px 18px;
  border-radius: 9999px;
  background: #fafafa;
  color: #18181b;
  border: 1px solid #71717a;
  font-family: 'Inter', system-ui, sans-serif;
  font-size: 14px;
  font-weight: 600;
}
