/* GIZAY landing page. Locked system, do not extend.
   Colour: Forest, Olive (labels only), Icy White (ground), Dusty Blue (under the photos only, since her verdict
   of 2026-09-04: no pale blue field on this page), Deep Teal and Slate (rare, never together).
   Type: Montas (display), Helvetica Neue (text), IBM Plex Mono (data). */

@font-face { font-family: "Montas"; src: url("fonts/Montas-Regular.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Helvetica Neue W"; src: url("fonts/HelveticaNeue-Light.woff2") format("woff2"); font-weight: 300; font-style: normal; font-display: swap; }
@font-face { font-family: "Helvetica Neue W"; src: url("fonts/HelveticaNeue-Roman.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Helvetica Neue W"; src: url("fonts/HelveticaNeue-Medium.woff2") format("woff2"); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: "IBM Plex Mono"; src: url("fonts/IBMPlexMono-Regular.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "IBM Plex Mono"; src: url("fonts/IBMPlexMono-Medium.woff2") format("woff2"); font-weight: 500; font-style: normal; font-display: swap; }

:root {
  --forest: #2F3821;
  --olive: #576034;
  --icy: #F2FAFE;
  --dusty: #C1D4DA;
  --teal: #496472;
  --slate: #53636D;
  --ground: var(--icy);

  --display: "Montas", "Cormorant Garamond", Georgia, serif;
  --text: "Helvetica Neue W", "Inter", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --gutter: clamp(1.25rem, 4vw, 3.5rem);
  --head-h: 5rem;
  --section-y: clamp(5rem, 14vh, 9rem);
  --ease-out: cubic-bezier(0.2, 0.7, 0.2, 1);
}

*, *::before, *::after { box-sizing: border-box; }

/* No CSS smooth scrolling: ScrollTrigger scrolls the page while it measures the pins, and a smooth scroll
   turns those measurements into a moving target. The one anchor (the hero CTA) is scrolled by script. */
html { background: var(--ground); color: var(--forest); -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font-family: var(--text);
  font-weight: 300;
  line-height: 1.5;
  background: var(--ground);
  color: var(--forest);
  -webkit-font-smoothing: antialiased;
}
img { display: block; max-width: 100%; }
a { color: inherit; }
:focus-visible { outline: 2px solid var(--forest); outline-offset: 4px; }
h1, h2, h3 { font-family: var(--display); font-weight: 400; letter-spacing: 0; margin: 0; }
p, dl, dd, figure { margin: 0; }
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* Shared: the mono label. Caps, 1px tracking, small only. */
.mono, .hero__spec, .jstop__spec, .swatch__code, .site-foot__spec, .placeholder-note, .lang, .ledger dt, .map__frame figcaption {
  font-family: var(--mono);
  font-weight: 400;
  font-size: 0.6875rem;
  letter-spacing: 1px;
  text-transform: uppercase;
}

/* Header: wordmark alone, per the brand rules. Clear space is half the cap height on all sides. */
.site-head {
  position: absolute;
  inset: 0 0 auto 0;
  z-index: 5;
  height: var(--head-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--gutter);
}
.site-head__mark { display: inline-block; text-decoration: none; }
.site-head__mark img { width: 6.25rem; height: auto; }
.site-head__right { display: flex; align-items: center; gap: 1.5rem; }
.lang {
  appearance: none;
  background: none;
  border: 0;
  padding: 0.5rem 0.25rem;
  margin: 0 -0.25rem 0 0;
  color: var(--forest);
  cursor: pointer;
  line-height: 1;
}
.lang:hover { color: var(--olive); }

/* Never silent: the placeholder is labelled on the preview build. */
.placeholder-note { color: var(--slate); font-size: 0.625rem; }
.placeholder-note--hero { display: none; }
.placeholder-note--close {
  position: absolute;
  right: var(--gutter);
  bottom: 1.25rem;
  z-index: 2;
  color: var(--icy);
}

/* ---------- Hero. The ground under the poster is Dusty Blue, never white; the poster itself is bone. ---------- */
.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  grid-template-rows: 1fr auto;
  overflow: hidden;
  background: var(--dusty);
  isolation: isolate;
}
/* The stage holds the picture and the icon. It drifts down at a fraction of the scroll once the
   sequence has resolved, straight down, so the picture leaves with depth and no edge. */
.hero__stage { position: absolute; inset: 0; z-index: 0; }
.hero__media { position: absolute; inset: 0; z-index: 0; }
.hero__media picture { display: block; width: 100%; height: 100%; }
.hero__still { width: 100%; height: 100%; object-fit: cover; object-position: 50% 50%; }
/* Two clips on top of the still. hero.js crossfades them so the loop never jumps.
   Locked-off camera in the clip; the push-in is a transform on .hero__media, centred on the boll. */
.hero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  opacity: 0;
}
/* The icon draws itself on over the boll during the push-in, then recedes.
   hero.js sizes and places it so its three circles sit on the three lobes. */
.hero__icon { position: absolute; z-index: 1; width: 15rem; pointer-events: none; opacity: 0; }
.hero__icon svg { display: block; width: 100%; height: auto; }
.is-seq .hero__media { will-change: transform; }
.is-seq .hero__icon { will-change: opacity, filter; }
.is-seq [data-land] { opacity: 0; }

.hero__copy {
  position: relative;
  z-index: 2;
  grid-row: 2;
  align-self: end;
  padding: 0 var(--gutter) clamp(2rem, 6vh, 4rem);
  max-width: 44rem;
}
.hero__title {
  margin: 0 0 1rem;
  font-size: clamp(2.5rem, 5.4vw, 5.5rem);
  line-height: 1.04;
  text-wrap: balance;
  max-width: 13ch;
}
.hero__sub {
  margin: 0 0 1.875rem;
  font-size: clamp(1.0625rem, 1.3vw, 1.375rem);
  font-weight: 300;
  line-height: 1.45;
  max-width: 32rem;
}
.cta {
  display: inline-block;
  padding: 0.9rem 1.5rem;
  background: var(--forest);
  color: var(--icy);
  font-family: var(--text);
  font-weight: 500;
  font-size: 0.9375rem;
  line-height: 1;
  letter-spacing: 0;
  text-decoration: none;
  white-space: nowrap;
  border: 0;
  border-radius: 0;
  cursor: pointer;
  transition: opacity 240ms ease;
}
.cta:hover { opacity: 0.88; }
.cta:disabled { opacity: 0.6; cursor: default; }
.cta:focus-visible { outline-color: var(--forest); outline-offset: 4px; }
/* Mono caption: the proof, in Olive. */
.hero__spec {
  position: absolute;
  right: var(--gutter);
  bottom: clamp(2rem, 6vh, 4rem);
  z-index: 2;
  color: var(--olive);
  white-space: nowrap;
}

/* Still frame (reduced motion, ?frame=still, no script): the poster and the type. Finished, never white. */
.is-still .hero__icon { display: none; }
@media (prefers-reduced-motion: reduce) {
  .hero__icon { display: none; }
  .hero__stage, .hero__media, [data-land], [data-reveal], .story__definition .w, .ledger__row > *, .ledger__row::before, .ledger__row::after, .close__still { opacity: 1 !important; transform: none !important; }
  .cta, .map__dot::after, .ledger__row::before { transition: none; }
  .map__dot::before { animation: none; }
  .map__head { display: none; }
}

/* ---------- Section two: the name, on the bone the hero leaves behind ---------- */
.story { position: relative; overflow: hidden; padding: var(--section-y) var(--gutter) calc(var(--section-y) * 0.6); }
.story__inner {
  position: relative;
  max-width: 80rem;
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: var(--gutter);
  row-gap: clamp(1.75rem, 4vh, 3rem);
  align-items: start;
}
.story__title {
  grid-column: 1 / span 7;
  font-size: clamp(2.25rem, 4vw, 3.75rem);
  line-height: 1.08;
  text-wrap: balance;
  max-width: 14ch;
  margin-bottom: 0;
}
/* The definition, read in word by word by the scroll. Each word rests at low opacity until the scroll reaches it. */
.story__definition {
  grid-column: 1 / span 8;
  font-family: var(--display);
  font-size: clamp(1.75rem, 3.4vw, 3.5rem);
  line-height: 1.22;
  max-width: 26ch;
  text-wrap: pretty;
}
.story__definition .w { display: inline; }
.has-scroll .story__definition .w { opacity: 0.16; }
/* Four beats on an asymmetric grid, not a column: heading and definition left, the source block opposite,
   the statement dropped low with air around it, the philosophy as the quiet last beat before the map. */
.story__source { grid-column: 7 / span 6; margin-top: clamp(0.75rem, 2vh, 1.5rem); }
.story__statement { grid-column: 2 / span 9; margin: clamp(0.5rem, 2vh, 1.5rem) 0 0; }
.story__close { grid-column: 8 / span 5; }
.story__eyebrow {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--slate);
  margin: 0 0 0.9rem;
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--dusty);
}
.story__lede, .story__philosophy { font-size: clamp(1.0625rem, 1.15vw, 1.1875rem); line-height: 1.55; margin: 0; }
.story__lede { max-width: 34ch; }
.story__philosophy { max-width: 32ch; }
/* The bridge from source to cloth: display face, one step up from body, well below the statement. */
.story__bridge {
  font-family: var(--display);
  font-size: clamp(1.1875rem, 1.55vw, 1.5rem);
  line-height: 1.3;
  margin: 1.4rem 0 0;
  max-width: 26ch;
}
.story__statement {
  font-family: var(--display);
  font-size: clamp(1.625rem, 2.7vw, 2.75rem);
  line-height: 1.16;
  max-width: 19ch;
  text-wrap: balance;
}
/* The official icon as a watermark: an embossed detail, never a logo. Behind the type, never over it. */
.story__mark {
  position: absolute;
  right: 2%;
  top: 34%;
  width: clamp(12rem, 19vw, 21rem);
  height: auto;
  opacity: 0.02;
  pointer-events: none;
  user-select: none;
  z-index: 0;
}
/* The official wordmark as a second watermark: oversized, cropped by the section's left edge, in the air below
   the definition. Desktop only - on a phone the column is too narrow for it to read as anything but a stray logo.
   The icon on the right was taken from .035 to .02 on 2026-09-10 so it stays behind the Faiyum copy, not beside it. */
.story__wordmark {
  position: absolute;
  left: -1.5%;
  top: 45%;
  width: clamp(26rem, 46vw, 44rem);
  height: auto;
  opacity: 0.03;
  pointer-events: none;
  user-select: none;
  z-index: 0;
}
@media (max-width: 900px) { .story__wordmark, .story__mark { display: none; } }
.story__inner > *:not(.story__mark):not(.story__wordmark) { position: relative; z-index: 1; }

/* ---------- Section three: the journey. The screen is the map. ----------
   The base layout is the finished one (no script, reduced motion, a failed map): the map holds the whole
   route in a box, the stops read as a row. journey.js adds .has-map when the SVG is in and .is-live when
   the scroll drives it; only then do the pieces go absolute and hide until their moment. */
.journey { position: relative; }
.journey__pin { position: relative; padding: var(--section-y) var(--gutter); }
.map {
  display: none;
  position: relative;
  height: 70vh;
  min-height: 24rem;
  overflow: hidden;
  max-width: 44rem;
  margin: 2.5rem auto 3rem;
}
.journey.has-map .map { display: block; }
/* No map at all (no script, or the fetch failed before the frames were moved): the frames read as a row, nothing else of the map shows. */
.journey:not(.has-map) .map {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.5rem, 4vw, 4rem);
  height: auto;
  min-height: 0;
  overflow: visible;
  margin: 2.5rem auto 0;
}
.journey:not(.has-map) .map__cam, .journey:not(.has-map) .map__dot, .journey:not(.has-map) .map__head { display: none; }
.journey.has-map:not(.is-live):not(.map-in) .map__dot { visibility: hidden; }   /* the still layout's dots wait for the map to place them */
/* The camera is the SVG viewBox (journey.js sets it per frame), so the browser paints the screen and nothing more.
   Every stroke keeps its pixel width at every zoom: vector-effect, set here and as an attribute. */
.map__cam { position: absolute; inset: 0; }
.map__cam svg { display: block; width: 100%; height: 100%; }
.map__cam path {
  fill: none;
  stroke: var(--forest);
  stroke-width: 1.6px;
  stroke-opacity: 0.8;
  vector-effect: non-scaling-stroke;
}
/* Land and water. Land is Forest at a breath of opacity over the ground, so the sea is the page and the coast is
   a coast without effort; lakes are the ground again, on top of the land. Same hue everywhere, one line weight. */
.map__cam .map__land { fill: var(--forest); fill-opacity: 0.06; stroke: none; }
.map__cam .map__lake { fill: var(--ground); stroke-width: 1.2px; stroke-opacity: 0.6; }
.map__cam .map__river { stroke-width: 1.6px; stroke-opacity: 0.7; }
.map__cam .map__route { stroke-width: 2.2px; stroke-opacity: 1; }
/* The stops. Dots in screen space, placed by journey.js on every camera move; they fill as the line arrives,
   and the current stop breathes: one slow ring, like a pulse under the skin. */
.map__dot {
  position: absolute;
  left: 0;
  top: 0;
  width: 0.875rem;
  height: 0.875rem;
  margin: -0.4375rem 0 0 -0.4375rem;
  border: 1.5px solid var(--forest);
  border-radius: 50%;
  background: var(--ground);
  will-change: transform, opacity;
}
.map__dot::after {
  content: "";
  position: absolute;
  inset: 2px;
  border-radius: 50%;
  background: var(--forest);
  transform: scale(0);
  transition: transform 480ms var(--ease-out);
}
.map__dot.is-on::after { transform: scale(1); }
.map__dot::before {
  content: "";
  position: absolute;
  inset: -1.5px;
  border-radius: 50%;
  border: 1px solid var(--forest);
  opacity: 0;
  transform: scale(1);
}
.map__dot.is-now::before { animation: gz-breathe 3.2s cubic-bezier(0.2, 0.6, 0.3, 1) infinite; }
@keyframes gz-breathe {
  0% { opacity: 0.55; transform: scale(1); }
  70%, 100% { opacity: 0; transform: scale(3.2); }
}
/* The pen: rides the route's tip while a leg draws. Placed by journey.js in screen space. */
.map__head {
  display: none;
  position: absolute;
  left: 0;
  top: 0;
  width: 0.5rem;
  height: 0.5rem;
  margin: -0.25rem 0 0 -0.25rem;
  border-radius: 50%;
  background: var(--forest);
  box-shadow: 0 0 0 5px rgba(47, 56, 33, 0.14);
  opacity: 0;
  transition: opacity 320ms ease;
  will-change: transform, opacity;
}
.journey.is-live .map__head { display: block; }
/* A frame beside each stop: a still, and one line saying it is not real yet. */
.map__frame { width: 100%; margin-bottom: 1.25rem; }
.map__frame img { width: 100%; height: auto; aspect-ratio: 3 / 4; object-fit: cover; }
.map__frame figcaption { margin-top: 0.5rem; color: var(--slate); font-size: 0.5625rem; }
.journey__copy { max-width: 80rem; margin: 0 auto; }
.journey__title {
  font-size: clamp(2.25rem, 4vw, 3.75rem);
  line-height: 1.08;
  text-wrap: balance;
  max-width: 12ch;
}
.journey__intro {
  margin-top: 1.25rem;
  max-width: 24rem;
  font-size: clamp(1.0625rem, 1.15vw, 1.1875rem);
  line-height: 1.55;
}
.journey__stops {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.5rem, 4vw, 4rem);
  list-style: none;
  margin: clamp(2rem, 6vh, 3.5rem) 0 0;
  padding: 0;
}
.jstop__place { font-size: clamp(2rem, 3vw, 2.75rem); line-height: 1.1; }
.jstop__verb { margin-top: 0.35rem; font-size: 1rem; font-weight: 400; }
.jstop__text { margin-top: 1rem; max-width: 26rem; font-size: clamp(1.0625rem, 1.15vw, 1.1875rem); line-height: 1.55; }
.jstop__spec { margin-top: 1.1rem; color: var(--olive); }

/* The live journey: pinned, the whole screen is the map, everything waits for its moment. */
/* The pin is the tall viewport (the phone's address bar collapsed), so no strip of ground shows under the map when
   the bar goes; the phone copy is anchored at the small height instead, so it never hides under the bar. */
.journey.is-live .journey__pin { height: 100vh; height: 100lvh; overflow: hidden; padding: 0; }
.journey.is-live .map { position: absolute; inset: 0; height: auto; min-height: 0; max-width: none; margin: 0; }
.journey.is-live .map__dot { opacity: 0; }
.journey.is-live .map__frame {
  position: absolute;
  left: 0;
  top: 0;
  width: clamp(11rem, 19vw, 17rem);
  margin: 0;
  opacity: 0;
  will-change: transform, opacity;
}
.journey.is-live .journey__copy {
  position: absolute;
  z-index: 2;
  left: var(--gutter);
  top: 50%;
  transform: translateY(-50%);
  width: min(30rem, 36vw);
  max-width: none;
  margin: 0;
}
/* A soft breath of ground behind the copy, no edge, so the type stays readable over the coastline at every zoom. */
.journey.is-live .journey__copy::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -4rem -8rem -4rem -6rem;
  background: radial-gradient(ellipse at 42% 50%, var(--ground) 34%, rgba(242, 250, 254, 0) 72%);
  pointer-events: none;
}
.journey.is-live .journey__stops { display: block; position: relative; min-height: 13rem; }
.journey.is-live .jstop { position: absolute; left: 0; top: 0; width: 100%; opacity: 0; will-change: transform, opacity; }

/* ---------- Section four: the proof, on the Forest field ---------- */
.proof {
  background: var(--forest);
  color: var(--icy);
  padding: var(--section-y) var(--gutter);
}
.proof__grid {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(2rem, 6vw, 7rem);
  max-width: 80rem;
  margin: 0 auto;
  align-items: start;
}
.proof__lead { position: sticky; top: clamp(4rem, 14vh, 8rem); }
.proof__title {
  font-size: clamp(2.25rem, 4vw, 3.75rem);
  line-height: 1.08;
  text-wrap: balance;
  max-width: 12ch;
}
.proof__intro {
  margin-top: 1.5rem;
  max-width: 24rem;
  font-size: clamp(1.0625rem, 1.15vw, 1.1875rem);
  line-height: 1.55;
  color: var(--dusty);
}
/* The ledger: one hairline per fact, drawn in as the row enters. Never a card. */
.ledger { margin: 0.4rem 0 0; }
.ledger__row {
  position: relative;
  display: grid;
  grid-template-columns: 13rem minmax(0, 1fr);
  gap: 0.5rem 2rem;
  padding: 1.35rem 0 1.45rem;
}
.ledger__row::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--dusty);
  opacity: 0.45;
  transform-origin: left center;
  transition: transform 1000ms var(--ease-out);
}
.has-scroll .ledger__row:not(.is-in)::before { transform: scaleX(0); }
.ledger__row:last-child::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--dusty);
  opacity: 0.45;
  transform-origin: left center;
  transition: transform 1000ms var(--ease-out) 200ms;
}
.has-scroll .ledger__row:not(.is-in):last-child::after { transform: scaleX(0); }
.ledger dt { padding-top: 0.25rem; color: var(--icy); font-weight: 500; }
.ledger dd { color: var(--dusty); font-size: clamp(1rem, 1.05vw, 1.125rem); line-height: 1.55; max-width: 30rem; }

/* ---------- Section five: the colourways, travelling sideways on bone ----------
   Base: the strip scrolls by hand (no script, reduced motion). With the scroll engine (.has-scroll on html)
   the section holds and the strip travels with the scroll. */
.colours { position: relative; }
.colours__pin { padding: var(--section-y) 0 var(--section-y) var(--gutter); }
.colours__head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 1rem 2rem;
  max-width: 56rem;
  padding-right: var(--gutter);
  margin-bottom: clamp(2rem, 5vh, 3.5rem);
}
.colours__title { font-size: clamp(2.25rem, 4vw, 3.75rem); line-height: 1.08; }
/* The filter: which group of colours is in the travelling strip. Underline marks the active one. */
/* Her verdict of 2026-09-10: several readers never realised the towel colours were behind a second tab.
   A bordered pair, square corners, GIZAY's own mono. Inactive stays Forest, not Slate: Slate read as disabled. */
.colours__head { display: flex; align-items: flex-end; gap: var(--gutter); flex-wrap: wrap;
  /* The header spans the section now so the arrows land on the strip's own right edge, not mid-page. */
  max-width: none; padding-right: var(--gutter); }
.colours__filter { display: inline-flex; gap: 0; border: 1px solid var(--forest); }
/* Mouse users only. One swatch per click; native scrolling stays the primary gesture. */
.colours__nav { display: none; gap: 0.35rem; margin-left: auto; padding-bottom: 0.35rem; }
@media (min-width: 901px) { .colours__nav { display: flex; } }
.colours__arrow {
  width: 30px; height: 30px; padding: 0;
  background: none; border: 0; cursor: pointer;
  font-family: var(--mono); font-size: 0.8125rem; line-height: 1;
  color: var(--slate); transition: color 180ms ease;
}
.colours__arrow:hover { color: var(--forest); }
.colours__arrow:focus-visible { outline: 2px solid var(--forest); outline-offset: 2px; }
.colours__tab {
  height: 44px;
  padding: 0 1.75rem;
  background: transparent;
  border: 0;
  border-right: 1px solid var(--forest);
  font-family: var(--mono);
  font-weight: 400;
  font-size: 0.6875rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--forest);
  cursor: pointer;
  transition: background-color 220ms ease, color 220ms ease;
}
.colours__tab:last-child { border-right: 0; }
.colours__tab:hover:not(.is-active) { background: rgba(47, 56, 33, 0.06); }
.colours__tab.is-active { background: var(--forest); color: var(--icy); }
.colours__tab:focus-visible { outline: 2px solid var(--forest); outline-offset: 3px; }
.colours__group[hidden] { display: none; }
.swatches {
  display: flex;
  overscroll-behavior-x: contain;
  scroll-snap-type: none;
  gap: clamp(1.125rem, 2.75vw, 2.75rem);
  list-style: none;
  margin: 0;
  padding: 0 var(--gutter) 0.5rem 0;
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.swatch { flex: none; width: clamp(9.25rem, 16vw, 14.75rem); }
.swatch__field { display: block; width: 100%; aspect-ratio: 3 / 4; background: var(--c); }
.swatch__field--white { box-shadow: inset 0 0 0 1px rgba(47, 56, 33, 0.16); }
.swatch__name { margin-top: 0.85rem; font-size: clamp(1.25rem, 1.6vw, 1.625rem); line-height: 1.15; }
.swatch__code { margin-top: 0.35rem; color: var(--olive); }
/* Her verdict of 2026-09-10: the pinned, scroll-scrubbed strip fought the gesture on trackpad and phone alike.
   The colourways are a plain native horizontal scroller now, on every device. page.js no longer tweens them. */
.has-scroll .colours__pin { height: auto; display: block; overflow: visible;
  padding: var(--section-y) 0 var(--section-y) var(--gutter); }
.has-scroll .swatches { width: auto; max-width: 100%; overflow-x: auto; overflow-y: hidden;
  padding-bottom: 0.5rem; will-change: auto; transform: none; }

/* ---------- Section six: the close, on the field ---------- */
.close {
  position: relative;
  /* Her ruling of 2026-09-09: full width always, but the section does not need the whole screen's height.
     Tall enough to hold the copy field with a band of the crop under it, never taller. */
  min-height: clamp(28rem, 62vh, 44rem);
  display: grid;
  /* One row, so the copy field can sit centred in the section's own height. */
  grid-template-rows: 1fr;
  overflow: hidden;
  /* The ground under the closing clip, sampled from the clip's own first frame, so no other colour
     flashes while the poster loads. */
  background: #AEA892;
  isolation: isolate;
}
.close__media { position: absolute; inset: 0; z-index: 0; }
.close__media picture { display: block; width: 100%; height: 100%; }
.close__still { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 60%; will-change: transform; }
/* The overlay shade: the page's Icy White laid over the top of the clip, heaviest where the copy sits and
   gone by two thirds down. Two jobs at once, it carries the midday sky into the page's own ground, and it
   holds the Forest type above AA over moving footage. */
/* The overlay shade, and it is deliberately only a whisper. Her ruling of 2026-09-09: the cotton has to be
   visible, and any wash heavy enough to carry the whole frame into the page's palette takes the bolls with it.
   So it touches the sky, where there is no detail to lose and where the clash with the page is worst, and it is
   gone before the field begins. The copy gets its legibility from its own ground, never from dimming the field. */
.close__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(to bottom,
    rgba(242, 250, 254, 0.34) 0%,
    rgba(242, 250, 254, 0.14) 17%,
    rgba(242, 250, 254, 0) 32%);
}
/* The closing copy sits on the page's own Icy White, laid over the clip as a quiet field, square like every
   other shape here. The clip underneath is untouched. */
.close__copy {
  position: relative;
  z-index: 1;
  align-self: center;
  margin: 0 0 0 var(--gutter);
  padding: clamp(2rem, 4.5vh, 3rem) clamp(2rem, 3vw, 3.25rem);
  max-width: 34rem;
  background: rgba(242, 250, 254, 0.95);
}
.close__title {
  font-size: clamp(2.5rem, 5vw, 5rem);
  line-height: 1.04;
  text-wrap: balance;
  max-width: 14ch;
}
.close__sub { margin: 1rem 0 1.875rem; max-width: 30rem; font-size: clamp(1.0625rem, 1.3vw, 1.375rem); line-height: 1.45; }
.signup { max-width: 32rem; }
/* The early-subscriber benefit. Set as a specification, not a promotion: mono, small, Slate, left of the
   spec strip's right edge so the two micro-lines never read as one block. It steps aside for any form message. */
.signup__note {
  margin: 0.55rem 0 0;
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  line-height: 1.4;
  color: var(--slate);
}
.signup__row[hidden] ~ .signup__note { display: none; }
.signup:has(.signup__msg:not(:empty)) .signup__note { display: none; }
.signup__row { display: flex; gap: 0.5rem; }
.signup__row[hidden] { display: none; }
.signup__input {
  flex: 1 1 auto;
  min-width: 0;
  height: 3.05rem;
  padding: 0 1rem;
  border: 1px solid var(--forest);
  border-radius: 0;
  background: var(--icy);
  color: var(--forest);
  font: inherit;
  font-size: 1rem;
}
.signup__input::placeholder { color: var(--slate); opacity: 1; }
.signup__input:focus { outline: 2px solid var(--forest); outline-offset: 2px; }
.signup__btn { height: 3.05rem; padding: 0 1.5rem; }
.signup__hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }
.signup__msg { margin-top: 0.9rem; min-height: 1.5em; font-size: 1rem; }

/* ---------- Footer ---------- */
.site-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 2rem var(--gutter);
}
.site-foot__mark { width: 5rem; height: auto; }
.site-foot__line { font-size: 0.875rem; }
.site-foot__spec { color: var(--olive); }
/* The studio credit sits on its own line under the footer row, behind a hairline, in the page's quietest voice. */
.site-foot__credit {
  flex-basis: 100%;
  margin-top: 1.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid rgba(47, 56, 33, 0.12);
  text-align: right;
}
.site-foot__credit a { color: var(--slate); text-decoration: none; transition: color 200ms ease; }
.site-foot__credit a:hover { color: var(--forest); }

/* ---------- Phone ---------- */
@media (max-width: 900px) {
  .story__inner { grid-template-columns: 1fr; row-gap: clamp(1.5rem, 3.5vh, 2.5rem); }
  .story__title, .story__definition, .story__source, .story__statement, .story__close { grid-column: 1 / -1; }
  .story__source { margin-top: 0.5rem; }
  .story__statement { max-width: 15ch; margin-top: 0.5rem; }
  .story__mark { right: -22%; top: auto; bottom: 4%; width: 14rem; opacity: 0.04; }
}

@media (max-width: 640px) {
  :root { --head-h: 4rem; --section-y: clamp(4rem, 12vh, 6rem); }
  .site-head__mark img { width: 5.25rem; }
  .placeholder-note--head { display: none; }
  .placeholder-note--hero { display: block; position: absolute; bottom: 0.4rem; right: var(--gutter); z-index: 3; font-size: 0.5625rem; }
  /* Statement first, the material beneath it, the action at the thumb. */
  .hero { grid-template-rows: auto auto 1fr auto auto; }
  .hero__copy { display: contents; }
  .hero__title { grid-row: 1; position: relative; z-index: 2; margin: calc(var(--head-h) + 1.25rem) var(--gutter) 0.75rem; font-size: 2.5rem; max-width: none; }
  .hero__sub { grid-row: 2; position: relative; z-index: 2; margin: 0 var(--gutter) 0; font-size: 1.0625rem; max-width: 22rem; }
  .hero .signup { grid-row: 4; position: relative; z-index: 2; margin: 0 var(--gutter) 1.25rem; max-width: none; }
  .hero__spec { position: relative; grid-row: 5; right: auto; bottom: auto; margin: 0 var(--gutter) 1.25rem; font-size: 0.625rem; white-space: normal; text-align: right; }

  .story__title { font-size: 2.25rem; max-width: none; }
  .story__definition { font-size: 1.625rem; max-width: none; }
  /* The wordmark returns on the phone only (641-900px keeps both marks off): centred behind the column,
     fainter than on desktop because the type sits over it rather than beside it. The icon stays hidden. */
  .story__wordmark {
    display: block;
    left: 50%;
    right: auto;
    top: 67%;
    transform: translateX(-50%);
    width: 86vw;
    opacity: 0.045;
  }

  .journey__stops { grid-template-columns: 1fr; gap: 2.5rem; }
  .map { height: 52vh; }
  .journey:not(.has-map) .map { grid-template-columns: 1fr; gap: 2rem; }
  .journey__title { font-size: 1.875rem; max-width: none; }
  .jstop__place { font-size: 1.75rem; }
  .jstop__verb { font-size: 0.9375rem; margin-top: 0.2rem; }
  .jstop__text { margin-top: 0.6rem; font-size: 0.9375rem; line-height: 1.45; }
  .jstop__spec { margin-top: 0.75rem; font-size: 0.625rem; }
  .journey.is-live .journey__copy { left: var(--gutter); right: var(--gutter); top: auto; bottom: 1.5rem; bottom: calc(1.5rem + (100lvh - 100svh)); transform: none; width: auto; }
  .journey.is-live .journey__intro { display: none; }
  .journey.is-live .journey__stops { margin-top: 1rem; min-height: 11.5rem; }
  .journey.is-live .map__frame { width: 38vw; }

  .proof__grid { grid-template-columns: 1fr; gap: 2rem; }
  .proof__lead { position: static; }
  .proof__title { font-size: 2.25rem; max-width: none; }
  .ledger__row { grid-template-columns: 1fr; gap: 0.35rem; padding: 1.1rem 0 1.2rem; }

  .colours__title { font-size: 2.25rem; }
  .colours__filter { gap: 1.25rem; }
  .swatch { width: 43vw; }
  .swatch__name { font-size: 1.5rem; }

  .close { min-height: clamp(26rem, 72svh, 38rem); }
  /* Her ruling of 2026-09-09: on a phone the closing field was eating the drone crop. Same design, same
     colours, same type, smaller footprint, so the field stays visible behind it. Scoped to .close so the
     hero's own form is untouched. */
  .close__copy { width: 72vw; max-width: none; margin: 0 auto; padding: 0.95rem 1rem 1.05rem; }
  /* 1.375rem is deliberate, not rounded off: it is the largest size at which the headline still sets on one
     line at 360px, the common Android width. 1.4rem clears it by three pixels there and wraps. */
  .close__title { font-size: 1.375rem; line-height: 1.12; max-width: none; }
  /* The thank-you line sets on two lines at 375 and 360. Tightened rather than shrunk: the card measures
     202px, 25% of the viewport, against 191px before. Type size is unchanged. */
  .close__sub { margin: 0.3rem 0 0.55rem; font-size: 0.8125rem; line-height: 1.25; max-width: none; }
  .close .signup__row { gap: 0.3rem; }
  .close .signup__input { height: 2.15rem; font-size: 0.875rem; padding: 0 0.8rem; }
  .close .signup__btn { height: 2.15rem; font-size: 0.875rem; }
  .close .signup__msg { margin-top: 0.4rem; font-size: 0.8125rem; }
  .close__still { object-position: 50% 70%; }
  .signup__row { flex-direction: column; }
  .signup__btn { width: 100%; }
  .placeholder-note--close { font-size: 0.5625rem; bottom: 0.4rem; }

  .site-foot { flex-direction: column; align-items: flex-start; gap: 0.75rem; }
  .site-foot__credit { align-self: stretch; text-align: left; margin-top: 0.5rem; padding-top: 1rem; }
}
