/* ---------------------------------------------------------------
   Timeline résumé — stylesheet
   Design notes: system fonts only (zero font downloads), one accent
   colour, hairline rules, generous whitespace. Dark mode is automatic.
   --------------------------------------------------------------- */

:root {
  --bg: #ffffff;
  --bg-soft: #f5f5f7;
  --text: #1d1d1f;
  --text-dim: #6e6e73;
  --hairline: #d2d2d7;
  --accent: #0071e3;
  --shadow: 0 2px 8px rgba(0, 0, 0, .06), 0 12px 32px rgba(0, 0, 0, .08);
  --radius: 18px;
  --maxw: 1000px;
  --pad: 22px;   /* .wrap side padding */
  --rail: 118px; /* width of the date gutter left of the spine */
  --gutter: 40px;/* space between the spine and the content */
  --laurel-w: 92px; /* one width for every laurel, so the gutter stays even */
  --imdb: #f5c518;  /* IMDb's yellow */
  --rt: #d1361a;    /* Rotten Tomatoes red, darkened for white-text contrast */
  --ks: #05ce78;    /* Kickstarter green, with near-black text over it */
  --poster-w: 335px; /* display width of square/portrait poster artwork */
  --ease: cubic-bezier(.22, .61, .36, 1);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #000000;
    --bg-soft: #1c1c1e;
    --text: #f5f5f7;
    --text-dim: #98989d;
    --hairline: #38383a;
    --accent: #2997ff;
    --shadow: 0 2px 8px rgba(0, 0, 0, .5), 0 12px 32px rgba(0, 0, 0, .6);
  }
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI",
    Roboto, Helvetica, Arial, sans-serif;
  font-size: 17px;
  line-height: 1.55;
  letter-spacing: -.011em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

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

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

.wrap {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--pad);
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--bg);
  padding: 12px 18px;
  z-index: 100;
}
.skip:focus { left: 12px; top: 12px; }

/* ---------- Header ---------- */

.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--bg) 90%, transparent);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid transparent;
  transition: border-color .3s var(--ease);
}
.nav.is-stuck { border-bottom-color: var(--hairline); }

.nav .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  height: 52px;
}

.nav-name {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.01em;
  color: var(--text);
}
.nav-name:hover { text-decoration: none; }

.nav-links {
  display: flex;
  gap: 22px;
  font-size: 13px;
  color: var(--text-dim);
  /* Year links were five short numbers; section labels are phrases. Let the
     row scroll sideways inside the bar instead of widening the page. */
  overflow-x: auto;
  white-space: nowrap;
  scrollbar-width: none;
  min-width: 0;
}
.nav-links::-webkit-scrollbar { display: none; }
.nav-links a { color: var(--text-dim); }
.nav-links a:hover { color: var(--text); text-decoration: none; }

/* ---------- Hero ---------- */

.hero {
  /* Bottom padding kept shallower than the top: the Skills toggle is the
     hero's last line, and too much air under it strands the filter row. */
  padding: clamp(72px, 13vw, 148px) 0 clamp(24px, 4vw, 40px);
}

.hero h1 {
  margin: 0 0 .28em;
  font-size: clamp(40px, 8.2vw, 76px);
  line-height: 1.05;
  font-weight: 700;
  letter-spacing: -.028em;
}

.hero .tagline {
  margin: 0 0 32px;
  font-size: clamp(20px, 3.2vw, 27px);
  line-height: 1.3;
  font-weight: 400;
  letter-spacing: -.018em;
  color: var(--text-dim);
  max-width: 30ch;
}

.hero .about {
  margin: 0 0 34px;
  max-width: 62ch;
  font-size: 19px;
  line-height: 1.6;
}

.meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 22px;
  font-size: 15px;
  color: var(--text-dim);
}
.meta a { color: var(--accent); }

.btn {
  display: inline-block;
  background: var(--accent);
  color: #fff;
  padding: 11px 22px;
  border-radius: 980px;
  font-size: 15px;
  font-weight: 500;
  transition: opacity .2s var(--ease);
}
.btn:hover { opacity: .85; text-decoration: none; }

/* ---------- Skills ---------- */

/* Screen-reader-only. The pips are decorative, so the score is carried in
   text that never paints. */
.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skills-wrap { margin: -8px 0 0; }

.skills-btn {
  appearance: none;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 16px;
  color: var(--accent);
  cursor: pointer;
}
.skills-btn:hover { text-decoration: underline; }

.skills {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, max-content));
  gap: 26px 56px;
  margin-top: 22px;
}
.skills[hidden] { display: none; }

.skill-head {
  margin: 0 0 12px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.skill-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 9px;
}

.skill-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  font-size: 15px;
}

.skill-name { color: var(--text); }

.pips { display: flex; gap: 5px; flex: none; }

.pip {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--hairline);
}
.pip.on { background: var(--text); }

/* ---------- Filters ---------- */

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 0 0 8px;
  border-top: 1px solid var(--hairline);
  padding-top: 26px;
  margin-top: 8px;
}

.chip {
  appearance: none;
  border: 1px solid var(--hairline);
  background: transparent;
  color: var(--text-dim);
  font: inherit;
  font-size: 14px;
  padding: 6px 15px;
  border-radius: 980px;
  cursor: pointer;
  transition: background .18s var(--ease), color .18s var(--ease),
    border-color .18s var(--ease);
}
.chip:hover { border-color: var(--text-dim); color: var(--text); }
.chip[aria-pressed="true"] {
  background: var(--text);
  border-color: var(--text);
  color: var(--bg);
}

/* ---------- Timeline ---------- */

/* The spine: one continuous hairline running the full height of the
   timeline, with a node on it for every year and every project. It fades
   out at both ends so it reads as a thread rather than a border. */

.timeline {
  position: relative;
  /* Long-hand on purpose: the padding shorthand would clobber .wrap's side
     padding and knock the nodes off the spine. */
  padding-top: 40px;
  padding-bottom: 96px;
}

.timeline::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 96px;
  left: calc(var(--pad) + var(--rail));
  width: 1px;
  background: var(--hairline);
  -webkit-mask-image: linear-gradient(
    to bottom, transparent 0, #000 46px, #000 calc(100% - 90px), transparent 100%);
  mask-image: linear-gradient(
    to bottom, transparent 0, #000 46px, #000 calc(100% - 90px), transparent 100%);
}

.year,
.entry {
  display: grid;
  /* minmax(0, 1fr) — without it the 1280px poster sets the column's
     min-content width and the whole grid blows past the viewport. */
  grid-template-columns: var(--rail) minmax(0, 1fr);
  column-gap: var(--gutter);
  align-items: start;
}

/* The rail holds the dot and date in row 1; laurels take row 2 beneath it,
   and the body spans both so it still starts at the top of the entry. */
.entry > .rail { grid-column: 1; grid-row: 1; }
.entry > .body { grid-column: 2; grid-row: 1 / span 2; }

.rail {
  position: relative;
  min-height: 1px;
}

/* --node-y is 60% of the adjacent heading's font size, so the dot lands on
   the optical centre of the first line of that heading at every width. */
.entry .rail { --node-y: clamp(13px, 2.04vw, 18px); }
.year  .rail { --node-y: clamp(18px, 3.30vw, 26px); }

/* Nodes sit dead centre on the spine because the rail column's right edge
   IS the spine. No magic numbers to keep in sync. */
.node {
  position: absolute;
  right: 0;
  top: var(--node-y);
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--bg);
  border: 1.5px solid var(--hairline);
  transform: translate(50%, -50%);
  transition: border-color .25s var(--ease), background .25s var(--ease),
    transform .25s var(--ease);
}

.node-year {
  width: 15px;
  height: 15px;
  background: var(--text);
  border-color: var(--text);
}

.entry:hover .node {
  border-color: var(--accent);
  background: var(--accent);
  transform: translate(50%, -50%) scale(1.15);
}

.rail-date {
  position: absolute;
  right: 26px;
  top: var(--node-y);
  transform: translateY(-50%);
  font-size: 14px;
  line-height: 1.2;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.year {
  padding: 40px 0 20px;
  scroll-margin-top: 70px;
}

.year .body {
  display: flex;
  align-items: baseline;
  gap: 14px;
}

.year h2 {
  margin: 0;
  font-size: clamp(30px, 5.5vw, 44px);
  font-weight: 700;
  letter-spacing: -.024em;
  font-variant-numeric: tabular-nums;
  /* Headings were four digits when this was sized; section labels can be
     whole phrases, which must wrap rather than push the page wide. */
  overflow-wrap: break-word;
  min-width: 0;
}

/* Baseline flex keeps "2026  ·  3 projects" on one line, but a long section
   label plus its count needs room to stack. */
.year .body { flex-wrap: wrap; }

.year .count {
  font-size: 14px;
  color: var(--text-dim);
  letter-spacing: 0;
}

.entry {
  padding: 14px 0 58px;
}

.entry.is-hidden { display: none; }

/* Two films sharing one row in the unfiltered view. Each column carries a
   full entry body, so it collapses to a single stack on a narrow screen
   rather than squeezing two posters side by side. */
.pair {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 34px 40px;
}
.pair-col { min-width: 0; }
.pair-col .desc-wrap { max-width: none; }

/* The date lives in the rail on wide screens, so hide the inline copy. */
.entry .body .date { display: none; }

/* Scroll-in reveal, respectfully */
.reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity .55s var(--ease), transform .55s var(--ease);
  will-change: opacity, transform;
}
.reveal.in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
  /* Laurels stay put rather than fading in and out. */
  .laurels { opacity: 1; transition: none; }
}

.entry-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 12px;
  margin-bottom: 6px;
}

.entry h3 {
  margin: 0;
  font-size: clamp(22px, 3.4vw, 30px);
  font-weight: 600;
  letter-spacing: -.02em;
  line-height: 1.2;
}

.entry .date {
  font-size: 14px;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.entry .role {
  margin: 0 0 12px;
  font-size: 17px;
  color: var(--text-dim);
}
.entry .role strong { color: var(--text); font-weight: 600; }

/* The description sits behind a More button — nothing of it shows until
   someone asks. Without JavaScript the text is simply visible, which is the
   right fallback: better to show it than to hide it behind a dead button. */
.desc-wrap { margin: 0 0 20px; max-width: 66ch; }

/* Stands in for a collapsed description in a side-by-side pair: same height
   as the More row, so the neighbouring columns stay level. Height is matched
   to the .more-btn line box. */
.desc-spacer { height: 26px; margin: 0 0 20px; }

.entry .desc { margin: 0; color: var(--text); }

.desc-wrap.is-collapsible .desc,
.desc-wrap.is-collapsible .desc-more { display: none; }

.desc-wrap.is-collapsible.is-open .desc { display: block; margin-top: 10px; }
.desc-wrap.is-collapsible.is-open .desc-more { display: block; }

.desc-more { margin: .7em 0 0; color: var(--text); }

.more-btn {
  appearance: none;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 14px;
  color: var(--accent);
  cursor: pointer;
}
.more-btn:hover { text-decoration: underline; }

/* Tags and laurels ride on the same line, laurels to the right. */
.entry-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 20px;
  margin: 0 0 20px;
}

.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.tags li {
  font-size: 12px;
  letter-spacing: .01em;
  color: var(--text-dim);
  background: var(--bg-soft);
  padding: 4px 11px;
  border-radius: 980px;
}

/* Score chips — tag-shaped, but each in its source's own colour so the number
   reads as theirs and not as one we made up. Their text colour is fixed, not
   themed: the background is the same in light and dark, so following the
   theme's text colour would make one of the two unreadable. */
.score {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  font-size: 12px;
  letter-spacing: .01em;
  padding: 4px 11px;
  border-radius: 980px;
  text-decoration: none;
  transition: filter .2s var(--ease);
}
.score:hover { filter: brightness(1.07); text-decoration: none; }
.score strong {
  color: inherit;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.rating { background: var(--imdb); color: #16161a; }
.rating:hover { color: #16161a; }

.rt { background: var(--rt); color: #fff; }
.rt:hover { color: #fff; }

/* Views are a fact about reach, not a score from a rating body — so a quiet
   outlined chip rather than a branded colour. */
.views {
  background: transparent;
  border: 1px solid var(--hairline);
  color: var(--text-dim);
}
.views strong { font-weight: 500; color: var(--text-dim); }

/* A funding total is the one number here that is a result rather than an
   opinion, so it gets Kickstarter's green and the weight to match. */
.raised { background: var(--ks); color: #052e16; }
.raised:hover { color: #052e16; }

/* ---------- Per-section More control ---------- */

/* Rows past the first four in a section, while it is closed. */
.entry.over-cap { display: none; }

/* Same two-column grid as an entry, so the button sits in the content
   column, on the spine's side of the page. */
.section-more {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  column-gap: var(--gutter);
  padding: 2px 0 26px;
}
.section-more[hidden] { display: none; }

.section-more-btn {
  grid-column: 2;
  justify-self: start;
  appearance: none;
  border: 1px solid var(--hairline);
  background: transparent;
  color: var(--accent);
  font: inherit;
  font-size: 14px;
  padding: 7px 18px;
  border-radius: 980px;
  cursor: pointer;
  transition: background .18s var(--ease);
}
.section-more-btn:hover { background: var(--bg-soft); }

/* ---------- Festival laurels ---------- */

/* Laurels live in the gutter, left of the spine, stacked under the date.
   Sized by WIDTH so every laurel is the same size regardless of whether it
   is a square wreath or a wide ribbon — height varies instead. */
.laurels {
  grid-column: 1;
  grid-row: 2;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 16px;
  margin: 0;
  padding: 14px 26px 0 0;
  list-style: none;
  opacity: 0;
  transition: opacity .6s var(--ease);
}

/* Faded until scrolled to, and faded again once past — main.js keeps
   watching rather than unobserving after the first reveal. */
.laurels.in-view { opacity: 1; }

.laurels li { display: flex; }

.laurels img {
  width: var(--laurel-w);
  height: auto;
  opacity: .88;
}

/* The source files are black artwork on transparency, so dark mode just
   flips them to white — one asset, both themes, no second export. */
@media (prefers-color-scheme: dark) {
  .laurels img { filter: invert(1); opacity: .92; }
}

/* On phones there's no room for a side column — laurels drop below the
   text and go back to a fixed height. */
@media (max-width: 760px) {
  /* The gutter is 9px here, so laurels move into the content column and
     lie in a row under the entry instead. */
  .entry > .body { grid-row: 1; }
  .laurels {
    grid-column: 2;
    grid-row: 2;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-start;
    gap: 14px 20px;
    padding: 18px 0 0;
  }
  .laurels img { width: 84px; }
}

/* ---------- Video ---------- */

.player {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: var(--bg-soft);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
  cursor: pointer;
  border: 0;
  padding: 0;
  display: block;
  transition: transform .35s var(--ease), box-shadow .35s var(--ease);
}
.player:hover { transform: translateY(-3px); }

.player img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .6s var(--ease), filter .35s var(--ease);
}

/* A poster much wider than the 16:9 frame — a title lockup, say — is
   letterboxed rather than having its ends cropped off. */
.player.is-wide img { object-fit: contain; }
.player.is-wide { background: #000; }
.player.is-wide:hover img { transform: none; }
.player:hover img { transform: scale(1.03); filter: brightness(.92); }

.player iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

.play {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 74px;
  height: 74px;
  border-radius: 50%;
  background: rgba(20, 20, 20, .55);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  display: grid;
  place-items: center;
  transition: background .25s var(--ease), transform .25s var(--ease);
  pointer-events: none;
}
.player:hover .play {
  background: rgba(20, 20, 20, .75);
  transform: translate(-50%, -50%) scale(1.06);
}
.play svg { width: 26px; height: 26px; fill: #fff; margin-left: 4px; }

.player .duration {
  position: absolute;
  right: 12px;
  bottom: 12px;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: #fff;
  background: rgba(0, 0, 0, .62);
  padding: 3px 8px;
  border-radius: 6px;
  pointer-events: none;
}

/* ---------- Campaign grid ---------- */

/* Several cutdowns under one entry. auto-fit keeps them one row on a wide
   screen and reflows to two, then one, as the column narrows. */
.campaign {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(155px, 1fr));
  gap: 14px;
}

.campaign-item {
  display: block;
  margin: 0;
  color: inherit;
  transition: transform .35s var(--ease);
}
/* Only the linked cards lift on hover — a plain gallery figure isn't
   clickable, so it shouldn't behave as though it were. */
a.campaign-item:hover { transform: translateY(-3px); text-decoration: none; }

/* The rounded, clipped picture box. Kept separate from the link so a
   caption can sit outside it without being cropped by the overflow. */
.campaign-thumb {
  position: relative;
  display: block;
  border-radius: 12px;
  overflow: hidden;
  background: var(--bg-soft);
  box-shadow: var(--shadow);
  line-height: 0;
}

.campaign-item img {
  width: 100%;
  /* Pinned to one ratio and cropped rather than left at height:auto. A video
     with no maxresdefault falls back to hqdefault, which is 4:3 — left to its
     own shape it would stand taller than the tiles beside it and the row
     would go ragged. --tile is set per row by build.py when the posters are
     vertical (Instagram); otherwise landscape video's 16:9 stands. */
  aspect-ratio: var(--tile, 16 / 9);
  height: auto;
  object-fit: cover;
  transition: filter .35s var(--ease);
}
.campaign-item:hover img { filter: brightness(.92); }

.campaign-item .play {
  width: 52px;
  height: 52px;
}
.campaign-item .play svg { width: 18px; height: 18px; }

.campaign-label {
  display: block;
  margin-top: 10px;
  font-size: 13px;
  line-height: 1.4;
  color: var(--text-dim);
}
.campaign-item:hover .campaign-label { color: var(--text); }

/* A poster with no video behind it. */
.still {
  margin: 0;
  width: 100%;
  /* --native is the image's own pixel width, written by build.py. */
  max-width: var(--native, 100%);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg-soft);
  box-shadow: var(--shadow);
  line-height: 0;
}
.still img { width: 100%; height: auto; }

/* A one-sheet sitting under a video needs air between the two. */
.player + .still,
.watch + .still { margin-top: 22px; }

/* Square and portrait artwork gets capped — at full column width a
   one-sheet swallows the screen and buries the next entry. min() takes
   whichever is smaller: the design width, or the image's own pixels. */
.still.is-tall {
  max-width: min(var(--poster-w), var(--native, 100%));
  border-radius: 12px;
}

/* Link out to the video's own page — hidden until it's needed. */
.watch {
  display: inline-block;
  margin: 14px 0 0;
  font-size: 14px;
  color: var(--text-dim);
}
.watch[hidden] { display: none; }
.watch:hover { color: var(--accent); text-decoration: none; }

/* When there's no player, the link is the entry's call to action. */
.watch-btn {
  margin-top: 18px;
  padding: 11px 24px;
  border-radius: 980px;
  background: var(--accent);
  color: #fff;
  font-size: 15px;
  font-weight: 500;
  transition: opacity .2s var(--ease);
}
.watch-btn:hover { opacity: .85; color: #fff; }

.player.is-live { cursor: default; }
.player.is-live:hover { transform: none; }
.player.is-live .play,
.player.is-live .duration { display: none; }

/* ---------- Footer ---------- */

.footer {
  border-top: 1px solid var(--hairline);
  padding: 44px 0 64px;
  font-size: 14px;
  color: var(--text-dim);
}
.footer .wrap {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 26px;
  align-items: center;
  justify-content: space-between;
}

/* Contact moved down here when the header was stripped back. */
.footer-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 22px;
}
.footer-meta a { color: var(--accent); }

.top {
  font-size: 14px;
  color: var(--text-dim);
}

/* ---------- Small screens ---------- */

/* Wide: line the hero and filters up with the timeline's content column so
   the whole page shares one left edge and the spine lives in the margin. */
@media (min-width: 761px) {
  .hero .wrap > *,
  .filters {
    margin-left: calc(var(--rail) + var(--gutter));
  }
}

/* Narrow: the date gutter collapses, the spine hugs the left edge, and the
   date moves inline under the project title. Same timeline, less furniture. */
@media (max-width: 760px) {
  :root {
    --pad: 20px;
    --rail: 9px;
    --gutter: 22px;
  }
  body { font-size: 16px; }
  .nav-links { gap: 16px; }
  .hero .about { font-size: 17px; }
  .rail-date { display: none; }
  .entry .body .date { display: inline; }
  .player { border-radius: 14px; }
  .play { width: 60px; height: 60px; }
  .play svg { width: 21px; height: 21px; }
  .entry { padding-bottom: 46px; }
  .year { padding: 32px 0 16px; }
  .timeline::before {
    -webkit-mask-image: linear-gradient(
      to bottom, transparent 0, #000 34px, #000 calc(100% - 70px), transparent 100%);
    mask-image: linear-gradient(
      to bottom, transparent 0, #000 34px, #000 calc(100% - 70px), transparent 100%);
  }
}

@media print {
  .nav, .filters, .play, .top { display: none; }
  .player { box-shadow: none; }
  body { font-size: 11pt; }
}
