:root {
  --white: #f2ede2;   /* unbleached paper */
  --black: #171512;   /* wet ink */
  --dark: #221f1b;
  --paper-deep: #e9e2d3;
  --reveal: #d1ddd3;
  --mediate: #fe7141;
  --translate: #cdabfe;
  --reveal-wash: #eef3ef;
  --mediate-wash: #fff1ea;
  --translate-wash: #f4edff;
  --line: rgba(23, 21, 18, 0.22);
  --line-invert: rgba(242, 237, 226, 0.24);
  --max: 1320px;
  --ease: cubic-bezier(0.455, 0.03, 0.515, 0.955);
  --radius: 0px;
  --mono: "Geist Mono", "JetBrains Mono", ui-monospace, monospace;
  --sans: "Geist Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  font-family: var(--sans);
  color: var(--black);
  background: var(--white);
  letter-spacing: 0;
}

body.is-ready {
  opacity: 1;
  transition: opacity 360ms ease;
}

body.page-exit {
  opacity: 0;
  transition: opacity 180ms ease;
}

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

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

p {
  font-size: 16px;
  line-height: 1.62;
  margin: 0;
}

.eyebrow,
.mono,
.tag,
.meta-grid,
.button,
.nav-link,
.section-number,
.card-meta,
.footer {
  font-family: var(--mono);
  letter-spacing: 0;
}

.brand-mark {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border: 1px solid currentColor;
  font-family: var(--mono);
  font-size: 11px;
}

.section {
  padding: 88px 24px;
}

.section-inner {
  max-width: var(--max);
  margin: 0 auto;
}

.hero {
  min-height: 100vh;
  display: flex;
  align-items: flex-end;
  padding-top: 132px;
  position: relative;
  overflow: hidden;
}

/* Drifting cloud field in the three verb colours, with a halftone screen over it.
   Three large soft radial blooms move on slow, differently-timed loops so they never
   repeat the same arrangement. */
.hero:before {
  content: "";
  position: absolute;
  inset: -12%;
  pointer-events: none;
  background:
    radial-gradient(38% 44% at 22% 30%, rgba(205, 171, 254, 0.72), transparent 68%),
    radial-gradient(42% 38% at 74% 26%, rgba(254, 113, 65, 0.5), transparent 66%),
    radial-gradient(46% 46% at 52% 76%, rgba(209, 221, 211, 0.85), transparent 70%);
  filter: blur(48px) saturate(1.15);
  animation: cloud-drift 34s ease-in-out infinite alternate;
  mask-image: linear-gradient(to bottom, black 8%, transparent 82%);
}

.hero:after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: radial-gradient(circle at center, rgba(254, 113, 65, 0.34) 1.1px, transparent 1.7px);
  background-size: 6px 6px;
  mask-image: linear-gradient(to bottom, black, transparent 72%);
}

@keyframes cloud-drift {
  0% {
    transform: translate3d(0, 0, 0) scale(1);
  }
  33% {
    transform: translate3d(3%, -2.5%, 0) scale(1.08);
  }
  66% {
    transform: translate3d(-2.5%, 2%, 0) scale(1.04);
  }
  100% {
    transform: translate3d(1.5%, 3%, 0) scale(1.11);
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero:before {
    animation: none;
  }
}

.hero-grid {
  position: relative;
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: 72px;
  align-items: end;
  width: 100%;
}

.hero h1,
.case-hero h1 {
  margin: 0;
  max-width: 15ch;
  font-size: clamp(52px, 8.5vw, 132px);
  line-height: 0.9;
  font-weight: 800;
  letter-spacing: -0.035em;
}

.hero-copy {
  display: grid;
  gap: 26px;
  max-width: 680px;
  padding-bottom: 10px;
}

.hero-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 140px));
  gap: 28px;
  border-top: 1px solid var(--line);
  padding-top: 18px;
}

.stat {
  padding: 0;
}

.stat strong {
  display: block;
  font-size: clamp(26px, 2.8vw, 40px);
  line-height: 1;
  font-weight: 300;
}

.stat span {
  display: block;
  margin-top: 8px;
  font-family: var(--mono);
  font-size: 11px;
  text-transform: uppercase;
}

.tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.tag {
  border: 1px solid currentColor;
  border-radius: 0;
  padding: 8px 10px;
  font-size: 12px;
  line-height: 1;
  text-transform: uppercase;
}

/* Filled tags carry their own edge through colour. The extra outline was making
   every chip read as a form field. */
.tag.reveal,
.tag.mediate,
.tag.translate,
.tag.synthesis {
  border-color: transparent;
  color: var(--black);
}

.tag.reveal {
  background: var(--reveal);
}

.tag.mediate {
  background: var(--mediate);
}

.tag.translate {
  background: var(--translate);
}

.tag.synthesis {
  background: var(--black);
  color: var(--white);
}

.scroll-cue {
  position: absolute;
  bottom: 28px;
  left: 24px;
  font-family: var(--mono);
  font-size: 12px;
  text-transform: uppercase;
}

/* Splash. Three phrases arrive a beat apart, the group lifts, the second line
   answers it, then the whole thing clears to the page. */
.splash {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: 40px 24px;
  background: var(--white);
  transition: opacity 900ms ease, visibility 900ms;
}

.splash.is-done {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.splash:before {
  content: "";
  position: absolute;
  inset: -12%;
  pointer-events: none;
  background:
    radial-gradient(38% 44% at 24% 32%, rgba(205, 171, 254, 0.6), transparent 68%),
    radial-gradient(42% 38% at 76% 28%, rgba(254, 113, 65, 0.42), transparent 66%),
    radial-gradient(46% 46% at 50% 74%, rgba(209, 221, 211, 0.7), transparent 70%);
  filter: blur(56px) saturate(1.1);
  animation: cloud-drift 34s ease-in-out infinite alternate;
}

.splash-bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
  z-index: 0;
}

.splash-inner {
  position: relative;
  z-index: 1;
  display: grid;
  gap: 30px;
  max-width: 900px;
  text-align: left;
  transition: transform 1000ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

.splash-inner.lifted {
  transform: translateY(-46px);
}

.splash-line {
  margin: 0;
  font-size: clamp(24px, 3vw, 42px);
  line-height: 1.28;
  font-weight: 300;
  letter-spacing: -0.01em;
  color: var(--black);
  text-shadow: 0 1px 22px rgba(255, 255, 255, 0.5);
}

.splash-second {
  font-size: clamp(17px, 1.7vw, 24px);
  font-weight: 300;
  font-style: italic;
  line-height: 1.4;
  color: rgba(0, 0, 0, 0.82);
  opacity: 0;
  transition: opacity 500ms ease;
}

.splash-second.is-shown {
  opacity: 1;
}

.splash-phrase {
  display: block;
}

.splash-second .splash-phrase {
  display: inline;
}

.splash-skip {
  position: absolute;
  z-index: 2;
  right: 26px;
  bottom: 24px;
  border: 1px solid var(--line);
  background: transparent;
  color: rgba(0, 0, 0, 0.6);
  padding: 9px 14px;
  font-family: var(--mono);
  font-size: 11px;
  text-transform: uppercase;
  cursor: pointer;
}

.splash-skip:hover {
  border-color: currentColor;
  color: var(--black);
}

body.splash-active {
  overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {
  .splash:before {
    animation: none;
  }
  .splash-inner {
    transition: none;
  }
}

/* LineNav. The horizontal line menu, and the only navigation on the page.
   --effect (0..1) is eased per item by the rAF loop in script.js, so label colour,
   vertical shift and tick height all read the same continuously-animating value. */
.line-nav {
  --accent-color: var(--mediate);
  --text-color: rgba(0, 0, 0, 0.5);
  --marker-color: rgba(0, 0, 0, 0.2);
  --tick-height: 14px;
  --max-shift: 5px;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  padding: 20px 30px 16px;
  opacity: 0;
  transform: translateY(-8px);
  pointer-events: none;
  transition: opacity 420ms ease, transform 420ms ease, color 400ms ease;
}

/* Arrives once the reader starts moving, so the opening screen stays clean. */
.line-nav.is-visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.line-nav.on-dark {
  --text-color: rgba(255, 255, 255, 0.62);
  --marker-color: rgba(255, 255, 255, 0.28);
}

.line-nav__brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--mono);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: color-mix(in srgb, var(--text-color) 100%, transparent);
  flex: 0 0 auto;
}

.line-nav.on-dark .line-nav__brand {
  color: rgba(255, 255, 255, 0.9);
}

.line-nav__brand .brand-mark {
  width: 30px;
  height: 30px;
  font-size: 11px;
}

.line-sidebar__list {
  list-style: none;
  margin: 0;
  padding: 0;
  width: 100%;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  align-items: start;
}

.line-sidebar__item {
  position: relative;
  cursor: pointer;
  padding-top: 16px;
  padding-right: 24px;
}

.line-sidebar__item::before {
  content: "";
  position: absolute;
  inset: -8px -20px;
}

.line-sidebar__label {
  position: relative;
  display: inline-flex;
  align-items: baseline;
  font-family: var(--mono);
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  line-height: 1.2;
  color: color-mix(in srgb, var(--accent-color) calc(var(--effect, 0) * 100%), var(--text-color));
  transform: translateY(calc(var(--effect, 0) * var(--max-shift)));
}

.line-sidebar__index {
  margin-right: 7px;
  font-size: 0.85em;
  opacity: calc(0.45 + var(--effect, 0) * 0.55);
}

/* Vertical tick above each label, growing as the cursor nears it. */
.line-sidebar__marker {
  position: absolute;
  top: 0;
  left: 0;
  width: 26px;
  height: 1px;
  background-color: color-mix(in srgb, var(--accent-color) calc(var(--effect, 0) * 100%), var(--marker-color));
  transform-origin: left center;
  transform: scaleX(calc(1 + var(--effect, 0) * 1.4));
}

/* Half-height tick sitting in the gap between two items. */


.line-nav.case-nav {
  justify-content: space-between;
  gap: 24px;
}

.line-nav__link {
  font-family: var(--mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--text-color);
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  transition: color 220ms ease, border-color 220ms ease;
}

.line-nav__link:hover {
  color: var(--accent-color);
  border-bottom-color: var(--accent-color);
}

@media (max-width: 720px) {
  .line-nav {
    gap: 18px;
    padding: 14px 16px 12px;
  }

  .line-nav__name {
    display: none;
  }

  .line-sidebar__list {
    grid-template-columns: repeat(2, 1fr);
    row-gap: 12px;
  }
}

/* BlurText. Three-stage arrival per word: blur 10px at zero opacity and offset,
   through a half-resolved midpoint, to sharp. Staggered per word by --bt-delay. */
.hero-verse {
  max-width: 30ch;
  font-size: clamp(19px, 1.6vw, 24px);
  line-height: 1.45;
  font-style: italic;
  color: rgba(0, 0, 0, 0.72);
}

.blur-text .bt-word {
  display: inline-block;
  opacity: 0;
  will-change: transform, filter, opacity;
}

.blur-text.is-lit .bt-word {
  animation: blur-text-in 0.7s cubic-bezier(0.22, 0.61, 0.36, 1) both;
  animation-delay: var(--bt-delay, 0ms);
}

.blur-text.from-top .bt-word {
  --bt-from-y: -50px;
  --bt-mid-y: 5px;
}

.blur-text.from-bottom .bt-word {
  --bt-from-y: 50px;
  --bt-mid-y: -5px;
}

@keyframes blur-text-in {
  0% {
    filter: blur(10px);
    opacity: 0;
    transform: translateY(var(--bt-from-y, -50px));
  }
  50% {
    filter: blur(5px);
    opacity: 0.5;
    transform: translateY(var(--bt-mid-y, 5px));
  }
  100% {
    filter: blur(0);
    opacity: 1;
    transform: translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .blur-text.is-lit .bt-word {
    animation: none;
  }
}

/* Blur highlight. The opening statement arrives out of focus and resolves word by
   word, so the sentence is read rather than skimmed. Key words carry an accent
   highlight that sweeps in behind them as they land. */
.blur-highlight .bh-word {
  display: inline-block;
  filter: blur(9px);
  opacity: 0.25;
  transform: translateY(0.14em);
  transition: filter 620ms cubic-bezier(0.22, 0.61, 0.36, 1), opacity 620ms ease, transform 620ms ease;
  transition-delay: var(--bh-delay, 0ms);
}

.blur-highlight.is-lit .bh-word {
  filter: blur(0);
  opacity: 1;
  transform: translateY(0);
}

.blur-highlight .bh-key {
  position: relative;
  padding: 0 0.08em;
}

.blur-highlight .bh-key::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0.02em;
  height: 0.44em;
  z-index: -1;
  background: var(--bh-accent, var(--mediate));
  opacity: 0;
  transform: scaleX(0.15);
  transform-origin: left center;
  transition: transform 540ms cubic-bezier(0.22, 0.61, 0.36, 1), opacity 540ms ease;
  transition-delay: calc(var(--bh-delay, 0ms) + 240ms);
}

.blur-highlight.is-lit .bh-key::after {
  opacity: 0.55;
  transform: scaleX(1);
}

@media (prefers-reduced-motion: reduce) {
  .blur-highlight .bh-word,
  .blur-highlight .bh-key::after {
    transition: none;
    filter: none;
    opacity: 1;
    transform: none;
  }
}

.section-kicker {
  display: grid;
  grid-template-columns: 90px minmax(0, 1fr);
  border-top: 1px solid currentColor;
  padding-top: 22px;
  gap: 24px;
  align-items: end;
  margin-bottom: 44px;
  border-bottom: 1px solid currentColor;
  padding-bottom: 18px;
}

.section-number {
  font-size: 12px;
}

.section-title {
  margin: 0;
  font-size: clamp(34px, 4.6vw, 68px);
  line-height: 0.94;
  font-weight: 800;
  letter-spacing: -0.03em;
}

/* Featured Case is a full colour field, in Chula's own Reveal colour. It also keeps
   two black sections (Work, About) from running into each other. */
.featured {
  background: var(--reveal);
  color: var(--black);
}

.featured-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(320px, 0.75fr);
  gap: 48px;
  align-items: center;
}

.image-frame {
  position: relative;
  border: 1px solid currentColor;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--dark);
}

.image-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Same processing language as the project cards, at hero scale. */
.image-frame.halftone::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background-image: radial-gradient(circle at center, rgba(255, 255, 255, 0.3) 1px, transparent 1.8px);
  background-size: 6px 6px;
  mix-blend-mode: overlay;
  opacity: 0.4;
  transition: opacity 700ms ease;
}

.image-frame.halftone:hover::after {
  opacity: 0;
}

.scan {
  filter: saturate(0.6) contrast(1.04);
  transition: filter 700ms ease, transform 700ms ease;
}

.image-frame:hover .scan {
  filter: none;
  transform: scale(1.015);
}

.featured .image-frame {
  min-height: 520px;
}

.featured-copy {
  display: grid;
  gap: 24px;
}

.featured-copy h2,
.case-section h2,
.about h2 {
  margin: 0;
  font-size: clamp(23px, 2.4vw, 34px);
  line-height: 1.14;
  font-weight: 400;
  letter-spacing: -0.008em;
}

.button {
  display: inline-flex;
  width: fit-content;
  align-items: center;
  gap: 10px;
  border: 1px solid currentColor;
  border-radius: var(--radius);
  padding: 12px 18px;
  text-transform: uppercase;
  font-size: 12px;
  font-weight: 500;
  transition: transform 0.3s var(--ease), background 0.3s var(--ease), color 0.3s var(--ease), box-shadow 0.3s var(--ease);
}

.button.dark {
  color: var(--black);
  background: var(--white);
}

.button.light {
  color: var(--white);
  background: var(--black);
}

.button:hover {
  transform: translateY(-2px);
}

.button .arrow,
.button span[aria-hidden] {
  transition: transform 0.3s var(--ease);
}

.button:hover span[aria-hidden] {
  transform: translateX(3px);
}

.work {
  background: var(--black);
  color: var(--white);
}

.work-tools {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 24px;
}

.filter-button {
  border: 1px solid var(--line-invert);
  border-radius: 0;
  background: transparent;
  color: var(--white);
  padding: 9px 12px;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 0.3s var(--ease), color 0.3s var(--ease), border-color 0.3s var(--ease);
}

.filter-button.is-active,
.filter-button:hover {
  background: var(--white);
  color: var(--black);
}

/* Waterfall, three tiers of support.
   Base: CSS multi-column, a true waterfall in every browser shipping today.
   Upgrade 1: grid-template-rows: masonry (older masonry spec).
   Upgrade 2: display: grid-lanes (the shipped spec, Safari 26 first). */
.work-grid {
  columns: 3;
  column-gap: 18px;
}

@supports (grid-template-rows: masonry) {
  .work-grid {
    columns: auto;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(24ch, 1fr));
    grid-template-rows: masonry;
    gap: 18px;
  }
}

@supports (display: grid-lanes) {
  .work-grid {
    columns: auto;
    display: grid-lanes;
    grid-template-columns: repeat(auto-fill, minmax(24ch, 1fr));
    gap: 18px;
  }
}

.project-card {
  position: relative;
  display: block;
  break-inside: avoid;
  margin-bottom: 18px;
  border: 1px solid var(--line-invert);
  border-top: 4px solid var(--accent, var(--line-invert));
  border-radius: var(--radius);
  background: #080808;
  color: var(--white);
  overflow: hidden;
  transition: transform 0.3s var(--ease), border-color 0.3s var(--ease), opacity 0.3s var(--ease), box-shadow 0.3s var(--ease);
}

.project-card:hover {
}

@supports (grid-template-rows: masonry) {
  .project-card {
    margin-bottom: 0;
  }
}

@supports (display: grid-lanes) {
  .project-card {
    margin-bottom: 0;
  }
}

.project-card:focus-visible {
  outline: 2px solid var(--accent, var(--white));
  outline-offset: 4px;
}

/* The category chip sits on top of the tinted image, so it has to invert against
   the accent instead of sharing it. */
.project-card::after {
  content: attr(data-label);
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 3;
  border-radius: 0;
  border: 1px solid var(--accent, var(--white));
  background: var(--black);
  color: var(--accent, var(--white));
  padding: 7px 9px;
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1;
  text-transform: uppercase;
}

.project-card.is-muted {
  display: none;
}

/* Media keeps its own proportions, which is what gives the column its rhythm. The
   one exception is the flagship: a 16:9 clip at column width is short, so it gets a
   taller crop to actually lead the grid. */
.project-card.flagship .project-media {
  aspect-ratio: 4 / 3;
}

.project-card.flagship .project-media video,
.project-card.flagship .project-media img {
  height: 100%;
  object-fit: cover;
}

.project-card[data-category*="Reveal"] {
  --accent: var(--reveal);
}

.project-card[data-category*="Mediate"] {
  --accent: var(--mediate);
}

.project-card[data-category*="Translate"] {
  --accent: var(--translate);
}

#liminal-grounds {
  --accent: var(--reveal);
}

/* Duotone halftone. The image loads processed, tinted in its own R/M/T colour and
   screened with a dot grid, then resolves to the real photograph on hover. This is
   the practice's own Reveal verb made literal, and it gives nine source images shot
   under wildly different conditions one shared surface. */
.project-media {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background: #101010;
  border-bottom: 1px solid var(--line-invert);
}

.project-media img,
.project-media video {
  display: block;
  width: 100%;
  height: auto;
  filter: saturate(0.62) contrast(1.02) brightness(1.05);
  transition: filter 620ms ease, transform 620ms ease;
}

/* Colour wash. soft-light keeps the photograph's own midtones instead of crushing
   them onto the accent, which is what made the first version look grim. */
.project-media::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: var(--accent, transparent);
  mix-blend-mode: soft-light;
  opacity: 0.62;
  transition: opacity 620ms ease;
}

/* Dot screen, light enough to read as print texture rather than a scrim. */
.project-media::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background-image: radial-gradient(circle at center, rgba(255, 255, 255, 0.34) 0.85px, transparent 1.5px);
  background-size: 5px 5px;
  mix-blend-mode: overlay;
  opacity: 0.45;
  transition: opacity 620ms ease;
}

.project-media.contain {
  background: #f6f6f4;
}

.project-media.contain img {
  padding: 16px;
}

/* Static covers carry a second frame that cross-fades in on hover, so a card that
   cannot autoplay still answers the cursor. */
.project-media img.swap {
  position: absolute;
  inset: 0;
  height: 100%;
  object-fit: cover;
  opacity: 0;
}

.project-media.contain img.swap {
  object-fit: contain;
}

.project-card:hover .project-media img.swap,
.project-card:focus-visible .project-media img.swap {
  opacity: 1;
}

.project-card:hover .project-media img,
.project-card:hover .project-media video,
.project-card:focus-visible .project-media img,
.project-card:focus-visible .project-media video {
  filter: none;
  transform: scale(1.03);
}

.project-card:hover .project-media::before,
.project-card:hover .project-media::after,
.project-card:focus-visible .project-media::before,
.project-card:focus-visible .project-media::after {
  opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
  .project-media img,
  .project-media video,
  .project-media::before,
  .project-media::after {
    transition: none;
  }
}

.project-body {
  display: grid;
  gap: 14px;
  padding: 20px;
  align-content: start;
}

.project-title-row {
  display: flex;
  align-items: start;
  justify-content: space-between;
  gap: 16px;
  border-bottom: 3px solid var(--accent);
  padding-bottom: 12px;
}

.project-body h3 {
  margin: 0;
  font-size: clamp(19px, 1.7vw, 25px);
  line-height: 1.1;
  font-weight: 400;
}

.project-arrow {
  flex: 0 0 auto;
  font-family: var(--mono);
  font-size: 16px;
  transition: transform 180ms ease;
}

.project-card:hover .project-arrow {
  transform: translateX(6px);
}

.card-link-label {
  width: fit-content;
  margin-top: auto;
  border: 1px solid currentColor;
  padding: 8px 10px;
  font-family: var(--mono);
  font-size: 12px;
  text-transform: uppercase;
}

.detail-content {
  display: grid;
  gap: 16px;
  padding-top: 8px;
}

.detail-content ul,
.case-section ul,
.method-block ul {
  margin: 0;
  padding-left: 18px;
}

.detail-content li,
.case-section li,
.method-block li {
  margin: 8px 0;
  line-height: 1.45;
}

.card-meta {
  display: grid;
  gap: 6px;
  border-top: 1px solid var(--line-invert);
  padding-top: 12px;
  font-size: 12px;
  line-height: 1.35;
}

.mini-gallery {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-bottom: 6px;
}

.mini-gallery img {
  height: 150px;
  min-width: 220px;
  object-fit: cover;
  border: 1px solid var(--line-invert);
  scroll-snap-align: start;
}

.method {
  background: var(--white);
}

.method-layout {
  display: grid;
  grid-template-columns: minmax(240px, 0.35fr) minmax(0, 1fr);
  gap: 56px;
}

.method-intro {
  position: sticky;
  top: 96px;
  align-self: start;
  display: grid;
  gap: 18px;
}

.method-block {
  display: grid;
  gap: 30px;
}

.method-panel {
  border-left: 6px solid var(--accent, var(--black));
  background: var(--wash, transparent);
  padding: 26px 26px 26px 24px;
  display: grid;
  gap: 14px;
}

.method-panel h3,
.move h3 {
  margin: 0;
  font-size: clamp(21px, 2.2vw, 30px);
  line-height: 1.15;
  font-weight: 400;
}

.method-panel.reveal {
  --accent: var(--reveal);
  --wash: var(--reveal-wash);
}

.method-panel.mediate {
  --accent: var(--mediate);
  --wash: var(--mediate-wash);
}

.method-panel.translate {
  --accent: var(--translate);
  --wash: var(--translate-wash);
}

.evidence-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.evidence-links a {
  border: 1px solid var(--line);
  border-radius: 0;
  padding: 8px 11px;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  transition: border-color 0.3s var(--ease), color 0.3s var(--ease);
}

.evidence-links a:hover {
  border-color: currentColor;
  color: var(--accent, currentColor);
}

/* Hairline separators rather than a full box grid. Same information, less cage. */
.moves-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  column-gap: 40px;
  row-gap: 0;
}

.move {
  padding: 24px 0;
  display: grid;
  gap: 10px;
  border-top: 1px solid var(--line);
}

.move .mono {
  color: rgba(0, 0, 0, 0.45);
  font-size: 12px;
}

.about {
  background: var(--black);
  color: var(--white);
}

.about-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(300px, 0.6fr);
  gap: 56px;
}

.contact-list {
  display: grid;
  gap: 1px;
  border: 1px solid var(--line-invert);
  background: var(--line-invert);
}

.contact-list a,
.contact-list span {
  display: block;
  background: var(--black);
  padding: 14px;
  font-family: var(--mono);
  font-size: 13px;
}

/* Portrait field: photographs pinned across a dark ground at varied sizes and
   slight rotations, overlapping rather than queued in a line. */
.portrait-field {
  position: relative;
  margin-top: 64px;
  height: 460px;
  overflow: hidden;
}

.portrait-scatter {
  position: absolute;
  inset: 0;
}

.portrait-scatter img {
  position: absolute;
  top: var(--t);
  left: var(--l);
  width: var(--w);
  height: auto;
  z-index: var(--z);
  transform: rotate(var(--rot));
  filter: grayscale(1) contrast(1.04);
  transition: filter 0.4s var(--ease), transform 0.4s var(--ease), z-index 0s;
}

.portrait-scatter img:hover {
  filter: none;
  transform: rotate(0deg) scale(1.06);
  z-index: 20;
}

@media (max-width: 920px) {
  .portrait-field {
    height: 300px;
  }
  .portrait-scatter img {
    width: calc(var(--w) * 0.6);
  }
}

/* Writing: papers as a list of hairline-separated rows, not cards. */
.writing-list {
  display: grid;
  gap: 0;
  max-width: var(--max);
}

.writing-item {
  display: grid;
  grid-template-columns: 74px minmax(0, 1fr) auto;
  gap: 26px;
  align-items: start;
  padding: 26px 0;
  border-top: 1px solid var(--line);
  transition: opacity 0.3s var(--ease);
}

.writing-item:last-child {
  border-bottom: 1px solid var(--line);
}

.writing-item:hover {
  opacity: 0.62;
}

.writing-item img {
  width: 74px;
  height: auto;
  border: 1px solid var(--line);
}

.writing-item .mono {
  display: block;
  font-family: var(--mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  opacity: 0.55;
  margin-bottom: 8px;
}

.writing-item h3 {
  margin: 0 0 8px;
  font-size: clamp(18px, 1.8vw, 24px);
  line-height: 1.2;
  font-weight: 400;
  max-width: 46ch;
}

.writing-item p {
  max-width: 58ch;
  opacity: 0.72;
}

.writing-arrow {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  opacity: 0.5;
  padding-top: 4px;
}

@media (max-width: 720px) {
  .writing-item {
    grid-template-columns: 56px minmax(0, 1fr);
  }
  .writing-item img {
    width: 56px;
  }
  .writing-arrow {
    display: none;
  }
}

.footer {
  font-family: var(--mono);
  letter-spacing: 0;
}

.brand-mark {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border: 1px solid currentColor;
  font-family: var(--mono);
  font-size: 11px;
}

.section {
  padding: 88px 24px;
}

.section-inner {
  max-width: var(--max);
  margin: 0 auto;
}

.hero {
  min-height: 100vh;
  display: flex;
  align-items: flex-end;
  padding-top: 132px;
  position: relative;
  overflow: hidden;
}

/* Drifting cloud field in the three verb colours, with a halftone screen over it.
   Three large soft radial blooms move on slow, differently-timed loops so they never
   repeat the same arrangement. */
.hero:before {
  content: "";
  position: absolute;
  inset: -12%;
  pointer-events: none;
  background:
    radial-gradient(38% 44% at 22% 30%, rgba(205, 171, 254, 0.72), transparent 68%),
    radial-gradient(42% 38% at 74% 26%, rgba(254, 113, 65, 0.5), transparent 66%),
    radial-gradient(46% 46% at 52% 76%, rgba(209, 221, 211, 0.85), transparent 70%);
  filter: blur(48px) saturate(1.15);
  animation: cloud-drift 34s ease-in-out infinite alternate;
  mask-image: linear-gradient(to bottom, black 8%, transparent 82%);
}

.hero:after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: radial-gradient(circle at center, rgba(254, 113, 65, 0.34) 1.1px, transparent 1.7px);
  background-size: 6px 6px;
  mask-image: linear-gradient(to bottom, black, transparent 72%);
}

@keyframes cloud-drift {
  0% {
    transform: translate3d(0, 0, 0) scale(1);
  }
  33% {
    transform: translate3d(3%, -2.5%, 0) scale(1.08);
  }
  66% {
    transform: translate3d(-2.5%, 2%, 0) scale(1.04);
  }
  100% {
    transform: translate3d(1.5%, 3%, 0) scale(1.11);
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero:before {
    animation: none;
  }
}

.hero-grid {
  position: relative;
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: 72px;
  align-items: end;
  width: 100%;
}

.hero h1,
.case-hero h1 {
  margin: 0;
  max-width: 15ch;
  font-size: clamp(52px, 8.5vw, 132px);
  line-height: 0.9;
  font-weight: 800;
  letter-spacing: -0.035em;
}

.hero-copy {
  display: grid;
  gap: 26px;
  max-width: 680px;
  padding-bottom: 10px;
}

.hero-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 140px));
  gap: 28px;
  border-top: 1px solid var(--line);
  padding-top: 18px;
}

.stat {
  padding: 0;
}

.stat strong {
  display: block;
  font-size: clamp(26px, 2.8vw, 40px);
  line-height: 1;
  font-weight: 300;
}

.stat span {
  display: block;
  margin-top: 8px;
  font-family: var(--mono);
  font-size: 11px;
  text-transform: uppercase;
}

.tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.tag {
  border: 1px solid currentColor;
  border-radius: 0;
  padding: 8px 10px;
  font-size: 12px;
  line-height: 1;
  text-transform: uppercase;
}

/* Filled tags carry their own edge through colour. The extra outline was making
   every chip read as a form field. */
.tag.reveal,
.tag.mediate,
.tag.translate,
.tag.synthesis {
  border-color: transparent;
  color: var(--black);
}

.tag.reveal {
  background: var(--reveal);
}

.tag.mediate {
  background: var(--mediate);
}

.tag.translate {
  background: var(--translate);
}

.tag.synthesis {
  background: var(--black);
  color: var(--white);
}

.scroll-cue {
  position: absolute;
  bottom: 28px;
  left: 24px;
  font-family: var(--mono);
  font-size: 12px;
  text-transform: uppercase;
}

/* Splash. Three phrases arrive a beat apart, the group lifts, the second line
   answers it, then the whole thing clears to the page. */
.splash {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: 40px 24px;
  background: var(--white);
  transition: opacity 900ms ease, visibility 900ms;
}

.splash.is-done {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.splash:before {
  content: "";
  position: absolute;
  inset: -12%;
  pointer-events: none;
  background:
    radial-gradient(38% 44% at 24% 32%, rgba(205, 171, 254, 0.6), transparent 68%),
    radial-gradient(42% 38% at 76% 28%, rgba(254, 113, 65, 0.42), transparent 66%),
    radial-gradient(46% 46% at 50% 74%, rgba(209, 221, 211, 0.7), transparent 70%);
  filter: blur(56px) saturate(1.1);
  animation: cloud-drift 34s ease-in-out infinite alternate;
}

.splash-bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
  z-index: 0;
}

.splash-inner {
  position: relative;
  z-index: 1;
  display: grid;
  gap: 30px;
  max-width: 900px;
  text-align: left;
  transition: transform 1000ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

.splash-inner.lifted {
  transform: translateY(-46px);
}

.splash-line {
  margin: 0;
  font-size: clamp(24px, 3vw, 42px);
  line-height: 1.28;
  font-weight: 300;
  letter-spacing: -0.01em;
  color: var(--black);
  text-shadow: 0 1px 22px rgba(255, 255, 255, 0.5);
}

.splash-second {
  font-size: clamp(17px, 1.7vw, 24px);
  font-weight: 300;
  font-style: italic;
  line-height: 1.4;
  color: rgba(0, 0, 0, 0.82);
  opacity: 0;
  transition: opacity 500ms ease;
}

.splash-second.is-shown {
  opacity: 1;
}

.splash-phrase {
  display: block;
}

.splash-second .splash-phrase {
  display: inline;
}

.splash-skip {
  position: absolute;
  z-index: 2;
  right: 26px;
  bottom: 24px;
  border: 1px solid var(--line);
  background: transparent;
  color: rgba(0, 0, 0, 0.6);
  padding: 9px 14px;
  font-family: var(--mono);
  font-size: 11px;
  text-transform: uppercase;
  cursor: pointer;
}

.splash-skip:hover {
  border-color: currentColor;
  color: var(--black);
}

body.splash-active {
  overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {
  .splash:before {
    animation: none;
  }
  .splash-inner {
    transition: none;
  }
}

/* LineNav. The horizontal line menu, and the only navigation on the page.
   --effect (0..1) is eased per item by the rAF loop in script.js, so label colour,
   vertical shift and tick height all read the same continuously-animating value. */
.line-nav {
  --accent-color: var(--mediate);
  --text-color: rgba(0, 0, 0, 0.5);
  --marker-color: rgba(0, 0, 0, 0.2);
  --tick-height: 14px;
  --max-shift: 5px;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  padding: 20px 30px 16px;
  opacity: 0;
  transform: translateY(-8px);
  pointer-events: none;
  transition: opacity 420ms ease, transform 420ms ease, color 400ms ease;
}

/* Arrives once the reader starts moving, so the opening screen stays clean. */
.line-nav.is-visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.line-nav.on-dark {
  --text-color: rgba(255, 255, 255, 0.62);
  --marker-color: rgba(255, 255, 255, 0.28);
}

.line-nav__brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--mono);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: color-mix(in srgb, var(--text-color) 100%, transparent);
  flex: 0 0 auto;
}

.line-nav.on-dark .line-nav__brand {
  color: rgba(255, 255, 255, 0.9);
}

.line-nav__brand .brand-mark {
  width: 30px;
  height: 30px;
  font-size: 11px;
}

.line-sidebar__list {
  list-style: none;
  margin: 0;
  padding: 0;
  width: 100%;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  align-items: start;
}

.line-sidebar__item {
  position: relative;
  cursor: pointer;
  padding-top: 16px;
  padding-right: 24px;
}

.line-sidebar__item::before {
  content: "";
  position: absolute;
  inset: -8px -20px;
}

.line-sidebar__label {
  position: relative;
  display: inline-flex;
  align-items: baseline;
  font-family: var(--mono);
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  line-height: 1.2;
  color: color-mix(in srgb, var(--accent-color) calc(var(--effect, 0) * 100%), var(--text-color));
  transform: translateY(calc(var(--effect, 0) * var(--max-shift)));
}

.line-sidebar__index {
  margin-right: 7px;
  font-size: 0.85em;
  opacity: calc(0.45 + var(--effect, 0) * 0.55);
}

/* Vertical tick above each label, growing as the cursor nears it. */
.line-sidebar__marker {
  position: absolute;
  top: 0;
  left: 0;
  width: 26px;
  height: 1px;
  background-color: color-mix(in srgb, var(--accent-color) calc(var(--effect, 0) * 100%), var(--marker-color));
  transform-origin: left center;
  transform: scaleX(calc(1 + var(--effect, 0) * 1.4));
}

/* Half-height tick sitting in the gap between two items. */


.line-nav.case-nav {
  justify-content: space-between;
  gap: 24px;
}

.line-nav__link {
  font-family: var(--mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--text-color);
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  transition: color 220ms ease, border-color 220ms ease;
}

.line-nav__link:hover {
  color: var(--accent-color);
  border-bottom-color: var(--accent-color);
}

@media (max-width: 720px) {
  .line-nav {
    gap: 18px;
    padding: 14px 16px 12px;
  }

  .line-nav__name {
    display: none;
  }

  .line-sidebar__list {
    grid-template-columns: repeat(2, 1fr);
    row-gap: 12px;
  }
}

/* BlurText. Three-stage arrival per word: blur 10px at zero opacity and offset,
   through a half-resolved midpoint, to sharp. Staggered per word by --bt-delay. */
.hero-verse {
  max-width: 30ch;
  font-size: clamp(19px, 1.6vw, 24px);
  line-height: 1.45;
  font-style: italic;
  color: rgba(0, 0, 0, 0.72);
}

.blur-text .bt-word {
  display: inline-block;
  opacity: 0;
  will-change: transform, filter, opacity;
}

.blur-text.is-lit .bt-word {
  animation: blur-text-in 0.7s cubic-bezier(0.22, 0.61, 0.36, 1) both;
  animation-delay: var(--bt-delay, 0ms);
}

.blur-text.from-top .bt-word {
  --bt-from-y: -50px;
  --bt-mid-y: 5px;
}

.blur-text.from-bottom .bt-word {
  --bt-from-y: 50px;
  --bt-mid-y: -5px;
}

@keyframes blur-text-in {
  0% {
    filter: blur(10px);
    opacity: 0;
    transform: translateY(var(--bt-from-y, -50px));
  }
  50% {
    filter: blur(5px);
    opacity: 0.5;
    transform: translateY(var(--bt-mid-y, 5px));
  }
  100% {
    filter: blur(0);
    opacity: 1;
    transform: translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .blur-text.is-lit .bt-word {
    animation: none;
  }
}

/* Blur highlight. The opening statement arrives out of focus and resolves word by
   word, so the sentence is read rather than skimmed. Key words carry an accent
   highlight that sweeps in behind them as they land. */
.blur-highlight .bh-word {
  display: inline-block;
  filter: blur(9px);
  opacity: 0.25;
  transform: translateY(0.14em);
  transition: filter 620ms cubic-bezier(0.22, 0.61, 0.36, 1), opacity 620ms ease, transform 620ms ease;
  transition-delay: var(--bh-delay, 0ms);
}

.blur-highlight.is-lit .bh-word {
  filter: blur(0);
  opacity: 1;
  transform: translateY(0);
}

.blur-highlight .bh-key {
  position: relative;
  padding: 0 0.08em;
}

.blur-highlight .bh-key::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0.02em;
  height: 0.44em;
  z-index: -1;
  background: var(--bh-accent, var(--mediate));
  opacity: 0;
  transform: scaleX(0.15);
  transform-origin: left center;
  transition: transform 540ms cubic-bezier(0.22, 0.61, 0.36, 1), opacity 540ms ease;
  transition-delay: calc(var(--bh-delay, 0ms) + 240ms);
}

.blur-highlight.is-lit .bh-key::after {
  opacity: 0.55;
  transform: scaleX(1);
}

@media (prefers-reduced-motion: reduce) {
  .blur-highlight .bh-word,
  .blur-highlight .bh-key::after {
    transition: none;
    filter: none;
    opacity: 1;
    transform: none;
  }
}

.section-kicker {
  display: grid;
  grid-template-columns: 90px minmax(0, 1fr);
  border-top: 1px solid currentColor;
  padding-top: 22px;
  gap: 24px;
  align-items: end;
  margin-bottom: 44px;
  border-bottom: 1px solid currentColor;
  padding-bottom: 18px;
}

.section-number {
  font-size: 12px;
}

.section-title {
  margin: 0;
  font-size: clamp(34px, 4.6vw, 68px);
  line-height: 0.94;
  font-weight: 800;
  letter-spacing: -0.03em;
}

/* Featured Case is a full colour field, in Chula's own Reveal colour. It also keeps
   two black sections (Work, About) from running into each other. */
.featured {
  background: var(--reveal);
  color: var(--black);
}

.featured-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(320px, 0.75fr);
  gap: 48px;
  align-items: center;
}

.image-frame {
  position: relative;
  border: 1px solid currentColor;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--dark);
}

.image-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Same processing language as the project cards, at hero scale. */
.image-frame.halftone::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background-image: radial-gradient(circle at center, rgba(255, 255, 255, 0.3) 1px, transparent 1.8px);
  background-size: 6px 6px;
  mix-blend-mode: overlay;
  opacity: 0.4;
  transition: opacity 700ms ease;
}

.image-frame.halftone:hover::after {
  opacity: 0;
}

.scan {
  filter: saturate(0.6) contrast(1.04);
  transition: filter 700ms ease, transform 700ms ease;
}

.image-frame:hover .scan {
  filter: none;
  transform: scale(1.015);
}

.featured .image-frame {
  min-height: 520px;
}

.featured-copy {
  display: grid;
  gap: 24px;
}

.featured-copy h2,
.case-section h2,
.about h2 {
  margin: 0;
  font-size: clamp(23px, 2.4vw, 34px);
  line-height: 1.14;
  font-weight: 400;
  letter-spacing: -0.008em;
}

.button {
  display: inline-flex;
  width: fit-content;
  align-items: center;
  gap: 10px;
  border: 1px solid currentColor;
  border-radius: var(--radius);
  padding: 12px 18px;
  text-transform: uppercase;
  font-size: 12px;
  font-weight: 500;
  transition: transform 0.3s var(--ease), background 0.3s var(--ease), color 0.3s var(--ease), box-shadow 0.3s var(--ease);
}

.button.dark {
  color: var(--black);
  background: var(--white);
}

.button.light {
  color: var(--white);
  background: var(--black);
}

.button:hover {
  transform: translateY(-2px);
}

.button .arrow,
.button span[aria-hidden] {
  transition: transform 0.3s var(--ease);
}

.button:hover span[aria-hidden] {
  transform: translateX(3px);
}

.work {
  background: var(--black);
  color: var(--white);
}

.work-tools {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 24px;
}

.filter-button {
  border: 1px solid var(--line-invert);
  border-radius: 0;
  background: transparent;
  color: var(--white);
  padding: 9px 12px;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 0.3s var(--ease), color 0.3s var(--ease), border-color 0.3s var(--ease);
}

.filter-button.is-active,
.filter-button:hover {
  background: var(--white);
  color: var(--black);
}

/* Waterfall, three tiers of support.
   Base: CSS multi-column, a true waterfall in every browser shipping today.
   Upgrade 1: grid-template-rows: masonry (older masonry spec).
   Upgrade 2: display: grid-lanes (the shipped spec, Safari 26 first). */
.work-grid {
  columns: 3;
  column-gap: 18px;
}

@supports (grid-template-rows: masonry) {
  .work-grid {
    columns: auto;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(24ch, 1fr));
    grid-template-rows: masonry;
    gap: 18px;
  }
}

@supports (display: grid-lanes) {
  .work-grid {
    columns: auto;
    display: grid-lanes;
    grid-template-columns: repeat(auto-fill, minmax(24ch, 1fr));
    gap: 18px;
  }
}

.project-card {
  position: relative;
  display: block;
  break-inside: avoid;
  margin-bottom: 18px;
  border: 1px solid var(--line-invert);
  border-top: 4px solid var(--accent, var(--line-invert));
  border-radius: var(--radius);
  background: #080808;
  color: var(--white);
  overflow: hidden;
  transition: transform 0.3s var(--ease), border-color 0.3s var(--ease), opacity 0.3s var(--ease), box-shadow 0.3s var(--ease);
}

.project-card:hover {
}

@supports (grid-template-rows: masonry) {
  .project-card {
    margin-bottom: 0;
  }
}

@supports (display: grid-lanes) {
  .project-card {
    margin-bottom: 0;
  }
}

.project-card:focus-visible {
  outline: 2px solid var(--accent, var(--white));
  outline-offset: 4px;
}

/* The category chip sits on top of the tinted image, so it has to invert against
   the accent instead of sharing it. */
.project-card::after {
  content: attr(data-label);
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 3;
  border-radius: 0;
  border: 1px solid var(--accent, var(--white));
  background: var(--black);
  color: var(--accent, var(--white));
  padding: 7px 9px;
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1;
  text-transform: uppercase;
}

.project-card.is-muted {
  display: none;
}

/* Media keeps its own proportions, which is what gives the column its rhythm. The
   one exception is the flagship: a 16:9 clip at column width is short, so it gets a
   taller crop to actually lead the grid. */
.project-card.flagship .project-media {
  aspect-ratio: 4 / 3;
}

.project-card.flagship .project-media video,
.project-card.flagship .project-media img {
  height: 100%;
  object-fit: cover;
}

.project-card[data-category*="Reveal"] {
  --accent: var(--reveal);
}

.project-card[data-category*="Mediate"] {
  --accent: var(--mediate);
}

.project-card[data-category*="Translate"] {
  --accent: var(--translate);
}

#liminal-grounds {
  --accent: var(--reveal);
}

/* Duotone halftone. The image loads processed, tinted in its own R/M/T colour and
   screened with a dot grid, then resolves to the real photograph on hover. This is
   the practice's own Reveal verb made literal, and it gives nine source images shot
   under wildly different conditions one shared surface. */
.project-media {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background: #101010;
  border-bottom: 1px solid var(--line-invert);
}

.project-media img,
.project-media video {
  display: block;
  width: 100%;
  height: auto;
  filter: saturate(0.62) contrast(1.02) brightness(1.05);
  transition: filter 620ms ease, transform 620ms ease;
}

/* Colour wash. soft-light keeps the photograph's own midtones instead of crushing
   them onto the accent, which is what made the first version look grim. */
.project-media::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: var(--accent, transparent);
  mix-blend-mode: soft-light;
  opacity: 0.62;
  transition: opacity 620ms ease;
}

/* Dot screen, light enough to read as print texture rather than a scrim. */
.project-media::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background-image: radial-gradient(circle at center, rgba(255, 255, 255, 0.34) 0.85px, transparent 1.5px);
  background-size: 5px 5px;
  mix-blend-mode: overlay;
  opacity: 0.45;
  transition: opacity 620ms ease;
}

.project-media.contain {
  background: #f6f6f4;
}

.project-media.contain img {
  padding: 16px;
}

/* Static covers carry a second frame that cross-fades in on hover, so a card that
   cannot autoplay still answers the cursor. */
.project-media img.swap {
  position: absolute;
  inset: 0;
  height: 100%;
  object-fit: cover;
  opacity: 0;
}

.project-media.contain img.swap {
  object-fit: contain;
}

.project-card:hover .project-media img.swap,
.project-card:focus-visible .project-media img.swap {
  opacity: 1;
}

.project-card:hover .project-media img,
.project-card:hover .project-media video,
.project-card:focus-visible .project-media img,
.project-card:focus-visible .project-media video {
  filter: none;
  transform: scale(1.03);
}

.project-card:hover .project-media::before,
.project-card:hover .project-media::after,
.project-card:focus-visible .project-media::before,
.project-card:focus-visible .project-media::after {
  opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
  .project-media img,
  .project-media video,
  .project-media::before,
  .project-media::after {
    transition: none;
  }
}

.project-body {
  display: grid;
  gap: 14px;
  padding: 20px;
  align-content: start;
}

.project-title-row {
  display: flex;
  align-items: start;
  justify-content: space-between;
  gap: 16px;
  border-bottom: 3px solid var(--accent);
  padding-bottom: 12px;
}

.project-body h3 {
  margin: 0;
  font-size: clamp(19px, 1.7vw, 25px);
  line-height: 1.1;
  font-weight: 400;
}

.project-arrow {
  flex: 0 0 auto;
  font-family: var(--mono);
  font-size: 16px;
  transition: transform 180ms ease;
}

.project-card:hover .project-arrow {
  transform: translateX(6px);
}

.card-link-label {
  width: fit-content;
  margin-top: auto;
  border: 1px solid currentColor;
  padding: 8px 10px;
  font-family: var(--mono);
  font-size: 12px;
  text-transform: uppercase;
}

.detail-content {
  display: grid;
  gap: 16px;
  padding-top: 8px;
}

.detail-content ul,
.case-section ul,
.method-block ul {
  margin: 0;
  padding-left: 18px;
}

.detail-content li,
.case-section li,
.method-block li {
  margin: 8px 0;
  line-height: 1.45;
}

.card-meta {
  display: grid;
  gap: 6px;
  border-top: 1px solid var(--line-invert);
  padding-top: 12px;
  font-size: 12px;
  line-height: 1.35;
}

.mini-gallery {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-bottom: 6px;
}

.mini-gallery img {
  height: 150px;
  min-width: 220px;
  object-fit: cover;
  border: 1px solid var(--line-invert);
  scroll-snap-align: start;
}

.method {
  background: var(--white);
}

.method-layout {
  display: grid;
  grid-template-columns: minmax(240px, 0.35fr) minmax(0, 1fr);
  gap: 56px;
}

.method-intro {
  position: sticky;
  top: 96px;
  align-self: start;
  display: grid;
  gap: 18px;
}

.method-block {
  display: grid;
  gap: 30px;
}

.method-panel {
  border-left: 6px solid var(--accent, var(--black));
  background: var(--wash, transparent);
  padding: 26px 26px 26px 24px;
  display: grid;
  gap: 14px;
}

.method-panel h3,
.move h3 {
  margin: 0;
  font-size: clamp(21px, 2.2vw, 30px);
  line-height: 1.15;
  font-weight: 400;
}

.method-panel.reveal {
  --accent: var(--reveal);
  --wash: var(--reveal-wash);
}

.method-panel.mediate {
  --accent: var(--mediate);
  --wash: var(--mediate-wash);
}

.method-panel.translate {
  --accent: var(--translate);
  --wash: var(--translate-wash);
}

.evidence-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.evidence-links a {
  border: 1px solid var(--line);
  border-radius: 0;
  padding: 8px 11px;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  transition: border-color 0.3s var(--ease), color 0.3s var(--ease);
}

.evidence-links a:hover {
  border-color: currentColor;
  color: var(--accent, currentColor);
}

/* Hairline separators rather than a full box grid. Same information, less cage. */
.moves-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  column-gap: 40px;
  row-gap: 0;
}

.move {
  padding: 24px 0;
  display: grid;
  gap: 10px;
  border-top: 1px solid var(--line);
}

.move .mono {
  color: rgba(0, 0, 0, 0.45);
  font-size: 12px;
}

.about {
  background: var(--black);
  color: var(--white);
}

.about-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(300px, 0.6fr);
  gap: 56px;
}

.contact-list {
  display: grid;
  gap: 1px;
  border: 1px solid var(--line-invert);
  background: var(--line-invert);
}

.contact-list a,
.contact-list span {
  display: block;
  background: var(--black);
  padding: 14px;
  font-family: var(--mono);
  font-size: 13px;
}

/* Portrait strip. A slow marquee of photographs across the foot of the About
   section, doubled in the markup so the loop has no seam. */
.portrait-strip {
  margin-top: 64px;
  overflow: hidden;
  mask-image: linear-gradient(to right, transparent, black 6%, black 94%, transparent);
}

.portrait-track {
  display: flex;
  gap: 14px;
  width: max-content;
  animation: portrait-scroll 110s linear infinite;
}

.portrait-strip:hover .portrait-track {
  animation-play-state: paused;
}

.portrait-track img {
  height: 220px;
  width: auto;
  object-fit: cover;
  border-radius: 0;
  border: 1px solid var(--line-invert);
  filter: grayscale(1) contrast(1.05);
  transition: filter 500ms ease, transform 500ms ease;
}

.portrait-track img:hover {
  filter: none;
  transform: translateY(-4px);
}

@keyframes portrait-scroll {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .portrait-track {
    animation: none;
  }
}

@media (max-width: 920px) {
  .portrait-track img {
    height: 150px;
  }
}

.footer {
  margin-top: 72px;
  padding-top: 18px;
  border-top: 1px solid var(--line-invert);
  font-size: 12px;
  text-transform: uppercase;
}

.case-hero {
  min-height: 92vh;
  display: grid;
  align-items: end;
  padding-top: 132px;
}

.project-case.reveal {
  --accent: var(--reveal);
}

.project-case.mediate {
  --accent: var(--mediate);
}

.project-case.translate {
  --accent: var(--translate);
}

.project-case .eyebrow,
.project-case .callout {
  border-color: var(--accent);
}

.project-case .callout {
  color: var(--black);
}

.project-hero-image {
  background: var(--paper-deep);
  align-self: center;
}

/* Let the media set the frame's height instead of forcing a tall box around it. */
.project-hero-image video,
.project-hero-image img {
  width: 100%;
  height: auto;
  object-fit: contain;
}

.project-hero-image.cover video,
.project-hero-image.cover img {
  object-fit: contain;
}



.project-hero-image.cover {
  background: var(--black);
}

.case-hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(320px, 0.65fr);
  gap: 54px;
  align-items: end;
}

.case-hero-copy {
  display: grid;
  gap: 22px;
}

.meta-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  font-size: 12px;
}

.meta-grid div {
  background: var(--white);
  padding: 14px;
  min-height: 74px;
}

.meta-grid strong {
  display: block;
  text-transform: uppercase;
  margin-bottom: 6px;
}

.case-section {
  padding: 76px 24px;
}

.case-section.dark {
  background: var(--black);
  color: var(--white);
}

.case-two {
  max-width: var(--max);
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(220px, 0.35fr) minmax(0, 1fr);
  gap: 56px;
}

.case-copy {
  display: grid;
  gap: 22px;
  max-width: 850px;
}

.archive-index {
  display: grid;
  gap: 1px;
  background: var(--line-invert);
  border: 1px solid var(--line-invert);
}

.archive-index article {
  background: var(--black);
  display: grid;
  grid-template-columns: 76px minmax(0, 1fr);
  gap: 22px;
  padding: 20px;
}

.case-gallery {
  display: flex;
  gap: 16px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
}

.case-gallery figure {
  margin: 0;
  min-width: min(720px, 88vw);
  scroll-snap-align: start;
}

.case-gallery img,
.case-gallery video {
  display: block;
  width: 100%;
  height: 460px;
  object-fit: contain;
  background: #f4f4f4;
  border: 1px solid currentColor;
}

.case-gallery video {
  background: #101010;
}

/* Spreads layout: for projects whose evidence is an existing portfolio document.
   One hero, one paragraph, then the spreads laid out full width, stacked, at their
   own proportions. No horizontal scroll, nothing cropped. */
.case-gallery.spreads {
  display: grid;
  grid-template-columns: 1fr;
  gap: 28px;
  overflow: visible;
  scroll-snap-type: none;
  max-width: var(--max);
  margin: 0 auto;
}

.case-gallery.spreads figure {
  min-width: 0;
}

.case-gallery.spreads img {
  width: 100%;
  height: auto;
  object-fit: contain;
  background: transparent;
  border-radius: var(--radius);
  border: 1px solid var(--line);
}

/* Wall: many small artefacts at once, so the quantity is the point. Captions are
   redundant when every tile is the same kind of thing. */
.case-gallery.wall {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 10px;
  overflow: visible;
  scroll-snap-type: none;
  max-width: var(--max);
  margin: 0 auto;
}

.case-gallery.wall figure {
  min-width: 0;
}

.case-gallery.wall img {
  width: 100%;
  height: 190px;
  object-fit: cover;
  border-radius: 0;
  border: 1px solid var(--line);
  background: transparent;
  transition: transform 320ms ease, filter 320ms ease;
}

.case-gallery.wall img:hover {
  transform: scale(1.06);
  z-index: 2;
  position: relative;
}

.case-gallery.wall figcaption {
  display: none;
}

/* Lead media: a full-width opener for projects a film explains faster than prose. */
.lead-media {
  padding-top: 0;
}

.lead-media .case-video video {
  width: 100%;
  max-height: 78vh;
  object-fit: cover;
}

.case-gallery figcaption {
  margin-top: 10px;
  font-family: var(--mono);
  font-size: 12px;
}

/* Full-width video block, for the one walkthrough that carries a whole case. */
.case-video {
  margin: 0;
  max-width: var(--max);
}

.case-video video {
  display: block;
  width: 100%;
  background: #101010;
  border: 1px solid currentColor;
}

.case-video figcaption {
  margin-top: 12px;
  max-width: 720px;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.5;
}

.walkthrough-note {
  margin-top: 20px;
  font-family: var(--mono);
  font-size: 12px;
}

.walkthrough-note a {
  border-bottom: 1px solid currentColor;
}

.image-frame video {
  display: block;
  width: 100%;
  height: auto;
}

/* Table and step blocks for case pages that carry a comparison or a sequence. */
.case-table-wrap {
  max-width: var(--max);
  margin: 0 auto;
  overflow-x: auto;
}

.case-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
  text-align: left;
}

.case-table th {
  font-family: var(--mono);
  font-size: 11px;
  text-transform: uppercase;
  font-weight: 520;
  letter-spacing: 0.02em;
  padding: 0 18px 12px 0;
  border-bottom: 1px solid currentColor;
  white-space: nowrap;
}

.case-table td {
  padding: 16px 18px 16px 0;
  border-bottom: 1px solid var(--line);
  line-height: 1.45;
  vertical-align: top;
}

.case-section.dark .case-table td {
  border-bottom-color: var(--line-invert);
}

.case-table tr td:nth-child(3) {
  font-family: var(--mono);
  font-size: 13px;
  text-transform: uppercase;
  color: var(--accent, currentColor);
  white-space: nowrap;
}

.case-steps {
  max-width: var(--max);
  margin: 0 auto;
  display: grid;
  gap: 0;
}

.case-steps article {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  gap: 24px;
  padding: 26px 0;
  border-top: 1px solid var(--line);
}

.case-section.dark .case-steps article {
  border-top-color: var(--line-invert);
}

.case-steps .mono {
  font-size: 12px;
  opacity: 0.55;
}

.case-steps h3 {
  margin: 0 0 8px;
  font-size: clamp(18px, 1.7vw, 23px);
  line-height: 1.2;
  font-weight: 400;
}

@media (max-width: 720px) {
  .case-steps article {
    grid-template-columns: 1fr;
    gap: 8px;
  }
}

.callout {
  border-left: 4px solid var(--reveal);
  padding-left: 22px;
  font-size: clamp(20px, 2.1vw, 29px);
  line-height: 1.3;
  font-weight: 300;
}

@media (max-width: 1180px) {
  .work-grid {
    columns: 2;
  }
}

@media (max-width: 920px) {
  .hero-grid,
  .featured-layout,
  .method-layout,
  .about-grid,
  .case-hero-grid,
  .case-two {
    grid-template-columns: 1fr;
  }

  .method-intro {
    position: static;
  }

  .work-grid {
    columns: 1;
    grid-template-columns: 1fr;
  }

  .moves-grid,
  .hero-stats,
  .meta-grid {
    grid-template-columns: 1fr;
  }

  .section {
    padding: 86px 18px;
  }

  .featured .image-frame {
    min-height: 320px;
  }
}

@media (max-width: 560px) {
  .hero h1,
  .case-hero h1 {
    font-size: 54px;
  }

  .section-kicker {
    grid-template-columns: 1fr;
  }


  .mini-gallery img {
    min-width: 190px;
  }
}

/* Media sitting inside a section, next to the claim it supports. */
.section-media {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 18px;
  margin-top: 12px;
}

.section-media figure {
  margin: 0;
  position: relative;
}

.section-media figure.swap-pair img + img {
  position: absolute;
  inset: 0;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 420ms ease;
}

.section-media figure.swap-pair:hover img + img {
  opacity: 1;
}

.section-media video,
.section-media img {
  width: 100%;
  height: auto;
  border-radius: var(--radius);
  border: 1px solid currentColor;
  background: #0d0d0d;
}

.section-media figcaption {
  margin-top: 8px;
  font-family: var(--mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  opacity: 0.62;
}

/* A run of dark sections should read as one block, not as stripes. */
.case-section.dark + .case-section.dark {
  padding-top: 0;
}

/* AccordionGallery. Collapsed panels sit desaturated and slightly rotated; the open
   one flattens, regains colour, and reveals its caption. Ported from the React
   component using CSS transitions instead of GSAP. */
.accordion-gallery {
  --ag-accent: var(--accent, #ffffff);
  --ag-overlay: #0a0a0a;
  --ag-text: #ffffff;
  display: flex;
  gap: 10px;
  width: 100%;
  max-width: var(--max);
  margin: 0 auto;
  height: 460px;
  perspective: 1400px;
}

.ag-panel {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
  border-radius: 0;
  cursor: pointer;
  background: #0a0a0a;
  transform-style: preserve-3d;
  transition: flex-grow 600ms cubic-bezier(0.22, 0.61, 0.36, 1), transform 600ms cubic-bezier(0.22, 0.61, 0.36, 1);
  outline: none;
}

.ag-panel:focus-visible {
}

.ag-panel__frame {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: inherit;
}

.ag-panel__media {
  position: absolute;
  inset: 0;
}

.ag-panel__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1);
  transition: filter 600ms ease;
  user-select: none;
}

.ag-panel--active .ag-panel__media img {
  filter: grayscale(0);
}

.ag-panel__overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(180deg, transparent 45%, rgba(10, 10, 10, 0.78) 100%),
    rgba(10, 10, 10, 0.35);
  transition: background 600ms ease;
}

.ag-panel--active .ag-panel__overlay {
  background: linear-gradient(180deg, transparent 52%, rgba(10, 10, 10, 0.74) 100%);
}

.ag-panel__label {
  position: absolute;
  left: 20px;
  right: 20px;
  bottom: 20px;
  display: flex;
  align-items: center;
  gap: 12px;
  pointer-events: none;
  z-index: 2;
}

.ag-panel__bar {
  flex: 0 0 auto;
  width: 3px;
  height: 24px;
  border-radius: 0;
  background: var(--ag-accent);
  opacity: 0;
  transform: translateX(-14px);
  transition: opacity 500ms ease, transform 500ms ease;
}

.ag-panel__text {
  color: var(--ag-text);
  font-family: var(--mono);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  opacity: 0;
  transform: translateX(-14px);
  transition: opacity 500ms ease 60ms, transform 500ms ease 60ms;
}

.ag-panel--active .ag-panel__bar,
.ag-panel--active .ag-panel__text {
  opacity: 1;
  transform: translateX(0);
}

/* Case-page nav: a Work dropdown plus two flat links, in the Origin manner. */
.line-nav.case-nav {
  align-items: center;
  gap: 34px;
  padding: 18px 30px;
}

.line-nav__brand {
  padding: 0;
  line-height: 1;
}

.line-nav__links {
  display: flex;
  align-items: center;
  align-self: center;
  gap: 26px;
}

/* The brand carries a 34px mark while the links are 12px text, so both need to be
   centred against the same row rather than against their own line boxes. */
.line-nav.case-nav > * {
  align-self: center;
}

.nav-drop {
  display: flex;
  align-items: center;
}

.nav-drop {
  position: relative;
}

.nav-drop__trigger,
.nav-drop__flat {
  display: inline-flex;
  align-items: center;
  line-height: 1;
  gap: 7px;
  border: 0;
  background: transparent;
  color: var(--text-color);
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  cursor: pointer;
  padding: 0;
  transition: color 0.3s var(--ease);
}

.nav-drop__trigger:hover,
.nav-drop__flat:hover,
.nav-drop.is-open .nav-drop__trigger {
  color: var(--accent-color);
}

.nav-drop__chev {
  width: 6px;
  height: 6px;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  transform: rotate(45deg) translateY(-1px);
  transition: transform 0.3s var(--ease);
}

.nav-drop.is-open .nav-drop__chev {
  transform: rotate(-135deg) translateY(-2px);
}

.nav-drop__panel {
  position: absolute;
  top: calc(100% + 12px);
  left: -18px;
  min-width: 330px;
  padding: 8px;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 0;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity 0.3s var(--ease), transform 0.3s var(--ease), visibility 0s 0.3s;
  z-index: 5;
}

.nav-drop.is-open .nav-drop__panel {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  transition: opacity 0.3s var(--ease), transform 0.3s var(--ease), visibility 0s 0s;
}

.nav-drop__item {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border-radius: 0;
  color: var(--black);
  transition: background 0.3s var(--ease);
}

.nav-drop__item:hover {
  background: rgba(0, 0, 0, 0.045);
}

.nav-drop__item.is-here {
  background: rgba(0, 0, 0, 0.06);
}

.nav-drop__num {
  font-family: var(--mono);
  font-size: 10px;
  opacity: 0.45;
}

.nav-drop__title {
  font-size: 14px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.nav-drop__verb {
  font-family: var(--mono);
  font-size: 9.5px;
  text-transform: uppercase;
  padding: 4px 7px;
  border-radius: 0;
  color: var(--black);
}

.nav-drop__verb.reveal {
  background: var(--reveal);
}

.nav-drop__verb.mediate {
  background: var(--mediate);
}

.nav-drop__verb.translate {
  background: var(--translate);
}

@media (max-width: 720px) {
  .nav-drop__panel {
    min-width: 260px;
    left: -12px;
  }
}

/* Media sitting inside a section, next to the claim it supports. */
.section-media {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 18px;
  margin-top: 12px;
}

.section-media figure {
  margin: 0;
  position: relative;
}

.section-media figure.swap-pair img + img {
  position: absolute;
  inset: 0;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 420ms ease;
}

.section-media figure.swap-pair:hover img + img {
  opacity: 1;
}

.section-media video,
.section-media img {
  width: 100%;
  height: auto;
  border-radius: var(--radius);
  border: 1px solid currentColor;
  background: #0d0d0d;
}

.section-media figcaption {
  margin-top: 8px;
  font-family: var(--mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  opacity: 0.62;
}

/* A run of dark sections should read as one block, not as stripes. */
.case-section.dark + .case-section.dark {
  padding-top: 0;
}

/* AccordionGallery. Collapsed panels sit desaturated and slightly rotated; the open
   one flattens, regains colour, and reveals its caption. Ported from the React
   component using CSS transitions instead of GSAP. */
.accordion-gallery {
  --ag-accent: var(--accent, #ffffff);
  --ag-overlay: #0a0a0a;
  --ag-text: #ffffff;
  display: flex;
  gap: 10px;
  width: 100%;
  max-width: var(--max);
  margin: 0 auto;
  height: 460px;
  perspective: 1400px;
}

.ag-panel {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
  border-radius: 0;
  cursor: pointer;
  background: #0a0a0a;
  transform-style: preserve-3d;
  transition: flex-grow 600ms cubic-bezier(0.22, 0.61, 0.36, 1), transform 600ms cubic-bezier(0.22, 0.61, 0.36, 1);
  outline: none;
}

.ag-panel:focus-visible {
}

.ag-panel__frame {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: inherit;
}

.ag-panel__media {
  position: absolute;
  inset: 0;
}

.ag-panel__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1);
  transition: filter 600ms ease;
  user-select: none;
}

.ag-panel--active .ag-panel__media img {
  filter: grayscale(0);
}

.ag-panel__overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(180deg, transparent 45%, rgba(10, 10, 10, 0.78) 100%),
    rgba(10, 10, 10, 0.35);
  transition: background 600ms ease;
}

.ag-panel--active .ag-panel__overlay {
  background: linear-gradient(180deg, transparent 52%, rgba(10, 10, 10, 0.74) 100%);
}

.ag-panel__label {
  position: absolute;
  left: 20px;
  right: 20px;
  bottom: 20px;
  display: flex;
  align-items: center;
  gap: 12px;
  pointer-events: none;
  z-index: 2;
}

.ag-panel__bar {
  flex: 0 0 auto;
  width: 3px;
  height: 24px;
  border-radius: 0;
  background: var(--ag-accent);
  opacity: 0;
  transform: translateX(-14px);
  transition: opacity 500ms ease, transform 500ms ease;
}

.ag-panel__text {
  color: var(--ag-text);
  font-family: var(--mono);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  opacity: 0;
  transform: translateX(-14px);
  transition: opacity 500ms ease 60ms, transform 500ms ease 60ms;
}

.ag-panel--active .ag-panel__bar,
.ag-panel--active .ag-panel__text {
  opacity: 1;
  transform: translateX(0);
}

/* Case switcher: ten projects along the bar, current one held lit. */
.line-nav.case-nav {
  align-items: flex-start;
  padding: 20px 30px 20px;
}



@media (max-width: 720px) {
  .accordion-gallery {
    flex-direction: column;
    height: auto;
    perspective: none;
  }

  .ag-panel {
    min-height: 200px;
    transform: none !important;
  }
}

@media (prefers-reduced-motion: reduce) {
  .ag-panel,
  .ag-panel__media img {
    transition: none;
  }
}
