@font-face {
  font-family: "Cheltenham Light";
  src: url("Assets/Cheltenham%20Light.ttf") format("truetype");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Bagoss Condensed";
  src: url("Assets/BagossCondensed-Medium.ttf") format("truetype");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Gestalt";
  src: url("Assets/Gestalt-Regular.otf") format("opentype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  --paper: #ffffff;
  --ink: #050505;
  --charcoal: #252525;
  --rail-gray: #d9d9d9;
  --gutter: clamp(24px, 8.5vw, 38px);
  --type-lg: clamp(29px, 7.05vw, 34px);
  --line-tight: 0.97;
}

* {
  box-sizing: border-box;
}

html {
  min-height: 100%;
}

body {
  min-height: 100%;
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: "Cheltenham Light", Georgia, serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: geometricPrecision;
}

a {
  color: inherit;
  text-decoration: none;
}

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

.site-shell {
  width: 100%;
}

.panel {
  min-height: 100svh;
}

.panel-upper {
  background: var(--paper);
}

.upper-stage {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(100vw, 520px);
  min-height: 100svh;
  margin: 0 auto;
  padding: var(--gutter) 0 18px;
}

.intro {
  margin-bottom: 24px;
}

.mark {
  position: relative;
  float: left;
  z-index: 2;
  width: clamp(78px, 23vw, 100px);
  aspect-ratio: 1;
  margin: 0 clamp(20px, 7.4vw, 29px) 10px var(--gutter);
  border-radius: 999px;
  appearance: none;
  -webkit-appearance: none;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.mark-face {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* Pupil geometry measured from Assets/avatar_emptyeyes.png (788x788):
   each eye white is centered at (40.3%, 41.9%) / (59.3%, 41.9%) and is
   ~15.6% x 36.4% of the image, ringed by a ~3.2%-thick eyelid border; the
   pupil (Assets/pupil.png) is ~11.5% x 17.1%. script.js's --pupil-x/-y
   drift the pupil up to ~3.6%/11.2% from center — past the white edge and
   about halfway into the border, so it peeks under the eyelid at full
   deflection instead of stopping short of it. */
.mark-pupil {
  position: absolute;
  width: 11.5%;
  height: 17.1%;
  object-fit: contain;
  pointer-events: none;
  transform: translate(-50%, -50%) translate(var(--pupil-x, 0px), var(--pupil-y, 0px));
}

.mark-pupil-left {
  left: 40.3%;
  top: 41.9%;
}

.mark-pupil-right {
  left: 59.3%;
  top: 41.9%;
}

.intro-copy {
  position: relative;
  z-index: 1;
  margin: 2px var(--gutter) 0;
  font-size: 26px;
  font-weight: 300;
  line-height: var(--line-tight);
  letter-spacing: 0;
}

.intro-statement {
  margin: 0;
  font: inherit;
  letter-spacing: inherit;
}

.intro-toggle {
  display: inline-grid;
  place-items: center;
  width: clamp(20px, 4.6vw, 25px);
  height: clamp(20px, 4.6vw, 25px);
  margin: 0 0 0.06em 0.3em;
  vertical-align: middle;
  border: 1.5px solid currentColor;
  border-radius: 999px;
  background: transparent;
  padding: 0;
  color: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color 160ms ease, color 160ms ease, transform 120ms ease;
}

.intro-toggle:hover {
  background: var(--ink);
  color: var(--paper);
}

.intro-toggle:active {
  transform: scale(0.9);
}

.intro-toggle:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

.intro-toggle-icon {
  position: relative;
  width: 40%;
  height: 40%;
}

.intro-toggle-icon::before,
.intro-toggle-icon::after {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  background: currentColor;
  border-radius: 1px;
}

.intro-toggle-icon::before {
  width: 100%;
  height: 1.5px;
}

.intro-toggle-icon::after {
  width: 1.5px;
  height: 100%;
  transition: transform 200ms cubic-bezier(0.4, 0, 0.2, 1);
}

.intro-toggle[aria-expanded="true"] .intro-toggle-icon::after {
  transform: rotate(90deg);
}

.post-office {
  font-family: "Bagoss Condensed", Impact, sans-serif;
  font-weight: 500;
  white-space: nowrap;
}

.real-review {
  font-family: "Gestalt", Arial, sans-serif;
  font-size: 0.92em;
  white-space: nowrap;
}

/* Expanded intro: full-width light-grey rules bracket a three-column top row
   (bio · contacts · portrait) and a horizontally scrolling client list. */
.intro-more {
  margin-top: clamp(20px, 5vw, 26px);
  /* Break out of the intro copy's gutter so the rules span the full stage. */
  margin-inline: calc(-1 * var(--gutter));
}

.intro-rule {
  height: 1px;
  /* Equal gutter margins so the rule's left edge lines up with the start of
     the thumbnails (and the intro copy). */
  margin: 0 var(--gutter);
  background: var(--rail-gray);
}

/* Base (mobile) top row: identity + portrait share the first line, the note
   spans the second — so the square portrait sits above the note at the identity
   block's height. Desktop moves the portrait to the far right (see below). */
.intro-top {
  display: grid;
  /* identity flexes to fill, portrait is a fixed square on mobile so it can't
     squeeze the identity onto extra lines. */
  grid-template-columns: 1fr auto;
  grid-template-areas:
    "identity portrait"
    "note portrait"
    "clients clients";
  column-gap: 16px;
  row-gap: 12px;
  align-items: start;
  padding: clamp(16px, 4vw, 22px) var(--gutter);
  font-size: clamp(15px, 4.3vw, 18px);
  line-height: 1.4;
}

.intro-identity {
  grid-area: identity;
  /* Keep the identity block on its four <br> lines. */
  white-space: nowrap;
}

.intro-identity p {
  margin: 0;
}

.intro-bio-note {
  grid-area: note;
  color: rgba(0, 0, 0, 0.55);
}

.intro-bio-note p {
  margin: 0;
}

.intro-bio-note p + p {
  margin-top: 10px;
}

/* email · ig · newsletter as one horizontal line under the client list. */
.intro-contact {
  display: flex;
  align-items: baseline;
  gap: 0.5em;
  padding: clamp(12px, 3.5vw, 18px) var(--gutter);
  font-size: clamp(15px, 4.3vw, 18px);
  white-space: nowrap;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scrollbar-width: none;
}

.intro-contact::-webkit-scrollbar {
  display: none;
}

.intro-sep {
  color: rgba(0, 0, 0, 0.4);
}

/* The collapse toggle sits at the far right of the contacts line when open. */
.intro-contact .intro-toggle {
  margin: 0 0 0 auto;
  align-self: center;
}

.intro-contact a {
  position: relative;
}

.intro-contact a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.08em;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 180ms ease;
}

.intro-contact a:hover::after,
.intro-contact a:focus-visible::after {
  transform: scaleX(1);
}

.intro-contact a:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

/* Square portrait, sized to the height of the top row. The image is absolutely
   positioned so its intrinsic size can't inflate the row; aspect-ratio derives
   the width from the stretched height. */
.intro-portrait {
  grid-area: portrait;
  align-self: stretch;
  justify-self: start;
  position: relative;
  /* Mobile: fixed narrow width so the identity keeps its four lines; the height
     stretches down to the bottom of the note (which wraps to its left), and the
     square photo is cropped horizontally via cover. */
  width: clamp(76px, 21vw, 96px);
  border-radius: 6px;
  overflow: hidden;
}

/* Absolutely positioned so the image's intrinsic size can't inflate the row;
   the box dimensions are set from JS to match the bio height. */
.intro-portrait img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Auto-scrolling client marquee, sitting beneath the bio/note/photo. Breaks
   out of the intro-top gutter so names scroll fully off the stage edges (no
   inset margin), in line with the OUTPUT/INPUT rails and the footer below. */
.intro-clients {
  grid-area: clients;
  min-width: 0;
  margin-top: 4px;
  margin-inline: calc(-1 * var(--gutter));
  font-size: clamp(15px, 4.3vw, 18px);
  line-height: 1.4;
  color: rgba(0, 0, 0, 0.55);
  white-space: nowrap;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scrollbar-width: none;
}

.intro-clients::-webkit-scrollbar {
  display: none;
}

.intro-clients-run {
  display: inline-block;
  white-space: nowrap;
}

/* Colophon footer: a tiny line pinned to the bottom of the homepage stage that
   auto-scrolls horizontally. Full-bleed to the stage edges (no side gutter) so
   the text runs fully off-frame, matching the rails and the client marquee. */
.site-footer {
  margin-top: auto;
  padding-top: 14px;
}

.footer-marquee {
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  white-space: nowrap;
  scrollbar-width: none;
  font-family: Arial, sans-serif;
  font-size: 11px;
  letter-spacing: 0.06em;
  line-height: 1.4;
  color: rgba(0, 0, 0, 0.42);
}

.footer-marquee::-webkit-scrollbar {
  display: none;
}

.footer-marquee-run {
  display: inline-block;
  white-space: nowrap;
}

.feature-card {
  position: relative;
  width: auto;
  height: 100%;
  min-height: 200px;
  max-height: 420px;
  aspect-ratio: 233 / 306;
  background: var(--ink);
  border: 3px solid var(--ink);
  border-radius: 9px;
  overflow: hidden;
  transition: transform 160ms ease, filter 160ms ease;
}

.feature-card:active {
  transform: scale(0.985);
}

.feature-card img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* Photo/ad thumbnails: script.js sets an inline aspect-ratio from each
   image's natural size once it's known, so the card's width follows the
   actual photo instead of the shared 233:306 frame (different photos then
   run different widths along the rail, no cropping/letterboxing). Doing this
   in JS rather than pure CSS avoids a flexbox quirk: an auto-width flex
   item's content-based size is computed before cross-axis stretch resolves,
   so a percentage-height image inside one can't reliably drive the item's
   width from its intrinsic ratio — it was intermittently sizing to the
   image's full natural pixel width instead. The 233:306 ratio above is just
   the fallback shown before the real ratio is set. Text cards (no image)
   keep the fixed frame. */

.feature-card-text {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 14px;
  background: var(--paper);
  color: var(--ink);
}

.feature-wordmark {
  font-family: "Bagoss Condensed", Impact, sans-serif;
  font-weight: 500;
  font-size: clamp(44px, 13vw, 58px);
  line-height: 0.9;
}

.feature-caption {
  font-family: Arial, sans-serif;
  font-size: 10px;
  line-height: 1.3;
  text-transform: uppercase;
  color: rgba(0, 0, 0, 0.58);
}

.ad-flag {
  position: absolute;
  top: -3px;
  left: -3px;
  z-index: 2;
  display: inline-grid;
  min-width: 39px;
  height: 40px;
  place-items: center;
  background: var(--ink);
  color: var(--paper);
  border-top-left-radius: 9px;
  border-bottom-right-radius: 6px;
  font-size: 20px;
  line-height: 1;
}

/* --- inline OUTPUT expansion --------------------------------------------- */
/* Clicking a card expands it in place: an info panel slides in to its right,
   followed by the project's photos fanned out along the rail. The thumbnail
   toggles it shut (× / Escape also close); then the row scrolls as normal. */
.feature-shot {
  flex: 0 0 auto;
  width: auto;
  height: 100%;
  border-radius: 9px;
  object-fit: cover;
  background: var(--rail-gray);
  animation: feature-info-in 240ms ease both;
}

/* A gallery video embed in the inline rail: same height as the photos beside
   it. Width is set from the video's real aspect ratio once script.js looks
   it up (so the player fills the frame with no grey bars); 16:9 is just the
   fallback before that resolves. */
.feature-video {
  aspect-ratio: 16 / 9;
  border: 0;
}

/* Light-grey divider stripes that bracket an expanded entry — one before the
   thumbnail, one after the photos — marking the project off symmetrically. */
.feature-end {
  flex: 0 0 auto;
  align-self: stretch;
  width: 2px;
  height: 100%;
  margin: 0 10px;
  background: var(--rail-gray);
  border-radius: 2px;
  animation: feature-info-in 240ms ease both;
}

.feature-info {
  position: relative;
  flex: 0 0 auto;
  align-self: stretch;
  min-height: 0;
  width: min(74vw, 320px);
  display: flex;
  flex-direction: column;
  padding: 0 6px 6px 18px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
  animation: feature-info-in 240ms ease both;
}

.feature-info::-webkit-scrollbar {
  display: none;
}

@keyframes feature-info-in {
  from { opacity: 0; transform: translateX(-10px); }
  to { opacity: 1; transform: none; }
}

/* Absolute so it doesn't push the title down — the info block's top then lines
   up with the top of the thumbnail. */
.feature-close {
  position: absolute;
  top: 0;
  right: 4px;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 1px solid currentColor;
  border-radius: 999px;
  background: transparent;
  color: inherit;
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.feature-info h3 {
  margin: 0 34px 8px 0;
  font-family: "Cheltenham Light", Georgia, serif;
  font-weight: 300;
  font-size: clamp(22px, 5.5vw, 28px);
  line-height: 1;
  letter-spacing: 0;
}

.feature-info-meta {
  margin: 0 0 12px;
  font-family: Arial, sans-serif;
  font-size: 10px;
  line-height: 1.3;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, 0.58);
}

.feature-info-copy p {
  margin: 0 0 10px;
  font-family: Arial, sans-serif;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.45;
}

.feature-info .work-link {
  margin-top: 12px;
  align-self: flex-start;
  font-family: Arial, sans-serif;
  font-size: 14px;
  line-height: 1.4;
  white-space: nowrap;
  border-bottom: 1px solid currentColor;
}

.feature-info .work-link::after {
  content: " \2197";
}

.feature-close:focus-visible,
.feature-info .work-link:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .feature-info,
  .feature-shot,
  .feature-end {
    animation: none;
  }
}

.rail {
  position: relative;
  width: 100%;
}

.rail-work {
  flex: 1 1 0;
  /* Don't let the row shrink below one card's height: on a cramped phone the
     cards (min 200px) can't shrink, so a smaller row would overflow onto the
     INPUT row. Holding this floor makes the page scroll instead. */
  min-height: 200px;
  max-height: 420px;
  margin-top: 0;
}

/* MAKING cards fill the track height via flex stretch; the grid's
   max-content column sizing can't derive width from a filled height, so the
   cards would never grow to fill. */
.rail-work .rail-track {
  display: flex;
  align-items: stretch;
  height: 100%;
}

.rail-work .feature-card {
  flex: 0 0 auto;
  height: auto;
  /* Hard safety cap: a card can never be taller than its row, so it can't
     spill onto the INPUT row when the row is squeezed on small screens. */
  max-height: 100%;
}

.rail-feed {
  margin-top: 11px;
}

/* The label overlays the strip between the page edge and the first thumbnail
   (0 → gutter), sitting on top of the track so thumbnails scroll under it.
   No transform/z-index here: that would create a stacking context and stop
   mix-blend-mode from reading the thumbnails behind the word. */
.rail-label {
  position: absolute;
  left: 0;
  bottom: 0;
  width: var(--gutter);
  height: 100%;
  margin: 0;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  pointer-events: none;
}

.rail-label span {
  writing-mode: sideways-lr;
  font-size: 26px;
  font-weight: 300;
  line-height: 1;
  letter-spacing: 0;
  color: #ffffff;
  mix-blend-mode: difference;
}

/* The INPUT label doubles as the door to the archive page. The h2 itself is
   pointer-events: none so the rail scrolls freely; the anchor opts back in. */
.rail-label a {
  pointer-events: auto;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  text-decoration: none;
  color: inherit;
}

.rail-label a:focus-visible {
  outline: 2px solid #ffffff;
  outline-offset: 3px;
  mix-blend-mode: difference;
}

/* MORE closes the rail in the INPUT-label style — same sideways type and
   blend mode — but scrolls with the tiles and links to the archive. */
.rail-more {
  display: flex;
  align-items: flex-end;
  padding: 0 2px;
}

/* Unlike the INPUT label, nothing ever scrolls beneath MORE (it rides with
   the tiles on the paper background), so it uses plain ink — no blend mode.
   iOS composites blend modes inside scroll containers against the scroller
   itself, which made the blended version invisible there. */
.rail-more span {
  writing-mode: sideways-lr;
  font-size: 26px;
  font-weight: 300;
  line-height: 1;
  color: var(--ink);
}

.rail-more:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

.rail-track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: max-content;
  gap: 8px;
  min-width: 0;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  padding: 0 max(var(--gutter), env(safe-area-inset-right)) 0 var(--gutter);
  scroll-padding-inline: var(--gutter);
  scrollbar-width: none;
}

.rail-track::-webkit-scrollbar {
  display: none;
}

.feed-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 4px;
  width: 91px;
  height: 143px;
  padding: 10px;
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 9px;
  background: var(--rail-gray);
  overflow: hidden;
  font-family: Arial, sans-serif;
  font-size: 10px;
  line-height: 1.05;
  transition: transform 160ms ease, border-radius 160ms ease;
}

.rail-track.is-moving .feature-card,
.rail-track.is-moving .feed-tile {
  filter: contrast(1.04);
}

.feed-tile span {
  color: rgba(0, 0, 0, 0.58);
  text-transform: uppercase;
}

.feed-tile strong {
  font-size: 16px;
  font-weight: 700;
}

/* Media items whose artwork couldn't be found fall back to a text tile;
   smaller type lets a full book/album title fit the narrow width. */
.feed-tile strong.fit-title {
  font-size: 12px;
  line-height: 1.2;
  overflow-wrap: break-word;
}

/* Article headlines run long; on narrow screens shrink the tag + title so
   they stay inside the tile instead of cropping at its edge. */
@media (max-width: 699px) {
  .feed-tile.article span {
    font-size: 9px;
  }

  .feed-tile.article strong {
    font-size: 12px;
    line-height: 1.2;
    overflow-wrap: break-word;
  }
}

.feed-tile.dark {
  background: #101010;
  color: #f6f6f6;
}

.feed-tile.dark span {
  color: rgba(255, 255, 255, 0.62);
}

.feed-tile.light {
  background: #f4f1ea;
}

.feed-tile.text-heavy {
  width: 136px;
  background: #eeeeea;
  justify-content: flex-start;
}

.feed-tile.image-backed {
  width: 136px;
  color: #ffffff;
}

.feed-tile.image-backed img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.72);
}

.feed-tile.image-backed span,
.feed-tile.image-backed strong {
  position: relative;
  z-index: 1;
  color: #ffffff;
}

/* Media tiles (movies / tv / books / music): the artwork IS the tile —
   full-bleed, undimmed, no text; clicking links straight out. Posters run
   tall-and-thin at the rail height; album covers are square. Articles keep
   the classic dimmed image-backed treatment with the text always on. */
.feed-tile.media {
  position: relative;
  padding: 0;
}

/* Widths derive from the tile height (which flexes with the viewport), so
   posters stay 2:3 and album covers stay perfectly square at every size —
   no cropping when mobile shrinks the rail. */
.feed-tile.media.poster {
  width: auto;
  aspect-ratio: 2 / 3;
}

.feed-tile.media.cover {
  width: auto;
  aspect-ratio: 1 / 1;
}

.feed-tile.media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.feature-card:focus-visible,
.mark:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

@media (min-width: 700px) {
  :root {
    --gutter: clamp(32px, 3.4vw, 48px);
    --type-lg: clamp(28px, 2.4vw, 40px);
  }

  .panel {
    min-height: 100vh;
  }

  .upper-stage {
    width: 100%;
    max-width: 1440px;
    /* Left-align the capped column (not centered) so on windows wider than the
       cap the content hugs the left edge, matching the mobile layout. */
    margin-left: 0;
    margin-right: auto;
    min-height: 100vh;
    padding: var(--gutter) 0 24px;
  }

  .mark {
    width: clamp(96px, min(9vw, 14svh), 140px);
    margin: 0 clamp(28px, 3vw, 44px) 16px var(--gutter);
  }

  .rail-feed {
    margin-top: 12px;
  }

  .rail-track {
    gap: 12px;
  }

  /* Same fill behavior as the base rule (flex: 1 filling the leftover space),
     just a larger cap so desktop cards can grow bigger before topping out. */
  .rail-work {
    min-height: 220px;
    max-height: 560px;
  }

  .feature-card {
    width: auto;
    height: 100%;
    min-height: 220px;
    max-height: 560px;
    aspect-ratio: 233 / 306;
  }

  .ad-flag {
    min-width: 52px;
    height: 54px;
    font-size: 26px;
  }

  .feature-card-text {
    padding: 20px;
  }

  .feature-wordmark {
    font-size: clamp(56px, 5.6vw, 80px);
  }

  .feature-caption {
    font-size: 12px;
  }

  .feed-tile {
    width: 112px;
    height: clamp(118px, 17svh, 180px);
    padding: 12px;
    font-size: 12px;
  }

  .feed-tile strong {
    font-size: 18px;
  }

  .feed-tile.text-heavy,
  .feed-tile.image-backed {
    width: 168px;
  }

  /* Desktop: portrait spans the full bio (identity + note) on the far right. */
  .intro-top {
    grid-template-columns: minmax(0, 340px) 1fr auto;
    grid-template-areas:
      "identity . portrait"
      "note . portrait"
      "clients clients clients";
    column-gap: clamp(20px, 4vw, 48px);
  }

  /* Release the fixed mobile width; sizeIntroPortrait() sets it from the
     stretched height instead. */
  .intro-portrait {
    width: auto;
  }
}

@media (max-width: 699px) {
  /* Mobile: cards get a definite, viewport-proportional height instead of
     flex-filling the row. The desktop flex-fill relies on a percentage/stretch
     height chain that iOS Safari resolves inconsistently, letting a card grow
     taller than its row and overlap the INPUT row below. A definite height
     can't overflow, so the rows always stack cleanly (the page scrolls if the
     content is taller than the viewport). */
  .rail-work {
    flex: 0 0 auto;
    --card-h: min(46svh, 330px);
  }

  .rail-work .rail-track {
    align-items: flex-end;
    height: auto;
  }

  .rail-work .feature-card {
    height: var(--card-h);
    max-height: none;
  }

  /* The info panel matches the card's definite mobile height so it can never
     grow the row and overlap the INPUT rail below (see the note above). */
  .feature-info {
    height: var(--card-h);
    align-self: flex-end;
    width: min(64vw, 260px);
  }

  .feature-shot,
  .feature-end {
    height: var(--card-h);
    align-self: flex-end;
  }
}

@media (max-width: 699px) and (max-height: 860px) {
  .rail-work {
    --card-h: min(274px, 33svh);
  }

  .feed-tile {
    height: 124px;
  }
}

@media (max-width: 699px) and (max-height: 700px) {
  :root {
    --type-lg: clamp(23px, 6vw, 27px);
  }

  .upper-stage {
    padding-top: 22px;
  }

  .mark {
    width: clamp(72px, 22vw, 92px);
  }

  .rail-work {
    --card-h: min(218px, 31svh);
  }

  .feature-card {
    width: clamp(178px, 50vw, 214px);
  }

  .feed-tile {
    width: 82px;
    height: 106px;
  }

  .feed-tile.text-heavy,
  .feed-tile.image-backed {
    width: 124px;
  }

  .rail-feed {
    margin-top: 9px;
  }
}

.work-page {
  background: var(--paper);
  color: var(--ink);
}

/* Mirrors .upper-stage: a centered column on mobile, full-width on desktop.
   The text block is left-aligned within the gutter; the photo carousel bleeds
   to the stage edges and scrolls sideways, echoing the homepage rails. */
.work-detail {
  display: flex;
  flex-direction: column;
  width: min(100vw, 520px);
  min-height: 100svh;
  margin: 0 auto;
  padding: 24px 0 max(42px, env(safe-area-inset-bottom));
}

.back-link {
  align-self: flex-start;
  margin: 0 var(--gutter) 20px;
  font-family: Arial, sans-serif;
  font-size: 13px;
  letter-spacing: 0.02em;
}

.back-link::before {
  content: "\2190\00a0";
}

.work-detail h1 {
  margin: 0 var(--gutter) 8px;
  font-size: var(--type-lg);
  font-weight: 300;
  line-height: var(--line-tight);
  letter-spacing: 0;
}

.work-detail .work-meta {
  margin: 0 var(--gutter) 22px;
  font-family: Arial, sans-serif;
  font-size: 11px;
  line-height: 1.3;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, 0.58);
}

.work-copy {
  margin: 0 var(--gutter) clamp(26px, 6vw, 40px);
  max-width: 34em;
}

.work-copy p {
  margin: 0 0 14px;
  font-family: Arial, sans-serif;
  font-size: 18px;
  font-weight: 400;
  line-height: 1.5;
}

.work-copy p:last-child {
  margin-bottom: 0;
}

.work-link {
  display: inline-block;
  font-family: Arial, sans-serif;
  font-size: 18px;
  line-height: 1.5;
  white-space: nowrap;
  border-bottom: 1px solid currentColor;
}

.work-link::after {
  content: " \2197";
}

/* Photo carousel — bleeds to the stage edges and scrolls horizontally,
   sitting at the bottom of the first viewport like the homepage rails. */
.work-gallery {
  display: flex;
  gap: 10px;
  margin-top: auto;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  padding: 0 max(var(--gutter), env(safe-area-inset-right)) 0 var(--gutter);
  scroll-padding-inline: var(--gutter);
  scrollbar-width: none;
}

.work-gallery::-webkit-scrollbar {
  display: none;
}

.work-gallery img {
  flex: 0 0 auto;
  width: auto;
  height: min(52svh, 440px);
  border-radius: 10px;
  object-fit: cover;
  background: var(--rail-gray);
}

.work-gallery .work-video {
  flex: 0 0 auto;
  width: auto;
  height: min(52svh, 440px);
  aspect-ratio: 16 / 9;
  border-radius: 10px;
  overflow: hidden;
  background: var(--rail-gray);
}

.work-gallery .work-video iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

.work-gallery .work-hero-text {
  flex: 0 0 auto;
  display: flex;
  align-items: flex-end;
  width: auto;
  height: min(52svh, 440px);
  aspect-ratio: 233 / 306;
  padding: 18px;
  border: 3px solid var(--ink);
  border-radius: 10px;
  font-family: "Bagoss Condensed", Impact, sans-serif;
  font-weight: 500;
  font-size: clamp(56px, 15vw, 88px);
  line-height: 0.9;
}

.work-page .work-meta a:focus-visible,
.work-page .back-link:focus-visible,
.work-page .work-link:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

/* --- INPUT archive page --------------------------------------------------- */
/* Reached from the INPUT rail label. Reuses the feed-tile look in a wrapping
   grid, grouped under month headings with category filter chips up top. */
.archive-page {
  background: var(--paper);
  color: var(--ink);
}

.archive {
  display: flex;
  flex-direction: column;
  width: min(100vw, 980px);
  min-height: 100svh;
  margin: 0 auto;
  padding: 24px 0 max(42px, env(safe-area-inset-bottom));
}

.archive h1 {
  margin: 0 var(--gutter) 18px;
  font-size: var(--type-lg);
  font-weight: 300;
  line-height: var(--line-tight);
  letter-spacing: 0;
}

.archive .back-link:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

.archive-controls {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0 0 26px;
}

.archive-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0 var(--gutter);
}

.archive-filters button {
  font-family: Arial, sans-serif;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 6px 12px;
  border: 1px solid rgba(0, 0, 0, 0.22);
  border-radius: 999px;
  background: transparent;
  color: inherit;
  cursor: pointer;
}

.archive-filters button.is-active {
  background: #101010;
  border-color: #101010;
  color: #ffffff;
}

.archive-filters button:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

/* Live tally of how many items the active category/year filters leave on view. */
.archive-count {
  margin: 2px var(--gutter) 0;
  font-family: Arial, sans-serif;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: rgba(0, 0, 0, 0.5);
}

.archive-month {
  margin: 6px var(--gutter) 12px;
  font-family: Arial, sans-serif;
  font-size: 11px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: rgba(0, 0, 0, 0.5);
}

.archive-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 var(--gutter) 30px;
}

.archive-grid .feed-tile {
  flex: 0 0 auto;
}

.archive-grid .feed-tile:focus-visible {
  outline: 2px solid #101010;
  outline-offset: 2px;
}

.archive-empty {
  margin: 0 var(--gutter);
  font-family: Arial, sans-serif;
  font-size: 13px;
  color: rgba(0, 0, 0, 0.5);
}

/* List view: one compact row per item — thumb, title/subtitle, type, date. */
.archive-list {
  display: flex;
  flex-direction: column;
  margin: 0 var(--gutter) 30px;
}

.archive-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 0;
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  font-family: Arial, sans-serif;
  font-size: 13px;
}

.archive-row-thumb {
  flex: 0 0 auto;
  width: 32px;
  height: 44px;
  border-radius: 4px;
  object-fit: cover;
  background: var(--rail-gray);
}

.archive-row-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.archive-row-main strong {
  font-size: 14px;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.archive-row-main em {
  font-style: normal;
  font-size: 12px;
  color: rgba(0, 0, 0, 0.5);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.archive-row-type {
  flex: 0 0 auto;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: rgba(0, 0, 0, 0.5);
}

.archive-row-date {
  flex: 0 0 auto;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: rgba(0, 0, 0, 0.5);
}

.archive-row:focus-visible {
  outline: 2px solid #101010;
  outline-offset: 2px;
}

/* Desktop work-page overrides live here (after the base .work-detail rules)
   rather than in the shared min-width block above: media queries don't add
   specificity, so a later same-specificity rule would otherwise win. */
@media (min-width: 700px) {
  .work-detail {
    width: 100%;
    max-width: 1440px;
    margin-left: 0;
    margin-right: auto;
    min-height: 100vh;
    padding: var(--gutter) 0 28px;
  }

  .work-copy {
    max-width: 620px;
  }

  .work-copy p,
  .work-link {
    font-size: 19px;
  }

  .work-gallery img,
  .work-gallery .work-video,
  .work-gallery .work-hero-text {
    height: min(64svh, 620px);
  }

  .work-gallery .work-hero-text {
    font-size: clamp(72px, 7vw, 104px);
  }
}
