/* ==========================================================================
   Studio homepage — tokens lifted from the reference design
   ========================================================================== */

/* TAN Headline — licensed display face, used for the brand name. */
@font-face {
  font-family: "TAN Headline";
  src: url("../assets/fonts/TANHEADLINE-Regular.woff2") format("woff2"),
       url("../assets/fonts/TANHEADLINE-Regular.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  --black: #000;
  --ink: #0d0d12;
  --accent: #185448;      /* brand green, sampled from the Good Sourcing logo */
  --cta: #046454;         /* call-to-action fill */
  --cta-ink: #f2edc0;     /* call-to-action label, and the cream card tint */
  --pastel: #fae76d;      /* pastel yellow card tint */
  --white: #fff;
  --grey-f5: #f5f5f5;
  --grey-b3: #b3b3b3;
  --grey-line: #e6e6e6;

  --on-light: #000;
  --on-light-70: rgba(0, 0, 0, 0.55);
  --on-light-40: rgba(0, 0, 0, 0.28);
  --on-dark-75: rgba(255, 255, 255, 0.75);
  --on-dark-50: rgba(255, 255, 255, 0.5);
  --hairline-dark: rgba(255, 255, 255, 0.18);

  --panel-radius: 24px;
  --panel-inset: 72px;
  --panel-pad: 77px;
  /* How far a band's box runs on underneath its own white panel. That hidden stretch is
     the room its title/table need to stay pinned while the panel slides over them, so it
     must be at least the text block's height plus the band's 92px bottom padding. */
  --band-overlap: 300px;
  --card-radius: 16px;
  --pill: 196px;

  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-brand: "TAN Headline", "Instrument Serif", Georgia, serif;
  --ease: cubic-bezier(0.44, 0, 0.22, 1);
}

* { box-sizing: border-box; }
/* No `scroll-behavior: smooth` — it fights the JS smooth-scroll layer. */

body {
  margin: 0;
  background: var(--black);
  color: var(--white);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

h1, h2, h3, h4 { margin: 0; font-weight: 600; letter-spacing: -0.02em; line-height: 1.2; }
p { margin: 0; }
ul { list-style: none; margin: 0; padding: 0; }
a { color: inherit; text-decoration: none; transition: color 0.25s var(--ease), opacity 0.25s var(--ease); }
img { display: block; width: 100%; height: 100%; object-fit: cover; }
::selection { background: var(--accent); color: var(--white); }

/* ==========================================================================
   Panels & bands
   ========================================================================== */

.panel {
  background: var(--white);
  color: var(--on-light);
  border-radius: var(--panel-radius);
  padding: 96px var(--panel-pad) 104px;
  position: relative;
  z-index: 2;
}

/* Scroll-driven inset: JS overrides margin-inline per frame; this is the resting state. */
.panel, .panel-stack { margin-inline: var(--panel-inset); }
.panel-stack { position: relative; z-index: 2; }
.panel-stack > .panel { margin-inline: 0; }

/* Partly-expanding panel: rests narrower than the others and stops short of the screen
   edges at its widest, so its band photo keeps showing down both sides the whole way.
   JS reads these two values (see insetTargets in site.js). */
.panel-partial {
  --inset-rest: 118px;
  --inset-open: 24px;
  margin-inline: var(--inset-rest);
}

/* Panels stacked inside a group merge into one continuous white area */
.panel-stack > .panel + .panel { padding-top: 0; border-top-left-radius: 0; border-top-right-radius: 0; }
.panel-stack > .panel:has(+ .panel) { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }

/* Sits under the panel above it (z-index 1 vs the panel's 2) so its background can
   reach up behind that panel. No overflow:hidden — the media clips itself instead. */
.band {
  position: relative;
  z-index: 1;
  /* 560px shows; the overlap is hidden under this band's white panel. */
  min-height: calc(560px + var(--band-overlap));
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 0 calc(var(--panel-inset) + var(--panel-pad)) 92px;
}

/* Spacer filling the hidden stretch below the title/table. It has to be real content:
   a pinned (sticky) element can travel over its parent's content but not over its own
   margin, so a margin here would leave the text no room to stay put. */
.band::after {
  content: "";
  flex: none;
  height: var(--band-overlap);
}

/* The white panel after a band starts where the band visibly ends, overlapping the
   band's hidden stretch. */
.band + .panel { margin-top: calc(-1 * var(--band-overlap)); }

/* The background reaches beyond the band on both sides (both set by JS):
   --band-reach       up, behind the previous panel — clipped until .is-reaching reveals it
   --band-reach-down  down, behind this band's own white panel — always shown, since that
                      panel belongs to this section */
.band-media {
  position: absolute;
  inset: 0;
  top: calc(-1 * var(--band-reach, 0px));
  bottom: calc(-1 * var(--band-reach-down, 0px));
  z-index: 0;
  clip-path: inset(var(--band-reach, 0px) 0 0 0);
  /* clip-path only hides; this also stops a zoomed photo from lengthening the page. */
  overflow: hidden;
  overflow: clip;
}
.band-media.is-reaching { clip-path: inset(0); }

/* Scrim sits over the band plus a --band-fade zone (up to 160px) below it. Clear at the
   top so there's no seam against the panel above; at the bottom it eases back to clear
   across the fade zone, so the side strips of the panel below start without a hard edge. */
.band-media::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: var(--band-reach, 0px);
  /* ends --band-fade below where the band visibly stops (its box runs on under the panel) */
  bottom: calc(var(--band-reach-down, 0px) + var(--band-overlap) - var(--band-fade, 0px));
  background: linear-gradient(180deg,
    rgba(0, 0, 0, 0) 0%,
    rgba(0, 0, 0, 0) calc((100% - var(--band-fade, 0px)) * 0.38),
    rgba(0, 0, 0, 0.6) calc(100% - var(--band-fade, 0px) - 40px),
    rgba(0, 0, 0, 0) 100%);
}
/* Photos are far brighter than the placeholder tones, so the white title and table need a
   much heavier scrim where they sit. Stops before the fade zone are fractions of the band. */
.band-media.has-photo::after {
  background: linear-gradient(180deg,
    rgba(0, 0, 0, 0) 0%,
    rgba(0, 0, 0, 0) calc((100% - var(--band-fade, 0px)) * 0.28),
    rgba(0, 0, 0, 0.4) calc((100% - var(--band-fade, 0px)) * 0.45),
    rgba(0, 0, 0, 0.8) calc((100% - var(--band-fade, 0px)) * 0.58),
    rgba(0, 0, 0, 0.85) calc(100% - var(--band-fade, 0px) - 40px),
    rgba(0, 0, 0, 0) 100%);
}
/* Title and table pin just below the nav, then the band's white panel slides up over
   them, using the spacer below as room to stay put. */
.band > .band-inner {
  position: sticky;
  top: 110px;
  z-index: 1;
  width: 100%;
}

/* ==========================================================================
   Typography
   ========================================================================== */

.t-hero {
  font-size: 38px;
  font-weight: 600;
  line-height: 1.22;
  letter-spacing: -0.025em;
  max-width: 560px;
}

.t-statement {
  font-size: 46px;
  font-weight: 600;
  line-height: 1.45;
  letter-spacing: -0.025em;
  max-width: 690px;
}

.t-band-title {
  font-size: 78px;
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.035em;
}

.t-section {
  font-size: 46px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.03em;
}

.t-project { font-size: 38px; font-weight: 600; letter-spacing: -0.03em; }

.t-desc {
  font-size: 28px;
  line-height: 1.35;
  letter-spacing: -0.02em;
  color: var(--on-light-70);
}

.t-lead { font-size: 18px; line-height: 1.5; color: var(--on-light-70); }
.t-body { font-size: 16px; line-height: 1.5; color: var(--on-light-70); }
.t-small { font-size: 14px; line-height: 1.5; }
.t-eyebrow { font-size: 14px; letter-spacing: 0.02em; color: var(--on-light-40); }

.on-dark { color: var(--white); }
.on-dark .t-lead, .on-dark .t-body { color: var(--on-dark-75); }
.accent { color: var(--accent); }

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 19px 34px;
  border-radius: var(--pill);
  font-size: 15px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.01em;
  border: 0;
  cursor: pointer;
  transition: background 0.3s var(--ease), color 0.3s var(--ease), transform 0.3s var(--ease);
}
.btn svg { width: 13px; height: 13px; flex: none; }

/* Every call to action carries the same brand lock-up — green fill, cream label —
   whether it sits on the dark hero or on a white panel. Hover inverts the pair. */
.btn-white,
.btn-black,
.btn-outline-dark {
  background: var(--cta);
  color: var(--cta-ink);
  box-shadow: none;
}

.btn-white:hover,
.btn-black:hover,
.btn-outline-dark:hover {
  background: var(--cta-ink);
  color: var(--cta);
  transform: translateY(-2px);
}

.btn-lg { padding: 22px 44px; font-size: 16px; }

/* ==========================================================================
   Intro overlay
   ========================================================================== */

/* Fully CSS-driven so it starts on first paint, with no dependency on when JS runs.
   The self-clearing animation also means a failed script can never trap the page. */
.intro {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: var(--black);
  display: grid;
  place-items: center;
  animation: intro-exit 0.8s cubic-bezier(0.76, 0, 0.24, 1) 1.55s forwards;
}

/* The overlay lifts away as a panel rather than fading out: its bottom corners round
   early, then the whole sheet — final word included — travels up off screen. */
@keyframes intro-exit {
  0% {
    transform: translateY(0);
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
  }
  22% {
    border-bottom-left-radius: var(--panel-radius);
    border-bottom-right-radius: var(--panel-radius);
  }
  100% {
    transform: translateY(-100%);
    border-bottom-left-radius: var(--panel-radius);
    border-bottom-right-radius: var(--panel-radius);
    visibility: hidden;
  }
}


/* All three phases share one centred slot, so only one pair is ever on screen. */
.intro-stage {
  display: grid;
  width: 100%;
  /* Kept short. Words stay clear of each other because each cycle finishes inside its
     own slot (below), not because the travel is long. */
  --intro-travel: 34px;
}

/* Content starts at the exact horizontal centre: the dot straddles it (pulled back by
   half its width) and every word runs left-aligned from there, whatever its length. */
.intro-line {
  grid-area: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  padding-left: 50%;
  gap: 14px;
}

.intro-dot {
  width: 6px;
  height: 6px;
  margin-left: -3px;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
  opacity: 0;
}

.intro-word {
  font-size: 28px;
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.25;
  color: var(--white);
  white-space: nowrap;
  opacity: 0;
}

/* Dot travels top -> centre -> bottom; word travels bottom -> centre -> top.
   They cross in opposite directions and land on centre together. */
/* One phase every 0.5s. The cycle only just overruns its slot, so a pair is still
   leaving as the next arrives without the two words sharing the screen. */
.intro-line:nth-child(1) .intro-dot,
.intro-line:nth-child(2) .intro-dot { animation: dot-cycle 0.6s var(--ease) forwards; }
.intro-line:nth-child(1) .intro-word,
.intro-line:nth-child(2) .intro-word { animation: word-cycle 0.6s var(--ease) forwards; }

.intro-line:nth-child(2) .intro-dot,
.intro-line:nth-child(2) .intro-word { animation-delay: 0.5s; }

/* The closing phase is the brand name, so it carries the brand face. */
.intro-line:nth-child(3) .intro-word {
  font-family: var(--font-brand);
  font-weight: 400;
  font-size: 32px;
  letter-spacing: 0;
}

/* Final phase arrives and stays; the overlay fade carries it away. */
.intro-line:nth-child(3) .intro-dot { animation: dot-settle 0.3s var(--ease) 1s forwards; }
.intro-line:nth-child(3) .intro-word { animation: word-settle 0.3s var(--ease) 1s forwards; }

/* Strictly vertical travel — no X component, so the path is a straight line.
   Opacity is deliberately out of step with it: each element is fully visible by 16% but
   does not land until 40%, and stays opaque until 84% while already leaving. That keeps
   the movement on screen instead of hiding it behind a fade. */
@keyframes dot-cycle {
  0% { opacity: 0; transform: translateY(calc(var(--intro-travel) * -1)); }
  16% { opacity: 1; }
  40% { transform: translateY(0); }
  62% { transform: translateY(0); }
  84% { opacity: 1; }
  100% { opacity: 0; transform: translateY(var(--intro-travel)); }
}

@keyframes word-cycle {
  0% { opacity: 0; transform: translateY(var(--intro-travel)); }
  16% { opacity: 1; }
  40% { transform: translateY(0); }
  62% { transform: translateY(0); }
  84% { opacity: 1; }
  100% { opacity: 0; transform: translateY(calc(var(--intro-travel) * -1)); }
}

@keyframes dot-settle {
  0% { opacity: 0; transform: translateY(calc(var(--intro-travel) * -1)); }
  30% { opacity: 1; }
  100% { opacity: 1; transform: translateY(0); }
}

@keyframes word-settle {
  0% { opacity: 0; transform: translateY(var(--intro-travel)); }
  30% { opacity: 1; }
  100% { opacity: 1; transform: translateY(0); }
}

/* No JS: never trap the page behind the overlay */
.no-js .intro { display: none; }

/* Reduced motion keeps the same directional travel, just a gentler distance. */
@media (prefers-reduced-motion: reduce) {
  .intro-stage { --intro-travel: 30px; }
}

@media (max-width: 560px) {
  .intro-word { font-size: 22px; }
  /* The brand face is much wider per character, and the word starts at centre,
     so it has only half the viewport to live in. */
  .intro-line:nth-child(3) .intro-word { font-size: 20px; }
}

/* ==========================================================================
   Navigation
   ========================================================================== */

.site-nav {
  position: fixed;
  inset: 20px 0 auto 0;
  z-index: 100;
  pointer-events: none;
  will-change: transform, opacity;
  /* Returning: eased out, so it decelerates into place. */
  transition: transform 0.55s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.32s ease-out;
}

/* Travels its own height plus the 20px top inset so it clears the viewport entirely.
   Leaving: eased in, so it accelerates away rather than drifting. */
.site-nav.is-hidden {
  transform: translateY(calc(-100% - 28px));
  opacity: 0;
  transition: transform 0.42s cubic-bezier(0.7, 0, 0.84, 0), opacity 0.26s ease-in;
}

.nav-inner {
  margin-inline: var(--panel-inset);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.nav-brand,
.nav-cluster {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 7px;
  border-radius: var(--pill);
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(12, 12, 14, 0.55);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
}

/* White pill so the dark-green wordmark reads against the dark nav. */
.nav-brand {
  padding: 7px 16px;
  background: var(--white);
  border-color: transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.nav-logo { height: 28px; width: auto; display: block; object-fit: contain; }

.nav-cluster a { padding: 10px 18px; border-radius: var(--pill); font-size: 15px; color: var(--on-dark-75); }
.nav-cluster a:hover, .nav-cluster a.is-active { background: rgba(255, 255, 255, 0.1); color: var(--white); }

/* Links sit hard right, next to the logo on the left. */
.nav-cluster { margin-left: auto; }

/* Holds only the mobile toggle, so it is out of the way on desktop. */
.nav-actions { pointer-events: auto; display: none; align-items: center; gap: 10px; }

.nav-toggle {
  display: none;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(12, 12, 14, 0.55);
  backdrop-filter: blur(20px);
  color: var(--white);
  align-items: center;
  justify-content: center;
}

.nav-drawer {
  position: fixed;
  inset: 0;
  z-index: 99;
  /* Translucent so the page reads through it, frosted so the links stay legible over
     whatever card happens to be behind. */
  background: rgba(8, 8, 10, 0.78);
  -webkit-backdrop-filter: blur(22px);
  backdrop-filter: blur(22px);
  padding: 110px 28px 40px;
  display: none;
  flex-direction: column;
  gap: 30px;
  overflow-y: auto;
}
.nav-drawer.is-open { display: flex; }
.nav-drawer .drawer-group { display: flex; flex-direction: column; gap: 10px; }
.nav-drawer .drawer-group > a { font-size: 30px; font-weight: 600; letter-spacing: -0.03em; }
.nav-drawer .drawer-eyebrow { font-size: 13px; color: var(--on-dark-50); letter-spacing: 0.04em; text-transform: uppercase; margin-bottom: 6px; }
.nav-drawer .drawer-social a { font-size: 18px; color: var(--on-dark-75); }

/* ==========================================================================
   Hero
   ========================================================================== */

/* Sticky hero: following sections scroll over it */
.hero {
  position: sticky;
  top: 0;
  z-index: 0;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 100px calc(var(--panel-inset) + var(--panel-pad)) 0;
  overflow: hidden;
  container-type: inline-size;  /* lets the wordmark size itself to this width (cqw) */
}

.hero-media { position: absolute; inset: 0; z-index: 0; background: var(--ink); }
/* Starting scale matches the JS entry value so there's no jump before it runs;
   overflow:hidden on .hero / .band clips the enlarged edges. */
.hero-media img,
.hero-media video,
.band-media img { transform: scale(1.25); transform-origin: center; will-change: transform; }
/* Greyed like the footer film; the hero already carries a scrim, so it needs less
   darkening than the footer's 0.42. */
.hero-media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  filter: grayscale(1) brightness(0.55);
}
/* Band photos are sized and placed by JS so the part reaching behind the panel above is
   the same photo continuing upward, not a re-crop. */
.band-media img { position: absolute; max-width: none; }
/* 'band' fit photos end above and below the band; their edges fade into the band's fill
   (sampled from the photo's own backdrop) so the side strips show no seam. */
.band-media img[data-fit="band"] {
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 var(--fade-top, 0px), #000 calc(100% - var(--fade-bottom, 0px)), transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0, #000 var(--fade-top, 0px), #000 calc(100% - var(--fade-bottom, 0px)), transparent 100%);
}
.hero-media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.55) 0%, rgba(0, 0, 0, 0.15) 40%, rgba(0, 0, 0, 0.7) 100%);
}

.hero-top {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 48px;
  padding-top: 20px;
}

.hero-caps { text-align: right; display: flex; flex-direction: column; gap: 14px; }
.hero-caps li { font-size: 20px; font-weight: 600; letter-spacing: -0.01em; }

.wordmark {
  position: relative;
  z-index: 1;
  font-family: var(--font-brand);
  /* TAN Headline sets "good sourcing." at ~8.2x its font size in width, so dividing the
     hero's inner width (100cqw) by 8.3 fills it exactly at every screen size. */
  font-size: min(190px, calc(100cqw / 8.3));
  /* Only a Regular weight ships, so anything heavier would be faux-bolded. */
  font-weight: 400;
  line-height: 0.92;
  letter-spacing: -0.015em;
  padding-bottom: 34px;
  white-space: nowrap;
}
.wordmark .stop { color: var(--accent); }

/* ==========================================================================
   Statement panel
   ========================================================================== */

.statement-icon {
  display: inline-block;
  width: 0.62em;
  height: 0.62em;
  margin-inline: 0.1em -0.02em;
  color: var(--accent);
  vertical-align: -0.04em;
}
.statement-icon svg { width: 100%; height: 100%; display: block; }

/* Brand friendly section: statement and list share the left column, the card row sits
   right. --bf-card is both the card size and the width of that column. */
.brand-friendly { --bf-card: 520px; }
/* Statement in brand green; its inline icons follow the same colour. */
.brand-friendly .t-statement { color: var(--cta); }
.brand-friendly .t-statement .statement-icon { color: inherit; }
.brand-friendly-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--bf-card);
  gap: 64px;
  align-items: stretch;
}

/* Pinned run (desktop; JS adds .is-pinned and sets the wrapper's height to the panel plus
   one stretch of scroll per card). The panel sticks for that stretch, filling the screen,
   while the scroll steps through the cards instead of moving the page. */
.bf-pin { position: relative; z-index: 2; }
.bf-pin.is-pinned > .panel {
  position: sticky;
  top: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* All cards share one grid cell, so only the current one is seen and the rest wait out of
   sight: later cards below, earlier ones above. Moving the current mark forward makes the
   old card rise, shrink and fade while the new one rises in from below and settles;
   going back runs the same motion in reverse. */
.bf-stage {
  align-self: end;
  display: grid;
  width: var(--bf-card);
}
.bf-stage > .bf-card { grid-area: 1 / 1; }

/* Square because the cards carry their own text; the border gives white cards an edge on
   the white panel. The default state is "waiting below"; its transition is the exit, so
   a card leaving downwards (going back) uses it too. */
.bf-card {
  width: var(--bf-card);
  aspect-ratio: 1;
  border-radius: var(--card-radius);
  overflow: hidden;
  border: 1px solid var(--grey-line);
  background: var(--white);
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.05),
    0 10px 24px -8px rgba(0, 0, 0, 0.12),
    0 20px 40px -14px rgba(0, 0, 0, 0.18);
  opacity: 0;
  transform: translate3d(0, 80px, 0) scale(0.97);
  transition:
    transform 0.45s cubic-bezier(0.33, 0, 0.2, 1),
    opacity 0.3s ease;
  pointer-events: none;
  will-change: transform, opacity;
}
.bf-card.is-past { transform: translate3d(0, -56px, 0) scale(0.92); }
/* Entering: starts a beat after the old card begins to leave, then eases into place. */
.bf-card.is-current {
  opacity: 1;
  transform: none;
  z-index: 1;
  pointer-events: auto;
  transition:
    transform 0.6s cubic-bezier(0.16, 1, 0.3, 1) 0.06s,
    opacity 0.4s ease 0.06s;
}
.bf-card img { width: 100%; height: 100%; object-fit: cover; }

/* Heading pinned to the top, list to the bottom, whatever the row height. */
.brand-friendly-copy {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 44px;
}

/* Tighter bottom than other panels so the knitwear section follows closely. */
.panel.brand-friendly { padding-bottom: 56px; }

.showcase-list { display: flex; flex-direction: column; gap: 14px; }

.showcase-item {
  display: flex;
  align-items: baseline;
  gap: 30px;
  padding: 8px 0;
  background: none;
  border: 0;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  color: var(--grey-b3);
  transition: color 0.3s var(--ease);
}
.showcase-item .num { font-size: 15px; font-weight: 500; font-variant-numeric: tabular-nums; }
.showcase-item .label { font-size: 19px; font-weight: 600; letter-spacing: -0.02em; }
.showcase-item:hover { color: var(--on-light-70); }
.showcase-item.is-active { color: var(--on-light); }
.showcase-item.is-active .num { color: var(--accent); }


/* ==========================================================================
   Project band + detail
   ========================================================================== */

.band-foot {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 60px;
}

.band-meta { width: 360px; flex: none; }

.band-meta-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  padding-block: 13px;
  border-bottom: 1px dashed rgba(255, 255, 255, 0.3);
  font-size: 15px;
}
.band-meta-row:last-child { border-bottom: 0; }
.band-meta-row dt { color: var(--on-dark-75); }
.band-meta-row dd { margin: 0; font-weight: 600; color: var(--white); text-align: right; }

.project-detail {
  display: grid;
  grid-template-columns: minmax(0, 710px) minmax(0, 1fr);
  gap: 74px;
  align-items: stretch;
}

.project-media { border-radius: var(--card-radius); overflow: hidden; aspect-ratio: 710 / 718; }

.project-side { display: flex; flex-direction: column; padding-top: 34px; }
.project-side .t-desc { margin-top: 14px; max-width: 20ch; }
.project-side .btn { margin-top: 34px; align-self: flex-start; }

.project-foot {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: 20px;
  font-size: 14px;
  color: var(--on-light-70);
}
.project-foot .dashes { flex: 1; border-top: 1px dashed var(--on-light-40); }

/* ==========================================================================
   Generic section head
   ========================================================================== */

.section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 48px;
  flex-wrap: wrap;
  margin-bottom: 64px;
}
.section-head .t-lead { max-width: 46ch; }

/* ==========================================================================
   Studio / stats
   ========================================================================== */

.studio-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 74px; align-items: start; }

.chip-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 30px; }

.chip {
  padding: 9px 16px;
  border-radius: var(--pill);
  border: 1px solid var(--grey-line);
  font-size: 14px;
  color: var(--on-light-70);
}

.chip-status {
  border-color: rgba(24, 84, 72,0.3);
  background: rgba(24, 84, 72,0.07);
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  gap: 9px;
}
.status-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); flex: none; animation: pulse 2.4s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }

.meta-list { margin-top: 34px; display: flex; flex-direction: column; gap: 14px; }
.meta-row { display: flex; align-items: center; gap: 16px; font-size: 15px; }
.meta-row .lead-dots { flex: 1; border-top: 1px dashed var(--on-light-40); }
.meta-row .k { color: var(--on-light-70); }
.meta-row .v { display: inline-flex; align-items: center; gap: 8px; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.meta-row .v svg { width: 15px; height: 15px; flex: none; }

.stat-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--grey-line); border: 1px solid var(--grey-line); border-radius: var(--card-radius); overflow: hidden; }
.stat-cell { background: var(--white); padding: 40px 32px; }
.stat-value { font-size: 60px; font-weight: 600; line-height: 1; letter-spacing: -0.045em; font-variant-numeric: tabular-nums; }
.stat-cell:nth-child(odd) .stat-value { color: var(--accent); }
.stat-cell .t-small { color: var(--on-light-70); margin-top: 10px; }

/* Green panel (who we are section): brand green with cream text. Secondary text and
   rules are cream at lower strength; the button flips to cream so it doesn't vanish. */
.panel-dark {
  --on-dark-tint: rgba(242, 237, 192, 0.85);  /* lowest strength that keeps 4.5:1 */
  --on-dark-line: rgba(242, 237, 192, 0.25);
  background: var(--cta);
  color: var(--cta-ink);
}

/* Square bottom for a card the next full-width card meets head-on, so the two join with
   no notch. Only for those — every other card keeps its rounded corners. */
.panel-flush {
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}

/* Full-width sections (clients onward): always 100% wide, no scroll-driven widening, and
   square corners so each one meets the next without black notches. The last panel keeps
   its rounded bottom over the black footer. */
.panel.panel-full,
.panel-stack.panel-full { margin-inline: 0; }
.panel.panel-full { border-radius: 0; }
.panel-stack.panel-full > .panel:first-child { border-top-left-radius: 0; border-top-right-radius: 0; }
.panel-dark .t-lead,
.panel-dark .chip,
.panel-dark .meta-row .k,
.panel-dark .stat-cell .t-small { color: var(--on-dark-tint); }
.panel-dark .chip { border-color: var(--on-dark-line); }
.panel-dark .meta-row .lead-dots { border-top-color: var(--on-dark-line); }
/* Stats as a row of separate cards. Filled a shade darker than the panel (a lighter tint
   would drop the cream captions below 4.5:1) with a faint cream edge. */
.panel-dark .stat-grid {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
  background: none;
  border: 0;
  border-radius: 0;
  overflow: visible;
}
.panel-dark .stat-cell {
  background: rgba(0, 0, 0, 0.14);
  border: 1px solid var(--on-dark-line);
  border-radius: var(--card-radius);
  padding: 34px 28px;
}
/* The number cards read in white, not the cream used elsewhere on this card. */
.panel-dark .stat-value,
.panel-dark .stat-cell:nth-child(odd) .stat-value,
.panel-dark .stat-cell .t-small { color: var(--white); }
/* Who we are copy: cream heading (a full sentence, so smaller than other section heads),
   then white paragraphs. The brand name inside them is set in the brand face. */
.who-copy .t-section { font-size: 34px; line-height: 1.25; }
.who-copy .t-lead { margin-top: 18px; max-width: 52ch; }
.who-copy .t-section + .t-lead { margin-top: 30px; }
.panel-dark .who-copy .t-lead { color: var(--white); }
.brand-name { font-family: var(--font-brand); font-weight: 400; letter-spacing: -0.01em; }
/* MADE by good sourcing headings: only the brand name is in the brand face. */
.made-by-title .brand-name { white-space: nowrap; }  /* never split "good sourcing" */
.meta-row .v .tz { font-weight: 500; opacity: 0.8; }
.panel-dark .btn-outline-dark { background: var(--cta-ink); color: var(--cta); }
.panel-dark .btn-outline-dark:hover { background: transparent; color: var(--cta-ink); box-shadow: inset 0 0 0 1.5px var(--cta-ink); }

/* ==========================================================================
   Services
   ========================================================================== */

.service-list { border-top: 1px dashed var(--on-light-40); }

/* Card-stack: each row pins under the nav while the next slides over it */
.service-row {
  position: sticky;
  top: 120px;
  background: var(--white);
  display: grid;
  grid-template-columns: 230px minmax(0, 1fr) minmax(0, 420px);
  gap: 24px;
  align-items: start;
  padding-block: 46px;
  border-bottom: 1px dashed var(--on-light-40);
}
.service-row .num { font-size: 38px; font-weight: 600; line-height: 1; letter-spacing: -0.03em; color: var(--accent); }
.service-row h3 { font-size: 38px; letter-spacing: -0.03em; }
.made-by .service-row h3 { color: var(--cta); }

/* Heading left, square image card right (the cards carry their own text). Capped at 420px
   so a pinned row plus the nav still fits a laptop screen. */
.service-media {
  width: 100%;
  aspect-ratio: 1;
  border-radius: var(--card-radius);
  overflow: hidden;
  border: 1px solid var(--grey-line);
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.05),
    0 10px 24px -8px rgba(0, 0, 0, 0.12);
}
.service-media img { width: 100%; height: 100%; object-fit: cover; }

/* ==========================================================================
   Process
   ========================================================================== */

.process-rail {
  display: flex;
  align-items: center;
  gap: 18px;
  font-size: 14px;
  color: var(--on-light-70);
  margin-bottom: 34px;
}
.process-rail .rail { flex: 1; height: 1px; background: linear-gradient(90deg, var(--grey-line), var(--accent), var(--grey-line)); }

.process-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px; background: var(--grey-line); border: 1px solid var(--grey-line); border-radius: var(--card-radius); overflow: hidden; }
.process-cell { background: var(--white); padding: 32px 28px 40px; display: flex; flex-direction: column; gap: 60px; transition: background 0.35s var(--ease); }
.process-cell:hover { background: var(--grey-f5); }
.process-cell .num { font-size: 15px; font-weight: 500; color: var(--accent); }
.process-cell h3 { font-size: 22px; margin-bottom: 8px; }

/* ==========================================================================
   Pricing
   ========================================================================== */

.pricing-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; align-items: stretch; }

.price-card { border: 1px solid var(--grey-line); border-radius: var(--card-radius); padding: 36px; display: flex; flex-direction: column; }

.plan-switch { display: inline-flex; gap: 4px; padding: 4px; border-radius: var(--pill); background: var(--grey-f5); align-self: flex-start; }
.plan-switch button { border: 0; background: transparent; color: var(--on-light-70); font-family: inherit; font-size: 14px; font-weight: 600; padding: 10px 22px; border-radius: var(--pill); cursor: pointer; transition: background 0.3s var(--ease), color 0.3s var(--ease); }
.plan-switch button.is-active { background: var(--black); color: var(--white); }

.price-value { display: flex; align-items: baseline; gap: 6px; margin-top: 30px; }
.price-value strong { font-size: 64px; font-weight: 600; line-height: 1; letter-spacing: -0.045em; }
.price-value span { font-size: 18px; color: var(--on-light-70); }

.include-list { margin-top: 26px; display: grid; grid-template-columns: 1fr 1fr; gap: 12px 22px; }
.include-list li { display: flex; align-items: center; gap: 10px; font-size: 15px; color: var(--on-light-70); }
.check { width: 18px; height: 18px; border-radius: 50%; background: rgba(24, 84, 72,0.12); color: var(--accent); display: grid; place-items: center; flex: none; }
.check svg { width: 10px; height: 10px; }

.quote-card { border-radius: var(--card-radius); overflow: hidden; background: var(--ink); color: var(--white); display: flex; flex-direction: column; }
.quote-media { aspect-ratio: 4 / 3; position: relative; background: linear-gradient(140deg, #2a2a33, #0b0b0f); }
.quote-badge { position: absolute; left: 22px; bottom: 22px; padding: 10px 18px; border-radius: var(--pill); background: var(--cta); color: var(--cta-ink); font-size: 13px; font-weight: 600; }
.quote-body { padding: 30px 32px 34px; display: flex; flex-direction: column; gap: 22px; }
.quote-body blockquote { margin: 0; font-size: 20px; font-weight: 500; line-height: 1.5; letter-spacing: -0.02em; }
.quote-author { display: flex; align-items: center; gap: 12px; }
.quote-avatar { width: 42px; height: 42px; border-radius: 50%; background: linear-gradient(140deg, var(--accent), #7a1c00); flex: none; }
.quote-author .t-small { color: var(--on-dark-50); }

.benefit-grid { margin-top: 24px; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px; background: var(--grey-line); border: 1px solid var(--grey-line); border-radius: var(--card-radius); overflow: hidden; }
.benefit-cell { background: var(--white); padding: 30px 26px; display: flex; flex-direction: column; gap: 18px; }
.benefit-icon { width: 40px; height: 40px; border-radius: 50%; background: rgba(24, 84, 72,0.1); color: var(--accent); display: grid; place-items: center; flex: none; }
.benefit-icon svg { width: 18px; height: 18px; }
.benefit-cell h3 { font-size: 20px; }

/* ==========================================================================
   FAQ
   ========================================================================== */

.faq-grid { display: grid; grid-template-columns: 0.85fr 1.15fr; gap: 74px; align-items: start; }
.faq-list { border-top: 1px solid var(--grey-line); }
.faq-item { border-bottom: 1px solid var(--grey-line); }
.faq-q {
  width: 100%;
  background: none;
  border: 0;
  font-family: inherit;
  color: var(--on-light);
  font-size: 21px;
  font-weight: 600;
  letter-spacing: -0.02em;
  text-align: left;
  padding: 26px 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 22px;
  cursor: pointer;
}
.faq-q:hover { color: var(--accent); }
.faq-sign { width: 32px; height: 32px; border-radius: 50%; border: 1px solid var(--grey-line); display: grid; place-items: center; flex: none; transition: transform 0.35s var(--ease), background 0.35s var(--ease), color 0.35s var(--ease), border-color 0.35s var(--ease); }
.faq-item.is-open .faq-sign { transform: rotate(45deg); background: var(--accent); border-color: var(--accent); color: var(--white); }
.faq-a { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.4s var(--ease); }
.faq-item.is-open .faq-a { grid-template-rows: 1fr; }
.faq-a > div { overflow: hidden; }
.faq-a p { padding-bottom: 26px; max-width: 60ch; color: var(--on-light-70); }

/* ==========================================================================
   Blog
   ========================================================================== */

.blog-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }
.blog-card { display: flex; flex-direction: column; gap: 18px; }
.blog-thumb { border-radius: var(--card-radius); overflow: hidden; aspect-ratio: 4 / 3; transition: transform 0.5s var(--ease); }
.blog-card:hover .blog-thumb { transform: translateY(-4px); }
.blog-card h3 { font-size: 20px; }
.blog-card:hover h3 { color: var(--accent); }
.blog-card .t-small { color: var(--on-light-40); }

/* ==========================================================================
   Marquee + footer
   ========================================================================== */

.marquee { display: flex; overflow: hidden; user-select: none; gap: var(--gap, 40px); }
.marquee-track { flex: none; display: flex; align-items: center; gap: var(--gap, 40px); min-width: 100%; animation: marquee var(--dur, 30s) linear infinite; }
/* Hover pause only with a real pointer: on touch screens a tap would leave it frozen. */
@media (hover: hover) {
  .marquee:hover .marquee-track { animation-play-state: paused; }
}
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(calc(-100% - var(--gap, 40px))); } }
.marquee-item { display: flex; align-items: center; gap: 22px; white-space: nowrap; font-weight: 600; letter-spacing: -0.03em; }

/* Clients: cream panel with the logos running sideways. The tiles carry their own
   backgrounds (white, navy, yellow, black), so they sit as rounded squares on the cream;
   the edges fade so logos slide in and out rather than being cut off. */
.panel-cream { background: var(--cta-ink); color: var(--cta); }
.panel-yellow { background: var(--pastel); color: var(--cta); }
/* Secondary copy carries its own grey, which would fight the cream; keep it green. */
.panel-cream .t-desc, .panel-cream .t-lead,
.panel-yellow .t-desc, .panel-yellow .t-lead { color: var(--cta); }

/* Light tints: rules that assume a white card need the tint instead. The made-by rows
   stack over each other as they scroll, so they must be opaque in the card's own colour. */
.panel-cream .service-row { background: var(--cta-ink); }
.panel-yellow .service-row { background: var(--pastel); }
/* Rows slide over one another, so each needs its card's colour, opaque. */
.panel-dark .service-row { background: var(--cta); }

/* MADE by: only the heading block sits on the dark tint, in white. Everything below it —
   the numbered step rows — keeps the cream look it had before, so the list carries its own
   cream band across the full width of the card. */
.made-by.panel-dark { padding-bottom: 0; }
.made-by.panel-dark .t-section,
.made-by.panel-dark .t-lead { color: var(--white); }
.made-by.panel-dark .service-list {
  background: var(--white);
  margin-inline: calc(-1 * var(--panel-pad));
  padding-inline: var(--panel-pad);
  padding-bottom: 40px;
}
.made-by.panel-dark .service-list,
.made-by.panel-dark .service-row { border-color: var(--on-light-40); }
.made-by.panel-dark .service-row { background: var(--white); }
.made-by.panel-dark .service-row h3 { color: var(--cta); }
.made-by.panel-dark .service-row .num { color: var(--accent); }
.made-by.panel-dark .service-media { border-color: var(--grey-line); }
.panel-cream .service-list, .panel-yellow .service-list,
.panel-cream .service-row, .panel-yellow .service-row { border-color: rgba(4, 100, 84, 0.22); }
.panel-cream .service-media, .panel-yellow .service-media { border-color: rgba(4, 100, 84, 0.18); }

/* Dark tint: everything that is black or grey on a white card turns cream here. */
.panel-dark .t-statement,
.panel-dark .t-project,
.panel-dark .t-section { color: var(--cta-ink); }
.panel-dark .t-desc,
.panel-dark .showcase-item { color: var(--on-dark-tint); }
.panel-dark .showcase-item .num { color: rgba(242, 237, 192, 0.55); }
.panel-dark .showcase-item:hover { color: var(--cta-ink); }
.panel-dark .showcase-item.is-active { color: var(--cta-ink); }
.panel-dark .showcase-item.is-active .num { color: var(--cta-ink); }
.panel-dark .statement-icon { color: inherit; }
/* A green fill would vanish on the dark tint, so the buttons invert. */
.panel-dark .btn-black { background: var(--cta-ink); color: var(--cta); }
.panel-dark .btn-black:hover { background: transparent; color: var(--cta-ink); box-shadow: inset 0 0 0 1.5px var(--cta-ink); }

/* Contact form on the dark tint: the brand name and helper text are green on a white
   card, which would disappear here; the fields stay light so typing reads normally. */
.panel-dark .contact-intro .brand-name { color: var(--cta-ink); }
.panel-dark .field label,
.panel-dark .req { color: var(--cta-ink); }
.panel-dark .req-note { color: var(--on-dark-tint); }
.panel-dark .field input,
.panel-dark .field select,
.panel-dark .field textarea { background: var(--white); color: var(--on-light); }
.panel-dark .field input:focus,
.panel-dark .field select:focus,
.panel-dark .field textarea:focus { border-color: var(--cta-ink); box-shadow: 0 0 0 4px rgba(242, 237, 192, 0.3); }
.panel-dark .field-error { color: #ffc9c2; }
.panel-dark .field [aria-invalid="true"] { border-color: #ffc9c2; background: #fff5f4; }
.panel-dark .form-status { background: rgba(242, 237, 192, 0.16); color: var(--cta-ink); }
.panel.clients { padding-block: 72px 80px; }
.clients-label { text-align: center; font-size: 15px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; margin-bottom: 36px; }
.clients-marquee {
  --gap: 28px;
  --dur: 32s;
  margin-inline: calc(-1 * var(--panel-pad));
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 12%, #000 88%, transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 12%, #000 88%, transparent 100%);
}
.clients-marquee .marquee-track { margin: 0; padding: 6px 0 18px; list-style: none; }
.client-logo {
  flex: none;
  width: 150px;
  aspect-ratio: 1;
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06), 0 10px 22px -10px rgba(4, 100, 84, 0.35);
}
.client-logo img { width: 100%; height: 100%; object-fit: cover; }

/* Contact: heading left, form right. Last panel before the black footer, so it keeps its
   rounded bottom even though full-width panels are otherwise square. */
.panel.contact { border-bottom-left-radius: var(--panel-radius); border-bottom-right-radius: var(--panel-radius); }
.contact-grid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 74px; align-items: start; }
.contact-intro .t-section .brand-name { white-space: nowrap; color: var(--cta); }

.contact-form { display: flex; flex-direction: column; gap: 22px; }
.field-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px; }
.field { display: flex; flex-direction: column; gap: 8px; }
.field label { font-size: 14px; font-weight: 600; }
.req { color: var(--cta); margin-left: 2px; }

/* 16px text so phones don't zoom in on focus. */
.field input,
.field select,
.field textarea {
  width: 100%;
  font: inherit;
  font-size: 16px;
  color: var(--on-light);
  background: var(--grey-f5);
  border: 1px solid transparent;
  border-radius: 12px;
  padding: 15px 18px;
  transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease), background 0.2s var(--ease);
}
.field textarea { resize: vertical; min-height: 160px; }
.field input:hover, .field select:hover, .field textarea:hover { border-color: var(--grey-line); }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  background: var(--white);
  border-color: var(--cta);
  box-shadow: 0 0 0 4px rgba(4, 100, 84, 0.15);
}
.field [aria-invalid="true"] { border-color: #b42318; background: #fef3f2; }
.field-error { font-size: 14px; color: #b42318; }

.select-wrap { position: relative; }
.select-wrap select { appearance: none; -webkit-appearance: none; padding-right: 48px; cursor: pointer; }
.select-wrap select:invalid { color: var(--on-light-70); }  /* placeholder option showing */
.select-wrap svg { position: absolute; right: 18px; top: 50%; width: 14px; height: 14px; transform: translateY(-50%); pointer-events: none; color: var(--on-light-70); }

.form-foot { display: flex; align-items: center; justify-content: space-between; gap: 20px; flex-wrap: wrap; margin-top: 6px; }
.req-note { font-size: 14px; color: var(--on-light-70); }
.form-status { padding: 14px 18px; border-radius: 12px; background: rgba(4, 100, 84, 0.1); color: var(--cta); font-weight: 600; }

/* Spam trap: off-screen rather than display:none, which some bots skip. */
.hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Page lift-off: everything in main sits on black above the footer, which is pinned to the
   bottom of the screen behind it. The transparent .footer-spacer after main is the one
   place the footer shows through, so scrolling into it uncovers the footer. */
:root { --footer-h: 100vh; }
@supports (height: 100svh) { :root { --footer-h: 100svh; } }
main { position: relative; z-index: 1; background: var(--black); }
.footer-spacer { height: var(--footer-h); }

/* Ticker strip between the last section and the footer. */
/* Positioned above the sticky hero, which otherwise shows through at the end of the page. */
.ticker { position: relative; z-index: 2; background: var(--black); padding-block: 36px; }
.ticker-marquee { --gap: 35px; --dur: 60s; }
.ticker-item { flex: none; white-space: nowrap; font-size: 12px; line-height: 18px; font-weight: 600; text-transform: uppercase; color: var(--on-dark-50); }
.ticker-item .brand-name { text-transform: none; font-size: 14px; letter-spacing: 0; }
.ticker-diamond { flex: none; width: 12px; height: 16px; color: var(--cta); }

/* Footer: full screen, background film dimmed and greyed, links top-left, "Let's chat"
   top-right, a rule, then the wordmark filling the width at the bottom. */
.site-footer {
  position: fixed;
  inset: auto 0 0 0;
  height: var(--footer-h);
  z-index: 0;
  overflow: hidden;
  background: var(--black);
  color: var(--white);
}
.footer-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1) brightness(0.42);
}
.footer-inner {
  --ft-pad: 144px;
  position: relative;
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: 120px var(--ft-pad) 0;
  container-type: inline-size;
}
.footer-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 40px; }
.footer-links { display: grid; grid-template-columns: 296px auto; padding-top: 8px; }
.footer-label { font-size: 16px; line-height: 24px; color: var(--on-dark-50); margin-bottom: 16px; }
.footer-col ul { display: flex; flex-direction: column; gap: 8px; margin: 0; padding: 0; list-style: none; }
.footer-col a { font-size: 24px; line-height: 33.6px; font-weight: 600; letter-spacing: -0.02em; color: var(--on-dark-75); transition: color 0.25s var(--ease); }
.footer-col a:hover, .footer-col a.is-active { color: var(--white); }

.footer-chat { width: 280px; display: flex; flex-direction: column; gap: 16px; }
.footer-chat-title { font-size: 40px; line-height: 50px; font-weight: 600; letter-spacing: -0.03em; color: var(--white); margin: 0; }
.footer-btn {
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border-radius: var(--pill);
  font-size: 16px;
  font-weight: 600;
  transition: background 0.3s var(--ease), color 0.3s var(--ease), box-shadow 0.3s var(--ease), transform 0.3s var(--ease);
}
.footer-btn svg { width: 18px; height: 18px; flex: none; }
.footer-btn:hover { transform: translateY(-2px); }
.footer-btn-solid { background: var(--cta); color: var(--cta-ink); }
.footer-btn-solid:hover { background: var(--cta-ink); color: var(--cta); }
.footer-btn-outline { color: var(--white); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.9); }
.footer-btn-outline:hover { background: var(--white); color: var(--black); }

.footer-rule { margin-top: auto; height: 1px; background: var(--cta); flex: none; }
/* Sized from the brand face's proportions (about 8.2x as wide as its font size) so
   "good sourcing." spans the column exactly. */
.footer-wordmark {
  margin: clamp(56px, 19.5vh, 176px) 0 0;
  font-family: var(--font-brand);
  font-weight: 400;
  font-size: calc(100cqw / 8.3);
  line-height: 1;
  padding-bottom: 0.26em;  /* room for the g descenders above the screen edge */
  letter-spacing: -0.015em;
  white-space: nowrap;
  color: var(--white);
}
.footer-wordmark .stop { color: var(--cta); }

/* ==========================================================================
   Reveal
   ========================================================================== */

/* Not switched off under prefers-reduced-motion: the site owner wants every effect to play. */
[data-reveal] { opacity: 0; transform: translateY(30px); transition: opacity 0.85s var(--ease), transform 0.85s var(--ease); }
[data-reveal].is-visible { opacity: 1; transform: none; }

/* ==========================================================================
   Responsive
   ========================================================================== */

@media (max-width: 1180px) {
  :root { --panel-inset: 28px; --panel-pad: 44px; }
  .panel-partial { --inset-rest: 56px; --inset-open: 12px; }
  .t-hero { font-size: 34px; }
  .t-statement, .t-section { font-size: 36px; }
  .who-copy .t-section { font-size: 30px; }
  .t-band-title { font-size: 56px; }
  .brand-friendly { --bf-card: 400px; }
  .brand-friendly-grid { gap: 44px; }
  .project-detail { grid-template-columns: 1fr; gap: 40px; }
  .project-side { padding-top: 0; }
  .studio-grid, .faq-grid, .contact-grid { grid-template-columns: 1fr; gap: 48px; }
  .pricing-grid { grid-template-columns: 1fr; }
  .process-grid, .benefit-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .service-row { grid-template-columns: 56px minmax(0, 1fr); }
  .service-row .service-media { grid-column: 2; max-width: 420px; }
  .blog-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .panel-dark .stat-cell { padding: 28px 22px; }
  .panel-dark .stat-value { font-size: 48px; }
  .footer-inner { --ft-pad: 72px; }
  .footer-links { grid-template-columns: 220px auto; }
}

@media (max-width: 860px) {
  :root { --panel-inset: 14px; --panel-pad: 26px; }
  .panel-partial { --inset-rest: 26px; --inset-open: 6px; }
  .panel { padding-block: 64px 72px; }
  .nav-cluster { display: none; }
  .nav-actions { display: flex; }
  .nav-toggle { display: flex; }
  /* Translucent white so the photo behind shows through the logo pill. No backdrop blur:
     on some browsers and GPUs it paints as a solid black box inside the fixed nav. */
  .nav-brand { background: rgba(255, 255, 255, 0.72); }
  /* Title and table stack on small screens, so the pinned text block is taller. */
  :root { --band-overlap: 380px; }
  .band { min-height: calc(560px + var(--band-overlap)); }
  .band-foot { flex-direction: column; align-items: flex-start; gap: 32px; }
  .band-meta { width: 100%; }
  .hero-top { flex-direction: column; gap: 30px; }
  .hero-caps { text-align: left; }
  .brand-friendly-grid { grid-template-columns: 1fr; gap: 34px; }
  /* No scroll widening here, so the green section rests full width to meet the clients. */
  .panel-dark { margin-inline: 0; }
  /* Brand friendly, compact enough that the pinned panel fits a phone screen: tighter
     spacing and type, and the card sized from the height left over (~400px of copy plus
     the top room kept clear for the nav, which slides back in on the way up). The 200px
     floor is for the unpinned fallback on a phone turned sideways. */
  .brand-friendly { --bf-card: min(78vw, 420px, max(200px, calc(100svh - 465px))); }
  .bf-pin.is-pinned > .panel { min-height: 100svh; padding-block: 84px 24px; }
  .bf-pin.is-pinned .brand-friendly-grid { gap: 20px; }
  .bf-pin.is-pinned .brand-friendly-copy { gap: 18px; }
  .bf-pin.is-pinned .t-statement { font-size: 24px; }
  .bf-pin.is-pinned .showcase-list { gap: 2px; }
  .bf-pin.is-pinned .showcase-item { padding: 11px 0; gap: 18px; }
  .bf-pin.is-pinned .showcase-item .label { font-size: 16px; }
  /* Unpinned fallback: tap an item or swipe the card. */
  .bf-stage { touch-action: pan-y; }
  .t-band-title { font-size: 40px; }
  .t-desc { font-size: 22px; }
  .stat-grid, .process-grid, .benefit-grid, .blog-grid, .include-list { grid-template-columns: 1fr; }
  /* Footer as on the reference's phone layout: "Let's chat" and its buttons first, then
     the two link columns without their labels, smaller type. */
  .footer-inner { --ft-pad: 20px; padding-top: 64px; }
  .footer-top { flex-direction: column-reverse; gap: 66px; }
  .footer-chat { width: 100%; }
  .footer-chat-title { font-size: 24px; line-height: 30px; letter-spacing: -0.03em; }
  .footer-links { grid-template-columns: 1fr 1fr; gap: 0 16px; padding-top: 0; width: 100%; }
  .footer-label { display: none; }
  .footer-col a { font-size: 16px; line-height: 24px; letter-spacing: 0; }
  .footer-wordmark { margin-top: clamp(48px, 19vh, 160px); }
  /* Stat cards stay in one row down to phone width, just smaller. */
  .panel-dark .stat-grid { gap: 12px; }
  .panel-dark .stat-cell { padding: 22px 16px; }
  .panel-dark .stat-value { font-size: 34px; }

  /* Comfortable tap targets: a finger needs ~44px, these were 20-33px. */
  .showcase-item { padding: 11px 0; }
  .footer-col ul { gap: 2px; }
  .footer-col a,
  .footer-col .nav-plain { display: inline-block; padding-block: 10px; }

  /* MADE by: the band above already says "MADE by good sourcing", so the first row's
     repeat of it goes, and the band and rows lose some of their desktop spacing. */
  .made-by .section-head { margin-bottom: 30px; }
  .made-by .service-row:first-child .num:empty + h3 { display: none; }
  .service-row { padding-block: 28px; }

  /* The who we are copy is four long paragraphs; a touch smaller keeps it from running on. */
  .who-copy .t-lead { font-size: 16px; }
  .who-copy .t-lead { margin-top: 14px; }

  /* Product cards: less dead space under the button. */
  .panel { padding-block: 64px 56px; }
}

@media (max-width: 560px) {
  .t-hero { font-size: 27px; }
  .t-statement, .t-section { font-size: 28px; }
  .who-copy .t-section { font-size: 24px; }
  .stat-value { font-size: 44px; }
  /* Too narrow for four across: two rows of two cards. */
  .panel-dark .stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .panel-dark .stat-value { font-size: 36px; }
  .price-value strong { font-size: 46px; }
  /* Size comes from the clamp above — it already accounts for the brand face's width. */
  .wordmark { padding-bottom: 24px; }
  .field-row { grid-template-columns: 1fr; }
  .form-foot .btn { width: 100%; justify-content: center; }
  .clients-marquee { --gap: 18px; }
  .client-logo { width: 108px; border-radius: 12px; }
  /* Made by rows: smaller headings so the lockup fits, image across the full row. */
  .service-row h3 { font-size: 24px; }
  /* A row without a number gives its heading the number's space too, so "good sourcing?"
     (never split) fits even on the narrowest phones. */
  .service-row .num:empty { display: none; }
  .service-row .num:empty + h3 { grid-column: 1 / -1; }
  .service-row .service-media { grid-column: 1 / -1; max-width: none; }
}

/* Short phones (e.g. 320x568): the pinned brand friendly panel and the full-screen footer
   tighten up so everything fits under the nav. */
@media (max-width: 860px) and (max-height: 640px) {
  .brand-friendly { --bf-card: min(78vw, 420px, max(128px, calc(100svh - 430px))); }
  .bf-pin.is-pinned > .panel { padding-top: 72px; }
  .bf-pin.is-pinned .t-statement { font-size: 20px; }
  .bf-pin.is-pinned .showcase-item { padding: 9px 0; }
  .bf-pin.is-pinned .showcase-item .label { font-size: 15px; }
  .footer-inner { padding-top: 32px; }
  .footer-top { gap: 28px; }
  .footer-chat { gap: 10px; }
  .footer-btn { height: 52px; }
  .footer-wordmark { margin-top: 24px; }
}

/* Nav labels with no destination yet (About, Work, Contact): same look as the links, but
   not clickable. */
.nav-plain { cursor: default; }
.nav-cluster .nav-plain { padding: 10px 18px; border-radius: var(--pill); font-size: 15px; color: var(--on-dark-75); }
.nav-drawer .nav-plain { color: var(--on-dark-75); }
.footer-col .nav-plain { font-size: inherit; color: var(--on-dark-75); }

/* ==========================================================================
   Per-card colours set in the admin
   A card given its own colours carries .panel-custom plus two inline custom
   properties. Everything below derives from those two, so one pair of colours
   dresses the whole card: headings, secondary copy, rules, tiles and buttons.
   The preset tints above are left exactly as they were — a card with no
   colours set never gets this class.
   ========================================================================== */

.panel-custom {
  /* Secondary copy: the lowest strength that still clears 4.5:1 against the
     card when the pairing itself is readable. */
  --panel-ink-80: color-mix(in srgb, var(--panel-ink) 85%, transparent);
  --panel-ink-55: color-mix(in srgb, var(--panel-ink) 55%, transparent);
  --panel-ink-25: color-mix(in srgb, var(--panel-ink) 25%, transparent);
  --panel-ink-08: color-mix(in srgb, var(--panel-ink) 8%, transparent);
  background: var(--panel-bg);
  color: var(--panel-ink);
}

/* Headings and body copy, which otherwise carry their own ink. */
.panel-custom .t-statement,
.panel-custom .t-project,
.panel-custom .t-section,
.panel-custom .t-lead,
.panel-custom .who-copy .t-lead,
.panel-custom .contact-intro .brand-name { color: var(--panel-ink); }

.panel-custom .t-desc,
.panel-custom .showcase-item,
.panel-custom .chip,
.panel-custom .meta-row .k,
.panel-custom .req-note { color: var(--panel-ink-80); }

.panel-custom .showcase-item .num { color: var(--panel-ink-55); }
.panel-custom .showcase-item:hover,
.panel-custom .showcase-item.is-active,
.panel-custom .showcase-item.is-active .num { color: var(--panel-ink); }
.panel-custom .statement-icon { color: inherit; }

/* Hairlines and edges. */
.panel-custom .chip { border-color: var(--panel-ink-25); }
.panel-custom .meta-row .lead-dots { border-top-color: var(--panel-ink-25); }
.panel-custom .service-list,
.panel-custom .service-row,
.panel-custom .service-media { border-color: var(--panel-ink-25); }

/* The MADE by rows slide over one another, so each has to be opaque in the
   card's own colour rather than see-through. */
.panel-custom .service-row { background: var(--panel-bg); }
.panel-custom .service-row h3,
.panel-custom .service-row .num { color: var(--panel-ink); }

/* Number tiles: a wash of the card's own ink, so they read as recessed on a
   light card and raised on a dark one without needing to know which it is. */
.panel-custom .stat-grid {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
  background: none;
  border: 0;
  border-radius: 0;
  overflow: visible;
}

.panel-custom .stat-cell {
  background: var(--panel-ink-08);
  border: 1px solid var(--panel-ink-25);
  border-radius: var(--card-radius);
  padding: 34px 28px;
}

.panel-custom .stat-value,
.panel-custom .stat-cell:nth-child(odd) .stat-value { color: var(--panel-ink); }
.panel-custom .stat-cell .t-small { color: var(--panel-ink-80); }

/* Buttons invert the pair: the ink fills them, the card colour letters them. */
.panel-custom .btn-black,
.panel-custom .btn-outline-dark {
  background: var(--panel-ink);
  color: var(--panel-bg);
}

.panel-custom .btn-black:hover,
.panel-custom .btn-outline-dark:hover {
  background: transparent;
  color: var(--panel-ink);
  box-shadow: inset 0 0 0 1.5px var(--panel-ink);
}

/* Contact form: the fields stay white wells whatever the card colour, since the
   text typed into them is the visitor's, not the brand's. */
.panel-custom .field label,
.panel-custom .req { color: var(--panel-ink); }
.panel-custom .field input,
.panel-custom .field select,
.panel-custom .field textarea {
  background: var(--white);
  color: var(--on-light);
  border-color: var(--panel-ink-25);
}
.panel-custom .field input:focus,
.panel-custom .field select:focus,
.panel-custom .field textarea:focus {
  border-color: var(--panel-ink);
  box-shadow: 0 0 0 4px var(--panel-ink-25);
}
.panel-custom .form-status {
  background: var(--panel-ink-08);
  color: var(--panel-ink);
}

@media (max-width: 1024px) {
  .panel-custom .stat-cell { padding: 28px 22px; }
  .panel-custom .stat-value { font-size: 48px; }
}

@media (max-width: 760px) {
  .panel-custom .stat-grid { gap: 12px; }
  .panel-custom .stat-cell { padding: 22px 16px; }
  .panel-custom .stat-value { font-size: 34px; }
}

@media (max-width: 560px) {
  .panel-custom .stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .panel-custom .stat-value { font-size: 36px; }
}

/* MADE by is built as a coloured heading band sitting on a white band of step rows.
   Custom colours dress the heading band; the rows stay white, as they are with the
   preset tint. These carry the same weight as the .made-by.panel-dark rules above and
   come later, so they win without needing to be made artificially specific. */
.made-by.panel-custom .t-section,
.made-by.panel-custom .t-lead { color: var(--panel-ink); }
.made-by.panel-custom .service-list,
.made-by.panel-custom .service-row { background: var(--white); border-color: var(--on-light-40); }
.made-by.panel-custom .service-row h3 { color: var(--cta); }
.made-by.panel-custom .service-row .num { color: var(--accent); }
.made-by.panel-custom .service-media { border-color: var(--grey-line); }
