/* ==========================================================================
   zanderjein.com
   Navy and white. Instrument Serif for display, Geist for reading, Geist Mono for figures.
   Every section has its own physical structure; the tokens below are what they share.
   Motion is calm and always reduced-motion safe.
   ========================================================================== */

/* ---------------------------------------------------------------- fonts --
   Self-hosted so the first paint doesn't wait on a third-party server.
   Instrument Serif, Geist and Geist Mono, SIL Open Font License 1.1 — see assets/fonts/OFL-*.txt.
   Latin and Latin Extended only; nothing else on the page needs more.
   ------------------------------------------------------------------------ */

@font-face {
  font-family: "Instrument Serif";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("assets/fonts/instrument-serif-italic-latin-ext.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: "Instrument Serif";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("assets/fonts/instrument-serif-italic-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;
}
@font-face {
  font-family: "Instrument Serif";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("assets/fonts/instrument-serif-latin-ext.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: "Instrument Serif";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("assets/fonts/instrument-serif-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;
}
@font-face {
  font-family: "Geist";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("assets/fonts/geist-latin-ext.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: "Geist";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("assets/fonts/geist-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;
}
@font-face {
  font-family: "Geist Mono";
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url("assets/fonts/geist-mono-latin-ext.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: "Geist Mono";
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url("assets/fonts/geist-mono-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;
}

:root {
  color-scheme: light dark;

  /* --- navy is the only colour --- */
  --ink:        #0F2044;  /* headings, primary text  15.6:1 on bg */
  --ink-link:   #1E3A6E;  /* links, hover states     10.9:1 on bg */
  --ink-muted:  #52617E;  /* secondary text           6.1:1 on bg */
  --ink-faint:  #65738F;  /* figures, stamps          4.7:1 on bg */
  --rule:       #E2E7F0;
  --tint:       #F4F6FB;
  --tint-deep:  #ECF0F8;

  --bg:      #FCFCFC;
  --surface: #FFFFFF;

  /* the two bands that break the page: a raised strip of marks, and the navy close */
  --strip-bg: #FFFFFF;
  --close-bg: #0F2044;
  --close-ink: #F4F6FB;
  --close-muted: #A9B6D3;

  --display: "Instrument Serif", "Iowan Old Style", Georgia, "Times New Roman", serif;
  --sans: "Geist", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* --- type: six steps, far apart. Anything in between is a mistake.
         (The hero name and the closing address are fitted to the window instead.) --- */
  --t-mono: 0.75rem;
  --t-small: 0.875rem;
  --t-body: 1.0625rem;
  --t-lead: clamp(1.3125rem, 1.9vw, 1.625rem);
  --t-title: clamp(1.75rem, 3.2vw, 2.5rem);
  --t-display: clamp(3.75rem, 8.6vw, 8.25rem);

  /* --- rhythm --- */
  --gutter: clamp(1.25rem, 5vw, 4rem);
  --measure: 34rem;
  --section-gap: clamp(5rem, 11vw, 10rem);
  --page: 78rem;
  --rail: 12.5rem;
  --rail-gap: clamp(1.5rem, 3.4vw, 3.25rem);
  /* distance from the window edge to the start of the measure */
  --edge: max(var(--gutter), calc((100vw - var(--page)) / 2 + var(--gutter)));

  /* --- shape: two radii. Printed things (covers, posters) are nearly square;
         surfaces the page itself makes (the bar) are soft. --- */
  --r-s: 3px;
  --r-m: 12px;

  /* --- material: navy-tinted shadows with real falloff, tight and dark near the
         object, wide and faint far from it, all lit from above --- */
  --shade: 15, 32, 68;
  --shadow-low:
    0 1px 1px rgba(var(--shade), 0.07), 0 3px 5px rgba(var(--shade), 0.06),
    0 10px 18px rgba(var(--shade), 0.07);
  --shadow-rest:
    0 1px 1px rgba(var(--shade), 0.06), 0 2px 4px rgba(var(--shade), 0.05),
    0 6px 10px rgba(var(--shade), 0.05), 0 14px 24px rgba(var(--shade), 0.06),
    0 32px 56px rgba(var(--shade), 0.08);
  --shadow-high:
    0 1px 1px rgba(var(--shade), 0.08), 0 4px 6px rgba(var(--shade), 0.07),
    0 12px 18px rgba(var(--shade), 0.08), 0 28px 40px rgba(var(--shade), 0.10),
    0 56px 90px rgba(var(--shade), 0.14);
  --shadow-land:
    drop-shadow(0 1px 1px rgba(var(--shade), 0.12)) drop-shadow(0 5px 8px rgba(var(--shade), 0.07))
    drop-shadow(0 20px 30px rgba(var(--shade), 0.09));

  /* --- layers, bottom to top. Nothing on the page uses a z-index that isn't here. --- */
  --z-under: 0;     /* type that something lies across */
  --z-stage: 1;     /* pinned things that content passes over */
  --z-over: 2;      /* things that lie across other things */
  --z-topbar: 30;
  --z-grain: 60;
  --z-skip: 70;

  /* --- motion --- */
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-out: cubic-bezier(0.32, 0.72, 0, 1);
  --ease-expo: cubic-bezier(0.16, 1, 0.3, 1);      /* arrivals */
  --ease-inout: cubic-bezier(0.65, 0, 0.35, 1);    /* journeys, there and back */
  --ease-spring: cubic-bezier(0.2, 0.9, 0.3, 1.18); /* things under the hand: a touch of overshoot */
  --fast: 200ms;
  --mid: 320ms;
}

/* Dark: the same two colours, the other way up. */
@media (prefers-color-scheme: dark) {
  :root {
    --ink:        #EEF2FA;
    --ink-link:   #BCCBEE;
    --ink-muted:  #A5B2CD;
    --ink-faint:  #8492B0;
    --rule:       #1D2C4E;
    --tint:       #111F3D;
    --tint-deep:  #182B55;

    --bg:      #0A1428;
    --surface: #111E3B;

    --strip-bg: #EEF2FA;      /* in the dark, the strip of marks is the one pale band */
    --close-bg: #060D1B;
    --close-ink: #EEF2FA;
    --close-muted: #8E9CBB;

    --shade: 0, 3, 12;
    --shadow-low:
      0 1px 1px rgba(var(--shade), 0.3), 0 3px 5px rgba(var(--shade), 0.26), 0 10px 18px rgba(var(--shade), 0.3);
    --shadow-rest:
      0 1px 1px rgba(var(--shade), 0.3), 0 2px 4px rgba(var(--shade), 0.26), 0 6px 10px rgba(var(--shade), 0.26),
      0 14px 24px rgba(var(--shade), 0.3), 0 32px 56px rgba(var(--shade), 0.36);
    --shadow-high:
      0 1px 1px rgba(var(--shade), 0.34), 0 4px 6px rgba(var(--shade), 0.3), 0 12px 18px rgba(var(--shade), 0.34),
      0 28px 40px rgba(var(--shade), 0.4), 0 56px 90px rgba(var(--shade), 0.5);
    --shadow-land:
      drop-shadow(0 1px 1px rgba(var(--shade), 0.4)) drop-shadow(0 5px 8px rgba(var(--shade), 0.3))
      drop-shadow(0 20px 30px rgba(var(--shade), 0.4));
  }
}

/* --------------------------------------------------------------- reset -- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 5.5rem;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--t-body);
  line-height: 1.65;
  letter-spacing: -0.006em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: clip;   /* clip, not hidden: hidden would make body a scroll container and break sticky */
}

[hidden] { display: none !important; }
img { max-width: 100%; display: block; }
ul, ol { list-style: none; margin: 0; padding: 0; }
h1, h2, h3, p, figure { margin: 0; }
h1, h2, h3 { font-weight: 400; }
button { font: inherit; color: inherit; }
a { color: inherit; }

::selection { background: rgba(30, 58, 110, 0.18); }
:focus-visible { outline: 2px solid var(--ink-link); outline-offset: 3px; border-radius: 2px; }

/* ------------------------------------------------------------- shared -- */

.wrap {
  width: 100%;
  max-width: var(--page);
  margin: 0 auto;
  padding-inline: var(--gutter);
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: var(--z-skip);
  background: var(--ink);
  color: var(--bg);
  padding: 0.7rem 1rem;
  font-size: var(--t-small);
  text-decoration: none;
  border-radius: 0 0 var(--r-m) 0;
}
.skip:focus { left: 0; }

/* paper grain: fixed, so it never repaints on scroll, and never clickable */
.grain {
  position: fixed;
  inset: 0;
  z-index: var(--z-grain);
  pointer-events: none;
  opacity: 0.04;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 160px 160px;
}
@media (prefers-color-scheme: dark) { .grain { opacity: 0.07; mix-blend-mode: screen; } }

.section { padding-top: var(--section-gap); }

/* section names: serif, sentence case, no label above them */
.title {
  font-family: var(--display);
  font-size: var(--t-title);
  line-height: 1;
  letter-spacing: -0.02em;
}
.title-xl { font-size: var(--t-display); line-height: 0.86; letter-spacing: -0.04em; }

.text-link {
  color: var(--ink-link);
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 1px;
  padding-bottom: 2px;
  transition: background-size var(--mid) var(--ease-out);
}
.text-link:hover { background-size: 0% 1px; background-position: 100% 100%; }

.stamp { font-family: var(--mono); font-size: var(--t-mono); color: var(--ink-faint); }
.is-empty { color: var(--ink-faint); font-size: var(--t-small); }

.stars { display: inline-block; color: var(--ink-link); font-size: var(--t-small); letter-spacing: 0.1em; }
.stars .off { color: var(--rule); }

/* ------------------------------------------------------------- reading --
   A ledger: one entry per line between hairlines, the day it was read in the margin.
   Shared by the home page and /reading/.
   ------------------------------------------------------------------------ */

.reads { margin-top: clamp(1.75rem, 4vw, 2.75rem); max-width: 58rem; border-top: 1px solid var(--rule); }
.read { display: grid; gap: 0.4rem; padding-block: 1.4rem; border-bottom: 1px solid var(--rule); }
.read-when { font-family: var(--mono); font-size: var(--t-mono); color: var(--ink-faint); }
.read-what { display: grid; gap: 0.4rem; }
.read-title { font-family: var(--display); font-size: var(--t-lead); line-height: 1.14; letter-spacing: -0.016em; text-wrap: balance; }
.read-title a { text-decoration: none; transition: color var(--fast) var(--ease); }
.read-title a:hover { color: var(--ink-link); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.18em; }
.read-meta { font-size: var(--t-small); line-height: 1.45; color: var(--ink-muted); }
.read-dot { margin-inline: 0.15em; color: var(--ink-faint); }
.read-kind { margin-left: 0.5rem; font-family: var(--mono); font-size: var(--t-mono); letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-faint); }
.read-note { max-width: var(--measure); font-size: var(--t-small); line-height: 1.6; color: var(--ink-muted); text-wrap: pretty; }
.reads-more { margin-top: 1.25rem; font-size: var(--t-small); color: var(--ink-muted); }

@media (min-width: 40rem) {
  .read { grid-template-columns: 6.5rem minmax(0, 1fr); column-gap: var(--rail-gap); }
  .read-when { padding-top: 0.5rem; }
}

/* beside the Work copy the ledger is one narrow column: the day sits over the title */
.work-top { display: grid; row-gap: clamp(3rem, 8vw, 4.5rem); }
.work-reading-name { font-family: var(--display); font-style: italic; font-size: var(--t-lead); color: var(--ink-muted); letter-spacing: -0.01em; }
.work-reading .reads { margin-top: 1.1rem; }
.work-reading .read { grid-template-columns: minmax(0, 1fr); padding-block: 1.1rem; }
.work-reading .read-when { padding-top: 0; }
.work-reading .read-title { font-size: 1.25rem; line-height: 1.18; }

@media (min-width: 60rem) {
  .work-top { grid-template-columns: minmax(0, 42rem) minmax(0, 30rem); justify-content: space-between; column-gap: clamp(3rem, 6vw, 6rem); align-items: start; }
  /* the italic name sits level with "Work" */
  .work-reading { padding-top: 0.3rem; }
}

/* /reading/: the whole log, a month at a time */
.reading-page { padding-block: clamp(2rem, 5vw, 3.5rem) var(--section-gap); }
.reading-back { font-size: var(--t-small); }
.reading-page .title { margin-top: clamp(3rem, 8vw, 6rem); }
.reading-count { margin-top: 1.5rem; }
.reading-month { margin-top: clamp(3rem, 7vw, 5rem); }
.reading-month .reads { margin-top: 1.25rem; }

/* the rail: About's two-track opening */
.rail-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  column-gap: var(--rail-gap);
  row-gap: 1.25rem;
  align-items: start;
}

/* ------------------------------------------------------------- top bar --
   A bar that floats clear of the window edge, on the page's soft radius.
   It arrives once the hero has gone by.
   ------------------------------------------------------------------------ */

.topbar {
  position: fixed;
  top: 0.75rem;
  left: 50%;
  z-index: var(--z-topbar);
  width: min(calc(var(--page) - 2 * var(--gutter) + 2.5rem), calc(100vw - 1.5rem));
  height: 3.25rem;
  padding-inline: 1.25rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem;
  border-radius: var(--r-m);
  border: 1px solid var(--rule);
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  box-shadow: var(--shadow-low);
  opacity: 0;
  transform: translate(-50%, -150%);
  transition: opacity var(--mid) var(--ease-out), transform 520ms var(--ease-expo);
  pointer-events: none;
}
.topbar.is-visible { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
.topbar-name {
  font-family: var(--display);
  font-size: var(--t-lead);
  letter-spacing: -0.01em;
  text-decoration: none;
  white-space: nowrap;
}
.topbar-nav {
  display: flex;
  gap: clamp(0.8rem, 1.8vw, 1.5rem);
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.topbar-nav::-webkit-scrollbar { display: none; }
.topbar-nav a {
  position: relative;
  font-size: var(--t-small);
  color: var(--ink-muted);
  text-decoration: none;
  white-space: nowrap;
  padding-block: 0.35rem;
  transition: color var(--fast) var(--ease);
}
.topbar-nav a::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0.15rem;
  height: 1px; width: 100%;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--mid) var(--ease-out);
}
.topbar-nav a:hover { color: var(--ink); }
.topbar-nav a:hover::after,
.topbar-nav a[aria-current="true"]::after { transform: scaleX(1); }
.topbar-nav a[aria-current="true"] { color: var(--ink); }

/* ---------------------------------------------------------------- hero --
   A type poster. The name is fitted to the window, not to the page measure, so it is
   the one thing on the page that runs edge to edge. The sentence sits in the space
   the first name leaves free; nothing else competes.
   ------------------------------------------------------------------------ */

.hero {
  --name: min(calc((100vw - 2 * var(--gutter)) / 5.75), 25rem);
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  /* the bottom allows for the J, which hangs well below the line */
  padding: clamp(4rem, 9vh, 6rem) var(--gutter) calc(var(--name) * 0.12);
}
.hero-name {
  font-family: var(--display);
  font-size: var(--name);
  line-height: 0.86;
  letter-spacing: -0.035em;
  margin-left: -0.04em; /* optical: the stems, not the boxes, meet the margin */
  white-space: nowrap;
}
.hero-name > span { display: block; }
.hero-first { color: var(--ink-link); }
.rise { display: inline-block; animation: rise 1200ms var(--ease-expo) both; }
.hero-last .rise { animation-delay: 110ms; }
@keyframes rise {
  from { opacity: 0; transform: translateY(0.28em); }
  to   { opacity: 1; transform: none; }
}

.hero-aside { display: contents; }
.hero-line {
  margin-top: clamp(1.75rem, 4vw, 2.5rem);
  font-size: var(--t-lead);
  line-height: 1.38;
  letter-spacing: -0.014em;
  max-width: 31ch;
  text-wrap: pretty;
  animation: rise 1200ms var(--ease-expo) 260ms both;
}
.hero-line em { font-family: var(--display); font-style: italic; font-size: 1.12em; letter-spacing: -0.005em; }

@media (min-width: 64rem) {
  /* the sentence moves up into the first line, right of "Zander", level with its x-height */
  .hero { grid-template-columns: 47fr 53fr; }
  .hero-name { grid-column: 1 / -1; grid-row: 1; }
  .hero-line {
    grid-column: 2;
    grid-row: 1;
    z-index: var(--z-over);
    align-self: start;
    margin-top: calc(var(--name) * 0.24);
    /* fitted with the name, so the pair keep their proportion on a very wide window */
    font-size: clamp(1.3125rem, calc(var(--name) * 0.115), 2.25rem);
  }
}

/* --------------------------------------------------------------- about --
   A few sentences, then a journey: the map holds still on the left while two
   chapters scroll past it on the right. Structure unique to this section.
   ------------------------------------------------------------------------ */

/* a section's own words: one line under its name, then a paragraph at reading measure */
.copy { max-width: 42rem; }
.blurb { max-width: var(--measure); }
.title + .copy { margin-top: 1.25rem; }
.sub { font-size: var(--t-lead); line-height: 1.25; letter-spacing: -0.014em; color: var(--ink-muted); text-wrap: pretty; }
.blurb { margin-top: 1rem; line-height: 1.68; text-wrap: pretty; }
.sub + .blurb { margin-top: 1.1rem; }

/* --- land: one outline, its pin, its name. Used still and on the stage. --- */
.land { position: relative; }
.land > svg { display: block; width: 100%; height: 100%; overflow: visible; filter: var(--shadow-land); }
.land path {
  fill: var(--tint-deep);
  stroke: var(--ink-link);
  stroke-width: 1;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.pin { position: absolute; width: 0; height: 0; }
.pin-dot,
.pin-ring {
  position: absolute;
  top: 0;
  left: 0;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
}
.pin-dot { background: var(--ink); box-shadow: 0 0 0 3px var(--bg); }
.pin-ring { border: 1px solid var(--ink-link); opacity: 0; }
.pin-label {
  position: absolute;
  left: 0.9rem;
  top: 0;
  transform: translateY(-50%);
  white-space: nowrap;
  font-size: var(--t-small);
  font-weight: 500;
  letter-spacing: -0.005em;
  /* a paper-coloured halo, so the coastline breaks behind the name instead of striking through it */
  text-shadow: 0 0 3px var(--bg), 0 0 3px var(--bg), 0 0 5px var(--bg), 0 0 5px var(--bg);
}

/* --- the journey, stacked: map, list, map, list. This is the default; the pinned
       version below only switches on when main.js says the screen and the reader allow it. --- */
.journey {
  max-width: var(--page);
  margin-inline: auto;
  padding-inline: var(--gutter);
  margin-top: clamp(3rem, 7vw, 5.5rem);
}
.journey-stage { display: none; }
.journey:not([data-mode="pinned"]) { margin-bottom: clamp(3rem, 8vw, 5rem); }

.chapter + .chapter { margin-top: clamp(4rem, 12vw, 7rem); }
.chapter-map { margin: 0; }
.chapter-map .land { height: clamp(15rem, 62vw, 22rem); }
.chapter-map[data-map="newhaven"] .land { height: auto; width: min(100%, 24rem); }

/* the place name is the big thing, and it sits on the map's shoulder, not under it */
.chapter-head { position: relative; z-index: var(--z-over); margin-top: -2.4rem; }
.chapter-title {
  font-family: var(--display);
  font-weight: 400;
  font-size: var(--t-display);
  line-height: 0.86;
  letter-spacing: -0.04em;
  white-space: nowrap;
}
.chapter-note {
  margin-top: 0.9rem;
  font-size: var(--t-lead);
  line-height: 1.2;
  letter-spacing: -0.015em;
  color: var(--ink-muted);
}

/* --- marks: one visual language for the teams and the clubs. No boxes, no row rules;
       the year hangs in its own column and the space does the separating. --- */
.marks { margin-top: clamp(2rem, 5vw, 3rem); display: grid; gap: clamp(1.6rem, 4.5vw, 2.25rem); }
.mark { display: grid; grid-template-columns: clamp(4.9rem, 9vw, 5.75rem) minmax(0, 1fr); column-gap: 1rem; align-items: baseline; }
.mark-when {
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.01em;
  color: var(--ink-faint);
}
.mark-name {
  display: block;
  font-family: var(--display);
  font-size: var(--t-title);
  line-height: 1.04;
  letter-spacing: -0.022em;
  text-wrap: balance;
}
.mark-details { margin-top: 0.6rem; display: grid; gap: 0.3rem; font-size: var(--t-small); line-height: 1.45; color: var(--ink-muted); }
.mark-details li { padding-left: 1.05rem; position: relative; text-wrap: pretty; }
.mark-details li::before { content: ""; position: absolute; left: 0.1rem; top: 0.62em; width: 4px; height: 4px; border-radius: 50%; background: var(--ink-faint); }

.mark, .chapter-head {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 800ms var(--ease-expo), transform 800ms var(--ease-expo);
}
.mark.is-in, .chapter-head.is-in { opacity: 1; transform: none; }

/* on a phone the maps sit to the left, so the place name keeps to the right, off the coastline */
@media (max-width: 47.99rem) {
  .chapter-title { text-align: right; }
  /* Connecticut fills the width, so its name sits just under the shoreline rather than on it */
  .chapter-map[data-map="newhaven"] + .chapter-head { margin-top: -0.5rem; }
}

/* stacked, but with room: reduced motion on a wide screen. Still map, list, map, list in
   reading order; the map simply stands beside its list instead of above it. */
@media (min-width: 48rem) {
  .journey:not([data-mode="pinned"]) .chapter {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
    grid-template-rows: auto 1fr;
    column-gap: clamp(1.5rem, 4vw, 4rem);
    align-items: start;
  }
  .journey:not([data-mode="pinned"]) .chapter-map { grid-row: 1 / span 2; justify-self: center; }
  .journey:not([data-mode="pinned"]) .chapter-map .land { height: min(70svh, 34rem); }
  .journey:not([data-mode="pinned"]) .chapter-map[data-map="newhaven"] .land { height: auto; width: min(100%, 30rem); }
  .journey:not([data-mode="pinned"]) .chapter-head { margin-top: clamp(1rem, 6vw, 4rem); }
  .journey:not([data-mode="pinned"]) .chapter-title { margin-left: calc(-1 * clamp(2rem, 8vw, 8rem)); }
}

/* --- the journey, pinned ------------------------------------------------- */
.journey[data-mode="pinned"] {
  display: grid;
  grid-template-columns: minmax(0, 1.18fr) minmax(0, 1fr);
  column-gap: clamp(1.5rem, 4vw, 4rem);
  align-items: start;
}
.journey[data-mode="pinned"] .chapter-map { display: none; }
.journey[data-mode="pinned"] .journey-stage {
  display: block;
  position: sticky;
  top: max(4.5rem, calc(50svh - min(39svh, 23rem)));
  z-index: var(--z-stage);
}
.journey[data-mode="pinned"] .chapter { padding-block: 20svh 8svh; }
.journey[data-mode="pinned"] .chapter + .chapter { margin-top: 0; padding-top: 34svh; }
.journey[data-mode="pinned"] .chapter:last-child { padding-bottom: 18svh; }
.journey[data-mode="pinned"] .chapter-head { margin-top: 0; }
/* the name reaches back across the gap and lies over the map as it passes */
.journey[data-mode="pinned"] .chapter-title { margin-left: calc(-1 * clamp(3rem, 12vw, 12rem)); }
.journey[data-mode="pinned"] .marks { gap: clamp(3.5rem, 13svh, 7rem); margin-top: clamp(3.5rem, 12svh, 6rem); }

/* the stage is a size container, so everything on it is placed in shares of the stage
   (cqw, cqh) and the composition holds from 768px to any width */
.stage {
  position: relative;
  height: min(78svh, 46rem);
  container-type: size;
  --th-h: min(90cqh, 122cqw);   /* Thailand as tall as the stage allows, never wider than two thirds of it */
}
.stage .land {
  position: absolute;
  will-change: transform, opacity;
  transition: transform 1100ms var(--ease-inout), opacity 700ms var(--ease-inout);
}
.stage .pin-dot { transition: transform 1100ms var(--ease-inout); }
.stage .pin-label { transition: opacity 400ms var(--ease-inout); }

/* Bangkok: Thailand fills the stage */
.stage-th { height: var(--th-h); inset-block: 0; margin-block: auto; left: 30cqw; transform-origin: 0% 100%; }
.stage-ct { width: 66cqw; top: 17cqh; right: 0; opacity: 0; transform: translate(7%, -5%) scale(0.9); transform-origin: 60% 60%; }

/* New Haven: Thailand steps back into the near corner, still there, smaller and paler;
   Connecticut comes forward. Thailand leaves first, the line is drawn, then Connecticut arrives. */
.stage[data-place="newhaven"] .stage-th { transform: translate(-30cqw, calc((100cqh - var(--th-h)) / 2 - 1cqh)) scale(0.36); opacity: 0.6; }
.stage[data-place="newhaven"] .stage-th .pin-dot { transform: translate(-50%, -50%) scale(2.6); }
.stage[data-place="newhaven"] .stage-th .pin-label { opacity: 0; }
.stage[data-place="newhaven"] .stage-ct { opacity: 1; transform: none; transition-delay: 650ms; }

.stage-arc { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.arc-dots { fill: none; stroke: var(--ink-link); stroke-width: 1.25; stroke-dasharray: 1 6; stroke-linecap: round; }
.arc-draw {
  fill: none;
  stroke: #fff;
  stroke-width: 8;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 700ms var(--ease-inout);
}
.stage[data-place="newhaven"] .arc-draw { stroke-dashoffset: 0; transition: stroke-dashoffset 1500ms var(--ease-inout) 350ms; }

/* one dot makes the trip, and comes to rest as New Haven's pin */
.stage-flight {
  position: absolute;
  left: 0;
  top: 0;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ink);
  offset-rotate: 0deg;
  offset-distance: 0%;
  opacity: 0;
  transition: offset-distance 700ms var(--ease-inout), opacity 250ms var(--ease-inout);
}
.stage[data-place="newhaven"] .stage-flight {
  offset-distance: 100%;
  opacity: 1;
  transition: offset-distance 1500ms var(--ease-inout) 350ms, opacity 250ms var(--ease-inout) 350ms;
}
.stage[data-place="newhaven"] .stage-ct .pin-ring { animation: pin-pulse 900ms var(--ease-expo) 1850ms 1 both; }
@keyframes pin-pulse {
  from { opacity: 0.8; transform: translate(-50%, -50%) scale(1); }
  to   { opacity: 0;   transform: translate(-50%, -50%) scale(5); }
}

.stage-from,
.stage-miles {
  position: absolute;
  left: 0;
  top: 0;
  white-space: nowrap;
  opacity: 0;
  transition: opacity 400ms var(--ease-inout);
  text-shadow: 0 0 3px var(--bg), 0 0 3px var(--bg), 0 0 5px var(--bg);
}
.stage-from { font-size: var(--t-mono); font-weight: 500; color: var(--ink-muted); }
.stage-miles { font-family: var(--mono); font-size: var(--t-mono); letter-spacing: 0.01em; color: var(--ink-faint); }
.stage[data-place="newhaven"] .stage-from { opacity: 1; transition-delay: 900ms; }
.stage[data-place="newhaven"] .stage-miles { opacity: 1; transition-delay: 1500ms; }

/* while main.js measures where the pins come to rest, nothing may animate */
.stage.is-measuring, .stage.is-measuring * { transition: none !important; animation: none !important; }

/* --- the slow line of interests, as a full-bleed break. The only marquee on the page. --- */
.bleed-marquee {
  margin-top: clamp(1rem, 3vw, 2rem);
  padding-block: clamp(1.25rem, 2.6vw, 2rem);
  border-block: 1px solid var(--rule);
}
.marquee {
  position: relative;
  overflow: hidden;
  padding-block: 0.2rem;
  /* a wide fade, so words dissolve at the edges instead of being cut in half */
  -webkit-mask-image: linear-gradient(to right, transparent, #000 14%, #000 86%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 14%, #000 86%, transparent);
}
.marquee-track { display: flex; width: max-content; animation: marquee 64s linear infinite; }
.marquee:hover .marquee-track,
.marquee:focus-within .marquee-track { animation-play-state: paused; }
.marquee-run { display: flex; align-items: baseline; flex: none; padding-right: clamp(2rem, 4vw, 3.5rem); }
.marquee-gap { display: inline-block; width: clamp(2rem, 4vw, 3.5rem); }
.marquee-word {
  font-family: var(--display);
  font-style: italic;
  font-size: var(--t-title);
  line-height: 1.3;
  letter-spacing: -0.012em;
  white-space: nowrap;
  color: var(--ink-muted);
}
@keyframes marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* ---------------------------------------------------------------- work --
   Words, then one raised strip of marks running the full window. The strip is the
   only white-on-white surface with a shadow on the page, so it reads as lying on top.
   ------------------------------------------------------------------------ */

.work-strip {
  position: relative;
  z-index: var(--z-over);
  margin-top: clamp(2.5rem, 5vw, 4rem);
  background: var(--strip-bg);
  box-shadow: var(--shadow-rest), 0 -1px 0 var(--rule);
  /* the strip keeps its own light ink in both themes, so every mark is drawn as its owner drew it */
  --ink: #0F2044;
  --ink-faint: #65738F;
}
/* the strip's own heading, in the same voice as "Musicals" and "Last night": serif, full ink,
   on the measure. The marks line up under it, left edge to left edge. */
.work-label {
  max-width: var(--page);
  margin-inline: auto;
  padding: clamp(2.25rem, 4.5vw, 3.5rem) var(--gutter) 0;
  font-family: var(--display);
  font-size: var(--t-lead);
  line-height: 1.1;
  letter-spacing: -0.015em;
  color: var(--ink);
}
.work-band {
  max-width: var(--page);
  margin-inline: auto;
  padding: clamp(1.75rem, 3.5vw, 2.5rem) var(--gutter) clamp(3rem, 6vw, 4.75rem);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(2.5rem, 5vw, 3.5rem) clamp(1.25rem, 3vw, 2.5rem);
  align-items: center;
}

.work {
  position: relative;
  display: grid;
  justify-items: start;
  text-decoration: none;
  color: var(--ink);
  transition: transform var(--mid) var(--ease-spring);
}
.work:hover { transform: translateY(-3px); }
.work:active { transform: translateY(0) scale(0.98); }

.work-logo {
  position: relative;
  width: min(100%, calc(var(--logo-w, 0.6) * 250px));
  height: clamp(2.5rem, 4vw, 3.5rem);
}
.work-logo .mono {
  position: absolute;
  inset: 0;
  background: var(--ink);
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: left center;  mask-position: left center;
  -webkit-mask-size: contain;     mask-size: contain;
  transition: opacity var(--fast) var(--ease);
}
.work-logo .tint { opacity: 0; }
.work:hover .work-logo .tint,
.work:focus-visible .work-logo .tint { opacity: 1; }
.work:hover .work-logo .mono:not(.tint),
.work:focus-visible .work-logo .mono:not(.tint) { opacity: 0; }

.work-logo.as-published img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: contain;
  object-position: left center;
  filter: grayscale(1) contrast(1.05);
  opacity: 0.78;
  transition: filter var(--fast) var(--ease), opacity var(--fast) var(--ease);
}
.work:hover .as-published img,
.work:focus-visible .as-published img { filter: none; opacity: 1; }

/* the one caption: the Yale wordmark alone doesn't say which department */
.work-note {
  position: absolute;
  top: calc(100% + 0.5rem);
  left: 0; right: 0;
  text-align: left;
  font-size: var(--t-mono);
  color: var(--ink-faint);
  white-space: nowrap;
}

/* ------------------------------------------------------------- library --
   A table of books. The latest one is large, slightly turned, and lies across the
   corner of the shelf behind it; the shelf itself is out of step, row to row.
   ------------------------------------------------------------------------ */

/* the count sits at the shelf's top right corner, over the last column of covers */
.library-note { margin-bottom: clamp(1rem, 2.5vw, 1.5rem); text-align: right; font-size: var(--t-small); color: var(--ink-muted); }

.library-table { margin-top: clamp(2rem, 4vw, 3rem); display: grid; gap: clamp(2.5rem, 6vw, 4rem); }

.book-lead { display: grid; gap: 1.5rem; text-decoration: none; color: inherit; }
.book-cover { position: relative; overflow: hidden; border-radius: var(--r-s); background: var(--tint); }
.book-cover img { width: 100%; height: auto; display: block; }
.lead-cover {
  box-shadow: var(--shadow-high);
  transform: rotate(-2.5deg);
  transform-origin: 30% 60%;
  transition: transform 600ms var(--ease-spring), box-shadow 600ms var(--ease-out);
}
.book-lead:hover .lead-cover { transform: rotate(-1deg) translateY(-6px); }
.book-lead:active .lead-cover { transform: rotate(-1.5deg) scale(0.99); }

.lead-title { font-family: var(--display); font-size: var(--t-title); line-height: 1.04; letter-spacing: -0.022em; text-wrap: balance; }
.lead-author { color: var(--ink-muted); margin-top: 0.4rem; }
.book-lead .stars { margin-top: 0.5rem; }
.lead-date { font-family: var(--mono); font-size: var(--t-mono); color: var(--ink-faint); margin-top: 0.6rem; }
.lead-cue { display: inline-flex; align-items: center; gap: 0.35rem; font-size: var(--t-small); color: var(--ink-link); margin-top: 0.9rem; }
.lead-cue svg { transition: transform var(--mid) var(--ease-spring); }
.book-lead:hover .lead-cue svg { transform: translate(2px, -2px); }

.book-mini-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.5rem, 3vw, 2.25rem) clamp(0.9rem, 2vw, 1.5rem);
  align-content: start;
}
.mini { display: grid; gap: 0.55rem; align-content: start; text-decoration: none; color: inherit; }
.mini-cover { box-shadow: var(--shadow-low); transition: transform var(--mid) var(--ease-spring), box-shadow var(--mid) var(--ease-out); }
.mini:hover .mini-cover { transform: translateY(-5px) rotate(-1deg); box-shadow: var(--shadow-rest); }
.mini:active .mini-cover { transform: scale(0.98); }
.mini-title {
  font-size: var(--t-small);
  line-height: 1.3;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.mini-author { font-size: var(--t-mono); color: var(--ink-faint); }

/* -------------------------------------------------------------- health --
   A running track. Last night's sleep and recovery are the two lanes of a stadium
   oval, each run as far round as its score from the start line, and the year's
   miles stand in the infield. The lane that isn't run yet is a row of ticks, not a band.
   ------------------------------------------------------------------------ */

.health-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem 1.5rem; }
.health-note { color: var(--ink-muted); }

.track { position: relative; container-type: inline-size; margin-top: clamp(2rem, 4vw, 3rem); }
.track-svg { display: block; width: 100%; height: auto; overflow: visible; }
.lane-ticks { fill: none; stroke: var(--ink-faint); stroke-width: 13; stroke-dasharray: 0.07 0.43; opacity: 0.5; }
.lane-fill {
  fill: none;
  stroke: var(--ink-link);
  stroke-width: 13;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  transition: stroke-dashoffset 1800ms var(--ease-inout);
}
.lane-fill[data-lane="1"] { transition-delay: 150ms; }
.lane-start { stroke: var(--ink); stroke-width: 3; }

/* the infield sits inside the inner lane; its type is sized by the track, not the window.
   Every figure in it is a numeral at one size over a small caption. On phones that is the
   miles and the runs; from a tablet up the two scores join them. */
.infield {
  --fig: 20cqw;
  --cap: max(var(--t-small), 1.9cqw);
  position: absolute; inset: 17% 12%;
  display: flex; align-items: center; justify-content: center; gap: 7cqw;
}
.run-figure, .runs-infield, .laps-infield { min-width: 0; }
.run-miles, .runs-infield { display: grid; gap: 1cqw; }
.run-num, .runs-infield b, .lap-figure b, .ring-figure b {
  font-family: var(--display);
  font-weight: 400;
  font-size: var(--fig);
  line-height: 0.8;
  letter-spacing: -0.03em;
  font-variant-numeric: lining-nums;
  color: var(--ink);
  margin-left: -0.04em;
}
.run-cap, .runs-infield, .lap-cap, .ring-cap { font-size: var(--cap); line-height: 1.2; letter-spacing: -0.014em; color: var(--ink-muted); }
.pct { font-size: 0.42em; color: var(--ink-faint); margin-left: 0.04em; }

/* the two scores as figures in the infield (tablet up), the lane glyph in the caption */
.laps { display: none; }
.laps .is-empty { margin: 0; }
.lap-figure { display: grid; gap: 0.6cqw; flex: 1 1 0; min-width: 0; }
.lap-cap { display: flex; align-items: center; gap: 0.5cqw; white-space: nowrap; }
.lap-glyph { width: 2.2cqw; height: 1.1cqw; flex: none; }
.lap-glyph path { fill: none; stroke: var(--ink-faint); stroke-width: 1.5; opacity: 0.5; }
.lap-glyph .on { stroke: var(--ink-link); stroke-width: 2.5; opacity: 1; }

/* the two scores as rings (phones): the lane closed into a circle, the figure in the middle */
.rings { margin-top: clamp(1.5rem, 4vw, 2rem); display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem clamp(1rem, 4vw, 1.5rem); }
.lap-title { grid-column: 1 / -1; font-family: var(--display); font-size: var(--t-lead); letter-spacing: -0.015em; }
.ring { --fig: 30cqw; --cap: var(--t-small); position: relative; container-type: inline-size; }
.ring svg { display: block; width: 100%; height: auto; overflow: visible; }
.ring .lane-ticks, .ring .lane-fill { stroke-width: 2.8; }
.ring .lane-fill[data-score="recoveryScore"] { transition-delay: 150ms; }
.ring-figure { position: absolute; inset: 0; display: grid; place-content: center; justify-items: center; gap: 2.5cqw; text-align: center; }
.ring-figure b { margin-left: 0; }
.rings .is-empty { grid-column: 1 / -1; margin: 0; }

.track-foot { margin-top: clamp(1.5rem, 3vw, 2.25rem); display: grid; gap: 1.5rem; }
.track-stamps { display: flex; flex-wrap: wrap; gap: 0.25rem 1.5rem; }

/* the most recent race: one row between two hairlines, each value at title size under a small label */
.board {
  margin-top: clamp(2rem, 4vw, 3rem);
  border-block: 1px solid var(--rule);
  padding-block: clamp(1.5rem, 3vw, 2.25rem);
  display: grid;
  gap: 1.5rem 2rem;
}
.board-cell { display: grid; gap: 0.45rem; align-content: start; }
.board-k { font-family: var(--mono); font-size: var(--t-mono); color: var(--ink-faint); letter-spacing: 0.06em; text-transform: uppercase; }
.board-v { margin: 0; font-family: var(--display); font-size: var(--t-title); line-height: 1.02; letter-spacing: -0.022em; text-wrap: balance; font-variant-numeric: lining-nums; }
.board-v .unit { font-size: 0.5em; color: var(--ink-faint); }

@media (min-width: 40rem) {
  .board { grid-template-columns: 1fr 1fr; }
  .board-race { grid-column: 1 / -1; }
}

@media (min-width: 48rem) {
  /* from a tablet up the two scores move into the infield with the miles and runs, four
     figures at one size, and the rings stand down */
  .infield { --fig: 10cqw; --cap: max(var(--t-small), 1.8cqw); inset: 17% 11%; gap: 2.5cqw; justify-content: space-between; }
  .run-figure, .runs-infield, .laps-infield { flex: 1 1 0; }
  .run-miles, .runs-infield { gap: 0.6cqw; }
  .laps-infield { display: flex; gap: 2.5cqw; flex: 2.3 1 0; }
  .rings { display: none; }
  .track-foot { grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; }
  .track-stamps { grid-column: 2; flex-direction: column; gap: 0.35rem; text-align: right; }
}

@media (min-width: 60rem) {
  .board { grid-template-columns: 2.2fr 1fr 1.2fr 1fr; }
  .board.has-time { grid-template-columns: 2.2fr 1fr 1.2fr 1fr 1fr; }
  .board-race { grid-column: auto; }
}

/* ----------------------------------------------------------- interests --
   Two poster walls side by side, every other column hanging lower. On anything
   narrower than a laptop they become strips you push sideways.
   ------------------------------------------------------------------------ */

.walls { margin-top: clamp(2rem, 4vw, 3rem); display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(2rem, 5vw, 3rem); }
.wall { min-width: 0; }
.wall-name { font-family: var(--display); font-size: var(--t-lead); letter-spacing: -0.015em; padding-inline: var(--gutter); margin-bottom: 0.9rem; }

.tiles {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: clamp(7.5rem, 36vw, 10.5rem);
  gap: clamp(0.75rem, 1.6vw, 1.1rem);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  padding-inline: var(--gutter);
  scroll-padding-inline: var(--gutter);
  padding-bottom: 1.5rem;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.tiles::-webkit-scrollbar { display: none; }
.tile { scroll-snap-align: start; }

.poster {
  position: relative;
  aspect-ratio: 2 / 3;
  overflow: hidden;
  border-radius: var(--r-s);
  background: var(--tint);
  box-shadow: var(--shadow-low);
  transition: transform var(--mid) var(--ease-spring), box-shadow var(--mid) var(--ease-out);
}
.tile:hover .poster { transform: translateY(-5px); box-shadow: var(--shadow-rest); }
.poster img { width: 100%; height: 100%; object-fit: cover; display: block; }
.poster-set { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: space-between; padding: 0.8rem; color: var(--ink-link); }
.set-mark { opacity: 0.55; }
.set-kicker { font-size: var(--t-mono); color: var(--ink-faint); }
.set-title { font-family: var(--display); font-size: var(--t-body); line-height: 1.15; color: var(--ink); }
.tile-title {
  margin-top: 0.55rem;
  font-size: var(--t-mono);
  line-height: 1.35;
  color: var(--ink-muted);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.credit { margin-top: 1rem; font-family: var(--mono); font-size: var(--t-mono); color: var(--ink-faint); }

/* -------------------------------------------------------------- awards --
   One award at full size. The rest gather under three headings in three uneven
   columns. Space separates them; there is not a rule in the section.
   ------------------------------------------------------------------------ */

.award-lead { margin-top: clamp(1.25rem, 3vw, 2rem); }
.award-lead-name { font-family: var(--display); font-size: var(--t-display); line-height: 0.9; letter-spacing: -0.04em; text-wrap: balance; }
.award-lead-context { margin-top: 1rem; font-size: var(--t-lead); line-height: 1.25; letter-spacing: -0.014em; color: var(--ink-muted); max-width: 32ch; }

.award-groups { margin-top: clamp(3rem, 7vw, 5.5rem); display: grid; gap: clamp(2.5rem, 6vw, 3.5rem); }
.award-group-name { font-family: var(--display); font-style: italic; font-size: var(--t-lead); color: var(--ink-muted); letter-spacing: -0.01em; }
.award-list { margin-top: 1.25rem; display: grid; gap: 1.6rem; }
.award { display: grid; gap: 0.25rem; }
.award-name { font-family: var(--display); font-size: var(--t-lead); line-height: 1.12; letter-spacing: -0.016em; text-wrap: balance; }
.award-context { font-size: var(--t-small); line-height: 1.45; color: var(--ink-muted); text-wrap: pretty; }
.award-year { font-family: var(--mono); font-size: var(--t-mono); color: var(--ink-faint); }

/* --------------------------------------------------------------- close --
   The page ends on navy, edge to edge. The address is the headline, fitted to the
   measure the way the name is fitted to the window.
   ------------------------------------------------------------------------ */

.close {
  margin-top: var(--section-gap);
  background: var(--close-bg);
  color: var(--close-ink);
  padding-block: clamp(4.5rem, 11vw, 9rem) 2rem;
}
.close :focus-visible { outline-color: var(--close-ink); }
.close-title { font-family: var(--display); font-size: var(--t-title); letter-spacing: -0.02em; line-height: 1; }
.close-line { margin-top: 0.9rem; color: var(--close-muted); font-size: var(--t-lead); line-height: 1.3; letter-spacing: -0.014em; }

.close-email {
  --fit: calc((min(100vw, var(--page)) - 2 * var(--gutter)) / 8.15);
  display: inline-block;
  margin-top: clamp(2.5rem, 6vw, 4.5rem);
  font-family: var(--display);
  font-size: var(--fit);
  line-height: 0.96;
  letter-spacing: -0.035em;
  color: inherit;
  text-decoration: none;
}
.close-email span { display: block; white-space: nowrap; }
/* a stepped indent: the second line starts where the first name ends */
.close-email span + span { padding-left: 2.28em; color: var(--close-muted); transition: color var(--mid) var(--ease-out); }
.close-email:hover span + span { color: var(--close-ink); }
.close-email:active { transform: scale(0.995); }

.elsewhere { display: flex; flex-wrap: wrap; gap: 0.5rem 2rem; margin-top: clamp(2.5rem, 6vw, 4rem); }
.elsewhere a {
  color: var(--close-ink);
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 1px;
  padding-bottom: 2px;
  transition: background-size var(--mid) var(--ease-out);
}
.elsewhere a:hover { background-size: 0% 1px; background-position: 100% 100%; }

.colophon {
  margin-top: clamp(4rem, 9vw, 7rem);
  padding-top: 1.25rem;
  border-top: 1px solid color-mix(in srgb, var(--close-ink) 16%, transparent);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.4rem 2rem;
  font-size: var(--t-mono);
  color: var(--close-muted);
}

/* --------------------------------------------------------------- reveal --
   One arrival, used everywhere: up and in, on the expo curve. Things that belong to
   a row carry --i and arrive a beat apart, left to right.
   ------------------------------------------------------------------------ */

[data-reveal] {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 800ms var(--ease-expo), transform 800ms var(--ease-expo);
  transition-delay: calc(var(--i, 0) * 70ms);
}
[data-reveal].is-in { opacity: 1; transform: none; }

/* ------------------------------------------------------- from 40rem up -- */

@media (min-width: 40rem) {
  .work-band { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .book-mini-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  /* nine covers fill a 3 by 3 on phones; the ninth stands down for 4 by 2 */
  .mini-ninth { display: none; }
  /* out of step: every other book on the shelf sits lower */
  .mini:nth-child(even) { margin-top: 1.75rem; }
  .book-lead { grid-template-columns: minmax(0, 15rem) minmax(0, 1fr); align-items: end; gap: 2rem; }
  .award-groups { grid-template-columns: 1.35fr 1.2fr 1fr; align-items: start; }
}

/* ------------------------------------------------------- from 60rem up -- */

@media (min-width: 60rem) {
  .rail-grid { grid-template-columns: var(--rail) minmax(0, 1fr); }

  .work-band { grid-template-columns: repeat(6, minmax(0, 1fr)); }

  /* the latest book lies across the corner of the shelf; the heading stays clear above it */
  .library-table {
    grid-template-columns: minmax(0, 21rem) minmax(0, 1fr);
    gap: 0;
    align-items: start;
    margin-top: clamp(1.5rem, 2.5vw, 2.25rem);
  }
  .book-feature { position: relative; z-index: var(--z-over); margin-right: -2.75rem; }
  .book-lead { grid-template-columns: minmax(0, 1fr); gap: 1.75rem; }
  .shelf { padding-left: 5.5rem; padding-top: 0.75rem; }

}

/* ------------------------------------------------------- from 64rem up --
   The strips stand up into walls: three rows deep, side by side, sized by their columns. */

@media (min-width: 64rem) {
  .walls {
    grid-template-columns: none;
    display: flex;
    align-items: start;
    gap: clamp(2rem, 4vw, 4rem);
    padding-inline: var(--edge);
  }
  .wall { flex: var(--cols) 1 0; min-width: 0; }
  .wall-name { padding-inline: 0; }
  .tiles {
    grid-auto-flow: row;
    grid-auto-columns: auto;
    grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
    overflow: visible;
    padding: 0 0 2.75rem;
  }
  .tile.is-low { transform: translateY(2.75rem) !important; }
  .wall[data-reveal] { opacity: 1; transform: none; }
  .wall .tile { opacity: 0; transition: opacity 800ms var(--ease-expo) calc(var(--i, 0) * 80ms); }
  .wall.is-in .tile { opacity: 1; }
}

/* -------------------------------------------------------------- phones -- */

@media (max-width: 39.99rem) {
  .topbar-name { display: none; }
  .book-lead { grid-template-columns: minmax(0, 44%) minmax(0, 1fr); gap: 1.25rem; align-items: end; }
  .close-email span + span { padding-left: 0; }
}

/* ------------------------------------------------------- reduced motion -- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    transition-delay: 0ms !important;
  }
  [data-reveal], .mark, .chapter-head, .wall .tile { opacity: 1; transform: none; }
  .marquee { -webkit-mask-image: none; mask-image: none; }
  .marquee-track { animation: none; width: auto; flex-wrap: wrap; }
  .marquee-run[aria-hidden="true"] { display: none; }
  .marquee-run { flex-wrap: wrap; padding-right: 0; row-gap: 0.25rem; }
}
