:root {
  --color-bg: #08080a;
  --color-bg-alt: #1a1a1d;
  --color-surface-2: #212124;
  --color-ink: #ffffff;
  --color-text: #ffffff;
  --color-text-soft: #9b9ba1;
  --color-border: rgba(255, 255, 255, 0.08);
  --color-border-strong: rgba(255, 255, 255, 0.16);
  --color-accent: #b9bcc4;
  --color-accent-soft: #e3e4e8;
  --color-cta-bg: #f75c03;
  --color-cta-text: #ffffff;
  --font-sans: "Inter", "Nanum Gothic", -apple-system, BlinkMacSystemFont, sans-serif;
  --font-serif: "Playfair Display", "Nanum Gothic", serif;

  --container-width: 1120px;
  --space-1: 8px;
  --space-2: 16px;
  --space-3: 24px;
  --space-4: 40px;
  --space-5: 64px;
  --space-6: 96px;
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

section,
.hero {
  scroll-margin-top: 88px;
}

body {
  margin: 0;
  font-family: var(--font-sans);
  color: var(--color-text);
  background: var(--color-bg);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
}

.container {
  width: 100%;
  max-width: var(--container-width);
  margin: 0 auto;
  padding: 0 var(--space-3);
}

h1, h2, h3, h4 {
  font-weight: 700;
  line-height: 1.3;
  margin: 0;
  letter-spacing: -0.01em;
  color: var(--color-ink);
  text-wrap: balance;
}

h1 {
  font-size: clamp(2rem, 4.4vw, 3rem);
}

h2 {
  font-size: clamp(1.5rem, 2.8vw, 2rem);
}

h3 {
  font-size: 1.2rem;
}

h4 {
  font-size: 0.85rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-soft);
  margin-bottom: var(--space-1);
}

p {
  margin: 0;
  color: var(--color-text-soft);
}

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

ul, ol, dl {
  margin: 0;
  padding: 0;
}

.eyebrow {
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  color: var(--color-accent);
  margin: 0 0 var(--space-2);
}

.section-intro {
  max-width: 560px;
  margin-top: var(--space-2);
}

.section-head {
  margin-bottom: var(--space-5);
}

/* Every section pairs a big serif English word with a Korean line beneath
   it — the serif carries the display moment, Nanum Gothic carries meaning. */
.section-heading-en {
  font-family: var(--font-serif);
  font-weight: 400; /* Playfair Display's lightest static cut; it has no 200 */
  letter-spacing: 0.01em;
  font-size: clamp(2.1rem, 4.4vw, 3.2rem);
  line-height: 1.15;
  --reveal-from: var(--color-text-soft);
  --reveal-to: var(--color-ink);
  color: var(--reveal-to);
}

.section-heading-ko {
  margin-top: var(--space-2);
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 1.05rem;
  color: var(--color-text-soft);
}

.card-heading-en {
  font-family: var(--font-serif);
  font-weight: 400;
  letter-spacing: 0.01em;
  font-size: 1.6rem;
  --reveal-from: var(--color-text-soft);
  --reveal-to: var(--color-ink);
  color: var(--reveal-to);
}

.card-heading-ko {
  margin-top: 4px;
  font-family: var(--font-sans);
  font-size: 0.9rem;
  color: var(--color-text-soft);
}

/* A two-column head — eyebrow+heading on the left, supporting copy on the
   right — used where a section benefits from more editorial weight. */
.section-head--split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-5);
  align-items: end;
}

.section-head--split .section-intro {
  margin-top: 0;
  max-width: 460px;
}

/* Header — a single translucent-dark surface; the whole site shares one
   fixed dark theme now, so the header never needs to swap looks. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--color-bg) 75%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--color-border);
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 72px;
}

.logo {
  display: inline-flex;
  align-items: center;
}

.logo-mark {
  height: 28px;
  width: auto;
  filter: brightness(0) invert(1);
}

.site-nav {
  display: flex;
  gap: var(--space-4);
}

.site-nav a {
  font-family: var(--font-serif);
  font-size: 0.95rem;
  font-weight: 400;
  color: var(--color-text-soft);
  transition: color 0.2s ease;
}

.site-nav a:hover,
.site-nav a:focus-visible {
  color: var(--color-ink);
}

.nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 32px;
  height: 32px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
}

.nav-toggle span {
  display: block;
  height: 2px;
  width: 100%;
  background: var(--color-ink);
}

a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* Media placeholder (stand-in for BOX&COX_CRD_*.jpg reference images) —
   a generative "cool/futuristic" visual: grid overlay + slow conic glow sweep,
   revealed by a curtain wipe (see .media-curtain below). */
.media-frame {
  position: relative;
  aspect-ratio: 16 / 7;
  border-radius: 12px;
  margin: var(--space-4) 0;
  overflow: hidden;
  isolation: isolate;
  display: flex;
  align-items: flex-end;
  justify-content: flex-start;
  background:
    radial-gradient(circle at 18% 28%, color-mix(in srgb, var(--color-accent) 18%, transparent), transparent 46%),
    radial-gradient(circle at 82% 74%, color-mix(in srgb, var(--color-accent) 9%, transparent), transparent 52%),
    linear-gradient(135deg, var(--color-surface-2), var(--color-bg-alt));
}

.media-frame::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(color-mix(in srgb, var(--color-ink) 6%, transparent) 1px, transparent 1px),
    linear-gradient(90deg, color-mix(in srgb, var(--color-ink) 6%, transparent) 1px, transparent 1px);
  background-size: 32px 32px;
  pointer-events: none;
}

.media-frame::after {
  content: "";
  position: absolute;
  inset: -30%;
  background: conic-gradient(
    from 0deg,
    transparent 0deg,
    color-mix(in srgb, var(--color-accent) 16%, transparent) 40deg,
    transparent 90deg
  );
  animation: media-sweep 14s linear infinite;
  pointer-events: none;
  z-index: -1;
}

@keyframes media-sweep {
  to {
    transform: rotate(360deg);
  }
}

.media-label {
  position: relative;
  z-index: 2;
  font-size: 0.75rem;
  font-family: monospace;
  color: var(--color-text-soft);
  background: color-mix(in srgb, var(--color-bg) 70%, transparent);
  padding: 4px 10px;
  margin: var(--space-2);
  border-radius: 999px;
}

/* The wipe-reveal curtain — a separate overlay, never the observed element
   itself. Clipping/hiding the observed target directly would zero out its
   own IntersectionObserver bounding rect and it could never be seen as
   "visible", so the wipe instead animates this child curtain sliding away. */
.media-curtain {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: var(--color-bg-alt);
  transform: scaleX(0);
  transform-origin: left center;
}

.media-frame.reveal-anim .media-curtain {
  transform: scaleX(1);
  transition: transform 1.1s cubic-bezier(0.16, 1, 0.3, 1);
}

.media-frame.reveal-anim.is-visible .media-curtain {
  transform: scaleX(0);
}

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

/* Sections — one continuous near-black canvas, but not a flat one: each
   section carries its own faint color wash so the black "군데군데" (here and
   there) picks up a little of the brand's blue-violet gradient as you scroll,
   rather than repeating one fixed backdrop. */
section {
  padding: var(--space-6) 0;
}

.prologue {
  background:
    radial-gradient(circle at 12% 15%, color-mix(in srgb, var(--color-accent) 6%, transparent), transparent 40%),
    var(--color-bg);
}

.work-scope {
  background:
    radial-gradient(circle at 88% 80%, color-mix(in srgb, var(--color-accent-soft) 5%, transparent), transparent 44%),
    var(--color-bg);
}

.work-process {
  background:
    radial-gradient(circle at 18% 75%, color-mix(in srgb, var(--color-accent) 5%, transparent), transparent 42%),
    var(--color-bg);
}

.projects {
  background:
    radial-gradient(circle at 82% 12%, color-mix(in srgb, var(--color-accent-soft) 4%, transparent), transparent 40%),
    var(--color-bg);
}

/* Hero and the closing CTA band bookend the page with the same generative
   dark backdrop (grid + glow), the way a full-bleed photo bookends fora.so. */
.hero,
.cta-band {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}

.hero::before,
.cta-band::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at 50% 10%, color-mix(in srgb, var(--color-accent) 14%, transparent), transparent 55%),
    radial-gradient(circle at 12% 90%, color-mix(in srgb, var(--color-accent) 6%, transparent), transparent 50%),
    linear-gradient(180deg, #08080a 0%, #0c0c0e 40%, #101012 60%, #08080a 100%);
  z-index: -2;
}

/* Falls back to this glow/grid look when the hero video hasn't loaded (or
   doesn't exist yet) — the video sits at z-index -1, right on top of this. */
.cta-band::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
  background-size: 48px 48px;
  mask-image: linear-gradient(180deg, transparent, black 25%, black 75%, transparent);
  -webkit-mask-image: linear-gradient(180deg, transparent, black 25%, black 75%, transparent);
  z-index: -1;
}

/* Hero-specific scrim: sits on top of the video (which is also z-index -1,
   but painted first) so the video reads clear near the header and fades to
   black by the time it reaches the logo mark at the very bottom. */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.4) 65%, rgba(0, 0, 0, 0.88) 100%);
  z-index: -1;
}

/* Animated grain: a dense grid of tiny squares. The dot pattern itself is
   canvas-drawn and only redrawn every ~1.4s (see initGrainCanvases() in
   main.js) -- cheap even at a fine resolution, since it isn't touched every
   frame. The "wave" that makes it ripple is pure CSS (an animated gradient
   in .grain-wave, blended against the dots via the isolated group below),
   so the sweep costs nothing on the JS main thread regardless of how fine
   the underlying grid is. */
.grain-layer {
  position: absolute;
  inset: 0;
  z-index: 0;
  isolation: isolate;
  mix-blend-mode: screen;
  opacity: 0.14;
  pointer-events: none;
  overflow: hidden;
}

.grain-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  image-rendering: pixelated;
}

.grain-wave {
  position: absolute;
  inset: 0;
  mix-blend-mode: multiply;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0, 0, 0, 1) 0%,
    rgba(0, 0, 0, 0.15) 20%,
    rgba(0, 0, 0, 1) 40%
  );
  background-size: 100% 250%;
  animation: grain-wave-sweep 3s linear infinite;
}

/* Animating background-position instead of transform here: with a large
   canvas underneath inside an isolated mix-blend-mode group, a transform
   animation forced a full repaint of the whole group every frame (measured
   ~30fps with visible stutter); background-position avoids that repaint
   path entirely and measured a clean 60fps in the same setup. */
@keyframes grain-wave-sweep {
  from {
    background-position: 0% 0%;
  }
  to {
    background-position: 0% 100%;
  }
}

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

.hero {
  /* Pull the hero up under the sticky header (which still reserves its own
     72px of flow) so the header sits over the hero's own background. A
     column flex layout lets the centered copy take the remaining space
     above the full-width logo mark, so the two never overlap. */
  margin-top: -72px;
  min-height: 100vh;
  padding-top: 72px;
  display: flex;
  flex-direction: column;
}

/* Full-bleed cover video, sitting above the gradient (::before) and below the
   grid overlay (::after) and content. Darkened/desaturated in place so the
   headline stays legible without a separate scrim element. Renders as
   nothing until assets/hero-video.mp4 (and its poster) are added. */
.hero-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: -1;
  filter: grayscale(0.3) brightness(0.55);
  transition: opacity 0.6s ease;
}

.hero-inner {
  position: relative;
  flex: 1;
  max-width: 720px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  text-align: center;
  padding: var(--space-5) var(--space-3);
}

.hero-pill {
  display: inline-flex;
  padding: 6px 16px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--color-border-strong);
  font-family: var(--font-serif);
  font-size: 0.8rem;
  font-weight: 400;
  letter-spacing: 0.12em;
  color: var(--color-text-soft);
}

.hero-heading {
  font-family: var(--font-serif);
  font-weight: 400;
  letter-spacing: 0;
  font-size: clamp(3.2rem, 9vw, 6.4rem);
  line-height: 1.05;
  --reveal-from: var(--color-text-soft);
  --reveal-to: var(--color-ink);
  color: var(--reveal-to);
}

.hero-sub {
  max-width: 520px;
  color: var(--color-text-soft);
  font-size: 1.05rem;
}

.hero-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-top: var(--space-1);
  padding: 14px 28px;
  border-radius: 999px;
  font-weight: 600;
  font-size: 0.95rem;
  background: var(--color-cta-bg);
  color: var(--color-cta-text);
  transition: transform 0.15s ease;
}

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

/* A full-width wordmark bookending the hero's bottom edge, over the video --
   sized by its own aspect ratio as a normal flex item so it never overlaps
   the centered copy above it. Plain solid white mark, same as the original
   header logo treatment. */
.hero-logo-mark {
  position: relative;
  width: 100%;
  line-height: 0;
  pointer-events: none;
}

.hero-logo-mark img {
  display: block;
  width: 100%;
  height: auto;
  filter: brightness(0) invert(1);
  opacity: 0.92;
}

/* A faint shadow band that sweeps across the logo every ~2.8s. Masked to
   the logo's own alpha shape so the shadow only ever appears inside the
   letterforms, not as a rectangle floating over the transparent space
   around them. */
.hero-logo-sweep {
  position: absolute;
  inset: 0;
  overflow: hidden;
  -webkit-mask-image: url("../assets/logo.png");
  mask-image: url("../assets/logo.png");
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}

.hero-logo-sweep::before {
  content: "";
  position: absolute;
  top: 0;
  left: -30%;
  width: 30%;
  height: 100%;
  background: linear-gradient(100deg, transparent, rgba(0, 0, 0, 0.4), transparent);
  animation: logo-shadow-sweep 2.8s ease-in-out infinite;
}

@keyframes logo-shadow-sweep {
  0% {
    left: -30%;
  }
  55%,
  100% {
    left: 100%;
  }
}

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

/* Closing CTA band — a compact echo of the hero, bookending the page. */
.cta-band {
  padding: var(--space-6) 0;
}

.cta-band-inner {
  position: relative;
  max-width: 640px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  text-align: center;
}


/* Prologue */
.prologue-inner h2 {
  max-width: 640px;
}

.prologue-split {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: var(--space-5);
}

.prologue-stat {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.prologue-stat-number {
  font-family: var(--font-serif);
  font-size: clamp(3rem, 6vw, 4.5rem);
  line-height: 1;
  color: var(--color-ink);
}

.prologue-stat-label {
  font-size: 0.85rem;
  color: var(--color-text-soft);
  max-width: 180px;
}

.prologue-blocks {
  display: grid;
  gap: var(--space-4);
}

.prologue-block .tagline {
  color: var(--color-accent);
  font-size: 1.3rem;
  margin-bottom: var(--space-2);
}

.prologue-block p {
  max-width: 760px;
}

/* Clients band — real, named clients from the project history, treated as a
   bold text wordmark row rather than fabricated logo marks. */
.clients-band {
  padding: var(--space-5) 0;
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
}

.client-list {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-3);
  margin-top: var(--space-4);
}

.client-list li {
  text-align: center;
  padding: var(--space-2) 0;
  font-family: var(--font-serif);
  font-size: clamp(1rem, 1.6vw, 1.3rem);
  color: var(--color-text-soft);
  border-left: 1px solid var(--color-border);
}

.client-list li:first-child {
  border-left: none;
}

/* Punch statement — a single line set edge-to-edge across the full browser
   width, breaking out of .container the same way the hero logo mark does. */
.punch-band {
  padding: var(--space-6) var(--space-2);
  text-align: center;
}

.punch-text-en {
  margin: 0;
  font-family: var(--font-serif);
  font-weight: 400;
  line-height: 1.05;
  font-size: clamp(2.4rem, 8vw, 6.5rem);
  color: var(--color-ink);
}

.punch-text-ko {
  margin: var(--space-2) 0 0;
  font-size: 1rem;
  color: var(--color-text-soft);
}

/* Work Scope */
.scope-list {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-3);
}

.scope-card {
  background: var(--color-bg-alt);
  border: 1px solid var(--color-border);
  border-radius: 20px;
  padding: var(--space-5);
}

.scope-card-head {
  margin-bottom: var(--space-3);
}

.scope-meta {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border);
}

/* A quiet dotted checklist rather than a wall of pill chips — reads calmer
   at 6-7 items per column. */
.tag-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.tag-list li {
  position: relative;
  padding-left: 14px;
  font-size: 0.85rem;
  color: var(--color-text-soft);
}

.tag-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--color-accent);
}

/* Work Process */
.process-label {
  font-weight: 600;
  color: var(--color-ink);
  margin-bottom: var(--space-3);
}

/* Auto-playing stepper: one step is "active" (full number + title +
   description) while the rest sit small on the side; initProcessCarousel()
   in main.js cycles .is-active on a timer, pausing on hover/click. */
.process-steps {
  list-style: none;
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
}

.process-step {
  position: relative;
  flex: 1 1 0%;
  padding-top: var(--space-4);
  border-top: 2px solid var(--color-border);
  cursor: pointer;
  transition: flex-grow 0.6s ease, border-color 0.4s ease;
}

.process-step.is-active {
  flex-grow: 3.5;
  border-top-color: var(--color-accent);
}

.process-number {
  position: absolute;
  top: -15px;
  left: 0;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--color-bg);
  background: var(--color-accent);
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.4s ease;
}

.process-step.is-active .process-number {
  transform: scale(1.15);
}

.process-body h3 {
  font-size: 0.95rem;
  margin-bottom: 6px;
  color: var(--color-text-soft);
  transition: font-size 0.4s ease, color 0.4s ease;
}

.process-step.is-active .process-body h3 {
  font-size: 1.3rem;
  color: var(--color-ink);
}

.process-body p {
  font-size: 0.82rem;
  max-height: 0;
  margin: 0;
  opacity: 0;
  overflow: hidden;
  transition: max-height 0.5s ease, opacity 0.3s ease;
}

.process-step.is-active .process-body p {
  max-height: 200px;
  opacity: 1;
}

/* Projects — cards overlap slightly like a fanned accordion, each one
   settling over the tail of the one before it as it rises into view. */
.project-list {
  display: flex;
  flex-direction: column;
}

.project-card {
  position: relative;
  background: var(--color-bg-alt);
  border: 1px solid var(--color-border);
  border-radius: 16px;
  overflow: hidden;
  margin-top: -28px;
}

.project-card:first-child {
  margin-top: 0;
}

.project-card.reveal-anim {
  transform: translateY(40px);
}

.project-card.reveal-anim.is-visible {
  transform: translateY(0);
}

.project-toggle {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  color: inherit;
}

.project-toggle-head {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.project-title {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(1.5rem, 3.2vw, 2.4rem);
  line-height: 1.15;
  color: var(--color-ink);
}

.project-meta {
  font-size: 0.85rem;
  color: var(--color-text-soft);
}

.project-toggle-icon {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  position: relative;
}

.project-toggle-icon::before,
.project-toggle-icon::after {
  content: "";
  position: absolute;
  background: var(--color-ink);
  transition: transform 0.2s ease;
}

.project-toggle-icon::before {
  top: 9px;
  left: 0;
  width: 20px;
  height: 2px;
}

.project-toggle-icon::after {
  top: 0;
  left: 9px;
  width: 2px;
  height: 20px;
}

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

.project-panel {
  padding: 0 var(--space-4) var(--space-4);
}

.project-panel .media-frame {
  margin: 0 0 var(--space-3);
  aspect-ratio: 16 / 9;
}

.project-facts {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

.project-facts dt {
  font-size: 0.75rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-text-soft);
  margin-bottom: 4px;
}

.project-facts dd {
  margin: 0;
  font-size: 0.9rem;
  color: var(--color-ink);
}

.project-desc {
  font-size: 0.95rem;
}

/* Footer */
.site-footer {
  border-top: 1px solid var(--color-border);
  padding: var(--space-3) 0;
}

.footer-inner {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 0.85rem;
  color: var(--color-text-soft);
}

.footer-links a:hover {
  color: var(--color-ink);
}

/* Reveal animation (progressive enhancement: visible by default, JS opts elements in).
   Elements that declare --reveal-from/--reveal-to (headings) also fade their own
   text color in — e.g. dim gray brightening to full white as the block scrolls
   into view — instead of only fading opacity. Elements that don't declare those
   custom properties are unaffected (the color rule falls back to "inherit"). */
.reveal-anim {
  opacity: 0;
  transform: translateY(16px);
  color: var(--reveal-from, inherit);
  transition: opacity 0.9s ease, transform 0.9s ease, color 1.1s ease;
}

.reveal-anim.is-visible {
  opacity: 1;
  transform: translateY(0);
  color: var(--reveal-to, inherit);
}

@media (prefers-reduced-motion: reduce) {
  .reveal-anim {
    opacity: 1;
    transform: none;
    color: var(--reveal-to, inherit);
    transition: none;
  }
}

/* Responsive */
@media (max-width: 960px) {
  .process-steps {
    flex-wrap: wrap;
  }

  .process-step {
    flex-basis: 21%;
  }

  .process-step.is-active {
    flex-basis: 100%;
    flex-grow: 0;
  }

  .project-facts {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 860px) {
  .section-head--split {
    grid-template-columns: 1fr;
    gap: var(--space-2);
  }

  .scope-list {
    grid-template-columns: 1fr;
  }

  .scope-meta {
    grid-template-columns: 1fr;
  }

  .prologue-split {
    grid-template-columns: 1fr;
    gap: var(--space-3);
  }

  .client-list {
    grid-template-columns: repeat(2, 1fr);
  }

  .client-list li:nth-child(2n + 1) {
    border-left: none;
  }
}

@media (max-width: 640px) {
  .nav-toggle {
    display: flex;
  }

  .site-nav {
    position: absolute;
    top: 72px;
    left: 0;
    right: 0;
    background: var(--color-bg-alt);
    border-bottom: 1px solid var(--color-border);
    flex-direction: column;
    padding: var(--space-2) var(--space-3);
    gap: var(--space-2);
    display: none;
  }

  .site-nav.is-open {
    display: flex;
  }

  .process-steps {
    flex-direction: column;
  }

  .process-step {
    flex-basis: auto;
    padding-top: var(--space-2);
  }

  .process-step.is-active {
    flex-basis: auto;
  }

  .project-toggle {
    padding: var(--space-2) var(--space-3);
  }

  .project-panel {
    padding: 0 var(--space-3) var(--space-3);
  }

  .project-facts {
    grid-template-columns: 1fr;
  }

  .footer-inner {
    flex-direction: column;
    gap: var(--space-1);
    text-align: center;
  }

  .hero-feature-body {
    flex-direction: column;
    align-items: flex-start;
  }
}
