/* ═══════════════════════════════════════════════════════════════
   irvo.eu — Martin Irvo Jaroš
   One stylesheet. No preprocessor, no build step, no JavaScript.

   Palette sampled from the Through cover. Every colour below is a
   real pixel off the artwork; contrast ratios against the page
   background are noted so nothing gets swapped for something
   unreadable later.
   ═══════════════════════════════════════════════════════════════ */

:root {
  /* Surfaces */
  --space:      #07122E;   /* page background — the deepest cover navy */
  --panel:      #101B39;   /* Carolyn's surface: the same navy, lifted 7% */
  --ink:        #07122E;   /* dark text on bright fills */
  --violet:     #161235;   /* sampled deep-space violet — currently unused */

  /* Text — ratios are against --space */
  --white:      #FFFFFF;   /* 17.9:1  headings */
  --silver:     #B5B8C5;   /* 9.1:1   body text (the THROUGH lettering) */
  --steel:      #8B95CB;   /* 6.2:1   secondary text (engine-ring metal) */
  --light:      #C4CAF6;   /* 11.2:1  metal highlights — borders, rules */

  /* Accents */
  --cyan:       #6DB6F4;   /* 8.2:1   links (outer engine glow) */
  --exhaust:    #03F8FD;   /* 13.5:1  held in reserve for the buy button ONLY */
  --warm:       #DCB6B5;   /* 9.7:1   star halo — sampled, currently unused */

  /* Not for text. Both fail WCAG AA on --space. Fills and glows only. */
  --nebula:     #0850CD;   /* 2.6:1 */
  --periwinkle: #6474BF;   /* 4.1:1 — passes for large text, fails for body */

  /* Type */
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "Cascadia Mono", "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;

  /* Roboto Condensed — the book titles, matching Argon on the cover */
  --display: "Display", var(--sans);

  /* Rhythm */
  --gap: 1.5rem;
  --measure: 34rem;   /* body text never exceeds this — roughly 70 characters */
  --shell: 64rem;
}

/* ── Self-hosted type ──────────────────────────────────────────
   Two faces, two files, no CDN and no build step. Both are Google
   Fonts, and both licences permit self-hosting.
   ────────────────────────────────────────────────────────────── */

@font-face {
  font-family: "Display";
  src: url("fonts/display.woff2") format("woff2");
  font-weight: 300 400;
  font-style: normal;
  font-display: swap;
}

/* ── Reset ─────────────────────────────────────────────────── */

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--space);
  color: var(--silver);
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; display: block; }

a { color: var(--cyan); text-underline-offset: 0.2em; }
a:hover { color: var(--white); }

:focus-visible {
  outline: 2px solid var(--exhaust);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip {
  position: absolute;
  left: -9999px;
}
.skip:focus {
  left: 1rem;
  top: 1rem;
  z-index: 10;
  padding: 0.6rem 1rem;
  background: var(--exhaust);
  color: var(--ink);
  font-weight: 600;
  text-decoration: none;
}

/* ── Layout ────────────────────────────────────────────────── */

.wrap {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: 1.25rem;
}

.prose { max-width: calc(var(--measure) + 2.5rem); }
.prose p { max-width: var(--measure); }
.prose p, .strapline, .carolyn-copy p { text-wrap: pretty; }

/* ── Shared type devices ───────────────────────────────────── */

/* The utility voice: small, spaced, uppercase mono. Used for labels
   that name a thing rather than say something about it. */
.eyebrow {
  margin: 0 0 0.75rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--steel);
}

/* ── Header ────────────────────────────────────────────────── */

.site-head {
  padding-block: 1.75rem 1.25rem;
  border-bottom: 1px solid rgba(196, 202, 246, 0.12);
}

.brand {
  margin: 0;
  line-height: 1.2;
  font-size: 1.0625rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.brand a {
  color: var(--white);
  text-decoration: none;
}
.brand a:hover { color: var(--cyan); }

.strapline {
  margin: 0.1rem 0 1.25rem;
  max-width: 30rem;
  font-size: 0.9375rem;
  line-height: 1.4;
  color: var(--steel);
}

.nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 2.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}
.nav a {
  text-decoration: none;
  color: var(--steel);
  padding-block: 0.35rem;   /* taller tap target on phones */
  display: inline-block;
}
.nav a:hover { color: var(--white); }
.nav a[aria-current="page"] {
  color: var(--white);
  box-shadow: inset 0 -1px 0 var(--exhaust);
}

/* ── Hero ──────────────────────────────────────────────────── */

.hero { padding-block: 3rem 3.5rem; }

.hero-grid { display: grid; gap: 2.5rem; }

.hero-art { display: flex; justify-content: center; }

/* The cover is the brightest object on the page, so let it behave
   like one: a faint cyan bloom, as if the engines were lighting the
   background. This is the one piece of decoration on the site. */
.cover {
  width: min(78vw, 20rem);
  height: auto;
  border-radius: 3px;
  box-shadow:
    0 0 0 1px rgba(196, 202, 246, 0.15),
    0 2px 18px rgba(8, 80, 205, 0.35),
    0 18px 60px -12px rgba(3, 248, 253, 0.22),
    0 30px 60px -20px rgba(0, 0, 0, 0.7);
}

.title {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(3.25rem, 16vw, 5.75rem);
  line-height: 1;
  letter-spacing: 0.035em;
  font-weight: 300;
  text-transform: uppercase;
  color: var(--white);
}

.subtitle {
  margin: 0.9rem 0 0;
  font-family: var(--display);
  font-size: 1.125rem;
  line-height: 1.4;
  letter-spacing: 0.02em;
  color: var(--steel);
}

/* Catalogue data for the star the book is set in. Hairline rules and
   a mono face because it is instrument output, not prose. */
.datastrip {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0.85rem;
  margin: 1.5rem 0 0;
  padding-top: 0.9rem;
  border-top: 1px solid rgba(196, 202, 246, 0.18);
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--steel);
}
.datastrip span + span { padding-left: 0.85rem; border-left: 1px solid rgba(196, 202, 246, 0.2); }


.status {
  margin: 2rem 0 1rem;
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--light);
}

.cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 0;
}

/* ── Buttons ───────────────────────────────────────────────── */

.btn {
  display: inline-block;
  padding: 0.85rem 1.5rem;
  border: 1px solid transparent;
  border-radius: 2px;
  font-family: var(--mono);
  font-size: 0.8125rem;
  line-height: 1.4;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.15s ease, filter 0.15s ease;
}
.btn:hover { transform: translateY(-1px); filter: brightness(1.08); }
.btn:active { transform: translateY(0); }

/* Exhaust cyan is the loudest thing available and appears exactly once,
   on the button that takes money. It is deliberately absent until the
   preorder opens, so its arrival is itself a signal. */
.btn-cyan { background: var(--exhaust); color: var(--ink); }
.btn-cyan:hover { color: var(--ink); }

/* Carolyn: bright enough to lead, and deliberately not the cyan. */
.btn-light { background: var(--light); color: var(--ink); }
.btn-light:hover { color: var(--ink); }

.btn-ghost {
  background: transparent;
  color: var(--silver);
  border-color: rgba(196, 202, 246, 0.3);
}
.btn-ghost:hover { color: var(--white); border-color: var(--light); }

/* ── Bands ─────────────────────────────────────────────────── */

.band {
  padding-block: 3.25rem;
  border-top: 1px solid rgba(196, 202, 246, 0.12);
}

.band-deep {
  background: var(--panel);
  border-top-color: rgba(196, 202, 246, 0.2);
}

.carolyn-grid { display: grid; gap: 2rem; }

.carolyn-copy p { max-width: var(--measure); }

.carolyn-cover {
  width: min(52vw, 11rem);
  height: auto;
  border-radius: 3px;
  box-shadow:
    0 0 0 1px rgba(196, 202, 246, 0.18),
    0 14px 40px -14px rgba(0, 0, 0, 0.75);
}

.h2-book {
  margin: 0 0 1.25rem;
  font-family: var(--display);
  font-size: clamp(2.25rem, 11vw, 3.25rem);
  line-height: 1;
  letter-spacing: 0.035em;
  font-weight: 300;
  text-transform: uppercase;
  color: var(--white);
}

/* The one-line statement of the deal, just above the form. */
.offer {
  margin-top: 1.75rem;
  padding-top: 1.25rem;
  border-top: 1px solid rgba(196, 202, 246, 0.22);
  color: var(--light);
}

.more {
  margin-top: 1.75rem;
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* ── Legal page ────────────────────────────────────────────── */

.page-title {
  margin: 0 0 1.5rem;
  font-family: var(--display);
  font-size: clamp(1.75rem, 6vw, 2.5rem);
  line-height: 1.1;
  letter-spacing: 0.035em;
  font-weight: 300;
  text-transform: uppercase;
  color: var(--white);
}

.jump {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.5rem;
  padding-bottom: 1.5rem;
  border-bottom: 1px solid rgba(196, 202, 246, 0.15);
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* Remove this block, and every .todo in the HTML, before launch. */
.draft {
  margin: 1.75rem 0 0;
  padding: 0.9rem 1.1rem;
  border: 1px dashed var(--exhaust);
  border-radius: 2px;
  font-size: 0.9375rem;
  color: var(--light);
}
.todo {
  padding: 0.05em 0.35em;
  border-bottom: 2px dotted var(--exhaust);
  font-family: var(--mono);
  font-size: 0.85em;
  color: var(--exhaust);
}

.legal-section {
  margin-top: 3.5rem;
  padding-top: 2.5rem;
  border-top: 1px solid rgba(196, 202, 246, 0.15);
  scroll-margin-top: 1.5rem;
}

.legal-section h2 {
  margin: 0 0 1.5rem;
  font-family: var(--display);
  font-size: clamp(1.75rem, 7vw, 2.25rem);
  line-height: 1.1;
  letter-spacing: 0.035em;
  font-weight: 300;
  text-transform: uppercase;
  color: var(--white);
}

.legal-section h3 {
  margin: 2.25rem 0 0.5rem;
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.4;
  color: var(--light);
}

.legal-section p {
  margin: 0 0 0.9rem;
  max-width: var(--measure);
  font-size: 1rem;
  line-height: 1.65;
  text-wrap: pretty;
}

.lede { color: var(--steel); font-style: italic; }

.note, .stand {
  margin-top: 2rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--steel);
}

/* ── About page ────────────────────────────────────────────── */

.about-grid { display: grid; gap: 2rem; }

/* Constrain the whole column, not just the paragraphs — otherwise
   anything centred inside it centres on the column rather than on
   the text, and drifts right. */
.about-copy { max-width: var(--measure); }
.about-copy p { text-wrap: pretty; }

.author-photo {
  width: min(48vw, 10rem);
  height: auto;
  border-radius: 3px;
  box-shadow:
    0 0 0 1px rgba(196, 202, 246, 0.18),
    0 14px 40px -14px rgba(0, 0, 0, 0.75);
}

.contact {
  margin-top: 2rem;
  padding-top: 1.5rem;
  border-top: 1px solid rgba(196, 202, 246, 0.15);
  font-family: var(--mono);
  font-size: 0.8125rem;
  letter-spacing: 0.08em;
}

/* The logo is a dark mark, invisible on a dark page. brightness(0)
   flattens it to black, invert(1) then makes it white. */
.about-logo {
  display: block;
  margin: 2.75rem auto 0;
  filter: brightness(0) invert(1);
  opacity: 0.6;
}

/* ── Signup form ───────────────────────────────────────────── */

.signup { margin-top: 2rem; max-width: 30rem; }

.signup-row {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
}

@media (min-width: 30rem) {
  .signup-row {
    flex-direction: row;
    align-items: flex-end;
    gap: 0.75rem;
  }
  .signup-row .field { flex: 1 1 auto; }
  .signup-row .btn { flex: 0 0 auto; }
}

.field label {
  display: block;
  margin-bottom: 0.4rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--steel);
}

.field input {
  width: 100%;
  padding: 0.8rem 0.9rem;
  background: var(--ink);
  border: 1px solid rgba(196, 202, 246, 0.28);
  border-radius: 2px;
  color: var(--white);
  font-family: var(--sans);
  font-size: 1rem;   /* 16px minimum, or iOS zooms the page on focus */
}
.field input::placeholder { color: rgba(139, 149, 203, 0.65); }
.field input:focus { border-color: var(--light); }

/* Honeypot: off-screen rather than display:none, because some bots
   skip fields that are display:none. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.formstatus:empty { display: none; }
.formstatus {
  margin: 1rem 0 0;
  padding: 0.7rem 0.9rem;
  border: 1px solid rgba(196, 202, 246, 0.35);
  border-radius: 2px;
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--light);
}

.formnote {
  margin: 1.25rem 0 0;
  font-size: 0.875rem;
  line-height: 1.55;
  color: var(--steel);
}

/* ── Footer ────────────────────────────────────────────────── */

.site-foot {
  padding-block: 2.5rem 3rem;
  text-align: center;
  border-top: 1px solid rgba(196, 202, 246, 0.12);
}

.foot-meta {
  margin: 0;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--steel);
}
.foot-meta a { color: var(--steel); }
.foot-meta a:hover { color: var(--white); }

/* ═══════════════════════════════════════════════════════════════
   Wider screens. Mobile is the default above; everything below is
   an enhancement, not a correction.
   ═══════════════════════════════════════════════════════════════ */

@media (min-width: 44rem) {
  .site-head-inner {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: start;
    gap: 1rem 2rem;
  }
  .brand { grid-column: 1; }
  .strapline { grid-column: 1; margin-bottom: 0; }
  .site-nav { grid-column: 2; grid-row: 1 / span 2; align-self: center; }
  .nav { justify-content: flex-end; }
}

@media (min-width: 56rem) {
  body { font-size: 1.125rem; }

  .hero { padding-block: 5rem 5.5rem; }

  .hero-grid {
    grid-template-columns: 22rem 1fr;
    align-items: center;
    gap: 4rem;
  }

  .cover { width: 22rem; }

  .band { padding-block: 5rem; }

  .carolyn-grid,
  .about-grid {
    grid-template-columns: 14rem 1fr;
    gap: 3.5rem;
    align-items: start;
  }
  .carolyn-cover, .author-photo { width: 14rem; }
}

/* ── Reduced motion ────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
  .btn:hover { transform: none; }
}

/* ═══════════════════════════════════════════════════════════════
   THROUGH PAGE
   The sample-chapter page. Adds: the 3D-mockup treatment, the book-
   facts list, the epigraph, the scene teasers with their cut marks,
   and the pull quotes — the one place the type is allowed to shout.
   All in the established voice; nothing new in the palette.
   ═══════════════════════════════════════════════════════════════ */

.through-hero { display: grid; gap: 2.5rem; }

.through-art { display: flex; justify-content: center; }

/* The render already carries its own starfield glow, and its edges are
   feathered to the page navy, so it needs no bloom here: a drop-shadow
   would draw a rectangular halo and stop it merging into the page. The
   home-page cover keeps its glow — that is a separate rule (.cover). */
.mockup {
  width: min(80vw, 22rem);
  height: auto;
}

/* Book facts — catalogue data, so the mono instrument voice, laid out
   as label / value pairs with hairline rules. */
.facts {
  margin: 2rem 0 0;
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.05em;
}
.facts > div {
  display: grid;
  grid-template-columns: 7rem 1fr;
  gap: 0.4rem 1.1rem;
  padding: 0.6rem 0;
  border-top: 1px solid rgba(196, 202, 246, 0.12);
}
.facts > div:last-child { border-bottom: 1px solid rgba(196, 202, 246, 0.12); }
.facts dt {
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--steel);
}
.facts dd { margin: 0; color: var(--light); line-height: 1.5; }

/* Chapter heading — one step above the scene labels, which are h3
   eyebrows. Display face, like the book titles but smaller. */
.sample-head { max-width: calc(var(--measure) + 2.5rem); }
.chapter-head {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(1.75rem, 5.5vw, 2.5rem);
  line-height: 1.1;
  letter-spacing: 0.06em;
  font-weight: 300;
  text-transform: uppercase;
  color: var(--white);
}

/* Framing line under the chapter heading. */
.sample-lede {
  max-width: var(--measure);
  margin: 0.6rem 0 0;
  color: var(--steel);
  text-wrap: pretty;
}

/* Epigraph — the chapter's cold open in The Eye's voice. Set apart
   from the scenes: hairline-ruled top and bottom, italic, a cooler
   register than the human POVs below it. */
.epigraph {
  max-width: 40rem;
  margin: 2.5rem auto 3rem;
  padding: 2.25rem 0;
  border-top: 1px solid rgba(196, 202, 246, 0.18);
  border-bottom: 1px solid rgba(196, 202, 246, 0.18);
  font-style: italic;
  color: var(--silver);
  text-wrap: pretty;
}
.epigraph p { max-width: none; }
.epigraph p:first-child { margin-top: 0; }
.epigraph p:last-child { margin-bottom: 0; }
.epigraph cite {
  display: block;
  margin-top: 1.25rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-style: normal;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--steel);
}

/* Teasers — plain prose in the reading measure, separated by a rule. */
.teaser { margin-inline: auto; }
.teaser + .teaser {
  margin-top: 3.5rem;
  padding-top: 3.5rem;
  border-top: 1px solid rgba(196, 202, 246, 0.12);
}
.teaser p { text-wrap: pretty; }
.teaser .eyebrow { margin-bottom: 1.25rem; }

/* The cut mark — where the scene stops and Carolyn takes over. Now a
   full sentence, so sentence case rather than the label uppercase. */
.cut {
  margin-top: 1.75rem;
  padding-top: 1rem;
  border-top: 1px solid rgba(196, 202, 246, 0.18);
  font-family: var(--mono);
  font-size: 0.8125rem;
  letter-spacing: 0.02em;
  color: var(--steel);
}

/* The Carolyn payoff block after the three teasers. */
.sample-cta {
  max-width: calc(var(--measure) + 2.5rem);
  margin-top: 3.5rem;
  padding-top: 2.5rem;
  border-top: 1px solid rgba(196, 202, 246, 0.2);
}
.sample-cta p { max-width: var(--measure); }
.sample-cta .cta-row { margin-top: 1.5rem; }

/* Pull quotes — the loud moment. Display face, large, alternated
   left/right for rhythm, each opened by a short cyan rule. */
.pulls { display: grid; gap: 3rem; max-width: 46rem; }
.pulls-label { margin: 0; }

.pull { margin: 0; }
.pull p {
  margin: 0;
  max-width: 34rem;
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(1.4rem, 4.5vw, 2rem);
  line-height: 1.25;
  letter-spacing: 0.01em;
  color: var(--white);
  text-wrap: balance;
}
.pull::before {
  content: "";
  display: block;
  width: 2.5rem;
  height: 2px;
  margin-bottom: 1.1rem;
  background: var(--cyan);
  opacity: 0.65;
}
/* Every other quote hangs to the right, so the closer lands there. */
.pull:nth-child(even) { justify-self: end; text-align: right; }
.pull:nth-child(even) p { margin-left: auto; }
.pull:nth-child(even)::before { margin-left: auto; }

/* The closing buy block sits under the pull quotes, whose last line hangs
   to the right. Centring the status line and button settles that rhythm
   instead of snapping hard back to the left margin. */
.buy { text-align: center; }
.buy .status { margin-top: 0; }
.buy .cta-row { justify-content: center; }

/* ── Through page, wider screens ───────────────────────────── */

@media (min-width: 56rem) {
  .through-hero {
    grid-template-columns: 24rem 1fr;
    align-items: center;
    gap: 4rem;
  }
  .mockup { width: 24rem; }

  .facts > div { grid-template-columns: 8rem 1fr; }

  .pulls { gap: 4rem; }
}


/* ═══════════════════════════════════════════════════════════════
   FIELD NOTES
   The blog. A listing page and the essay pages. Two registers:
   the reading measure of ordinary prose, and a timeline device
   that has to keep a reader oriented between documented fact and
   invention. Nothing new in the palette; all of it in the
   established voice.
   ═══════════════════════════════════════════════════════════════ */

/* On an article page the current *location* is the Field Notes section,
   not the listing page itself — so it earns the same underline as an
   aria-current="page" nav item without lying about which page this is. */
.nav a[aria-current="location"] {
  color: var(--white);
  box-shadow: inset 0 -1px 0 var(--exhaust);
}

/* ── Listing page ──────────────────────────────────────────────
   A typographic list, not a card grid. With a handful of essays a
   grid looks like a half-empty shelf; a list reads as deliberate. */
.notes-intro { max-width: var(--measure); }
.notes-intro .lead {
  margin: 0.6rem 0 0;
  font-size: 1.0625rem;
  color: var(--steel);
  text-wrap: pretty;
}

.notes-list {
  margin: 3rem 0 0;
  max-width: calc(var(--measure) + 4rem);
}

.note-card {
  padding: 2rem 0;
  border-top: 1px solid rgba(196, 202, 246, 0.12);
}
.note-card:last-child { border-bottom: 1px solid rgba(196, 202, 246, 0.12); }

.note-card .meta {
  margin: 0 0 0.6rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--steel);
}
.note-card .meta span + span::before {
  content: "·";
  padding: 0 0.55em;
  color: rgba(196, 202, 246, 0.4);
}

.note-card h2 {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(1.6rem, 5.5vw, 2.15rem);
  line-height: 1.1;
  letter-spacing: 0.02em;
  font-weight: 300;
  text-transform: uppercase;
  color: var(--white);
}
.note-card h2 a { color: inherit; text-decoration: none; }
.note-card h2 a:hover { color: var(--cyan); }

.note-card .dek {
  margin: 0.7rem 0 0;
  max-width: var(--measure);
  color: var(--silver);
  text-wrap: pretty;
}
.note-card .readmore {
  margin: 0.9rem 0 0;
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* ── Article shell ─────────────────────────────────────────────
   Shared by every essay: the header block, the body measure, the
   subheads, figures, further-reading and the way back. */
.note-head { max-width: var(--measure); }
.note-head .meta {
  margin: 0 0 1rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--steel);
}
.note-head .meta span + span::before {
  content: "·";
  padding: 0 0.55em;
  color: rgba(196, 202, 246, 0.4);
}

.note-title {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(2.1rem, 8vw, 3.25rem);
  line-height: 1.05;
  letter-spacing: 0.03em;
  font-weight: 300;
  text-transform: uppercase;
  color: var(--white);
}

.note-dek {
  margin: 1rem 0 0;
  font-family: var(--display);
  font-size: clamp(1.05rem, 2.6vw, 1.3rem);
  line-height: 1.4;
  letter-spacing: 0.01em;
  color: var(--steel);
  text-wrap: pretty;
}

/* The body owns the reading measure. Subheads step down from the
   title in the same display face. */
.note-body { margin-top: 2.75rem; }
.note-body > p:first-child { margin-top: 0; }
.note-body p { text-wrap: pretty; }

.note-body h2 {
  margin: 2.75rem 0 0.75rem;
  font-family: var(--display);
  font-size: clamp(1.4rem, 4.5vw, 1.85rem);
  line-height: 1.15;
  letter-spacing: 0.03em;
  font-weight: 300;
  text-transform: uppercase;
  color: var(--white);
}

.note-body .lead {
  font-size: 1.0625rem;
  color: var(--light);
}

/* ── Figures ───────────────────────────────────────────────────
   For the diagram, and for any photo dropped in later. The caption
   carries the credit line — the mono instrument voice again. */
.fig {
  margin: 2.5rem 0;
  max-width: calc(var(--measure) + 6rem);
}
.fig svg, .fig img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 3px;
}
.fig figcaption {
  margin-top: 0.85rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
  line-height: 1.6;
  letter-spacing: 0.06em;
  color: var(--steel);
  text-transform: uppercase;
}
.fig figcaption a { color: var(--steel); }
.fig figcaption a:hover { color: var(--white); }

/* Sequence diagram — a static process needs frames, not one still. Three
   steps: catch-up, swap, fall behind. Row on wide screens, stacked on
   phones. Colour hooks keep the palette out of the markup. */
.seq { display: flex; flex-wrap: wrap; gap: 1.5rem; margin: 0; }
.seq-step { flex: 1 1 150px; margin: 0; }
.seq-step svg { display: block; width: 100%; height: auto; }
/* Number sits in its own flex column so it never disturbs the caption's
   line boxes; its bottom lines up with the first line of text. */
.seq-cap {
  display: flex;
  gap: 0.55rem;
  align-items: baseline;
  margin: 0.5rem 0 0;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--silver);
  text-wrap: pretty;
}
.seq-n {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.35rem;
  height: 1.35rem;
  border-radius: 50%;
  background: rgba(109, 182, 244, 0.14);
  color: var(--cyan);
  font-family: var(--mono);
  font-size: 0.7rem;
  position: relative;
  top: 0.28rem;
}
.seq .s-lane { fill: none; stroke: rgba(196, 202, 246, 0.22); }
.seq .s-body { fill: var(--warm); }
.seq .s-a    { fill: var(--light); }        /* the chaser — bright */
.seq .s-b    { fill: var(--periwinkle); }   /* the other — deeper blue, easy to tell apart */
.seq .s-arr  { stroke: var(--cyan); }
.seq .s-swap { stroke: var(--warm); }

@media (max-width: 34rem) {
  .seq { flex-direction: column; gap: 1.9rem; }
  .seq-step { max-width: 19rem; margin-inline: auto; }
}

/* ── Further reading ───────────────────────────────────────────
   External links are permitted — they are plain anchors, not the
   embeds and CDNs the rest of the site refuses. */
.further {
  margin-top: 3rem;
  padding-top: 1.75rem;
  border-top: 1px solid rgba(196, 202, 246, 0.18);
  max-width: var(--measure);
}
.further h2 {
  margin: 0 0 1rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--steel);
}
.further ul { margin: 0; padding: 0; list-style: none; }
.further li { margin: 0 0 0.6rem; }
.further li a { text-decoration: none; }
.further li a:hover { text-decoration: underline; }

/* The way back, at the foot of every essay. */
.note-foot {
  margin-top: 3.5rem;
  padding-top: 1.75rem;
  border-top: 1px solid rgba(196, 202, 246, 0.12);
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.75rem;
  align-items: baseline;
}
.back, .uplink {
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
}
.back::before  { content: "\2190\00a0\00a0"; }   /* back to the listing */
.uplink::before { content: "\2191\00a0\00a0"; }   /* up to home */

/* ═══════════════════════════════════════════════════════════════
   TIMELINE
   The device carrying the real→fiction essay. A reader must always
   know which side of the line an entry sits on. Two signals do it:
   a per-entry marker on the spine (filled = documented, hollow =
   invented) and one loud, labelled boundary where the record turns
   into the story.
   ═══════════════════════════════════════════════════════════════ */

/* Legend — sets the rule before the reader meets the first marker. */
.tl-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 1.75rem;
  margin: 2.5rem 0 0;
  padding: 1rem 0;
  border-top: 1px solid rgba(196, 202, 246, 0.15);
  border-bottom: 1px solid rgba(196, 202, 246, 0.15);
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--steel);
}
.tl-key { display: inline-flex; align-items: center; gap: 0.6rem; }
.tl-key::before {
  content: "";
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 50%;
  flex: 0 0 auto;
}
.tl-key-real::before     { background: var(--cyan); }
.tl-key-invented::before { background: transparent; box-shadow: inset 0 0 0 1.5px var(--steel); }

/* The timeline body: a spine down the left, entries hung off it. */
.timeline {
  margin: 2.75rem 0 0;
  max-width: calc(var(--measure) + 3rem);
}

.tl-section {
  margin: 0 0 0.5rem;
  padding-top: 2.25rem;
  font-family: var(--display);
  font-size: clamp(1.3rem, 4vw, 1.6rem);
  line-height: 1.15;
  letter-spacing: 0.04em;
  font-weight: 300;
  text-transform: uppercase;
  color: var(--white);
}

.tl-track {
  position: relative;
  margin-left: 0.35rem;
  padding-left: 1.85rem;
  border-left: 1px solid rgba(196, 202, 246, 0.22);
}

.tl-entry { position: relative; padding: 0.85rem 0 1.15rem; }

/* The marker on the spine. Filled cyan for documented fact; a hollow
   steel ring for invention. This is the signal that persists on every
   single entry, so the reader is never more than one line from knowing. */
.tl-entry::before {
  content: "";
  position: absolute;
  left: calc(-1.85rem - 1px);
  top: 1.35rem;
  width: 0.65rem;
  height: 0.65rem;
  margin-left: -0.325rem;
  border-radius: 50%;
  background: var(--cyan);
}
.tl-entry.invented::before {
  background: var(--space);
  box-shadow: inset 0 0 0 1.5px var(--steel);
}

.tl-year {
  margin: 0 0 0.3rem;
  font-family: var(--mono);
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  color: var(--light);
}
.tl-entry.invented .tl-year { color: var(--steel); }

.tl-entry p.tl-text { margin: 0; max-width: var(--measure); }

.tl-cite {
  margin: 0.4rem 0 0;
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--steel);
  font-style: italic;
}

/* The boundary — the one loud moment. Where the documented record
   ends and Through begins. Dashed cyan, centred, unmissable. */
.tl-boundary {
  margin: 1.5rem 0;
  padding: 1.5rem 1.25rem;
  border: 1px dashed rgba(3, 248, 253, 0.5);
  border-radius: 3px;
  text-align: center;
  background: rgba(3, 248, 253, 0.04);
}
.tl-boundary p { margin: 0; max-width: none; }
.tl-boundary .bnd-label {
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--exhaust);
}
.tl-boundary .bnd-note {
  margin-top: 0.5rem;
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--light);
  text-wrap: pretty;
}

/* Book anchors — where a story you can actually read sits inside the
   invented history. Deliberately NOT the dashed cyan of the fact/fiction
   boundary: that box means one thing only, and reusing it would blur the
   signal. These are warm where the record is cool — the human layer
   against the instrument log — and they finally spend the star-halo warm. */
.tl-book {
  margin: 1.75rem 0;
  padding: 1.15rem 1.4rem;
  border-left: 2px solid var(--warm);
  border-radius: 0 3px 3px 0;
  background: rgba(220, 182, 181, 0.06);
}
.tl-book-label {
  margin: 0;
  font-family: var(--display);
  font-size: 1.25rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--warm);
}
.tl-book-line {
  margin: 0.3rem 0 0;
  max-width: var(--measure);
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--silver);
}
.tl-book-line a { color: var(--warm); text-underline-offset: 0.2em; }
.tl-book-line a:hover { color: var(--white); }

/* ── Field Notes, wider screens ────────────────────────────────
   The timeline can afford a wider year gutter once there is room. */
@media (min-width: 44rem) {
  .tl-entry {
    display: grid;
    grid-template-columns: 4.5rem 1fr;
    gap: 0 1.25rem;
    align-items: baseline;
  }
  .tl-year { margin: 0; text-align: right; }
  .tl-entry::before { top: 0.55rem; }
  .tl-boundary { display: block; }
}
