/* ==========================================================================
   SECTIONS — page-level composition. Layout only; all visual atoms live in
   components.css.
   ========================================================================== */

/* Every section opens with the same meta row: index + label. */
.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5rem;
  padding-bottom: clamp(1.25rem, 2.4vw, 2.25rem);
  border-bottom: 1px solid var(--c-rule);
}

/* --------------------------------------------------------------------------
   Hero — deliberately near-empty
   -------------------------------------------------------------------------- */

.hero {
  min-height: 100svh;
  padding-top: calc(var(--header-h) + clamp(2rem, 8vh, 7rem));
  padding-bottom: clamp(1.5rem, 4vh, 3rem);
  display: grid;
  grid-template-rows: auto 1fr auto;
  row-gap: clamp(2rem, 6vh, 5rem);
}

.hero__meta {
  row-gap: 1rem;
}

.hero__meta > *:nth-child(1) {
  grid-column: 1 / span 3;
}

.hero__meta > *:nth-child(2) {
  grid-column: 5 / span 3;
}

.hero__meta > *:nth-child(3) {
  grid-column: 10 / span 3;
  text-align: right;
}

.hero__center {
  align-self: center;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  row-gap: clamp(2rem, 5vw, 4rem);
  align-items: end;
}

.hero__statement {
  grid-column: 1 / span 7;
  font-size: clamp(1.5rem, 0.9rem + 2.6vw, 3.75rem);
  line-height: 1.08;
  letter-spacing: var(--tracking-display);
  text-wrap: balance;
}

.hero__aside {
  grid-column: 9 / span 4;
  display: grid;
  gap: 1.25rem;
  align-content: end;
}

.hero__still {
  aspect-ratio: 16 / 10;
}

/* Two screens tall: the first is the seed, the second is the space it opens
   into. The frame inside is pinned, so the whole transition is scrubbed by
   one screen of scroll rather than animated on a timer. */
.hero--scene {
  position: relative;
  display: block;
  /* 260svh: ~100svh of transition (unchanged in feel) plus ~60svh of hold at
     the end, which is what keeps the second line on screen. */
  height: 260svh;
  min-height: 0;
  padding: 0;
  overflow: clip; /* not `hidden` — that would make the sticky child scroll */
}

.scene__frame {
  position: sticky;
  top: 0;
  height: 100svh;
  display: grid;
  place-items: center;
  overflow: hidden;
}

.hero__canvas {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: block;
  width: 100%;
  height: 100%;
}

/* --scene-open is written by the scene each frame, 0 on the first screen and
   1 once the creative space has taken over. The two lines share one grid cell
   so they sit in exactly the same place and cross-fade rather than shifting. */
.hero__scene-copy {
  position: relative;
  z-index: 1;
  text-align: center;
  display: grid;
}

.hero__scene-copy > * {
  grid-area: 1 / 1;
  align-self: center;
}

/* The seed's line clears first… */
.hero__scene-copy > #hero-statement {
  opacity: calc(1 - (var(--scene-open, 0) * 2.2));
  transform: translateY(calc(var(--scene-open, 0) * -3rem));
  will-change: opacity, transform;
}

/* …and the second arrives only once it has gone, so the two never overlap.
   Opacity outside 0–1 is clamped, which is what gives the hold at each end. */
.hero__statement--after {
  /* Full opacity by 0.75 rather than 0.94, so it is readable for the last
     quarter of the transition as well as through the hold that follows. */
  opacity: calc((var(--scene-open, 0) - 0.5) * 4);
  transform: translateY(calc((1 - var(--scene-open, 0)) * 2rem));
  will-change: opacity, transform;
}

@media (prefers-reduced-motion: reduce) {
  .hero--scene {
    height: auto;
    min-height: 100svh;
  }
  .scene__frame {
    position: static;
    min-height: 100svh;
    height: auto;
  }
  .hero__scene-copy {
    opacity: 1;
    transform: none;
  }
}

/* The scene headlines sit on one line. The 20ch cap was inherited from the
   old, much longer statement and now breaks "Plant the Seed" in half. Width is
   left to the type, and only genuinely narrow screens are allowed to wrap. */
.hero--scene .hero__statement {
  max-width: none;
  margin-inline: auto;
  text-wrap: nowrap;
}

@media (max-width: 30rem) {
  .hero--scene .hero__statement {
    text-wrap: balance;
  }
}

.hero__foot {
  align-items: end;
  row-gap: 1.5rem;
}

.hero__scroll {
  grid-column: 1 / span 4;
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
}

.hero__scroll svg {
  animation: nudge 2.4s var(--ease-inout) infinite;
}

@keyframes nudge {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(4px);
  }
}

.hero__tags {
  grid-column: 8 / span 5;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  justify-content: flex-end;
}

/* --------------------------------------------------------------------------
   Bian page — intro
   -------------------------------------------------------------------------- */

.bian-hero {
  padding-top: calc(var(--header-h) + clamp(2.5rem, 9vh, 8rem));
  padding-bottom: clamp(3rem, 7vw, 7rem);
  display: grid;
  row-gap: clamp(3rem, 7vw, 6rem);
}

.bian-hero__body {
  row-gap: clamp(2.5rem, 5vw, 4rem);
  align-items: end;
}

.bian-hero__name {
  grid-column: 1 / span 12;
}

.bian-hero__name .indent {
  display: block;
  padding-left: 14vw;
}

.bian-hero__portrait {
  grid-column: 1 / span 5;
  aspect-ratio: 4 / 5;
}

.bian-hero__bio {
  grid-column: 7 / span 5;
  display: grid;
  gap: 1.5rem;
  align-content: end;
}

.bian-hero__bio p {
  max-width: 48ch;
}

/* Software list ------------------------------------------------------------ */

.software {
  margin-top: clamp(3rem, 7vw, 7rem);
  padding-top: clamp(1.25rem, 2vw, 2rem);
  border-top: 1px solid var(--c-rule);
  row-gap: 1.5rem;
}

.software__title {
  grid-column: 1 / span 2;
}

.software__list {
  grid-column: 3 / span 10;
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem clamp(1.5rem, 4vw, 4rem);
  font-size: clamp(1.125rem, 0.8rem + 1.2vw, 2.25rem);
  letter-spacing: var(--tracking-tight);
  text-transform: uppercase;
  line-height: 1.1;
}

@media (max-width: 64rem) {
  .bian-hero__portrait {
    grid-column: 1 / span 6;
  }

  .bian-hero__bio {
    grid-column: 7 / span 6;
  }

  .software__title {
    grid-column: 1 / span 12;
  }

  .software__list {
    grid-column: 1 / span 12;
  }
}

@media (max-width: 44rem) {
  .bian-hero__portrait,
  .bian-hero__bio {
    grid-column: 1 / span 12;
  }

  .bian-hero__name .indent {
    padding-left: 18vw;
  }
}

/* Clients ------------------------------------------------------------------ */

.clients {
  margin-top: clamp(2.5rem, 5vw, 5rem);
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 0;
}

.clients li {
  padding-block: clamp(0.85rem, 1.6vw, 1.35rem);
  border-top: 1px solid var(--c-rule);
  font-size: clamp(1rem, 0.8rem + 0.7vw, 1.5rem);
  text-transform: uppercase;
  letter-spacing: var(--tracking-tight);
  transition: color var(--dur-fast) var(--ease-out);
}

.clients li:hover {
  color: var(--c-grey);
}

/* About us — the team leader, given the weight of a feature -----------------
   A raised beige panel with the portrait alongside, so this reads as the one
   thing on the page rather than the second of four equal sections. Beige is
   the system's own secondary surface — the same one the project plates use —
   so the emphasis costs no new colour. */

.leader {
  margin-top: clamp(2rem, 4vw, 3.5rem);
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(1.75rem, 4vw, 4rem);
  align-items: center;
  padding: clamp(1.5rem, 3.5vw, 3.25rem);
  background: var(--c-beige);
  /* Square corners, like the rest of the site. --radius-card is scoped to
     .how-page, so referencing it here would silently resolve to nothing and
     leave the corners square by accident rather than by decision. */
}

.leader__portrait {
  aspect-ratio: 4 / 5;
  overflow: hidden;
}

.leader__text {
  display: grid;
  row-gap: clamp(0.85rem, 1.8vw, 1.4rem);
  max-width: 52ch;
}

.leader__name {
  font-size: clamp(2.5rem, 1.4rem + 4.4vw, 5.5rem);
  line-height: 0.92;
  letter-spacing: var(--tracking-display);
  text-transform: uppercase;
}

.leader__role {
  color: var(--fg-muted);
}

.leader__text .lead {
  max-width: 44ch;
}

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

  .leader__portrait {
    max-width: 22rem;
  }
}

/* Get in touch ------------------------------------------------------------- */

.touch {
  margin-top: clamp(2.5rem, 5vw, 5rem);
  row-gap: 0;
}

.touch__row {
  grid-column: 1 / span 12;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  align-items: baseline;
  padding-block: clamp(1rem, 2vw, 1.75rem);
  border-top: 1px solid var(--c-rule);
}

.touch__row:last-child {
  border-bottom: 1px solid var(--c-rule);
}

.touch__row dt {
  grid-column: 1 / span 2;
}

.touch__row dd {
  grid-column: 3 / span 10;
}

.touch__link {
  position: relative;
  font-size: clamp(1.375rem, 0.8rem + 2.4vw, 3.25rem);
  line-height: 1.05;
  letter-spacing: var(--tracking-display);
  transition: color var(--dur-base) var(--ease-out);
}

.touch__link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -0.06em;
  width: 100%;
  height: 1px;
  background: var(--c-cyan);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform var(--dur-base) var(--ease-out);
}

.touch__link:hover,
.touch__link:focus-visible {
  color: var(--c-cyan);
}

.touch__link:hover::after,
.touch__link:focus-visible::after {
  transform: scaleX(1);
  transform-origin: left;
}

@media (max-width: 44rem) {
  .touch__row dt,
  .touch__row dd {
    grid-column: 1 / span 12;
  }

  .touch__row dd {
    margin-top: 0.5rem;
  }
}

/* --------------------------------------------------------------------------
   Selected work
   -------------------------------------------------------------------------- */

.work__title {
  margin-top: clamp(2rem, 5vw, 4.5rem);
}

.work__title .display span.indent {
  display: block;
  padding-left: 18vw;
}

/* --------------------------------------------------------------------------
   Selected work — scroll-pinned gallery

   A band of 5:4 cards that browses sideways as the page scrolls down. The
   stage sticks to the top of the viewport while the wrapper's spare height
   is consumed; that scroll distance is mapped to a position along the strip,
   so scrolling down walks left → right and scrolling up walks back. Because
   the pin is nothing but a tall element with a sticky child, the page is
   never intercepted: the section releases on its own at either end, and the
   scrollbar, keyboard and trackpad momentum all behave as they normally do.

   The track is full-bleed — it breaks out of the shell's padding so cards
   run off both edges rather than stopping at the text column.

   Positioning is JavaScript's job (initGallery in main.js writes a transform
   on each card every frame). Everything here is the resting state, which is
   also the no-JS state: a plain horizontally scrollable row in normal flow.
   -------------------------------------------------------------------------- */

.work-pin {
  position: relative;
}

.work-pin__stage {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* Inside the pinned stage the whole section has one screen to live in, and
   the display face at its full size eats most of it — which is what pushed
   the cards off the bottom edge. Here the heading is a heading rather than a
   statement, and it sits on one line so it costs one line's height. */
.work-pin__stage .work__title {
  margin-top: clamp(0.25rem, 0.6vw, 0.6rem);
}

.work-pin__stage .work__title .display {
  font-size: clamp(2rem, 1.2rem + 3.4vw, 4.5rem);
  line-height: 1;
}

.work-pin__stage .work__title .display span.indent {
  display: inline;
  padding-left: 0.25em;
}

/* The line splitter runs before the webfont has settled and reads the two
   words as two lines, so each gets its own block-level mask and they stack.
   Laying the masks inline puts them back on one line without touching the
   splitter — the wipe wrappers inside them are untouched, so the reveal
   animation still plays. */
.work-pin__stage .work__title .line-mask {
  display: inline-block;
  width: auto;
  vertical-align: top;
}

/* The cards take whatever the heading leaves, rather than a fixed slice of
   the viewport that could overrun it. Centred rather than top-aligned, so if
   a short viewport does squeeze the band it loses the same amount top and
   bottom instead of dropping the captions off the edge. */
.work-pin__stage .gallery {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* The band is most of the stage now; the old gap above it no longer fits.
     It has to clear the track outright — the track carries `slack` on top of
     the card so the centred one can scale up, and any shortfall here is taken
     out of that headroom by the gallery's own overflow clip. */
  margin-top: clamp(0.25rem, 0.6vw, 0.6rem);
}

/* Only once the loop is running does the stage pin. Until then the section is
   ordinary flow, which is what a no-JS reader gets. */
.work-pin.is-pinned .work-pin__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  padding-top: var(--header-h);
}

.gallery {
  /* Sized off the height the stage has left, not off viewport width: the
     limit here is vertical, and a vw-based height made the cards small on a
     wide screen precisely where there was the most room for them.

     54svh is the card image alone. The band around it — caption, plus the
     `slack` the loop adds so the centred card can grow without being sheared
     — brings the whole thumbnail area to roughly 70% of the stage. */
  /* The ceiling is the pinned stage, not taste: the band renders at
     (card + caption) x 1.08, and the stage leaves ~0.82svh for it — so the
     card itself tops out near 0.72svh. 66svh sits just inside that. */
  --gallery-card-h: clamp(12rem, min(42vw, 64svh), 42rem);
  /* Tight, so the row reads as one strip rather than separate pictures. */
  --gallery-gap: clamp(0.4rem, 0.8vw, 0.9rem);

  margin-top: clamp(2rem, 4vw, 4rem);
  margin-inline: calc(var(--pad-x) * -1);
  overflow: hidden;
}

.gallery__track {
  display: flex;
  gap: var(--gallery-gap);
  padding-inline: var(--pad-x);
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.gallery__track::-webkit-scrollbar {
  display: none;
}

/* Once the loop is running the cards are placed absolutely and the flex row
   is only there to hold the track's height open. */
.gallery.is-live .gallery__track {
  position: relative;
  display: block;
  overflow: visible;
  padding-inline: 0;
  /* Height is written inline by the loop, measured from a real card so the
     meta line under the image is inside the clip rather than cut off. */
  min-height: var(--gallery-card-h);
}

.gallery.is-live .gcard {
  position: absolute;
  top: 0;
  left: 0;
  will-change: transform;
  backface-visibility: hidden;
}

.gcard {
  flex: none;
  width: calc(var(--gallery-card-h) * 5 / 4);
  transform-origin: 50% 50%;
}

.gcard__link {
  position: relative;
  display: block;
  height: 100%;
}

/* The 5:4 crop. The thumbnail keeps its own dimensions in the markup and is
   centre-cropped to fit by object-fit: cover on .media img — nothing is
   pre-cut, so swapping a thumbnail needs no new file. */
.gcard__media {
  aspect-ratio: 5 / 4;
  height: var(--gallery-card-h);
  width: 100%;
  border-radius: 0;
  /* The focused card lifts off the row. Written as a variable so the loop can
     fade it with the same curve it uses for opacity — a shadow at full
     strength on a card scaled to 0.66 reads as a smudge, not depth. */
  box-shadow: 0 calc(18px * var(--lift, 0)) calc(50px * var(--lift, 0))
    rgb(0 0 0 / calc(0.18 * var(--lift, 0)));
}

/* Scale, opacity and saturation are all written per-frame by the loop onto the
   frame rather than the image, which leaves the image's own reveal transform
   alone. Scaling from the centre is what keeps every thumbnail's midline on
   the same row while the sizes differ. */
.gallery.is-live .gcard__media {
  transform-origin: 50% 50%;
  will-change: transform, opacity;
}

.gcard__index,
.gcard__arrow {
  position: absolute;
  top: clamp(0.6rem, 1.1vw, 1.1rem);
  z-index: 2;
  color: var(--c-offwhite);
  mix-blend-mode: difference;
}

.gcard__index {
  left: clamp(0.6rem, 1.1vw, 1.1rem);
  font-size: var(--t-micro);
  letter-spacing: var(--tracking-label);
}

.gcard__arrow {
  right: clamp(0.6rem, 1.1vw, 1.1rem);
  display: grid;
  place-items: center;
  transition: transform var(--dur-base) var(--ease-out);
}

.gcard__link:hover .gcard__arrow,
.gcard__link:focus-visible .gcard__arrow {
  transform: translate(0.25rem, -0.25rem);
}

.gcard__meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-top: clamp(0.6rem, 1vw, 0.9rem);
  padding-top: clamp(0.5rem, 0.8vw, 0.75rem);
  border-top: 1px solid var(--c-rule);
}

.gcard__title {
  /* Deliberately small. The thumbnail is the content here; the caption is a
     label under it, not a headline competing with the image above. */
  font-size: clamp(0.625rem, 0.56rem + 0.28vw, 0.8125rem);
  line-height: 1.2;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  transition: color var(--dur-fast) var(--ease-out);
}

/* The label follows the card the loop has focused — the one nearest the
   middle, or whichever is hovered. */
.gallery.is-live .gcard__meta {
  opacity: 0;
  transform: translateY(0.4rem);
  transition: opacity var(--dur-base) var(--ease-out),
    transform var(--dur-base) var(--ease-out);
}

.gallery.is-live .gcard.is-focused .gcard__meta {
  opacity: 1;
  transform: none;
}

.gallery__hint {
  margin-top: clamp(1rem, 2vw, 1.75rem);
  text-align: right;
}

.gallery__hint [data-gallery-count] {
  color: var(--fg);
  font-variant-numeric: tabular-nums;
}

.gallery:not(.is-live) ~ .gallery__hint {
  display: none;
}

@media (hover: none) {
  .gallery__hint::after {
    content: " →";
  }
}

.work__foot {
  margin-top: clamp(4rem, 9vw, 9rem);
  padding-top: clamp(1.25rem, 2vw, 2rem);
  border-top: 1px solid var(--c-rule);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1.5rem;
}

/* --------------------------------------------------------------------------
   Work index page
   -------------------------------------------------------------------------- */

.page-head {
  padding-top: calc(var(--header-h) + clamp(2.5rem, 9vh, 8rem));
  padding-bottom: clamp(2rem, 5vw, 4rem);
}

.page-head__title {
  margin-top: clamp(1.5rem, 3vw, 3rem);
}

.page-head__intro {
  margin-top: clamp(1.5rem, 3vw, 2.5rem);
  max-width: 58ch;
  color: var(--fg-muted);
}

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem clamp(1rem, 2.5vw, 2.5rem);
  margin-top: clamp(2rem, 4vw, 3.5rem);
  padding-top: clamp(1rem, 2vw, 1.75rem);
  border-top: 1px solid var(--c-rule);
}

.filter {
  position: relative;
  font-size: var(--t-small);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--fg-muted);
  padding-bottom: 0.3em;
  transition: color var(--dur-fast) var(--ease-out);
}

.filter::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 1px;
  background: var(--c-cyan);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform var(--dur-base) var(--ease-out);
}

.filter:hover,
.filter[aria-pressed="true"] {
  color: var(--fg);
}

.filter[aria-pressed="true"]::after,
.filter:hover::after {
  transform: scaleX(1);
  transform-origin: left;
}

/* The index reuses the homepage rhythm but in even pairs. */
.work-index {
  row-gap: clamp(3rem, 7vw, 7rem);
  padding-bottom: var(--section-y);
}

.work-index > * {
  grid-column: span 6;
}

.work-index > *:nth-child(4n + 2),
.work-index > *:nth-child(4n + 3) {
  margin-top: clamp(1rem, 6vw, 6rem);
}

.work-index > *[hidden] {
  display: none;
}

.work-empty {
  padding-block: clamp(4rem, 10vw, 9rem);
  font-size: var(--t-lead);
  color: var(--fg-muted);
}

.work-empty[hidden] {
  display: none;
}

/* --------------------------------------------------------------------------
   Project detail page
   -------------------------------------------------------------------------- */

.project-hero__title {
  margin-top: clamp(1.5rem, 3vw, 3rem);
}

.project-cover {
  margin-top: clamp(2rem, 5vw, 4.5rem);
  aspect-ratio: 16 / 9;
}

.project-meta {
  margin-top: clamp(2.5rem, 5vw, 5rem);
  row-gap: clamp(2rem, 4vw, 3rem);
}

.project-meta__intro {
  grid-column: 1 / span 6;
  font-size: var(--t-lead);
  line-height: 1.35;
}

.project-meta__facts {
  grid-column: 8 / span 5;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.5rem var(--gutter);
  align-content: start;
}

.project-meta__facts dt {
  font-size: var(--t-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--fg-muted);
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--c-rule);
  margin-bottom: 0.6rem;
}

.project-meta__facts dd {
  font-size: var(--t-body);
}

/* Full-bleed banner used by the hero and the About section (1440×600-ish). */
.project-banner {
  margin-top: clamp(2rem, 5vw, 4.5rem);
  aspect-ratio: 12 / 5;
}

/* Section heading + body copy, two columns. */
.project-copy {
  margin-top: clamp(2rem, 4vw, 3.5rem);
  row-gap: clamp(1.5rem, 3vw, 2.5rem);
}

.project-copy__title {
  grid-column: 1 / span 5;
}

.project-copy__body {
  grid-column: 7 / span 6;
  display: grid;
  gap: 1rem;
  align-content: start;
  font-size: var(--t-body);
  line-height: 1.6;
  color: var(--fg-muted);
}

.project-copy__body:empty {
  display: none;
}

.project-copy__body p {
  max-width: 62ch;
}

.project-plates {
  margin-top: clamp(3rem, 7vw, 7rem);
  row-gap: clamp(2rem, 5vw, 5rem);
}

.plate--full {
  grid-column: 1 / span 12;
  aspect-ratio: 16 / 9;
}

.plate--half {
  grid-column: span 6;
  aspect-ratio: 4 / 5;
}

.plate--offset {
  grid-column: 3 / span 8;
  aspect-ratio: 3 / 2;
}

/* A lone trailing portrait plate: same 4:5 footprint as a paired half, but
   centred since it has no partner to sit beside. */
.plate--half-center {
  grid-column: span 6;
  aspect-ratio: 4 / 5;
}

@media (min-width: 44.0625rem) {
  .plate--half-center {
    grid-column: 4 / span 6;
  }
}

.plate__caption {
  margin-top: 0.75rem;
  grid-column: span 12;
}

.project-next {
  display: block;
  padding-block: clamp(3rem, 7vw, 7rem);
  border-top: 1px solid var(--c-rule);
  margin-top: clamp(4rem, 9vw, 9rem);
}

.project-next__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
}

.project-next__title {
  font-size: clamp(2rem, 0.9rem + 4.6vw, 5.5rem);
  line-height: 0.95;
  letter-spacing: var(--tracking-display);
  text-transform: uppercase;
  transition: color var(--dur-base) var(--ease-out);
}

.project-next:hover .project-next__title {
  color: var(--c-grey);
}

@media (max-width: 64rem) {
  .project-copy__title {
    grid-column: 1 / span 12;
  }

  .project-copy__body {
    grid-column: 1 / span 10;
  }

  .project-meta__intro {
    grid-column: 1 / span 7;
  }

  .project-meta__facts {
    grid-column: 8 / span 5;
  }

  .plate--offset {
    grid-column: 2 / span 10;
  }
}

@media (max-width: 44rem) {
  .work-index > *,
  .work-index > *:nth-child(4n + 2),
  .work-index > *:nth-child(4n + 3) {
    grid-column: 1 / span 12;
    margin-top: 0;
  }

  .project-meta__intro,
  .project-meta__facts,
  .project-copy__body,
  .plate--half,
  .plate--half-center,
  .plate--offset {
    grid-column: 1 / span 12;
  }

  .project-cover,
  .project-banner,
  .plate--full {
    aspect-ratio: 4 / 3;
  }
}

/* --------------------------------------------------------------------------
   About
   -------------------------------------------------------------------------- */

.about {
  --bg: var(--c-beige);
  background: var(--bg);
}

.about__body {
  margin-top: clamp(2.5rem, 6vw, 6rem);
  row-gap: clamp(2.5rem, 5vw, 4rem);
}

.about__statement {
  grid-column: 1 / span 9;
}

.about__col {
  grid-column: 3 / span 4;
  display: grid;
  gap: 1.5rem;
  align-content: start;
}

.about__col p {
  max-width: 46ch;
}

.about__aside {
  grid-column: 8 / span 5;
  display: grid;
  gap: 1.5rem;
}

.about__still {
  aspect-ratio: 4 / 5;
}

/* --------------------------------------------------------------------------
   Stats
   -------------------------------------------------------------------------- */

.stats__grid {
  margin-top: clamp(2.5rem, 6vw, 6rem);
  row-gap: clamp(2.5rem, 5vw, 4rem);
}

/* Three stats across. */
.stats__grid > * {
  grid-column: span 4;
}

/* --------------------------------------------------------------------------
   Team
   -------------------------------------------------------------------------- */

.team__title {
  margin-top: clamp(2rem, 4vw, 3.5rem);
}

.team__grid {
  margin-top: clamp(3rem, 7vw, 7rem);
  row-gap: clamp(3rem, 6vw, 5rem);
}

/* Two members: a wide pair, the second dropped to keep the asymmetry. Used
   by the Bian page's "My Team" grid. */
.team__grid > *:nth-child(1) {
  grid-column: 1 / span 5;
}

.team__grid > *:nth-child(2) {
  grid-column: 7 / span 5;
  margin-top: clamp(2rem, 8vw, 9rem);
}

/* --------------------------------------------------------------------------
   Core Team (homepage) — a text intro beside a pair of numbered cards,
   one person, one a standing invitation to the wider freelance network.
   -------------------------------------------------------------------------- */

.team-layout {
  margin-top: clamp(3rem, 6vw, 6rem);
  align-items: start;
}

.team-layout__intro {
  grid-column: 1 / span 4;
}

.team-layout__rule {
  margin: clamp(1.5rem, 3vw, 2.25rem) 0;
}

.team-layout__note {
  font-size: clamp(1rem, 0.9rem + 0.4vw, 1.25rem);
  line-height: 1.5;
  letter-spacing: var(--tracking-tight);
  color: var(--fg-muted);
  max-width: 30ch;
  text-wrap: balance;
}

.team-cards {
  grid-column: 6 / span 7;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1rem, 2vw, 1.5rem);
}

.team-card {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-height: clamp(20rem, 30vw, 27rem);
  padding: clamp(1.5rem, 2.2vw, 2rem);
  border-radius: 1.25rem;
  overflow: hidden;
  background: var(--c-beige);
  color: var(--c-black);
  transition: transform var(--dur-base) var(--ease-out);
}

.team-card--dark {
  background: var(--c-black);
  color: var(--c-offwhite);
}

.team-card:hover {
  transform: translateY(-0.35rem);
}

/* Hold on the card and Bian's portrait fades in behind the text — hidden
   the rest of the time so the card reads as text-first, same spirit as the
   rest of the site's hover reveals. */
.team-card__media {
  position: absolute;
  inset: 0;
  z-index: 0;
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
}

.team-card__media::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  opacity: 1;
  background: linear-gradient(
    to top,
    color-mix(in srgb, var(--c-black) 70%, transparent),
    transparent 60%
  );
}

.team-card--photo:hover .team-card__media,
.team-card--photo:focus-within .team-card__media {
  opacity: 1;
}

.team-card--photo:hover .team-card__head,
.team-card--photo:hover .team-card__body,
.team-card--photo:focus-within .team-card__head,
.team-card--photo:focus-within .team-card__body {
  color: var(--c-offwhite);
}

.team-card__head,
.team-card__body {
  position: relative;
  z-index: 1;
  transition: color var(--dur-base) var(--ease-out);
}

.team-card__head {
  display: flex;
  flex-direction: column;
  gap: clamp(0.85rem, 1.6vw, 1.1rem);
}

.team-card__index {
  font-size: var(--t-small);
  letter-spacing: var(--tracking-label);
}

.team-card__rule {
  display: block;
  height: 1px;
  background: currentColor;
  opacity: 0.16;
}

.team-card__name {
  font-size: clamp(1.75rem, 1.2rem + 2vw, 2.75rem);
  text-transform: uppercase;
  line-height: 1.05;
}

.team-card__role {
  margin-top: 0.6rem;
  font-size: var(--t-small);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: inherit;
  opacity: 0.6;
}

/* Two roles stack on the right of the name row. */
.person__row .label--micro {
  text-align: right;
  line-height: 1.35;
}

/* --------------------------------------------------------------------------
   Services
   -------------------------------------------------------------------------- */

.services__head {
  row-gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: start;
  margin-bottom: clamp(3rem, 6vw, 6rem);
}

/* Small marker label at far left, oversized title pushed right. */
.services__label {
  grid-column: 1 / span 3;
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  color: var(--fg);
}

.services__dot {
  width: 0.45em;
  height: 0.45em;
  border-radius: 50%;
  background: var(--c-cyan);
  flex: none;
}

.services__title {
  grid-column: 5 / span 8;
  text-align: right;
}

/* Service rows — a three-column table: what it is, its name, what you get. */
.service-row {
  align-items: start;
  row-gap: 1rem;
  padding-block: clamp(1.75rem, 3.4vw, 3rem);
  border-top: 1px solid var(--c-rule);
}

.service-row:last-child {
  border-bottom: 1px solid var(--c-rule);
}

.service-row__desc {
  grid-column: 1 / span 3;
  font-size: var(--t-small);
  line-height: 1.5;
  color: var(--fg-muted);
}

.service-row__name {
  grid-column: 5 / span 4;
  font-size: clamp(1.5rem, 0.9rem + 1.9vw, 2.75rem);
  line-height: 1.05;
  letter-spacing: var(--tracking-tight);
}

.service-row__list {
  grid-column: 10 / span 3;
  display: grid;
  gap: 0.5rem;
  align-content: start;
}

.service-row__list li {
  position: relative;
  padding-left: 1.1em;
  font-size: clamp(0.875rem, 0.8rem + 0.3vw, 1.0625rem);
  line-height: 1.35;
}

.service-row__list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 0.32em;
  height: 0.32em;
  border-radius: 50%;
  background: var(--c-cyan);
}

@media (max-width: 64rem) {
  .service-row__desc {
    grid-column: 1 / span 4;
  }

  .service-row__name {
    grid-column: 6 / span 3;
  }

  .service-row__list {
    grid-column: 9 / span 4;
  }
}

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

.site-footer {
  background: var(--c-black);
  color: var(--c-offwhite);
  padding-top: clamp(4rem, 9vw, 10rem);
  padding-bottom: clamp(1.5rem, 3vw, 2.5rem);
}

.footer__cta {
  display: block;
  margin-bottom: clamp(3rem, 8vw, 8rem);
}

.footer__cta .display {
  transition: color var(--dur-base) var(--ease-out);
}

.footer__cta:hover .display,
.footer__cta:focus-visible .display {
  color: var(--c-cyan);
}

.footer__cta .indent {
  display: block;
  padding-left: 12vw;
}

.footer__cols {
  row-gap: clamp(2.5rem, 5vw, 3.5rem);
  padding-top: clamp(1.5rem, 3vw, 2.5rem);
  border-top: 1px solid var(--c-rule-inv);
}

.footer__col {
  grid-column: span 3;
  display: grid;
  gap: 1rem;
  align-content: start;
}

.footer__col:first-child {
  grid-column: 1 / span 3;
}

.footer__list {
  display: grid;
  gap: 0.6rem;
}

.footer__link {
  position: relative;
  display: inline-block;
  font-size: clamp(1rem, 0.85rem + 0.5vw, 1.375rem);
  letter-spacing: var(--tracking-tight);
  transition: color var(--dur-fast) var(--ease-out);
}

.footer__link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -0.15em;
  width: 100%;
  height: 1px;
  background: var(--c-cyan);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform var(--dur-base) var(--ease-out);
}

.footer__link:hover,
.footer__link:focus-visible {
  color: var(--c-cyan);
}

.footer__link:hover::after,
.footer__link:focus-visible::after {
  transform: scaleX(1);
  transform-origin: left;
}

.footer__bottom {
  margin-top: clamp(3rem, 7vw, 7rem);
  padding-top: 1.25rem;
  border-top: 1px solid var(--c-rule-inv);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
}

.footer__mark {
  width: clamp(2rem, 4vw, 3.25rem);
  color: var(--c-cyan);
}

@media (max-width: 44rem) {
  .services__label,
  .services__title {
    grid-column: 1 / span 12;
    text-align: left;
  }

  .service-row__name {
    grid-column: 1 / span 12;
    order: -1;
  }

  .service-row__desc,
  .service-row__list {
    grid-column: 1 / span 12;
  }
}


/* Tablet ------------------------------------------------------------------ */
@media (max-width: 64rem) {
  .hero__statement {
    grid-column: 1 / span 9;
  }

  .hero__aside {
    grid-column: 1 / span 7;
  }

  .hero__scroll {
    grid-column: 1 / span 5;
  }

  .hero__tags {
    grid-column: 6 / span 7;
  }

  .about__statement {
    grid-column: 1 / span 11;
  }

  .about__col {
    grid-column: 1 / span 6;
  }

  .about__aside {
    grid-column: 8 / span 5;
  }

  .service__desc {
    grid-column: 1 / span 6;
  }

  .service__list {
    grid-column: 8 / span 5;
  }

  .services__title {
    grid-column: 1 / span 12;
  }

  .services__intro {
    grid-column: 1 / span 8;
  }

  .team__grid > *:nth-child(1) {
    grid-column: 1 / span 6;
  }

  .team__grid > *:nth-child(2) {
    grid-column: 7 / span 6;
    margin-top: 0;
  }

  .footer__col,
  .footer__col:first-child {
    grid-column: span 6;
  }
}

/* Mobile ------------------------------------------------------------------ */
@media (max-width: 44rem) {
  .hero {
    min-height: 92svh;
  }

  .hero__meta > *:nth-child(1) {
    grid-column: 1 / span 6;
  }

  .hero__meta > *:nth-child(2) {
    grid-column: 7 / span 6;
    text-align: right;
  }

  .hero__meta > *:nth-child(3) {
    display: none;
  }

  .hero__statement,
  .hero__aside {
    grid-column: 1 / span 12;
  }

  .hero__scroll {
    grid-column: 1 / span 6;
  }

  .hero__tags {
    grid-column: 7 / span 6;
  }

  .work__title .display span.indent {
    padding-left: 22vw;
  }

  /* Narrow screens are width-bound rather than height-bound, so the card is
     sized from the viewport width here — but capped by svh as well, so a
     short landscape phone cannot push the band past the stage. */
  .gallery {
    --gallery-card-h: clamp(11rem, min(64vw, 52svh), 24rem);
  }

  .about__statement,
  .about__col,
  .about__aside {
    grid-column: 1 / span 12;
  }

  .stats__grid > * {
    grid-column: span 12;
  }

  .team__grid > *:nth-child(n) {
    grid-column: 1 / span 12;
    margin-top: 0;
  }

  .team-layout__intro,
  .team-cards {
    grid-column: 1 / span 12;
  }

  .team-cards {
    grid-template-columns: 1fr;
    margin-top: clamp(2rem, 8vw, 3rem);
  }

  .team-card {
    min-height: 16rem;
  }

  .service__trigger {
    grid-template-columns: auto 1fr auto;
    gap: 1rem;
  }

  .service__desc,
  .service__list {
    grid-column: 1 / span 12;
  }

  .footer__col,
  .footer__col:first-child {
    grid-column: span 12;
  }

  .footer__cta .indent {
    padding-left: 8vw;
  }
}

/* ==========================================================================
   HOW — the studio's operating manual.

   This page is the one place the system uses soft corners: the brief calls for
   rounded cards and a rounded CTA. The radii live here rather than in
   tokens.css so the rest of the site stays sharp-edged.
   ========================================================================== */

.how-page {
  --bg: var(--c-beige);
  --radius-card: 1.5rem;
  --radius-inner: 0.9rem;
  background: var(--bg);
}

.how-page .site-header {
  background: var(--c-beige);
}

.how-card {
  background: var(--c-offwhite);
  border-radius: var(--radius-card);
  padding: clamp(1.5rem, 3vw, 2.75rem);
}

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

.how-hero {
  padding-top: calc(var(--header-h) + clamp(3rem, 10vh, 9rem));
  padding-bottom: clamp(3rem, 8vw, 8rem);
  row-gap: clamp(3rem, 6vw, 5rem);
  align-items: start;
}

.how-hero__intro {
  grid-column: 1 / span 6;
}

.how-hero__label {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  margin-bottom: clamp(1.5rem, 3vw, 2.5rem);
}

.how-hero__label::before {
  content: "";
  width: 0.45em;
  height: 0.45em;
  border-radius: 50%;
  background: var(--c-cyan);
}

.how-hero__title {
  font-size: clamp(2rem, 1rem + 3.4vw, 4.25rem);
  line-height: 1.04;
  letter-spacing: var(--tracking-display);
  text-wrap: balance;
}

.how-hero__body {
  margin-top: clamp(1.75rem, 3vw, 2.75rem);
  display: grid;
  gap: 1.1rem;
  max-width: 46ch;
  color: var(--fg-muted);
  font-size: var(--t-body);
  line-height: 1.6;
}

.how-hero__body strong {
  color: var(--fg);
  font-weight: 400;
}

/* -- The operating-system diagram ------------------------------------------ */

.os {
  grid-column: 8 / span 5;
  display: grid;
  gap: 0;
}

.os__step {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 1rem;
  padding: clamp(0.85rem, 1.6vw, 1.15rem) clamp(1rem, 2vw, 1.5rem);
  background: var(--c-offwhite);
  border-radius: var(--radius-inner);
  font-size: clamp(0.9375rem, 0.85rem + 0.4vw, 1.125rem);
  letter-spacing: var(--tracking-tight);
}

/* The connector sits in the gap between cards, not inside them. */
.os__step + .os__step {
  margin-top: 2.25rem;
}

.os__step + .os__step::before {
  content: "";
  position: absolute;
  left: 50%;
  top: -2.25rem;
  height: 2.25rem;
  width: 1px;
  /* translateX pulls the 1px rule onto the true centre; left:50% alone leaves
     it half a pixel to the right. */
  transform: translateX(-50%);
  background: var(--c-rule-strong);
}

.os__num {
  font-size: var(--t-micro);
  letter-spacing: var(--tracking-label);
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
}

/* The single AI step — the only accent on the diagram. */
.os__step--accent {
  background: var(--c-cyan);
}

.os__step--accent .os__num {
  color: color-mix(in srgb, var(--c-black) 55%, transparent);
}

.os__note {
  display: block;
  font-size: var(--t-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: color-mix(in srgb, var(--c-black) 55%, transparent);
  margin-top: 0.15rem;
}

/* -- 02 Comparison table --------------------------------------------------- */

.compare-head {
  row-gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: start;
}

.compare-head__label {
  grid-column: 1 / span 4;
  padding-top: 0.6em;
}

.compare-head__title {
  grid-column: 6 / span 7;
  text-align: right;
  font-size: clamp(1.75rem, 1rem + 2.8vw, 3.5rem);
  line-height: 1.06;
  letter-spacing: var(--tracking-display);
  text-wrap: balance;
}

.compare {
  margin-top: clamp(2rem, 4vw, 3.5rem);
  padding: clamp(0.5rem, 1vw, 0.85rem);
}

.compare__table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  text-align: left;
}

.compare__table th {
  background: var(--c-black);
  color: var(--c-offwhite);
  font-weight: 400;
  padding: clamp(0.9rem, 1.8vw, 1.3rem) clamp(1rem, 2.2vw, 1.9rem);
  font-size: clamp(0.9375rem, 0.85rem + 0.4vw, 1.125rem);
  letter-spacing: var(--tracking-tight);
}

.compare__table th:first-child {
  border-radius: var(--radius-inner) 0 0 var(--radius-inner);
}

.compare__table th:last-child {
  border-radius: 0 var(--radius-inner) var(--radius-inner) 0;
}

.compare__table td {
  padding: clamp(1rem, 2.2vw, 1.65rem) clamp(1rem, 2.2vw, 1.9rem);
  border-bottom: 1px solid var(--c-rule);
  font-size: clamp(0.9375rem, 0.85rem + 0.45vw, 1.1875rem);
  letter-spacing: var(--tracking-tight);
}

.compare__table tbody tr:last-child td {
  border-bottom: 0;
}

/* Left column is the "before": present but receding. */
.compare__table td:first-child {
  color: var(--fg-muted);
  width: 50%;
}

/* The Seedsee column is the answer — it gets its own tinted lane, the accent
   in the header, and full-strength type. */
.compare__us {
  position: relative;
}

.compare__table th.compare__us {
  color: var(--c-cyan);
}

.compare__table td.compare__us {
  color: var(--fg);
  background: color-mix(in srgb, var(--c-cyan) 13%, transparent);
}

.compare__table tbody tr:last-child td.compare__us {
  border-radius: 0 0 var(--radius-inner) var(--radius-inner);
}

@media (max-width: 44rem) {
  .compare-head__label,
  .compare-head__title {
    grid-column: 1 / span 12;
    text-align: left;
  }

  .compare__table th,
  .compare__table td {
    padding-inline: 0.85rem;
  }
}

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

.timeline {
  margin-top: clamp(2.5rem, 5vw, 4.5rem);
}

.timeline__step {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  row-gap: 0.5rem;
  align-items: baseline;
  padding-block: clamp(1.35rem, 2.6vw, 2.25rem);
  border-top: 1px solid var(--c-rule);
}

.timeline__step:last-child {
  border-bottom: 1px solid var(--c-rule);
}

.timeline__num {
  grid-column: 1 / span 1;
  font-size: var(--t-micro);
  letter-spacing: var(--tracking-label);
  color: var(--fg-muted);
}

.timeline__name {
  grid-column: 2 / span 4;
  font-size: clamp(1.25rem, 0.9rem + 1.3vw, 2.125rem);
  line-height: 1.05;
  letter-spacing: var(--tracking-tight);
}

.timeline__text {
  grid-column: 7 / span 5;
  color: var(--fg-muted);
  font-size: var(--t-body);
  line-height: 1.55;
  max-width: 46ch;
}

.timeline__step--accent .timeline__name {
  color: var(--fg);
}

.timeline__step--accent .timeline__num {
  color: var(--c-cyan);
}

/* -- 04 Reason cards ------------------------------------------------------- */

.how-reasons {
  row-gap: var(--gutter);
  margin-top: clamp(2.5rem, 5vw, 4rem);
}

.how-reasons > * {
  grid-column: span 3;
  display: grid;
  align-content: start;
  gap: 0.9rem;
  min-height: clamp(12rem, 18vw, 16rem);
}

.how-reasons h3 {
  font-size: clamp(1.125rem, 0.9rem + 0.8vw, 1.5rem);
  letter-spacing: var(--tracking-tight);
}

.how-reasons p {
  color: var(--fg-muted);
  font-size: var(--t-small);
  line-height: 1.55;
}

.how-reasons__index {
  font-size: var(--t-micro);
  letter-spacing: var(--tracking-label);
  color: var(--c-cyan);
}

/* -- Final statement + CTA ------------------------------------------------- */

.how-final {
  padding-block: clamp(5rem, 12vw, 12rem);
  text-align: center;
}

.how-final__statement {
  max-width: 22ch;
  margin-inline: auto;
  font-size: clamp(1.75rem, 1rem + 3vw, 3.75rem);
  line-height: 1.08;
  letter-spacing: var(--tracking-display);
}

.how-final__sub {
  max-width: 48ch;
  margin: clamp(1.5rem, 3vw, 2.25rem) auto 0;
  color: var(--fg-muted);
  font-size: var(--t-lead);
  line-height: 1.4;
}

/* The one rounded button in the system — the brief asks for it by name. */
.button-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.8em;
  margin-top: clamp(2rem, 4vw, 3rem);
  padding: clamp(0.9rem, 1.6vw, 1.15rem) clamp(1.6rem, 3vw, 2.5rem);
  border-radius: 999px;
  background: var(--c-black);
  color: var(--c-offwhite);
  font-size: var(--t-small);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  transition:
    background var(--dur-base) var(--ease-out),
    color var(--dur-base) var(--ease-out);
}

.button-pill:hover,
.button-pill:focus-visible {
  background: var(--c-cyan);
  color: var(--c-black);
}

.button-pill svg {
  transition: transform var(--dur-base) var(--ease-out);
}

.button-pill:hover svg {
  transform: translate(0.25em, -0.25em);
}

/* -- Breakpoints ----------------------------------------------------------- */

@media (max-width: 64rem) {
  .how-hero__intro,
  .os {
    grid-column: 1 / span 12;
  }

  .os {
    max-width: 34rem;
  }

  .how-reasons > * {
    grid-column: span 6;
  }

  .timeline__name {
    grid-column: 2 / span 5;
  }

  .timeline__text {
    grid-column: 8 / span 5;
  }
}

@media (max-width: 44rem) {
  .how-reasons > * {
    grid-column: 1 / span 12;
  }

  .timeline__num,
  .timeline__name,
  .timeline__text {
    grid-column: 1 / span 12;
  }

  .timeline__text {
    margin-top: 0.35rem;
  }
}

/* -- How page: language buttons -------------------------------------------- */

/* Only this page is translated, so the control lives on the page rather than
   in the global header. */
.how-lang-bar {
  padding-top: calc(var(--header-h) + clamp(1.5rem, 4vh, 3rem));
}

.how-lang {
  display: inline-flex;
  gap: 0.4rem;
}

.how-lang__btn {
  padding: 0.55em 1.1em;
  border: 1px solid var(--c-rule-strong);
  border-radius: 999px;
  font-size: var(--t-small);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--fg-muted);
  transition:
    background var(--dur-base) var(--ease-out),
    color var(--dur-base) var(--ease-out),
    border-color var(--dur-base) var(--ease-out);
}

.how-lang__btn:hover,
.how-lang__btn:focus-visible {
  color: var(--c-black);
  border-color: var(--c-black);
}

.how-lang__btn[aria-current="true"] {
  background: var(--c-black);
  border-color: var(--c-black);
  color: var(--c-offwhite);
}

@media (max-width: 30rem) {
  .how-lang {
    flex-wrap: wrap;
  }

  .how-lang__btn {
    padding: 0.5em 0.85em;
    letter-spacing: 0.06em;
  }
}

/* --------------------------------------------------------------------------
   New project inquiry

   Eight questions. Inputs are ruled lines rather than boxes, so the form reads
   as part of the editorial system instead of a widget dropped into it.
   -------------------------------------------------------------------------- */

.inquiry {
  margin-top: clamp(2rem, 5vw, 4.5rem);
  row-gap: clamp(2.5rem, 5vw, 4rem);
}

.inquiry__intro {
  grid-column: 1 / span 4;
}

.inquiry__lede {
  margin-top: clamp(1rem, 2vw, 1.5rem);
  max-width: 34ch;
  color: var(--fg-muted);
  font-size: var(--t-body);
  line-height: var(--leading-body);
}

.inquiry__form {
  grid-column: 6 / span 7;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.5rem, 3vw, 2.5rem) clamp(1.25rem, 2.5vw, 2rem);
  align-content: start;
}

.field {
  display: grid;
  gap: 0.5rem;
  align-content: start;
}

/* The brief, and the row of controls under it, run the full width. */
.field--wide,
.inquiry__foot {
  grid-column: 1 / -1;
}

.field__label {
  font-size: var(--t-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--fg-muted);
}

/* Required is carried by the asterisk in the label as well as the attribute,
   so it is visible and announced rather than only enforced on submit. */
.field__label span {
  color: var(--accent);
}

.field__input {
  width: 100%;
  padding: 0.55rem 0 0.6rem;
  border: 0;
  border-bottom: 1px solid var(--c-rule-strong);
  border-radius: 0;
  background: none;
  color: var(--fg);
  font: inherit;
  font-size: var(--t-body);
  line-height: 1.4;
  transition: border-color var(--dur-fast) var(--ease-out);
}

.field__input::placeholder {
  color: var(--fg-muted);
  opacity: 1; /* Firefox dims placeholders again on top of the colour */
}

.field__input:hover {
  border-bottom-color: var(--fg);
}

.field__input:focus-visible {
  outline: none;
  border-bottom-color: var(--accent);
  border-bottom-width: 2px;
  /* Compensate so the text does not shift down by the extra pixel. */
  padding-bottom: calc(0.6rem - 1px);
}

/* The native arrow is drawn in the platform's own colour and sits oddly on a
   ruled line, so it is replaced with the site's chevron. */
.field__input--select {
  appearance: none;
  padding-right: 1.5rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 6l5 5 5-5' fill='none' stroke='%23000' stroke-width='1.2'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.15rem center;
  background-size: 0.9rem;
  cursor: pointer;
}

/* Until something is chosen the control shows its placeholder option, which is
   labelling rather than an answer — greyed to say so. */
.field__input--select:invalid,
.field__input--select:has(option[value=""]:checked) {
  color: var(--fg-muted);
}

.field__input--area {
  min-height: 8rem;
  resize: vertical;
  border: 1px solid var(--c-rule-strong);
  padding: 0.85rem 1rem;
}

.field__input--area:focus-visible {
  border-color: var(--accent);
  border-width: 1px;
  padding-bottom: 0.85rem;
  box-shadow: inset 0 0 0 1px var(--accent);
}

.field__error {
  font-size: var(--t-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: #b3261e;
}

.field__input[aria-invalid="true"] {
  border-bottom-color: #b3261e;
}

.inquiry__foot {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.5vw, 2rem);
  flex-wrap: wrap;
  margin-top: clamp(0.5rem, 1.5vw, 1rem);
}

.inquiry__submit svg {
  margin-left: 0.5rem;
  vertical-align: -0.1em;
}

.inquiry__submit[disabled] {
  opacity: 0.5;
  pointer-events: none;
}

.inquiry__note {
  font-size: var(--t-small);
  color: var(--fg-muted);
}

/* Off-screen rather than display:none — a bot reading the markup should find
   it as an ordinary field, which is the whole point. */
.inquiry__trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.inquiry__done {
  grid-column: 6 / span 7;
  align-self: start;
  padding: clamp(1.75rem, 3.5vw, 3rem);
  background: var(--c-beige);
  border-radius: 2px;
}

.inquiry__done:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

.inquiry__done-title {
  font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.5rem);
  line-height: 1.1;
  letter-spacing: var(--tracking-tight);
}

.inquiry__done-body {
  margin-top: clamp(0.75rem, 1.5vw, 1.25rem);
  max-width: 38ch;
  color: var(--fg-muted);
  font-size: var(--t-body);
  line-height: var(--leading-body);
}

@media (max-width: 64rem) {
  .inquiry__intro,
  .inquiry__form,
  .inquiry__done {
    grid-column: 1 / span 12;
  }
}

@media (max-width: 44rem) {
  .inquiry__form {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Contact-method checkboxes ------------------------------------------------ */

/* A fieldset carries default border, margin and padding in every browser, and
   its default `min-width: min-content` stops it shrinking inside a grid. */
.field--choices {
  border: 0;
  margin: 0;
  padding: 0;
  min-width: 0;
}

.field--choices legend {
  padding: 0;
  margin-bottom: 0.75rem;
}

.choices {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem clamp(1.25rem, 3vw, 2.5rem);
}

.choice {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  cursor: pointer;
  font-size: var(--t-body);
  line-height: 1.2;
}

/* The real control stays in the accessibility tree and keeps every native
   behaviour — it is only made invisible, never replaced. */
.choice input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  margin: 0;
}

.choice__box {
  position: relative;
  flex: none;
  width: 1.15rem;
  height: 1.15rem;
  border: 1px solid var(--c-rule-strong);
  border-radius: 2px;
  transition:
    background var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out);
}

/* The tick, drawn as two borders on a rotated block. */
.choice__box::after {
  content: "";
  position: absolute;
  left: 0.36rem;
  top: 0.14rem;
  width: 0.3rem;
  height: 0.58rem;
  border: solid var(--c-offwhite);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg) scale(0);
  transition: transform var(--dur-fast) var(--ease-out);
}

.choice:hover .choice__box {
  border-color: var(--fg);
}

.choice input:checked + .choice__box {
  background: var(--fg);
  border-color: var(--fg);
}

.choice input:checked + .choice__box::after {
  transform: rotate(45deg) scale(1);
}

/* Focus has to be drawn on the stand-in, since the real box is invisible. */
.choice input:focus-visible + .choice__box {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.choices__other {
  display: grid;
  gap: 0.5rem;
  margin-top: clamp(1rem, 2vw, 1.5rem);
  max-width: 26rem;
}

@media (prefers-reduced-motion: reduce) {
  .choice__box,
  .choice__box::after {
    transition: none;
  }
}

/* The services heading is a link to the services page ---------------------- */

/* An <a> wrapping the whole heading block, not the <h2> — the line splitter
   rebuilds the heading's innerHTML, and an anchor nested inside it would be
   thrown away on the first split. */
.services__head--link {
  position: relative;
  display: grid;
  color: inherit;
  text-decoration: none;
}

.services__head-arrow {
  grid-column: 1 / -1;
  justify-self: end;
  align-self: start;
  display: inline-grid;
  place-items: center;
  color: var(--fg-muted);
  transition:
    transform var(--dur-base) var(--ease-out),
    color var(--dur-fast) var(--ease-out);
}

.services__head--link:hover .services__head-arrow,
.services__head--link:focus-visible .services__head-arrow {
  transform: translate(0.3rem, -0.3rem);
  color: var(--accent);
}

.services__head--link:hover .services__title,
.services__head--link:focus-visible .services__title {
  color: var(--fg-muted);
}

.services__title {
  transition: color var(--dur-fast) var(--ease-out);
}

.services__head--link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 0.75rem;
}

@media (prefers-reduced-motion: reduce) {
  .services__head-arrow {
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   Services — overview, detail, packages

   Overview is a ruled list, not cards: the same editorial device the Work
   index and the process list already use, so the page reads as part of the
   site rather than a pricing page bolted on.
   -------------------------------------------------------------------------- */

.svc-overview {
  position: relative; /* the cursor preview is positioned against the page */
}

.svc-list {
  display: grid;
  border-top: 1px solid var(--c-rule);
}

.svc-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: baseline;
  gap: clamp(1rem, 3vw, 3rem);
  padding-block: clamp(1.5rem, 3.4vw, 2.75rem);
  border-bottom: 1px solid var(--c-rule);
  color: inherit;
  transition: color var(--dur-fast) var(--ease-out);
}

/* The GIF is the hover feedback, so the row itself only shifts and greys —
   no background block, no card. */
.svc-row__body {
  display: grid;
  gap: 0.4rem;
  transition: transform var(--dur-base) var(--ease-out);
}

.svc-row:hover .svc-row__body,
.svc-row:focus-visible .svc-row__body {
  transform: translateX(clamp(0.5rem, 1.2vw, 1rem));
}

.svc-row__n {
  font-size: var(--t-micro);
  letter-spacing: var(--tracking-label);
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
}

.svc-row__name {
  font-size: clamp(1.75rem, 1rem + 3.4vw, 4rem);
  line-height: 1.02;
  letter-spacing: var(--tracking-display);
}

.svc-row__sum {
  font-size: var(--t-small);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--fg-muted);
}

.svc-row__cta {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: var(--t-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--fg-muted);
  white-space: nowrap;
  transition:
    color var(--dur-fast) var(--ease-out),
    transform var(--dur-base) var(--ease-out);
}

.svc-row:hover .svc-row__cta,
.svc-row:focus-visible .svc-row__cta {
  color: var(--accent);
  transform: translate(0.3rem, -0.2rem);
}

.svc-row:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 0.5rem;
}

/* ---- the cursor-following preview --------------------------------------- */

/* Outer: position only. It is rewritten every frame as the pointer moves, so
   nothing animated may live on it. */
.svc-preview {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 40; /* over the list, under the header (90) and cursor (120) */
  pointer-events: none;
  transform: translate3d(0, 0, 0);
  will-change: transform;
}

/* Inner: the 5:4 frame itself, and the thing that grows. Its transform-origin
   is set from JS to whichever corner the cursor is on, so it expands away
   from the pointer rather than from its own middle. */
.svc-preview__frame {
  width: clamp(12rem, 17vw, 17rem);
  aspect-ratio: 5 / 4;
  border-radius: 2px; /* the site's own frame radius, not a card */
  overflow: hidden;
  opacity: 0;
  transform: scale(0.6);
  transform-origin: 0 0; /* JS moves this to the corner the cursor is on */
  will-change: transform, opacity;
}

/* Layers crossfade when moving between services. The frame stays put for that
   — regrowing it every time the pointer crossed a row would read as a stutter,
   not as one preview tracking the reader. */
.svc-preview img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-out);
}

.svc-preview img.is-shown {
  opacity: 1;
}

/* Touch and coarse pointers never get it — there is no cursor to follow. */
@media not all and (hover: hover) and (pointer: fine) {
  .svc-preview {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .svc-preview {
    display: none;
  }
  .svc-row__body,
  .svc-row__cta {
    transition: none;
  }
}

/* ---- detail sections ----------------------------------------------------- */

.svc-detail {
  scroll-margin-top: calc(var(--header-h) + 3rem);
}

.svc-detail__head {
  margin-top: clamp(2rem, 4vw, 3.5rem);
  row-gap: clamp(1rem, 2vw, 1.5rem);
}

.svc-detail__name {
  grid-column: 1 / span 7;
}

.svc-detail__desc {
  grid-column: 8 / span 5;
  align-self: end;
  font-size: var(--t-lead);
  line-height: 1.4;
  letter-spacing: var(--tracking-tight);
  color: var(--fg-muted);
  text-wrap: pretty;
}

.svc-cols {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(1.5rem, 3vw, 2.5rem);
  margin-top: clamp(2.5rem, 5vw, 4.5rem);
  padding-top: clamp(1.25rem, 2vw, 2rem);
  border-top: 1px solid var(--c-rule);
}

.svc-col__head {
  font-size: var(--t-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--fg-muted);
  padding-bottom: 0.85rem;
}

.svc-col__list {
  display: grid;
  gap: 0.75rem;
  font-size: var(--t-body);
  line-height: 1.35;
  letter-spacing: var(--tracking-tight);
  text-wrap: balance; /* "Virtual Model / Character Content" wraps to two even lines */
}

.svc-detail__cta {
  margin-top: clamp(2.5rem, 5vw, 4rem);
}

/* ---- Brand Identity packages -------------------------------------------- */

/* Ruled columns, not pricing cards: no borders around each tier, no shadow,
   no accent panel on the "recommended" one. The hierarchy is typographic. */
.svc-packages {
  margin-top: clamp(4rem, 8vw, 7rem);
}

.svc-packages__note {
  margin-top: clamp(1rem, 2vw, 1.5rem);
  font-size: var(--t-small);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--fg-muted);
}

/* A real comparison matrix: rows are the deliverable, columns the three tiers,
   so a reader can trace one line across and see exactly what each step up
   buys. The old layout stacked three independent lists, which looked like a
   comparison without being one — the wording escalates ("Colour Palette" →
   "Colour System"), so each cell keeps the tier's own words rather than
   collapsing to a tick. */
.pkg-table-wrap {
  margin-top: clamp(2rem, 4vw, 3.5rem);
  overflow-x: auto; /* four columns will not fit a phone; the table scrolls */
  overscroll-behavior-x: contain;
}

.pkg-table {
  width: 100%;
  min-width: 46rem; /* below this the cells crush; scroll instead of wrap */
  border-collapse: collapse;
  text-align: left;
  font-size: var(--t-small);
  line-height: 1.35;
}

/* The row-label column is narrower than the three it describes. */
.pkg-table th[scope="row"] {
  width: 18%;
  padding: 0.85rem clamp(0.75rem, 1.4vw, 1.25rem) 0.85rem 0;
  font-weight: inherit;
  font-size: var(--t-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--fg-muted);
  vertical-align: top;
}

.pkg-table thead th {
  width: 27.33%;
  padding: 0 clamp(0.75rem, 1.4vw, 1.25rem) clamp(1.25rem, 2vw, 1.75rem);
  font-weight: inherit;
  vertical-align: top;
  border-bottom: 2px solid var(--fg);
}

.pkg-table__tier {
  display: block;
  margin-bottom: 0.6rem;
  font-size: clamp(1.35rem, 0.9rem + 1.4vw, 2.25rem);
  line-height: 1.05;
  letter-spacing: var(--tracking-display);
}

.pkg-table__best {
  display: block;
  font-size: var(--t-small);
  line-height: 1.5;
  color: var(--fg-muted);
  text-wrap: pretty;
}

.pkg-table tbody td {
  padding: 0.85rem clamp(0.75rem, 1.4vw, 1.25rem);
  vertical-align: top;
  border-bottom: 1px solid var(--c-rule);
}

.pkg-table tbody tr:last-child td,
.pkg-table tbody tr:last-child th {
  border-bottom: 0;
}

/* Not included. Held back rather than struck through — the row is about what
   the other tiers add, not about what this one lacks. */
.pkg-table .is-out {
  color: var(--fg-muted);
  opacity: 0.5;
}

/* The tier being pointed at. A tint of the house cyan running the full height
   of the column, so the eye follows one band down the table. */
.pkg-table__key {
  background: color-mix(in srgb, var(--c-cyan) 22%, transparent);
}

.pkg-table thead .pkg-table__key {
  padding-top: clamp(1rem, 1.8vw, 1.5rem);
  border-radius: 3px 3px 0 0;
}

.pkg-table tfoot .pkg-table__key {
  border-radius: 0 0 3px 3px;
}

.pkg-table tfoot td {
  padding: clamp(1.25rem, 2.4vw, 2rem) clamp(0.75rem, 1.4vw, 1.25rem);
  vertical-align: top;
}

.pkg__cta {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: var(--t-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

/* ---- responsive ---------------------------------------------------------- */

@media (max-width: 64rem) {
  .svc-detail__name,
  .svc-detail__desc {
    grid-column: 1 / span 12;
  }

  .svc-cols {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: clamp(2rem, 4vw, 3rem);
  }

  /* The table keeps its four columns and scrolls sideways instead — stacking
     it would destroy the row-by-row comparison that is the whole point. */
  .pkg-table {
    min-width: 42rem;
  }
}

@media (max-width: 44rem) {
  .svc-row {
    grid-template-columns: auto minmax(0, 1fr);
    row-gap: 0.75rem;
  }

  /* The CTA drops under the name rather than being squeezed beside it. */
  .svc-row__cta {
    grid-column: 2;
  }

  .svc-cols {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* The production chain. Rendered as a numbered run rather than a diagram —
   the sequence is the argument: direction and finishing sit either side of
   the generation step, which is what separates this from a prompt. */
.svc-flow {
  margin-top: clamp(3rem, 6vw, 5rem);
  padding-top: clamp(1.25rem, 2vw, 2rem);
  border-top: 1px solid var(--c-rule);
}

.svc-flow__label {
  font-size: var(--t-micro);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--fg-muted);
}

.svc-flow__list {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(0.75rem, 2vw, 1.75rem);
  margin-top: clamp(1rem, 2vw, 1.5rem);
}

.svc-flow__list li {
  display: inline-flex;
  align-items: baseline;
  gap: 0.55rem;
  font-size: clamp(0.9375rem, 0.85rem + 0.4vw, 1.25rem);
  letter-spacing: var(--tracking-tight);
}

/* An arrow between steps, never after the last one. */
.svc-flow__list li:not(:last-child)::after {
  content: "→";
  margin-left: clamp(0.25rem, 1vw, 0.75rem);
  color: var(--fg-muted);
}

.svc-flow__n {
  font-size: var(--t-micro);
  letter-spacing: var(--tracking-label);
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 44rem) {
  /* Stacked, so the chain reads as steps rather than wrapping mid-arrow. */
  .svc-flow__list {
    display: grid;
    gap: 0.6rem;
  }
  .svc-flow__list li:not(:last-child)::after {
    content: none;
  }
}
