/* Generated by tools/fetch-fonts.mjs. Do not edit by hand. */

@font-face {
  font-family: 'Jost';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('../fonts/jost-300-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Jost';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('../fonts/jost-300-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Jost';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/jost-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Jost';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/jost-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Jost';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/jost-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Jost';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/jost-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/playfair-display-400-italic-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/playfair-display-400-italic-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/playfair-display-500-italic-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Playfair Display';
  font-style: italic;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/playfair-display-500-italic-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/playfair-display-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/playfair-display-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/playfair-display-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/playfair-display-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/playfair-display-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Playfair Display';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/playfair-display-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ==========================================================================
   Studio Terminel
   Design system and page styles. See STYLE.md for the reasoning behind
   the tokens and the rules that govern them.

   Two locks worth stating up front, because breaking either one is the
   fastest way to make this page stop looking like the brand:

   1. THEME LOCK. Single dark theme, no light mode. The identity is black
      marble and ivory. Colour arrives only through photography.
   2. SHAPE LOCK. Every corner radius on this page is 0, buttons included.
      The deck is built from hard-edged rectangles and so is this.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */

:root {
  color-scheme: dark;

  /* Ink. The page floor and the surfaces that sit just above it. */
  --ink-000: #050505;
  --ink-100: #0a0a0a;
  --ink-200: #101010;
  --ink-300: #171717;

  /* Paper. One ivory, stepped by alpha so everything stays in one family. */
  --paper: #f7f1e8;
  --paper-90: rgb(247 241 232 / 0.90);
  --paper-70: rgb(247 241 232 / 0.70);
  --paper-52: rgb(247 241 232 / 0.52);
  --paper-38: rgb(247 241 232 / 0.38);
  --paper-20: rgb(247 241 232 / 0.20);
  --rule: rgb(247 241 232 / 0.14);
  --rule-soft: rgb(247 241 232 / 0.08);

  /* Type */
  --font-display: "Playfair Display", "Iowan Old Style", Georgia, serif;
  --font-ui: "Jost", ui-sans-serif, system-ui, -apple-system, sans-serif;

  /* Fluid type scale */
  /* Capped so each of the two headline lines stays on one line in both
     languages. The two longest are "en experiencias memorables." and "into
     experiences that last.", both 27 characters, which is what sets this
     ceiling. Re-check both languages before raising it. */
  --t-hero: clamp(2rem, 4.2vw, 3.7rem);
  --t-h2: clamp(1.9rem, 4.4vw, 3.6rem);
  --t-h3: clamp(1.45rem, 2.8vw, 2.35rem);
  --t-quote: clamp(1.5rem, 3.6vw, 3rem);
  --t-lede: clamp(1.02rem, 1.35vw, 1.2rem);
  --t-body: clamp(0.95rem, 1.1vw, 1.03rem);
  --t-small: clamp(0.84rem, 1vw, 0.92rem);
  --t-label: clamp(0.66rem, 0.8vw, 0.72rem);

  /* Rhythm */
  --gutter: clamp(1.15rem, 4.5vw, 3.5rem);
  --wrap: 1320px;
  --measure: 60ch;
  --section-y: clamp(4.5rem, 11vh, 8.5rem);
  --nav-h: 68px;

  /* Motion */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --dur: 0.75s;

  /* Shape lock */
  --radius: 0;

  /* Replaced at build time with the optimized texture from the manifest, so
     the filename never has to be kept in sync by hand. */
  --marble: url("../img/marble-1400.jpg");
}

@media (min-width: 900px) {
  :root { --nav-h: 76px; }
}

/* --------------------------------------------------------------------------
   2. Reset
   -------------------------------------------------------------------------- */

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

* { margin: 0; padding: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 1rem);
}

body {
  min-height: 100svh;
  background: var(--ink-100);
  color: var(--paper);
  font-family: var(--font-ui);
  font-size: var(--t-body);
  font-weight: 300;
  line-height: 1.65;
  letter-spacing: 0.01em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

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

/* No placeholder background on img: the brand logos are black line art on
   transparency and are shown through filter: invert(1), which would turn any
   background colour into a white block behind the mark. */
img { height: auto; }

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

ul, ol { list-style: none; }

button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

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

::selection { background: var(--paper); color: var(--ink-100); }

/* --------------------------------------------------------------------------
   3. Page backdrop
   The marble texture and vignette are fixed and pointer-transparent so they
   never repaint during scroll.
   -------------------------------------------------------------------------- */

.backdrop {
  position: fixed;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  background-color: var(--ink-100);
}

.backdrop::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--marble);
  background-size: cover;
  background-position: center;
  opacity: 0.5;
}

.backdrop::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(130% 90% at 50% 0%, rgb(20 20 20 / 0.15) 0%, rgb(5 5 5 / 0.75) 70%, rgb(5 5 5 / 0.95) 100%);
}

/* Film grain. Fixed layer only, never on a scrolling container. */
.grain {
  position: fixed;
  inset: 0;
  z-index: 60;
  pointer-events: none;
  opacity: 0.035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* --------------------------------------------------------------------------
   4. Layout primitives
   -------------------------------------------------------------------------- */

.wrap {
  width: min(var(--wrap), 100% - (var(--gutter) * 2));
  margin-inline: auto;
}

.wrap--narrow { width: min(940px, 100% - (var(--gutter) * 2)); }

.section { padding-block: var(--section-y); position: relative; }

.section--tight { padding-block: clamp(3rem, 7vh, 5rem); }

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 0.85rem 1.4rem;
  background: var(--paper);
  color: var(--ink-100);
  font-size: var(--t-label);
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.skip:focus { left: 0; }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   5. Type
   -------------------------------------------------------------------------- */

.display {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.06;
  letter-spacing: -0.012em;
}

/* Italic display needs descender room. leading-1 clips the y, g, j, p, q. */
.display em,
.display i {
  font-style: italic;
  line-height: 1.12;
  padding-bottom: 0.06em;
}

.h2 {
  font-family: var(--font-display);
  font-size: var(--t-h2);
  font-weight: 400;
  line-height: 1.08;
  letter-spacing: -0.012em;
}

.h3 {
  font-family: var(--font-display);
  font-size: var(--t-h3);
  font-weight: 500;
  line-height: 1.14;
}

.lede {
  font-size: var(--t-lede);
  line-height: 1.62;
  color: var(--paper-70);
  max-width: 46ch;
}

.body {
  color: var(--paper-52);
  max-width: var(--measure);
}

.label {
  font-size: var(--t-label);
  font-weight: 400;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--paper-38);
}

.rule {
  height: 1px;
  background: var(--rule);
  border: 0;
}

/* Section heading block. One hairline, drawn above the title. */
.head {
  border-top: 1px solid var(--rule);
  padding-top: clamp(1.25rem, 2.5vw, 2rem);
  margin-bottom: clamp(2rem, 5vw, 3.5rem);
}

.head__title { margin-bottom: 0.7rem; }

/* Used where the heading block sits inside a grid that already provides the
   spacing underneath it. */
.head--flush { margin-bottom: 0; }

/* --------------------------------------------------------------------------
   6. Buttons
   Shape lock: square, like everything else. Contrast is checked in both
   variants against the ink backdrop they sit on.
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6em;
  white-space: nowrap;             /* a wrapped CTA is a broken CTA */
  padding: 0.95em 1.85em;
  border: 1px solid var(--paper-38);
  border-radius: var(--radius);
  font-size: var(--t-label);
  font-weight: 400;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--paper);
  background: transparent;
  transition:
    background-color 0.45s var(--ease),
    border-color 0.45s var(--ease),
    color 0.45s var(--ease),
    transform 0.25s var(--ease);
}

.btn:hover {
  border-color: var(--paper);
  background: rgb(247 241 232 / 0.06);
  transform: translateY(-2px);
}

.btn:active { transform: translateY(0) scale(0.985); }

.btn--solid {
  background: var(--paper);
  border-color: var(--paper);
  color: var(--ink-100);          /* 4.5:1 and beyond against ivory */
}

.btn--solid:hover {
  background: transparent;
  color: var(--paper);
  border-color: var(--paper);
}

.btn svg { width: 1.05em; height: 1.05em; fill: currentColor; flex: none; }

/* --------------------------------------------------------------------------
   7. Navigation
   Single line at desktop, capped height, hamburger below 900px.
   -------------------------------------------------------------------------- */

.nav {
  position: fixed;
  inset: 0 0 auto;
  z-index: 50;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  transition: background-color 0.4s var(--ease), border-color 0.4s var(--ease);
  border-bottom: 1px solid transparent;
}

.nav.is-scrolled {
  background: rgb(8 8 8 / 0.82);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom-color: var(--rule-soft);
}

.nav__inner {
  width: min(var(--wrap), 100% - (var(--gutter) * 2));
  margin-inline: auto;
  display: flex;
  align-items: center;
  gap: clamp(1rem, 3vw, 2.5rem);
}

.nav__brand {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin-right: auto;
}

.nav__brand img {
  width: auto;
  height: clamp(26px, 3.4vw, 34px);
  filter: invert(1);
}

.nav__brand span {
  font-family: var(--font-display);
  font-size: 0.98rem;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

.nav__links {
  display: none;
  align-items: center;
  gap: clamp(1.1rem, 2.2vw, 2rem);
}

.nav__link {
  font-size: var(--t-label);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--paper-70);
  padding-block: 0.35rem;
  position: relative;
  transition: color 0.35s var(--ease);
}

.nav__link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.45s var(--ease);
}

.nav__link:hover { color: var(--paper); }
.nav__link:hover::after { transform: scaleX(1); }

.nav__lang {
  font-size: var(--t-label);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--paper-70);
  border: 1px solid var(--rule);
  padding: 0.5em 0.9em;
  transition: border-color 0.35s var(--ease), color 0.35s var(--ease);
}

.nav__lang:hover { color: var(--paper); border-color: var(--paper-38); }

.nav__cta { display: none; padding: 0.7em 1.35em; }

.nav__toggle {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 40px;
  height: 40px;
  align-items: flex-end;
}

.nav__toggle span {
  display: block;
  width: 22px;
  height: 1px;
  background: var(--paper);
  transition: transform 0.4s var(--ease), opacity 0.3s var(--ease), width 0.4s var(--ease);
}

.nav__toggle span:last-child { width: 14px; }

body.menu-open .nav__toggle span:first-child { transform: translateY(6px) rotate(45deg); }
body.menu-open .nav__toggle span:nth-child(2) { opacity: 0; }
body.menu-open .nav__toggle span:last-child { width: 22px; transform: translateY(-6px) rotate(-45deg); }

@media (min-width: 900px) {
  .nav__links { display: flex; }
  .nav__cta { display: inline-flex; }
  .nav__toggle { display: none; }
}

/* Mobile panel */
.menu {
  position: fixed;
  inset: 0;
  z-index: 45;
  background: rgb(6 6 6 / 0.97);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  padding: calc(var(--nav-h) + 2.5rem) var(--gutter) 3rem;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.4s var(--ease), visibility 0.4s;
}

body.menu-open .menu { opacity: 1; visibility: visible; }

body.menu-open { overflow: hidden; }

.menu__link {
  font-family: var(--font-display);
  font-size: clamp(1.8rem, 8vw, 2.6rem);
  line-height: 1.5;
  border-bottom: 1px solid var(--rule-soft);
  padding-block: 0.35rem;
}

.menu__foot { margin-top: auto; padding-top: 2rem; display: grid; gap: 1rem; }

@media (min-width: 900px) {
  .menu { display: none; }
}

/* --------------------------------------------------------------------------
   8. Hero
   Asymmetric split. Brand lockup and headline left, offset photography right.
   -------------------------------------------------------------------------- */

.hero {
  min-height: 100svh;
  display: flex;
  align-items: center;
  padding-block: calc(var(--nav-h) + clamp(1.5rem, 5vh, 3.5rem)) clamp(3rem, 8vh, 5rem);
}

/* No width here: this element also carries .wrap, which owns the measure. */
.hero__inner {
  display: grid;
  gap: clamp(2.5rem, 6vw, 5rem);
  align-items: center;
}

.hero__brand { margin-bottom: clamp(1.4rem, 3.5vh, 2.4rem); display: block; }

.hero__brand img {
  width: clamp(96px, 15vw, 150px);
  height: auto;
  filter: invert(1);
}

.hero__title {
  font-family: var(--font-display);
  font-size: var(--t-hero);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: -0.015em;
}

.hero__title .l {
  display: block;
  overflow: hidden;
}

.hero__title .l > span { display: block; }

.hero__lede {
  margin-top: clamp(1.1rem, 2.6vh, 1.7rem);
  font-size: var(--t-lede);
  line-height: 1.6;
  color: var(--paper-70);
  max-width: 40ch;
}

.hero__actions {
  margin-top: clamp(1.7rem, 4vh, 2.6rem);
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
}

.hero__media { position: relative; }

/* Both images are direct children, so the shared treatment is scoped by class
   rather than by `.hero__media img`. That descendant selector outranks the
   .hero__media-b class and would stretch the offset image to full width. */
.hero__media-a,
.hero__media-b { filter: grayscale(1) contrast(1.08); }

/* The primary frame is clipped so the drift below can overscale slightly and
   never expose a sliver of page behind a moving edge. */
.hero__frame {
  display: block;
  overflow: hidden;
}

.hero__media-a { width: 100%; }

/* A slow, unequal drift on the two hero frames. The periods are deliberately
   different (13s and 17s) so the pair never falls into step and the motion
   reads as ambient rather than as a loop. Transform only: it runs on the
   compositor and cannot shift layout.

   The clipped frame is scaled a little over 1 so the translation always has
   image to move into. The floating frame is not scaled, because it has a
   visible border that scaling would thin. */
.hero__media-a {
  transform-origin: center;
  animation: drift-a 13s ease-in-out 1.2s infinite;
}

.hero__media-b { animation: drift-b 17s ease-in-out 1.6s infinite; }

@keyframes drift-a {
  0%, 100% { transform: scale(1.045) translate3d(0.6%, 0.7%, 0); }
  50%      { transform: scale(1.045) translate3d(-0.6%, -0.7%, 0); }
}

@keyframes drift-b {
  0%, 100% { transform: translate3d(0, 0, 0); }
  50%      { transform: translate3d(1.4%, 1.8%, 0); }
}

.hero__media-b {
  display: none;
  position: absolute;
  right: -9%;
  bottom: -8%;
  width: 58%;
  border: 1px solid rgb(247 241 232 / 0.12);
  box-shadow: 0 30px 70px rgb(0 0 0 / 0.6);
}

@media (min-width: 900px) {
  .hero__inner { grid-template-columns: 1.32fr 0.68fr; }
  .hero__media-b { display: block; }
}

/* Below 900px the second hero image is dropped rather than stacked: it keeps
   the headline and both CTAs inside the first viewport on a phone. */

/* --------------------------------------------------------------------------
   9. Manifesto quote
   -------------------------------------------------------------------------- */

.manifesto {
  text-align: center;
  padding-block: clamp(5rem, 14vh, 10rem);
  border-block: 1px solid var(--rule-soft);
}

.manifesto__text {
  font-family: var(--font-display);
  font-size: var(--t-quote);
  font-weight: 400;
  font-style: italic;
  line-height: 1.24;
  letter-spacing: -0.012em;
  padding-bottom: 0.08em;
  max-width: 22ch;
  margin-inline: auto;
  text-wrap: balance;
}

.manifesto__author {
  margin-top: clamp(1.4rem, 3vw, 2.2rem);
  font-size: var(--t-label);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--paper-38);
}

/* --------------------------------------------------------------------------
   10. Studio mosaic
   Four cells, four pieces of content. No blank tiles.
   -------------------------------------------------------------------------- */

.mosaic {
  display: grid;
  gap: clamp(0.6rem, 1.4vw, 1.1rem);
  grid-template-columns: 1fr;
}

.mosaic__cell { position: relative; overflow: hidden; }

.mosaic__cell img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 1.2s var(--ease);
}

.mosaic__cell:hover img { transform: scale(1.03); }

.mosaic__text { align-self: center; padding-block: clamp(0.5rem, 2vw, 1.5rem); }

.mosaic__text .h2 { margin-bottom: 1rem; }

.mosaic__text .body { margin-top: 1rem; }

.mosaic__a, .mosaic__b, .mosaic__c { aspect-ratio: 16 / 10; }

@media (min-width: 860px) {
  .mosaic { grid-template-columns: repeat(12, 1fr); }
  .mosaic__text { grid-column: 1 / 6; }
  .mosaic__a { grid-column: 6 / 13; aspect-ratio: 16 / 10; }
  .mosaic__b { grid-column: 1 / 8; aspect-ratio: auto; }
  .mosaic__c { grid-column: 8 / 13; aspect-ratio: 3 / 4; }
}

/* --------------------------------------------------------------------------
   11. Value proposition
   Purely typographic. The one section on the page with no photograph, which
   is what gives it its weight.
   -------------------------------------------------------------------------- */

.value__title {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2.4rem, 8vw, 6rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  padding-bottom: 0.08em;
  margin-bottom: clamp(2rem, 5vw, 3.5rem);
}

.value__cols {
  display: grid;
  gap: clamp(1.5rem, 4vw, 3.5rem);
  font-size: var(--t-lede);
  line-height: 1.6;
  color: var(--paper-70);
}

@media (min-width: 780px) {
  .value__cols { grid-template-columns: 1fr 1fr; }
}

/* --------------------------------------------------------------------------
   12. Process
   Full-bleed band, then a six-cell numeric grid. One hairline per cell,
   drawn on top only.
   -------------------------------------------------------------------------- */

.band {
  position: relative;
  height: clamp(200px, 34vh, 380px);
  overflow: hidden;
  margin-bottom: clamp(2.5rem, 6vw, 4.5rem);
}

.band img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(0.35) contrast(1.05) brightness(0.82);
}

.band::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgb(10 10 10 / 0.55), rgb(10 10 10 / 0.15) 45%, rgb(10 10 10 / 0.85));
}

.steps {
  display: grid;
  gap: clamp(1.5rem, 3.5vw, 2.75rem);
  grid-template-columns: 1fr;
}

.step {
  border-top: 1px solid var(--rule);
  padding-top: clamp(1rem, 2vw, 1.5rem);
  display: grid;
  grid-template-columns: auto 1fr;
  gap: clamp(0.9rem, 2vw, 1.4rem);
  align-items: baseline;
}

.step__n {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 3vw, 2.4rem);
  line-height: 1;
  color: var(--paper-20);
  font-variant-numeric: tabular-nums;
}

.step__title {
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 1.9vw, 1.5rem);
  font-weight: 500;
  line-height: 1.2;
  margin-bottom: 0.3rem;
}

.step__body { color: var(--paper-52); font-size: var(--t-small); }

@media (min-width: 640px) { .steps { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .steps { grid-template-columns: repeat(3, 1fr); } }

/* --------------------------------------------------------------------------
   13. Global reach
   -------------------------------------------------------------------------- */

/* The map is real geography: Natural Earth coastlines projected
   equirectangular by tools/build-map.mjs. The pins are placed from the same
   projection, so they sit on their coastlines by construction.
   `aspect-ratio` and the .pin--<id> offsets are generated into this file by
   build.mjs and appear at the end. */
.map {
  position: relative;
  width: 100%;
  max-width: 1100px;
  margin: clamp(1.5rem, 4vw, 3rem) auto 0;
}

.map__land {
  width: 100%;
  height: 100%;
  display: block;
}

.map__pins {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* Pins are sized in px, not in map units, so they stay legible when the map
   shrinks to phone width instead of collapsing to specks. */
.pin {
  position: absolute;
  width: 0;
  height: 0;
  pointer-events: auto;
}

.pin i {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 7px;
  height: 7px;
  margin: -3.5px 0 0 -3.5px;
  border-radius: 50%;
  background: var(--paper);
  opacity: 0.55;
  transition: opacity 0.4s var(--ease), transform 0.4s var(--ease);
}

/* The halo doubles as the pointer target, which is why it is larger than it
   looks: a 7px dot is far below a comfortable tap size on its own. */
.pin::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 34px;
  height: 34px;
  margin: -17px 0 0 -17px;
  border-radius: 50%;
  cursor: pointer;
}

.pin::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 22px;
  height: 22px;
  margin: -11px 0 0 -11px;
  border-radius: 50%;
  border: 1px solid var(--paper);
  opacity: 0;
  transform: scale(0.45);
  transition: opacity 0.5s var(--ease), transform 0.5s var(--ease);
}

.pin:hover i,
.pin.is-active i {
  opacity: 1;
  transform: scale(1.5);
}

.pin:hover::after,
.pin.is-active::after {
  opacity: 0.7;
  transform: scale(1);
}

.map__caption {
  margin-top: clamp(0.75rem, 2vw, 1.15rem);
  text-align: center;
  font-size: var(--t-label);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--paper-38);
  min-height: 1.4em;
  transition: color 0.3s var(--ease);
}

.map__caption.is-active { color: var(--paper); }

.cities {
  columns: 2;
  column-gap: clamp(1.25rem, 4vw, 3rem);
  font-size: var(--t-small);
  letter-spacing: 0.06em;
  color: var(--paper-70);
  border-top: 1px solid var(--rule);
  padding-top: clamp(1.25rem, 3vw, 2rem);
  margin-top: clamp(1.75rem, 4vw, 2.75rem);
}

.cities li { break-inside: avoid; }

.city {
  display: block;
  width: 100%;
  text-align: left;
  padding-block: 0.42rem;
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
  transition: color 0.3s var(--ease), transform 0.3s var(--ease);
}

.city:hover,
.city.is-active {
  color: var(--paper);
  transform: translateX(3px);
}

@media (min-width: 620px) { .cities { columns: 3; } }
@media (min-width: 940px) { .cities { columns: 4; } }
@media (min-width: 1200px) { .cities { columns: 5; } }

/* --------------------------------------------------------------------------
   14. Partnerships
   -------------------------------------------------------------------------- */

.partners__lead {
  display: grid;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: end;
  margin-bottom: clamp(2rem, 5vw, 3.5rem);
}

@media (min-width: 900px) {
  .partners__lead { grid-template-columns: 1.1fr 0.9fr; }
}

.partners__hero img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

/* Horizontal scroll-snap strip. Breadth without a wall of thumbnails. */
.strip {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(150px, 21vw);
  gap: clamp(0.5rem, 1.2vw, 0.9rem);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-bottom: 0.75rem;
  margin-bottom: clamp(2.5rem, 6vw, 4rem);
  scrollbar-width: thin;
  scrollbar-color: var(--paper-20) transparent;
}

.strip img {
  scroll-snap-align: start;
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  filter: grayscale(1) contrast(1.05);
  transition: filter 0.6s var(--ease);
}

.strip img:hover { filter: grayscale(0) contrast(1); }

.sports {
  display: grid;
  gap: clamp(1.25rem, 3vw, 2.25rem);
  grid-template-columns: 1fr;
}

.sport {
  border-top: 1px solid var(--rule);
  padding-top: clamp(0.9rem, 2vw, 1.35rem);
}

.sport__name {
  font-family: var(--font-display);
  font-size: clamp(1.1rem, 1.8vw, 1.4rem);
  font-weight: 500;
  margin-bottom: 0.45rem;
}

.sport__detail { color: var(--paper-52); font-size: var(--t-small); line-height: 1.6; }

@media (min-width: 720px) { .sports { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .sports { grid-template-columns: repeat(4, 1fr); } }

/* Concerts. The single marquee on the page: seventeen names that need
   breadth, not individual attention. */
.concerts {
  position: relative;
  margin-top: clamp(3rem, 7vw, 5rem);
  overflow: hidden;
  border-block: 1px solid var(--rule-soft);
}

.concerts__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.28;
}

.concerts__veil {
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, var(--ink-100) 0%, rgb(10 10 10 / 0.35) 20%, rgb(10 10 10 / 0.35) 80%, var(--ink-100) 100%);
}

.concerts__inner {
  position: relative;
  padding-block: clamp(2.5rem, 6vw, 4rem);
}

.concerts__label {
  text-align: center;
  margin-bottom: clamp(1.25rem, 3vw, 2rem);
}

.marquee {
  display: flex;
  overflow: hidden;
  user-select: none;
  mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}

.marquee__track {
  display: flex;
  flex: none;
  gap: clamp(1.5rem, 4vw, 3rem);
  padding-right: clamp(1.5rem, 4vw, 3rem);
  min-width: 100%;
  animation: marquee 46s linear infinite;
}

.marquee:hover .marquee__track { animation-play-state: paused; }

.marquee__item {
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 2.4vw, 2rem);
  font-style: italic;
  line-height: 1.3;
  white-space: nowrap;
  color: var(--paper-70);
}

@keyframes marquee {
  from { transform: translateX(0); }
  to { transform: translateX(-100%); }
}

/* --------------------------------------------------------------------------
   15. Client wall
   The one light plate on the page. It is an image, not a theme flip: the
   section around it stays dark.
   -------------------------------------------------------------------------- */

/* Full-bleed on purpose: the track running past both edges of the viewport is
   what signals there is more to scroll, without needing a "scroll" label. */
.carousel {
  margin-top: clamp(1.75rem, 4vw, 3rem);
}

.carousel__track {
  display: flex;
  gap: clamp(0.6rem, 1.4vw, 1rem);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  padding-inline: var(--gutter);
  padding-bottom: 0.75rem;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

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

.brand {
  flex: 0 0 auto;
  scroll-snap-align: center;
  width: clamp(140px, 22vw, 210px);
  aspect-ratio: 16 / 10;
  display: grid;
  place-items: center;
  padding: clamp(0.8rem, 2vw, 1.4rem);
  /* Sampled from the marble the logos were sitting on in the deck, so each
     crop dissolves into its card rather than showing as a paler rectangle.
     The value is generated into this file by build.mjs. */
  background: var(--brand-card);
  transition: transform 0.5s var(--ease), filter 0.5s var(--ease);
  filter: saturate(0.25) contrast(0.95);
}

.brand img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
}

/* Colour arrives on hover. At rest the wall reads as one calm band of cards
   instead of twenty five competing brand palettes. */
.carousel__track:hover .brand { filter: saturate(0.12) contrast(0.95) opacity(0.55); }
.carousel__track .brand:hover { filter: none; transform: translateY(-4px); }

.carousel__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: clamp(1rem, 2.5vw, 1.5rem);
}

.carousel__hint {
  font-size: var(--t-label);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--paper-38);
}

.carousel__nav { display: flex; gap: 0.5rem; }

.carousel__btn {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border: 1px solid var(--rule);
  color: var(--paper-70);
  transition: border-color 0.35s var(--ease), color 0.35s var(--ease), opacity 0.35s var(--ease);
}

.carousel__btn svg { width: 18px; height: 18px; fill: currentColor; }

.carousel__btn:hover { border-color: var(--paper-38); color: var(--paper); }

.carousel__btn[disabled] { opacity: 0.3; cursor: default; }
.carousel__btn[disabled]:hover { border-color: var(--rule); color: var(--paper-70); }

@media (hover: none) {
  /* Without a pointer there is no hover to reveal colour, so show it. */
  .brand { filter: none; }
  .carousel__track:hover .brand { filter: none; }
}

/* --------------------------------------------------------------------------
   16. Cases
   Five compositions, deliberately different from one another. Never three
   image-and-text splits in a row.
   -------------------------------------------------------------------------- */

.case { padding-block: clamp(3rem, 8vh, 6rem); border-top: 1px solid var(--rule-soft); }

.case__name {
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 4.2vw, 3.4rem);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: -0.015em;
}

.case__tagline {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.05rem, 1.9vw, 1.5rem);
  line-height: 1.35;
  padding-bottom: 0.06em;
  color: var(--paper-70);
  margin-top: 0.7rem;
  max-width: 30ch;
}

.case__detail { margin-top: clamp(1.4rem, 3vw, 2.25rem); display: grid; gap: 1.4rem; }

.case__detail dt {
  font-size: var(--t-label);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--paper-38);
  margin-bottom: 0.5rem;
}

.case__detail dd { color: var(--paper-52); font-size: var(--t-small); line-height: 1.68; max-width: 52ch; }

.case__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Composition A: image beside text. */
.case--split { display: grid; gap: clamp(1.75rem, 4vw, 3.25rem); align-items: center; }

@media (min-width: 880px) {
  .case--split { grid-template-columns: 1.15fr 0.85fr; }
  .case--split.is-flipped > *:first-child { order: 2; }
}

.case--split .case__figure { aspect-ratio: 4 / 3; overflow: hidden; }

/* Composition B: paired images above, text in two columns below. */
/* An explicit row height rather than per-cell aspect ratios: the two frames
   are different widths, so matching ratios would leave the narrower one short
   and open a gap under it. */
.case--stacked .case__pair {
  display: grid;
  gap: clamp(0.6rem, 1.4vw, 1rem);
  margin-bottom: clamp(1.75rem, 4vw, 2.75rem);
  grid-auto-rows: clamp(210px, 30vw, 430px);
}

.case--stacked .case__pair > * { overflow: hidden; }

@media (min-width: 760px) {
  .case--stacked .case__pair { grid-template-columns: 1.4fr 1fr; }
  .case--stacked .case__body { display: grid; grid-template-columns: 0.9fr 1.1fr; gap: clamp(1.5rem, 4vw, 3rem); align-items: start; }
  .case--stacked .case__detail { margin-top: 0; grid-template-columns: 1fr 1fr; }
}

/* Composition C: heading, then a three-frame row, then the copy in columns.
   Fully stacked. A headline on the left with an explainer floating to its
   right is the section-header pattern this page deliberately avoids. */
.case--row .case__frames {
  display: grid;
  gap: clamp(0.6rem, 1.4vw, 1rem);
  margin-top: clamp(1.75rem, 4vw, 2.75rem);
  grid-template-columns: 1fr;
}

.case--row .case__frames > * { aspect-ratio: 16 / 9; overflow: hidden; }

@media (min-width: 760px) {
  .case--row .case__frames { grid-template-columns: repeat(3, 1fr); }
  .case--row .case__detail { grid-template-columns: 1fr 1fr; gap: clamp(1.5rem, 4vw, 3rem); }
}

/* Composition D: offset pair, text sitting between them. */
.case--offset { display: grid; gap: clamp(1.5rem, 3.5vw, 2.5rem); }

.case--offset .case__figure { overflow: hidden; aspect-ratio: 16 / 10; }

@media (min-width: 880px) {
  .case--offset { grid-template-columns: repeat(12, 1fr); align-items: center; }
  .case--offset .case__figure:first-child { grid-column: 1 / 6; aspect-ratio: 3 / 4; }
  .case--offset .case__body { grid-column: 6 / 10; }
  .case--offset .case__figure:last-child { grid-column: 10 / 13; aspect-ratio: 3 / 4; margin-top: clamp(2rem, 6vw, 5rem); }
}

/* Other work */
.others { margin-top: clamp(2rem, 5vw, 3.5rem); }

.others__grid {
  display: grid;
  gap: clamp(0.6rem, 1.4vw, 1rem);
  grid-template-columns: 1fr;
  margin-top: clamp(1.5rem, 3.5vw, 2.5rem);
}

.others__grid > * { aspect-ratio: 16 / 10; overflow: hidden; }

@media (min-width: 700px) { .others__grid { grid-template-columns: repeat(3, 1fr); } }

/* --------------------------------------------------------------------------
   17. Closing statement
   -------------------------------------------------------------------------- */

.closing {
  padding-block: clamp(5rem, 14vh, 9rem);
  border-top: 1px solid var(--rule-soft);
}

.closing__title {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.9rem, 5.2vw, 4rem);
  line-height: 1.14;
  letter-spacing: -0.015em;
  padding-bottom: 0.08em;
  /* Wide enough that the second authored line does not wrap again in either
     language. The line break in the copy is the intended one. */
  max-width: 34ch;
}

.closing__lines {
  margin-top: clamp(2rem, 5vw, 3.5rem);
  display: grid;
  gap: 0.35rem;
  font-family: var(--font-display);
  font-size: clamp(1.1rem, 2.4vw, 1.85rem);
  line-height: 1.35;
  color: var(--paper-70);
}

.closing__mark {
  margin-top: clamp(2rem, 5vw, 3rem);
  width: clamp(74px, 11vw, 118px);
  filter: invert(1);
  opacity: 0.75;
}

/* --------------------------------------------------------------------------
   18. Contact
   -------------------------------------------------------------------------- */

.contact { border-top: 1px solid var(--rule); }

.contact__inner {
  display: grid;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}

@media (min-width: 900px) {
  .contact__inner { grid-template-columns: 1fr 1fr; }
}

.contact__figure { overflow: hidden; aspect-ratio: 4 / 3; }

.contact__figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1) contrast(1.06);
}

.contact__lede { margin-top: 0.9rem; }

.contact__list { margin-top: clamp(1.75rem, 4vw, 2.5rem); display: grid; }

/* Grid rather than flex so the icon, label and value line up down the whole
   list. Labels differ in length, so a flex row leaves the values ragged. */
.contact__row {
  display: grid;
  grid-template-columns: 18px 11ch 1fr;
  align-items: center;
  gap: 1rem;
  padding-block: clamp(0.85rem, 2vw, 1.15rem);
  border-top: 1px solid var(--rule);
  transition: color 0.35s var(--ease);
  color: var(--paper-90);
}

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

.contact__row:hover { color: var(--paper); }

.contact__row svg { width: 18px; height: 18px; fill: currentColor; flex: none; opacity: 0.6; transition: opacity 0.35s var(--ease); }

.contact__row:hover svg { opacity: 1; }

.contact__row .k {
  font-size: var(--t-label);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--paper-38);
}

.contact__row .v {
  font-family: var(--font-display);
  font-size: clamp(1rem, 1.8vw, 1.3rem);
  letter-spacing: 0.01em;
}

.contact__actions { margin-top: clamp(1.75rem, 4vw, 2.5rem); display: flex; flex-wrap: wrap; gap: 0.85rem; }

/* --------------------------------------------------------------------------
   19. Footer
   -------------------------------------------------------------------------- */

.foot {
  border-top: 1px solid var(--rule-soft);
  padding-block: clamp(2rem, 5vw, 3rem);
}

.foot__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 2rem;
  font-size: var(--t-label);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--paper-38);
}

.foot__inner a:hover { color: var(--paper-70); }

.foot__spacer { margin-left: auto; }

/* --------------------------------------------------------------------------
   20. Motion
   Entrance and scroll reveals. Every one of these is driven by a class that
   IntersectionObserver adds; nothing here listens to the scroll event.
   -------------------------------------------------------------------------- */

.reveal {
  opacity: 0;
  transform: translateY(26px);
  transition:
    opacity var(--dur) var(--ease),
    transform var(--dur) var(--ease);
}

.reveal.is-visible { opacity: 1; transform: none; }

/* Children stagger in sequence, which is what makes the process grid and the
   city index read as a list being written rather than a block appearing.
   The delay is keyed off nth-child rather than an inline custom property so
   the Content-Security-Policy can forbid style attributes outright. Twenty
   four rules cover the longest group on the page, the 23 cities. */
.reveal-group > * {
  opacity: 0;
  transform: translateY(20px);
  transition:
    opacity 0.65s var(--ease),
    transform 0.65s var(--ease);
}

.reveal-group.is-visible > * { opacity: 1; transform: none; }

.reveal-group > :nth-child(1)  { transition-delay: 0ms; }
.reveal-group > :nth-child(2)  { transition-delay: 65ms; }
.reveal-group > :nth-child(3)  { transition-delay: 130ms; }
.reveal-group > :nth-child(4)  { transition-delay: 195ms; }
.reveal-group > :nth-child(5)  { transition-delay: 260ms; }
.reveal-group > :nth-child(6)  { transition-delay: 325ms; }
.reveal-group > :nth-child(7)  { transition-delay: 390ms; }
.reveal-group > :nth-child(8)  { transition-delay: 455ms; }
.reveal-group > :nth-child(9)  { transition-delay: 520ms; }
.reveal-group > :nth-child(10) { transition-delay: 585ms; }
.reveal-group > :nth-child(11) { transition-delay: 650ms; }
.reveal-group > :nth-child(12) { transition-delay: 715ms; }
.reveal-group > :nth-child(13) { transition-delay: 780ms; }
.reveal-group > :nth-child(14) { transition-delay: 845ms; }
.reveal-group > :nth-child(15) { transition-delay: 910ms; }
.reveal-group > :nth-child(16) { transition-delay: 975ms; }
.reveal-group > :nth-child(17) { transition-delay: 1040ms; }
.reveal-group > :nth-child(18) { transition-delay: 1105ms; }
.reveal-group > :nth-child(19) { transition-delay: 1170ms; }
.reveal-group > :nth-child(20) { transition-delay: 1235ms; }
.reveal-group > :nth-child(21) { transition-delay: 1300ms; }
.reveal-group > :nth-child(22) { transition-delay: 1365ms; }
.reveal-group > :nth-child(23) { transition-delay: 1430ms; }
.reveal-group > :nth-child(n + 24) { transition-delay: 1495ms; }

/* Hero entrance. Runs on load rather than on scroll: it is the first thing
   the visitor sees, so it establishes hierarchy instead of reacting to it. */
.hero__brand,
.hero__title .l > span,
.hero__lede,
.hero__actions,
.hero__media {
  opacity: 0;
  animation: rise 1.1s var(--ease) forwards;
}

.hero__brand { animation-delay: 0.15s; }
.hero__title .l:nth-child(1) > span { animation-delay: 0.3s; }
.hero__title .l:nth-child(2) > span { animation-delay: 0.42s; }
.hero__lede { animation-delay: 0.6s; }
.hero__actions { animation-delay: 0.74s; }
.hero__media { animation-delay: 0.4s; animation-duration: 1.5s; }

@keyframes rise {
  from { opacity: 0; transform: translateY(22px); }
  to { opacity: 1; transform: none; }
}

/* --------------------------------------------------------------------------
   21. Reduced motion
   Everything collapses to static. The marquee stops, the reveals are simply
   visible, the hero does not animate in.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }

  .reveal,
  .reveal-group > *,
  .hero__brand,
  .hero__title .l > span,
  .hero__lede,
  .hero__actions,
  .hero__media {
    opacity: 1;
    transform: none;
  }

  .marquee__track { animation: none; }

  .marquee {
    overflow-x: auto;
    mask-image: none;
    -webkit-mask-image: none;
  }
}

/* Transparency fallback for the blurred nav and mobile panel. */
@media (prefers-reduced-transparency: reduce) {
  .nav.is-scrolled { background: var(--ink-000); backdrop-filter: none; -webkit-backdrop-filter: none; }
  .menu { background: var(--ink-000); backdrop-filter: none; -webkit-backdrop-filter: none; }
}

/* --------------------------------------------------------------------------
   22. Print
   -------------------------------------------------------------------------- */

@media print {
  .nav, .menu, .grain, .backdrop, .strip, .marquee { display: none !important; }
  body { background: #fff; color: #000; }
  .reveal, .reveal-group > * { opacity: 1; transform: none; }
}


/* ---- generated by build.mjs, do not edit ---------------------------- */

:root { --brand-card: #ffffff; }

.map { aspect-ratio: 1000 / 344.4; }

.pin--mexico-city { left: 22.46%; top: 39.18%; }
.pin--bogota { left: 29.43%; top: 51.05%; }
.pin--brazil { left: 37.05%; top: 73.84%; }
.pin--toronto { left: 27.95%; top: 19.64%; }
.pin--quebec { left: 30.22%; top: 17.09%; }
.pin--new-york { left: 29.44%; top: 22.01%; }
.pin--paris { left: 50.65%; top: 15.44%; }
.pin--madrid { left: 48.97%; top: 22.25%; }
.pin--milan { left: 52.55%; top: 18.18%; }
.pin--london { left: 49.96%; top: 13.30%; }
.pin--sweden { left: 55.02%; top: 7.00%; }
.pin--germany { left: 53.72%; top: 12.49%; }
.pin--moscow { left: 60.45%; top: 9.88%; }
.pin--denmark { left: 53.49%; top: 9.94%; }
.pin--monaco { left: 52.06%; top: 19.58%; }
.pin--hong-kong { left: 81.71%; top: 36.85%; }
.pin--tokyo { left: 88.79%; top: 26.07%; }
.pin--taiwan { left: 83.77%; top: 34.66%; }
.pin--singapore { left: 78.84%; top: 53.76%; }
.pin--dubai { left: 65.35%; top: 34.52%; }
.pin--morocco { left: 47.89%; top: 27.77%; }
.pin--australia { left: 92.00%; top: 82.17%; }
.pin--hawaii { left: 6.15%; top: 37.66%; }
