/* ============================================================
   BeFirst Studio , v2
   Warm, quiet, editorial. Built on the logo's orange (#FF5100),
   soft black and warm white. Soft motion only , nothing techy.
   ============================================================ */

:root{
  /* surfaces */
  --paper:#FCF5E2;
  --sand:#F4EDD8;
  --sand-2:#EAE1C9;
  --night:#14120E;

  /* ink */
  --ink:#1A1A1A;
  --ink-70:#55514A;
  --ink-45:#8B857A;
  --on-night:#F5F0E2;
  --on-night-60:#A9A295;

  /* brand */
  --orange:#FF5100;
  --amber:#FFA946;
  --sun:#F7D44C;
  --line:rgba(26,26,26,.10);
  --line-night:rgba(245,240,226,.14);

  /* type */
  --serif:"Playfair Display", Georgia, "Times New Roman", serif;
  --sans:"Figtree", -apple-system, "Helvetica Neue", Arial, sans-serif;
  --mono:"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* form */
  --r-sm:12px;
  --r:20px;
  --r-lg:28px;
  --r-xl:44px;
  --pill:999px;
  /* asymmetric elliptical corners , the soft pillow shape from the reference */
  --squish:22px 22px 36px 36px / 30px 30px 50px 50px;
  --squish-tall:26px 26px 40px 40px / 20px 20px 34px 34px;
  --shadow-soft:0 2px 6px rgba(26,26,26,.04), 0 18px 44px rgba(26,26,26,.07);
  --shadow-lift:0 6px 16px rgba(26,26,26,.06), 0 30px 64px rgba(26,26,26,.13);
  --ease:cubic-bezier(.16,1,.3,1);

  /* ---- the fluid layout system ----
     Nothing here changes below about 1320px, which is where the laptop
     layout was tuned: every ramp starts from the value the page already
     had and only grows past it. Above that the page stops being a 1160px
     design centred in a bigger window.

     --gut       the page's own side padding
     --band-gut  the inset of the sand card and the night panel
     --strip-in  how far a media strip stays inside one of those cards
     --maxw      the reading column
     --maxw-wide sections that are compositions rather than paragraphs  */
  --gut:clamp(20px,2.2vw,44px);
  --band-gut:clamp(12px,3vw,28px);
  --strip-in:clamp(10px,1.4vw,26px);
  --maxw:clamp(1160px, calc(1160px + (100vw - 1320px) * .38), 1420px);
  --maxw-wide:clamp(1160px, calc(1160px + (100vw - 1320px) * .74), 1720px);
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;background:var(--paper)}
body{
  margin:0;
  background:var(--paper);
  color:var(--ink);
  font-family:var(--sans);
  font-size:17px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
img,svg,video{display:block;max-width:100%}
a{color:inherit}
::selection{background:var(--amber);color:var(--ink)}
:focus-visible{outline:2px solid var(--orange);outline-offset:3px;border-radius:4px}

.wrap{max-width:var(--maxw);margin:0 auto;padding-inline:var(--gut)}
section[id],.panel[id]{scroll-margin-top:86px}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
}

/* ---------- type roles ---------- */
.display{font-family:var(--serif);font-weight:400;letter-spacing:-.025em;line-height:1.0}
.display em{font-style:italic}
h1.display{font-size:clamp(40px,7.4vw,78px)}
h2.display{font-size:clamp(30px,4.9vw,56px)}
h3.display{font-size:clamp(21px,2.4vw,27px);line-height:1.1}
/* Above 1400px the original ramps have already hit their ceilings and the
   type stops growing, which is what made the page look small inside a large
   window. A second, much gentler ramp picks up exactly where each one
   stopped, so nothing changes at 1400 and nothing runs away at 2560. */
@media (min-width:1400px){
  h1.display{font-size:clamp(78px,4.6vw,98px)}
  h2.display{font-size:clamp(56px,3.4vw,72px)}
  h3.display{font-size:clamp(27px,1.6vw,34px)}
  .lede{font-size:clamp(19px,1.12vw,22px)}
  .panel .sec-head h2.display{font-size:clamp(48px,2.9vw,62px)}
  .story-step .lede{max-width:50ch}
  .sec-head .lede{max-width:58ch}
}
.eyebrow{
  font-family:var(--mono);font-size:11px;font-weight:400;
  letter-spacing:.17em;text-transform:uppercase;color:var(--ink-45);
  margin:0 0 13px;
}
.badge{
  display:inline-flex;align-items:center;gap:8px;
  font-family:var(--mono);font-size:10.5px;letter-spacing:.15em;text-transform:uppercase;
  padding:8px 15px;border-radius:var(--pill);margin:0 0 15px;
  background:rgba(255,81,0,.09);color:#B8390A;
  box-shadow:inset 0 0 0 1px rgba(255,81,0,.16);
}
.on-night .badge{background:rgba(255,169,70,.13);color:var(--amber);box-shadow:inset 0 0 0 1px rgba(255,169,70,.22)}

/* The label on the reels section, as a small piece of warm glass. The glow
   is one extra shadow layer whose size and alpha come from a registered
   number, so a keyframe can interpolate it: nothing else about the pill
   changes, it does not scale and it does not move. It lights once when the
   section is first reached, then again under the cursor. */
@property --bwg{syntax:'<number>';inherits:false;initial-value:0}

.badge.badge--glow{
  position:relative;overflow:hidden;
  padding:9px 20px;font-size:11px;letter-spacing:.14em;
  color:#fff;
  background:
    linear-gradient(180deg, rgba(255,255,255,.3), rgba(255,255,255,0) 54%),
    linear-gradient(112deg, #FF8E42 0%, #FF6418 40%, #FF4F02 66%, #FF9A47 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.52),
    inset 0 0 0 1px rgba(255,255,255,.2),
    0 1px 2px rgba(122,42,0,.2),
    0 8px 20px rgba(255,81,0,.18),
    0 0 calc(26px * var(--bwg)) calc(3px * var(--bwg)) rgba(255,150,60,calc(.62 * var(--bwg)));
  transition:--bwg .8s var(--ease);
}
.badge--glow:hover{--bwg:.72}
.badge--glow.is-lit{animation:bwPulse 1.9s var(--ease) 1}
@keyframes bwPulse{0%{--bwg:0}30%{--bwg:1}100%{--bwg:0}}

.bg-t{position:relative;z-index:1}
.bg-stars{position:absolute;inset:0;z-index:0;border-radius:inherit;overflow:hidden}
.bg-stars i{
  position:absolute;left:var(--sx);top:var(--sy);
  width:var(--s);height:var(--s);margin:calc(var(--s) / -2) 0 0 calc(var(--s) / -2);
  opacity:0;
  /* two crossed gradients make a four point sparkle without an image */
  background:
    radial-gradient(closest-side, #fff, rgba(255,255,255,0) 72%) center / 100% 20% no-repeat,
    radial-gradient(closest-side, #fff, rgba(255,255,255,0) 72%) center / 20% 100% no-repeat;
  animation:bwTwinkle var(--d) ease-in-out var(--dl) infinite;
}
@keyframes bwTwinkle{
  0%,100%{opacity:0;transform:translate3d(0,0,0) scale(.5)}
  46%{opacity:.95;transform:translate3d(var(--dx),var(--dy),0) scale(1)}
}
@media (prefers-reduced-motion:reduce){
  .badge--glow{transition:none}
  .badge--glow.is-lit{animation:none}
  .bg-stars i{animation:none;opacity:.5;transform:none}
}


/* the quiet ↳ marker used before headings and first list rows */
.mk{
  display:inline-block;color:var(--orange);opacity:.75;
  font-family:var(--sans);font-size:.42em;font-weight:500;
  vertical-align:.62em;margin-right:.3em;letter-spacing:0;
}

.lede{font-size:clamp(16.5px,1.5vw,19px);color:var(--ink-70);line-height:1.62;margin:0}
.on-night .eyebrow{color:var(--on-night-60)}
.on-night .lede{color:var(--on-night-60)}

/* ---------- buttons ---------- */
.btn{
  display:inline-flex;align-items:center;gap:9px;
  font-family:var(--sans);font-size:15px;font-weight:500;line-height:1;
  padding:15px 26px;border:0;border-radius:var(--pill);
  text-decoration:none;cursor:pointer;
  transition:transform .4s var(--ease), box-shadow .4s var(--ease), background .25s ease, color .25s ease;
}
.btn .arrow{transition:transform .4s var(--ease)}
.btn:hover .arrow{transform:translateX(3px)}
.btn--primary{background:var(--orange);color:#FFF8F2;box-shadow:0 6px 18px rgba(255,81,0,.22)}
.btn--primary:hover{transform:translateY(-2px);box-shadow:0 14px 32px rgba(255,81,0,.30)}
.btn--ink{background:var(--ink);color:var(--paper)}
.btn--ink:hover{transform:translateY(-2px);box-shadow:0 14px 30px rgba(26,26,26,.22)}
.btn--glass{background:rgba(255,252,239,.12);color:var(--on-night);box-shadow:inset 0 0 0 1px rgba(245,240,226,.34);backdrop-filter:blur(10px)}
.btn--glass:hover{background:rgba(255,252,239,.2);transform:translateY(-2px)}

/* ============================================================
   LOADER  (only exists when JS is on , see html.js gate)
   ============================================================ */
.loader{display:none}
html.js .loader{
  display:grid;place-items:center;
  position:fixed;inset:0;z-index:120;background:var(--night);
  /* The panel used to fade as one piece over seven tenths of a second, which
     meant the logo was still half there while the hero was already showing
     through it. The logo goes first and is completely gone before the panel
     behind it starts to clear, so there is never a moment with both. */
  transition:opacity .38s var(--ease) .18s, visibility .38s var(--ease) .18s;
  animation:loaderOut .38s var(--ease) 3.2s forwards;   /* escape hatch if JS stalls */
}
@keyframes loaderOut{to{opacity:0;visibility:hidden}}
.loader-in{
  display:grid;justify-items:center;gap:24px;
  transition:opacity .24s ease, transform .24s var(--ease);
  animation:loaderInOut .24s ease 3s forwards;          /* same escape hatch */
}
.loader.done .loader-in{opacity:0;transform:scale(.985)}
@keyframes loaderInOut{to{opacity:0;transform:scale(.985)}}
.loader img{width:min(230px,50vw);animation:logoIn 1.1s var(--ease) both}
.loader-bar{width:112px;height:2px;border-radius:var(--pill);background:rgba(245,240,226,.16);overflow:hidden}
.loader-bar i{display:block;height:100%;width:0;background:var(--orange);border-radius:var(--pill);animation:barFill 1.25s var(--ease) forwards}
.loader.done{opacity:0;visibility:hidden}
@keyframes logoIn{from{opacity:0;transform:scale(.94) translateY(8px)}to{opacity:1;transform:none}}
@keyframes barFill{from{width:0}to{width:100%}}

/* ============================================================
   NAV , floating pill
   ============================================================ */
/* ============================================================
   TOP GLASS   an iOS style frosted edge. Each layer blurs a little
   more than the one below and is masked to a shorter band, which
   gives a falloff rather than a hard line where a single
   backdrop-filter rectangle would end. Nothing is tinted, so the
   cream sections and the dark ones both keep their own colour.
   ============================================================ */
.topglass{
  position:fixed;top:0;left:0;right:0;z-index:60;
  height:var(--tg-h,112px);pointer-events:none;
  opacity:0;transition:opacity .5s var(--ease);
}
/* Two layers, not three. Every backdrop-filter layer repaints what is behind
   it on each scrolled frame, and three of them across the full width was
   enough work to be felt while scrolling. Two still give the falloff. */
.topglass span{position:absolute;inset:0;display:block}
.topglass span:nth-child(1){
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  -webkit-mask-image:linear-gradient(180deg,#000 0%,rgba(0,0,0,.55) 52%,transparent 100%);
          mask-image:linear-gradient(180deg,#000 0%,rgba(0,0,0,.55) 52%,transparent 100%);
}
.topglass span:nth-child(2){
  -webkit-backdrop-filter:blur(9px);backdrop-filter:blur(9px);
  -webkit-mask-image:linear-gradient(180deg,#000 0%,rgba(0,0,0,.45) 22%,transparent 48%);
          mask-image:linear-gradient(180deg,#000 0%,rgba(0,0,0,.45) 22%,transparent 48%);
}
/* off at the very top so the hero reads clean, fading in as soon as
   anything has scrolled under it */
html.scrolled .topglass{opacity:1}
.top-sentinel{position:absolute;top:0;left:0;width:1px;height:1px;pointer-events:none}
@media (max-width:860px){.topglass{--tg-h:78px}}
@media (max-width:560px){.topglass{--tg-h:64px}}
html.capture .topglass{display:none!important}
/* a backdrop-filter this size is not worth it if the browser cannot do it */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .topglass{display:none}
}

.nav{
  position:fixed;top:0;left:0;right:0;z-index:70;
  display:flex;justify-content:center;
  top:env(safe-area-inset-top,0px);
  padding:30px 16px 0;
  pointer-events:none;
  /* one eased move between two resting places, decided by whether the page
     is at the top. It answers scroll and nothing else: no pointer. */
  transition:transform .55s var(--ease);
}
html.js .nav.at-top{transform:translate3d(0,15px,0)}
@media (prefers-reduced-motion:reduce){.nav{transition:none}}
.nav-pill{
  pointer-events:auto;position:relative;isolation:isolate;
  display:flex;align-items:center;gap:6px;
  padding:5px 6px;border-radius:var(--pill);

  /* the glass body. It sits over a near black photograph at the top of the
     page, so it needs real opacity or it turns to mud and the dark link
     text stops being readable. */
  /* Over the near black hero the backdrop is lifted hard so a light,
     genuinely translucent glass still reads. On cream the lift is removed,
     see .on-light below. */
  background:rgba(252,247,236,.47);
  backdrop-filter:blur(20px) saturate(1.1) brightness(1.7);
  -webkit-backdrop-filter:blur(20px) saturate(1.1) brightness(1.7);

  /* specular rim: bright along the top, faint bounce along the bottom,
     hairline all the way round */
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.9),
    inset 0 -1px 0 rgba(255,255,255,.3),
    inset 0 0 0 1px rgba(255,255,255,.5),
    0 14px 38px rgba(12,14,10,.34),
    0 2px 6px rgba(12,14,10,.18);

  transition:opacity .7s var(--ease), transform .7s var(--ease),
             background .5s ease, box-shadow .5s ease;
}
/* hidden only while scripting is on, and cleared by the ready class, by the
   keyframe fallback, or by capture mode. Without JS it is simply visible. */
html.js .nav-pill{
  opacity:0;transform:translateY(-12px);
  animation:navIn .7s var(--ease) 1.4s forwards;
}
html.js .nav-pill.ready{opacity:1;transform:none;animation:none}
@keyframes navIn{to{opacity:1;transform:none}}
/* over cream the glass needs more body or it disappears */
.nav-pill.on-light{
  backdrop-filter:blur(18px) saturate(1.2) brightness(1.02);
  -webkit-backdrop-filter:blur(18px) saturate(1.2) brightness(1.02);
  background:rgba(255,255,255,.58);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.9),
    inset 0 0 0 1px rgba(26,26,26,.07),
    0 10px 28px rgba(26,26,26,.13),
    0 2px 5px rgba(26,26,26,.08);
}

/* Light travelling across the face. It is the only thing about the bar
   that answers the pointer: the capsule itself never moves, never scales
   and never tilts. --lg is how near the pointer is, written by the script,
   and it is already eased there, so nothing is transitioned here. */
.lg-sheen{
  position:absolute;inset:0;z-index:0;border-radius:inherit;pointer-events:none;
  background:radial-gradient(160px 66px at var(--mx,50%) var(--my,14%),
             rgba(255,255,255,.52), rgba(255,255,255,0) 76%);
  opacity:var(--lg,0);
}
/* fixed gloss along the top edge, the way light sits on a curved surface */
.lg-gloss{
  position:absolute;z-index:0;left:7px;right:7px;top:1px;height:46%;
  border-radius:var(--pill);pointer-events:none;
  background:linear-gradient(180deg, rgba(255,255,255,.52), rgba(255,255,255,0));
  opacity:calc(.55 + .2 * var(--lg, 0));
}

/* the liquid part: one capsule that glides between items */
.nav-ind{
  position:absolute;z-index:1;top:4px;bottom:4px;left:0;width:0;
  border-radius:var(--pill);background:var(--ink);
  transform:translateX(0);transform-origin:center;
  /* a calm ease rather than the old overshoot, which was half of what
     made the bar feel loose under the cursor */
  transition:transform .46s var(--ease), width .46s var(--ease);
  will-change:transform,width;
}
html:not(.js) .nav-ind{display:none}

.nav-links{position:relative;z-index:2;display:flex;align-items:center;gap:2px}
.nav-links a{
  font-size:12.5px;font-weight:500;text-decoration:none;color:#3A342B;
  padding:7px 12px;border-radius:var(--pill);
  transition:color .3s ease;
}
.nav-links a:hover{color:var(--ink)}
/* The pill is a fixed 373px at every width, which on a 27 inch reads as a
   small control floating in a lot of room. It grows a little, and only a
   little: the indicator capsule is measured from the links by script, so it
   follows whatever size they end up. */
@media (min-width:1600px){
  .nav-pill{gap:8px;padding:6px 7px}
  .nav-links a{font-size:13.5px;padding:8px 15px}
  .nav-cta{font-size:13.5px;padding:9px 18px}
}
@media (min-width:2200px){
  .nav-links a{font-size:14.5px;padding:9px 17px}
  .nav-cta{font-size:14.5px;padding:10px 20px}
}
/* whichever link the capsule is under gets light text. Driven from JS so a
   hover preview and the active section can never disagree. */
.nav-links a.lit,.nav-links a.lit:hover{color:var(--paper)}
.nav-links a:focus:not(:focus-visible),.nav-cta:focus:not(:focus-visible){outline:none}


.nav-cta{
  position:relative;z-index:2;
  font-weight:500;text-decoration:none;
  background:var(--orange);color:#FFF8F2;
  font-size:12.5px;padding:8px 15px;border-radius:var(--pill);
  box-shadow:0 4px 14px rgba(255,81,0,.3);
  transition:background .3s ease, transform .3s var(--ease), box-shadow .3s ease;
}
.nav-cta:hover{background:#E8420B;transform:translateY(-1px);box-shadow:0 8px 22px rgba(255,81,0,.4)}

@media (max-width:720px){
  .nav-links a:not(.nav-here){display:none}
}

/* ============================================================
   HERO   full bleed photograph, logo top left, copy on the right
   ============================================================ */
.hero{
  position:relative;overflow:hidden;background:var(--night);
  min-height:100vh;
  min-height:100svh;
  display:flex;flex-direction:column;justify-content:center;
  padding-top:calc(118px + env(safe-area-inset-top,0px));
  padding-bottom:clamp(40px,6vh,72px);
}
.hero-bg{position:absolute;inset:0;z-index:0}
/* The section behind it is already night coloured, so this lifts out of black
   rather than flashing. The keyframe is the escape hatch for a stalled load,
   the same trick the loader and the nav pill use. */
html.js .hero-bg{opacity:0;animation:heroBgIn .5s var(--ease) 3.3s forwards}
html.js.hero-open .hero-bg{opacity:1;animation:none;transition:opacity .5s var(--ease)}
@keyframes heroBgIn{to{opacity:1}}
.hero-bg img{width:100%;height:100%;object-fit:cover;object-position:33% 22%;will-change:transform}
.hero-tint{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    linear-gradient(180deg, rgba(8,10,6,.80) 0%, rgba(8,10,6,.20) 30%),
    linear-gradient(270deg, rgba(8,10,6,.80) 0%, rgba(8,10,6,.46) 40%, rgba(8,10,6,.04) 74%),
    linear-gradient(0deg, rgba(8,10,6,.76) 0%, rgba(8,10,6,0) 34%);
}
.hero-logo{
  position:absolute;z-index:3;
  left:clamp(20px,4vw,54px);
  top:calc(34px + env(safe-area-inset-top,0px));
}
.hero-logo img{width:clamp(112px,9.6vw,134px);height:auto}

.hero-inner{position:relative;z-index:3;width:100%;display:flex;justify-content:flex-end}
.hero-text{max-width:min(600px,100%);will-change:transform}
/* ============================================================
   HERO HEADLINE   set in a pixel face, and assembled out of one.
   Each line carries a two layer mask: a checkerboard the size of a
   few device pixels, and a solid layer over it whose alpha fades in.
   At alpha nought the letters are half a grid of blocks, at one they
   are ordinary sharp type, and the whole thing is three elements
   rather than a span for every character. The third layer is a soft
   hole under the pointer: it subtracts from the solid layer, so the
   dither shows through again and the letters go briefly pixelated
   exactly where the cursor is.
   ============================================================ */
@property --pxa{syntax:'<number>';inherits:false;initial-value:1}
@property --wp{syntax:'<percentage>';inherits:false;initial-value:130%}
@property --pxc{syntax:'<length>';inherits:false;initial-value:9px}
@property --pxw{syntax:'<length>';inherits:false;initial-value:5px}
@property --pxg{syntax:'<number>';inherits:false;initial-value:1}
@property --hr{syntax:'<length>';inherits:false;initial-value:1px}

.hero-title{
  /* hugging the text rather than the column, so the small marks can be
     placed against the letters instead of against the empty page */
  position:relative;margin:0 0 34px;display:grid;gap:0;
  width:fit-content;max-width:100%;
  font-family:"Pixelify Sans", var(--mono);
}
.px-l{
  display:block;position:relative;width:fit-content;max-width:100%;
  --cell:clamp(7px, .72vw, 11px);
}

/* the real text. A soft wipe travels across it, which is what turns the
   blocks underneath into finished letters as it passes, and the pointer
   subtracts a hole from it so the blocks can show through again. */
.px-sharp{
  display:block;
  --hr:1px;--mx:-50%;--my:50%;
  -webkit-mask-image:
    linear-gradient(96deg,
      rgba(0,0,0,var(--pxa)) 0 calc(var(--wp) - 24%),
      rgba(0,0,0,0) var(--wp) 100%),
    radial-gradient(var(--hr) var(--hr) at var(--mx) var(--my), #000 0%, rgba(0,0,0,0) 72%);
          mask-image:
    linear-gradient(96deg,
      rgba(0,0,0,var(--pxa)) 0 calc(var(--wp) - 24%),
      rgba(0,0,0,0) var(--wp) 100%),
    radial-gradient(var(--hr) var(--hr) at var(--mx) var(--my), #000 0%, rgba(0,0,0,0) 72%);
  -webkit-mask-size:100% 100%, 100% 100%;
          mask-size:100% 100%, 100% 100%;
  -webkit-mask-repeat:no-repeat, no-repeat;
          mask-repeat:no-repeat, no-repeat;
  -webkit-mask-composite:source-out;
          mask-composite:subtract;
  transition:--hr .45s var(--ease);
}

/* the clone, masked to a grid of square blocks. Two stripe layers crossed,
   which is what makes squares rather than the wedges a conic gradient would
   give at anything other than a quarter turn. Absolutely positioned, so it
   can never take part in layout. */
.px-ghost{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  white-space:pre;
  /* the resting grid, once the build has run and been cancelled. Keeping it
     in a rule rather than in an inline style means it still answers a
     resize. */
  --pxc:9px;--pxw:5px;
  opacity:var(--pxg);
  filter:brightness(1.22);
  transform:translate3d(var(--gx,0px), var(--gy,0px), 0);
  transition:transform .5s var(--ease), opacity .35s ease;
  -webkit-mask-image:
    repeating-linear-gradient(90deg, #000 0 var(--pxw), rgba(0,0,0,0) var(--pxw) var(--pxc)),
    repeating-linear-gradient(0deg,  #000 0 var(--pxw), rgba(0,0,0,0) var(--pxw) var(--pxc));
          mask-image:
    repeating-linear-gradient(90deg, #000 0 var(--pxw), rgba(0,0,0,0) var(--pxw) var(--pxc)),
    repeating-linear-gradient(0deg,  #000 0 var(--pxw), rgba(0,0,0,0) var(--pxw) var(--pxc));
  -webkit-mask-composite:source-in;
          mask-composite:intersect;
}

/* Before the script has measured the font there is nothing to see. It adds
   .is-built once the face is ready, which is what starts the build, so the
   letters never assemble in one font and finish in another. */
html.js .hero-title .px-sharp{--pxa:0;--wp:0%}
html.js .hero-title .px-ghost{--pxg:0}
html.js .hero-title.is-built .px-sharp{animation:pxSolid 1.05s linear forwards}
html.js .hero-title.is-built .px-ghost{animation:pxBuild 1.05s linear forwards}
.px-l2 .px-sharp,.px-l2 .px-ghost{animation-delay:.07s}
.px-l3 .px-sharp,.px-l3 .px-ghost{animation-delay:.14s}

/* coarse chunks first, then finer ones. Coverage climbs a little as the
   blocks shrink, which is what reads as more of the word arriving. */
/* Coverage starts at about eight percent in big chunks and climbs to a third
   in small ones. The first stage has to be sparse enough to read as a few
   fragments rather than as a word already. */
@keyframes pxBuild{
  0%   {--pxc:34px;--pxw:13px;--pxg:0}
  7%   {--pxg:1}
  22%  {--pxc:28px;--pxw:12px}
  44%  {--pxc:22px;--pxw:10px}
  64%  {--pxc:16px;--pxw:8px}
  82%  {--pxc:12px;--pxw:6.5px}
  100% {--pxc:9px;--pxw:5px;--pxg:1}
}
/* the sharp copy sweeps across, last, and settles */
/* the sharp copy holds off until a third of the way in, so the block stage
   is actually seen before anything resolves */
@keyframes pxSolid{
  0%   {--pxa:0;--wp:0%}
  30%  {--pxa:1;--wp:2%}
  56%  {--pxa:1;--wp:26%}
  80%  {--pxa:1;--wp:70%}
  100% {--pxa:1;--wp:132%}
}

.px-s{display:inline;color:var(--on-night)}
.px-s--sun{color:var(--sun)}
.px-s--fire{position:relative;color:var(--amber)}
/* a pixel rule under the last word instead of the drawn one */
.px-s--fire::after{
  content:"";position:absolute;left:0;right:0;bottom:-.12em;height:.075em;
  background:repeating-linear-gradient(90deg,
    var(--orange) 0 .055em, rgba(0,0,0,0) .055em .11em);
  opacity:.9;
}

.px-l1{
  font-weight:700;color:var(--sun);
  font-size:clamp(44px,7.1vw,94px);line-height:.94;letter-spacing:-.01em;
  text-shadow:0 6px 50px rgba(8,10,6,.5);
}
.px-l2,.px-l3{
  font-weight:400;color:var(--on-night);
  font-size:clamp(23px,3.4vw,44px);line-height:1.1;letter-spacing:.005em;
  text-shadow:0 2px 26px rgba(8,10,6,.66);
}
.px-l2{margin-top:.18em;font-weight:500;letter-spacing:.03em}
.px-l3{margin-top:.1em;font-weight:700}
.px-dots{font-style:normal;opacity:.45;font-size:.66em;letter-spacing:.06em}

/* ---------- the three small marks ---------- */
.px-mark{
  position:absolute;pointer-events:none;display:block;line-height:0;font-size:1rem;
}
html.js .hero-title .px-mark{opacity:0}
html:not(.js) .px-mark{opacity:var(--mo,1)}
html.js .hero-title.is-built .px-mark{animation:pxMarkIn .6s var(--ease) .45s forwards}
html.js .hero-title.is-built .px-mark--face{animation-delay:.62s}
html.js .hero-title.is-built .px-mark--bar{animation-delay:.78s}
@keyframes pxMarkIn{to{opacity:var(--mo,1)}}
.px-mark svg{display:block;width:100%;height:auto;fill:currentColor}
.px-mark--star{
  width:clamp(13px,1.2vw,18px);color:var(--sun);--mo:.85;
  top:-12px;right:-18px;
  animation:pxTwinkle 5.5s ease-in-out infinite;
}
.px-mark--face{
  width:clamp(15px,1.4vw,20px);color:var(--on-night);--mo:.55;
  bottom:-4px;right:-26px;
  animation:pxBob 6.5s ease-in-out infinite;
}
.px-mark--face .px-eye{fill:var(--night)}
.px-mark--bar{
  width:clamp(20px,2vw,28px);color:var(--orange);--mo:.85;
  bottom:-22px;left:2px;
}
.px-mark--bar .pb{animation:pxLoad 2.4s steps(1,end) infinite}
.px-mark--bar .pb2{animation-delay:.3s}
.px-mark--bar .pb3{animation-delay:.6s}
.px-mark--bar .pb4{animation-delay:.9s}
@keyframes pxLoad{0%,42%{opacity:.22}46%,100%{opacity:1}}
@keyframes pxTwinkle{0%,88%,100%{opacity:.85;transform:scale(1)}94%{opacity:1;transform:scale(1.18)}}
@keyframes pxBob{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}

@media (max-width:860px){
  /* a phone keeps the identity and drops one of the marks */
  .px-mark--face{display:none}
  /* a phone headline is a third of the width, so the same blocks would be
     three across. The build runs on a smaller grid instead. */
  html.js .hero-title.is-built .px-ghost{animation-name:pxBuildSm}
  .px-ghost{--pxc:6px;--pxw:3.4px}
}
@keyframes pxBuildSm{
  0%   {--pxc:20px;--pxw:8px;--pxg:0}
  7%   {--pxg:1}
  22%  {--pxc:17px;--pxw:7px}
  44%  {--pxc:13px;--pxw:6px}
  64%  {--pxc:10px;--pxw:5px}
  82%  {--pxc:7.5px;--pxw:4px}
  100% {--pxc:6px;--pxw:3.4px;--pxg:1}
}
@media (prefers-reduced-motion:reduce){
  /* the finished headline, straight away, with a short fade and nothing else */
  html.js .hero-title .px-sharp{--pxa:1;--wp:130%;animation:none}
  html.js .hero-title.is-built .px-sharp{animation:pxCalm .45s ease forwards}
  html.js .hero-title .px-ghost,
  html.js .hero-title.is-built .px-ghost{display:none;animation:none}
  html.js .hero-title .px-mark{opacity:var(--mo,1)}
  html.js .hero-title.is-built .px-mark{animation:none}
  .px-mark--star,.px-mark--face,.px-mark--bar .pb{animation:none}
  .hero-lede,html.js .hero-lede,html.js .cue{animation:none;opacity:1;transform:none}
  html.js .hero-bg{opacity:1;animation:none}
  html.js .loader,.loader-in{transition-duration:.2s;animation:none}
}
@keyframes pxCalm{from{opacity:.001}to{opacity:1}}

/* The platform lockup, as YouTube draws it: their own letterforms, their
   own red, sitting on our baseline. The light artwork is the same file as
   the brand wall with the wordmark lifted to paper colour, because the
   shipped one is near black and this paragraph runs on night. A little air
   on both sides so the mark reads as a logo and not as a word. */
.yt-mark{white-space:nowrap}
.yt-logo{
  display:inline-block;vertical-align:-.24em;
  height:1.18em;width:auto;
  margin:0 .30em 0 .26em;
}

.hero-lede{
  margin:0 0 28px;max-width:44ch;
  font-size:clamp(15.5px,1.4vw,18px);line-height:1.6;color:#E7DFCE;
  text-shadow:0 1px 18px rgba(8,10,6,.6);
}

.cue{display:inline-flex;align-items:center;gap:13px;text-decoration:none;margin-top:clamp(20px,3vh,32px)}
/* three stepped chevrons, lighting one after another downward */
.cue-px{width:15px;flex:none;display:block;line-height:0;color:var(--on-night)}
.cue-px svg{display:block;width:100%;height:auto;fill:currentColor}
.cv{opacity:.22;animation:cueFall 1.6s steps(1,end) infinite}
.cv2{animation-delay:.16s}
.cv3{animation-delay:.32s}
@keyframes cueFall{0%,30%{opacity:1}31%,100%{opacity:.22}}
.cue:hover .cue-px{color:var(--sun)}
.cue-text{
  font-family:var(--mono);font-size:11px;letter-spacing:.15em;text-transform:uppercase;
  color:var(--on-night-60);transition:color .3s ease;
}
.cue:hover .cue-text{color:var(--on-night)}

/* the lines start soft and sharpen as you begin to scroll */
/* The paragraph used to sit at a tenth of its opacity behind an eleven pixel
   blur until you scrolled, which is why the hero looked half loaded. It now
   comes in on its own, a beat after the headline starts building, and it is
   only ever opacity and eight pixels of travel: no pixels, no glitch. */
html.js .hero-lede{opacity:0;transform:translate3d(0,8px,0)}
html.js .hero-title.is-built ~ .hero-lede{animation:ledeIn .82s var(--ease) .32s forwards}
@keyframes ledeIn{to{opacity:1;transform:translate3d(0,0,0)}}
/* the scroll hint is last in the order: headline, then the copy, then this */
html.js .cue{opacity:0;transform:translate3d(0,6px,0)}
html.js .hero-title.is-built ~ .cue{animation:ledeIn .6s var(--ease) .68s forwards}

/* ---------- proof numbers: editorial, the type is the whole device ---------- */
.proof{
  list-style:none;margin:clamp(30px,3.6vw,48px) 0 0;padding:0;
  display:grid;grid-template-columns:repeat(4,1fr);
  border-top:1px solid var(--line);
}
@media (max-width:820px){.proof{grid-template-columns:repeat(2,1fr)}}
.stat{
  position:relative;display:block;
  padding:clamp(22px,2.6vw,34px) clamp(14px,2vw,26px) clamp(14px,1.8vw,22px);
  border-right:1px solid var(--line);
  will-change:transform;transition:transform .55s var(--ease);
}
.stat:last-child{border-right:0}
@media (max-width:820px){
  .stat:nth-child(2n){border-right:0}
  .stat:nth-child(-n+2){border-bottom:1px solid var(--line)}
}
.stat-n{
  display:block;
  font-family:var(--serif);font-weight:600;
  font-size:clamp(44px,6.6vw,96px);line-height:.84;letter-spacing:-.05em;
  color:var(--ink);
}
.stat-n i{
  font-style:normal;font-weight:400;letter-spacing:-.02em;
  font-size:.34em;vertical-align:.52em;margin-left:.06em;color:var(--ink-45);
}
.stat-k{
  display:block;margin-top:clamp(10px,1.2vw,16px);
  font-family:var(--mono);font-size:10px;letter-spacing:.18em;text-transform:uppercase;
  color:var(--ink-45);
}

/* a single colour disc behind one word, where a heading read flat */
.circ-word{position:relative;isolation:isolate;display:inline-block}
.circ-word .cw{
  position:absolute;z-index:-1;border-radius:50%;
  width:.86em;height:.86em;left:-.3em;top:.04em;
  background:rgba(255,81,0,.8);
}

@media (max-width:860px){
  .hero{padding-top:calc(96px + env(safe-area-inset-top,0px))}
  .hero-inner{justify-content:flex-start}
  .hero-text{max-width:none}
  /* left where it was on a phone: the nav pill is centred and already sits
     close to the mark at this width, and a bigger one runs under it */
  .hero-logo img{width:120px}
}

/* ============================================================
   SECTIONS
   ============================================================ */
.sec{padding-block:clamp(52px,6.5vw,96px)}
.sec--tight{padding-block:clamp(38px,4.6vw,64px)}
.sec-head{max-width:720px;margin:0 auto clamp(26px,3.4vw,44px);text-align:center}
.sec-head .lede{margin-top:13px;margin-inline:auto;max-width:52ch}

/* The four section headers that sit directly above something moving were
   each carrying a full section's worth of air, which left the label, the
   heading and the line under it reading as three separate things. This
   pulls them into one block. Small numbers on purpose: the sections still
   breathe, they just stop drifting apart. */
.band-sand .sec-head,
.panel .sec-head,
#process .sec-head,
#brands .sec-head{margin-bottom:clamp(14px,1.8vw,24px)}
.band-sand .sec-head .badge,
.panel .sec-head .badge,
#process .sec-head .badge,
#brands .sec-head .badge{margin-bottom:10px}
.band-sand .sec-head .lede,
.panel .sec-head .lede,
#process .sec-head .lede,
#brands .sec-head .lede{margin-top:7px}

/* statement */
.statement{text-align:center;max-width:900px;margin-inline:auto}
.statement p{font-family:var(--serif);font-weight:400;letter-spacing:-.025em;line-height:1.08;font-size:clamp(28px,4.6vw,52px);margin:0}
.statement em{font-style:italic;color:var(--orange)}
.statement .w{opacity:.14;filter:blur(3px);transition:opacity .36s ease-out, filter .36s ease-out}
html:not(.armed) .statement .w{opacity:1}

/* ---------- work cards ---------- */
.grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(26px,3vw,38px)}
.grid-3>*:nth-child(2){margin-top:clamp(20px,4.5vw,58px)}
.grid-3>*:nth-child(3){margin-top:clamp(8px,2vw,26px)}
@media (max-width:620px){.grid-3>*{margin-top:0!important}}
@media (max-width:920px){.grid-3{grid-template-columns:repeat(2,1fr)}}
@media (max-width:620px){.grid-3{grid-template-columns:1fr}}

.card{display:flex;flex-direction:column;gap:13px}

.card-media{
  position:relative;overflow:hidden;background:var(--sand);
  border-radius:var(--squish);
  box-shadow:var(--shadow-soft);
  transition:transform .6s var(--ease), box-shadow .6s var(--ease);
}
.card:hover .card-media{transform:translateY(-7px);box-shadow:var(--shadow-lift)}
.card-media.ar-916{border-radius:var(--squish-tall)}
.on-night .card-media{box-shadow:0 18px 44px rgba(0,0,0,.36), inset 0 0 0 1px rgba(245,240,226,.07)}
.on-night .card:hover .card-media{box-shadow:0 28px 64px rgba(0,0,0,.48), inset 0 0 0 1px rgba(255,169,70,.2)}
.card-media.ar-169{aspect-ratio:16/9}
.card-media.ar-916{aspect-ratio:9/16}
.card-media video,.card-media img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}

/* soft placeholder until the real clips land. It is hidden only once the
   clip or its poster has really loaded, so a missing file falls back to
   this tile rather than an empty black box. */
.card-media.has-media .ph{opacity:0;transition:opacity .45s var(--ease)}
.ph{
  position:absolute;inset:0;display:grid;place-content:center;justify-items:center;gap:14px;
  padding:20px;text-align:center;
  background:linear-gradient(168deg,#F8F3E5 0%,#EDE4CE 58%,#E6DBC2 100%);
}
.ph-dot{
  width:46px;height:46px;border-radius:var(--pill);background:rgba(255,81,0,.1);
  display:grid;place-items:center;
}
.ph-dot::after{content:"";width:0;height:0;border-left:11px solid var(--orange);border-block:7px solid transparent;margin-left:3px}
.ph-name{font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-45)}
.ph-spec{font-family:var(--mono);font-size:10px;line-height:1.5;color:#A69E8E;max-width:24ch}
.on-night .ph{background:linear-gradient(168deg,#2A251D 0%,#211D17 100%)}
.on-night .ph-name{color:#9C9384}
.on-night .ph-spec{color:#6E6759}
.on-night .ph-dot{background:rgba(255,81,0,.16)}

.card-body{padding:0 4px}
.card-title{font-family:var(--serif);font-weight:400;font-size:21px;line-height:1.14;letter-spacing:-.02em;margin:0 0 6px}
.card-sub{font-size:14px;color:var(--ink-45);margin:0}
.on-night .card-title{color:var(--on-night)}
.on-night .card-sub{color:var(--on-night-60)}
.card-tags{display:flex;flex-wrap:wrap;gap:8px;margin-top:16px}
.tag{
  font-family:var(--mono);font-size:10px;letter-spacing:.11em;text-transform:uppercase;
  padding:5px 11px;border-radius:var(--pill);background:var(--sand);color:var(--ink-45);
}
.on-night .tag{background:rgba(245,240,226,.09);color:var(--on-night-60)}

/* ---------- night panel ---------- */
.panel{
  background:var(--night);color:var(--on-night);
  border-radius:var(--r-xl);
  margin-inline:var(--band-gut);
  padding:clamp(44px,5.6vw,80px) 0;
}
.panel h2.display{color:var(--on-night)}
/* The dark panel had the same generous header spacing as a full section,
   which left the heading floating a long way above the films. Pulled in on
   every side: less air over the label, less under it, and the strip starts
   sooner. */
.panel{padding-block:clamp(34px,4vw,56px)}
.panel .sec-head h2.display{font-size:clamp(28px,4.2vw,48px)}

/* ---------- shorts rail ---------- */
.rail{
  display:grid;grid-auto-flow:column;grid-auto-columns:minmax(206px,1fr);gap:22px;
  overflow-x:auto;scroll-snap-type:x proximity;
  /* a scroller has to clip both axes, so the room for the hover lift and
     the card shadows is padding rather than overflow, pulled back with a
     negative margin so the section spacing is unchanged. Paging is measured
     from the cards themselves, so this padding cannot throw the maths off. */
  padding:14px 3px 26px;margin:-14px -3px -12px;
  scrollbar-width:none;overscroll-behavior-x:contain;
}
.rail::-webkit-scrollbar{display:none}
/* start, not centre: a page then sits flush at the left edge instead of
   leaving half a card hanging off both sides */
.rail>*{scroll-snap-align:start}

/* ============================================================
   REELS   the card shell is unchanged: the clip fills it, covers,
   and fades up once it has frames, so the card never resizes and
   there is nothing to look at while the CDN answers.
   ============================================================ */
.reel-media{background:var(--sand-2);isolation:isolate}
.reel-media video{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;display:block;
  opacity:0;transition:opacity .6s var(--ease);
}
.reel-media.is-ready video{opacity:1}

/* The focused card is the one that matters, so it says so: a warm ring and
   a low glow rather than dimming the two beside it. */
.reel-card{
  transition:transform .6s var(--ease), opacity .6s var(--ease);
  cursor:pointer;opacity:.82;
}
.reel-card .card-media{transition:box-shadow .6s var(--ease)}
.reel-card.is-active{transform:translateY(-6px);opacity:1}
.reel-card.is-active .card-media{
  box-shadow:0 18px 44px rgba(26,26,26,.18), 0 0 0 2px rgba(255,81,0,.5);
}
/* the warm edge itself, drawn just inside the corner so the radius holds */
.reel-card .card-media::after{
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  border-radius:inherit;opacity:0;transition:opacity .6s var(--ease);
  background:linear-gradient(180deg, rgba(255,81,0,.22) 0%, rgba(255,81,0,0) 26%,
                             rgba(255,81,0,0) 62%, rgba(255,105,0,.34) 100%);
}
.reel-card.is-active .card-media::after{opacity:1}
@media (prefers-reduced-motion:reduce){
  .reel-card{transition:none}
  .reel-card.is-active{transform:none}
}

/* ---------- play, pause and progress, on the focused card only ---------- */
.vid-pp{
  position:absolute;z-index:3;left:50%;top:50%;translate:-50% -50%;
  width:56px;height:56px;border:0;border-radius:50%;cursor:pointer;
  display:none;place-items:center;
  background:rgba(20,18,14,.44);color:#fff;
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
  box-shadow:0 4px 18px rgba(0,0,0,.28), inset 0 0 0 1px rgba(255,255,255,.24);
  opacity:0;transition:opacity .3s ease, scale .3s var(--ease), background .3s ease;
}
.vid-pp svg{width:22px;height:22px;fill:currentColor}
.reel-card.is-active .vid-pp{display:grid}
/* shown when the clip is held, or when the pointer is over the card */
.reel-card.is-active:hover .vid-pp,
.reel-card.is-active .is-paused .vid-pp{opacity:1}
.vid-pp:hover{background:rgba(20,18,14,.62);scale:1.06}

.vid-prog{
  position:absolute;z-index:3;left:14px;right:14px;bottom:13px;height:16px;
  display:none;align-items:flex-end;cursor:pointer;touch-action:none;
}
.reel-card.is-active .vid-prog{display:flex}
.vid-prog::before{
  content:"";position:absolute;left:0;right:0;bottom:5px;height:4px;border-radius:99px;
  background:rgba(255,255,255,.28);
  -webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);
}
.vid-prog i{
  position:absolute;left:0;right:0;bottom:5px;height:4px;border-radius:99px;
  background:linear-gradient(90deg, var(--amber), var(--orange));
  transform:scaleX(0);transform-origin:left center;
  box-shadow:0 0 10px rgba(255,81,0,.5);
}
.vid-prog:hover::before,.vid-prog:hover i{height:6px;bottom:4px}

/* ---------- sound, one pill for the whole strip ---------- */
.reel-sound{
  position:absolute;z-index:6;right:0;bottom:-6px;
  display:inline-flex;align-items:center;gap:9px;cursor:pointer;border:0;
  padding:10px 16px 10px 13px;border-radius:var(--pill);
  font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;
  background:rgba(252,245,226,.82);color:var(--ink-70);
  -webkit-backdrop-filter:blur(9px) saturate(1.1);backdrop-filter:blur(9px) saturate(1.1);
  box-shadow:0 6px 20px rgba(26,26,26,.1), inset 0 0 0 1px rgba(26,26,26,.1);
  opacity:0;transform:translateX(10px);
  transition:opacity .45s var(--ease), transform .45s var(--ease),
             background .3s ease, color .3s ease, box-shadow .3s ease;
}
.reel-sound.is-here{opacity:1;transform:none}
.reel-sound svg{
  width:15px;height:15px;flex:none;fill:none;stroke:currentColor;stroke-width:1.9;
  stroke-linecap:round;stroke-linejoin:round;
}
.reel-sound.is-on{
  background:var(--orange);color:#fff;
  box-shadow:0 8px 24px rgba(255,81,0,.3), inset 0 0 0 1px rgba(255,255,255,.2);
}
.reel-sound:hover{transform:translateY(-2px)}
/* the long form sits on the dark panel */
.reel-sound--night{
  background:rgba(245,240,226,.12);color:var(--on-night);
  box-shadow:0 6px 20px rgba(0,0,0,.24), inset 0 0 0 1px var(--line-night);
}
.reel-sound--night.is-on{background:var(--orange);color:#fff}

/* the deck treats every card the same, so the long form cards get the same
   focus language as the reels */
.rail--wide .card{transition:transform .6s var(--ease), opacity .6s var(--ease);opacity:.82}
.rail--wide .card.is-active{transform:translateY(-6px);opacity:1}
.rail--wide .card.is-active .card-media{
  box-shadow:0 18px 44px rgba(0,0,0,.4), 0 0 0 2px rgba(255,81,0,.5);
}
.rail--wide .card .card-media::after{
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  border-radius:inherit;opacity:0;transition:opacity .6s var(--ease);
  background:linear-gradient(180deg, rgba(255,81,0,.18) 0%, rgba(255,81,0,0) 30%,
                             rgba(255,81,0,0) 62%, rgba(255,105,0,.3) 100%);
}
.rail--wide .card.is-active .card-media::after{opacity:1}
.rail--wide .card.is-active .vid-pp{display:grid}
.rail--wide .card.is-active:hover .vid-pp,
.rail--wide .card.is-active .is-paused .vid-pp{opacity:1}
.rail--wide .card.is-active .vid-prog{display:flex}
@media (max-width:860px){
  .reel-sound{right:auto;left:50%;translate:-50% 0;bottom:-52px;padding:11px 18px}
  .reel-sound:hover{transform:none}
}

/* ============================================================
   TOUCH SIZING   a finger is not a cursor. Anything that can be
   tapped gets a 44px target, given by padding around the visible
   shape rather than by making the shape itself bigger, so nothing
   about the design changes. Safe area insets keep the fixed and
   floating pieces clear of the notch and the home bar.
   ============================================================ */
@media (hover:none),(max-width:860px){
  /* the page dots were 8px of glass to hit */
  .rail-dot{position:relative}
  .rail-dot::after{content:"";position:absolute;inset:-17px -9px;border-radius:99px}

  /* nav links and the call to action */
  .nav-links a{padding-block:11px}
  .nav-cta{padding-block:11px}

  /* sound pill, footer and social links */
  .reel-sound{padding-block:13px}
  .foot ul a,.foot-base a{display:inline-block;padding-block:8px}
  .cband-reach a{display:inline-block;padding-block:6px}

  /* the story caption and scribbles do not need to be hit at all */
  .scribble,.story-cap{pointer-events:none}
}

@media (max-width:860px){
  /* fixed and floating things respect the notch and the home bar */
  .nav{padding-top:calc(14px + env(safe-area-inset-top,0px))}
  .reel-sound{margin-bottom:env(safe-area-inset-bottom,0px)}
  .cband{padding-bottom:calc(clamp(50px,8vw,80px) + env(safe-area-inset-bottom,0px))}
}

/* ---------- brands ---------- */
.marquee{overflow:hidden;padding-block:6px}
.marquee-track{display:flex;width:max-content;align-items:center;
  animation:drift var(--lap,64s) linear infinite}
/* The script clones every cell once, so the track is two identical copies
   side by side, and travelling exactly half its own width lands the second
   copy where the first began. This keyframe was missing, which is why the
   wall has been standing still since it was built. */
@keyframes drift{
  from{transform:translate3d(0,0,0)}
  to{transform:translate3d(-50%,0,0)}
}
@media (prefers-reduced-motion:reduce){
  .marquee{overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none}
  .marquee::-webkit-scrollbar{display:none}
  .marquee-track{animation:none}
}
.marquee-track.rev{animation-direction:reverse}
.marquee:hover .marquee-track{animation-play-state:paused}
/* --bgap is the gap the script settles on. It starts at the value below and
   is widened until one pass of the row is wider than the window, which is
   what stops the same logo appearing twice on screen at once. */
.brand{
  flex:none;height:72px;margin-inline:var(--bgap,clamp(20px,3vw,46px));
  display:grid;place-items:center;
}
@media (max-width:640px){
  .brand{height:62px;margin-inline:var(--bgap,22px)}
  .brand img{max-width:132px}
}
/* --bh is written per logo in the markup. The width follows from the
   artwork, so nothing is ever stretched. Grey and held back at rest so the
   wall reads as one quiet row, and each brand's own colour comes back under
   the pointer. */
.brand img{
  height:var(--bh,26px);width:auto;max-width:180px;
  object-fit:contain;display:block;
  filter:grayscale(1) contrast(.92);opacity:.52;
  transition:filter .4s ease, opacity .4s ease;
}
.brand:hover img{filter:none;opacity:1}
@media (hover:none){
  /* nothing to hover on a phone, so the wall simply sits a little clearer */
  .brand img{opacity:.62}
}
/* On a wide screen the wall was holding 26px logos in a 2000px canvas, and
   the script opened the gaps to fill it, which read as drift rather than as
   spacing. The logos themselves grow instead. Every one keeps its own --bh
   from the markup, so the optical balance between a wide wordmark and a
   square mark survives the scaling. */
.marquee{--bscale:1}
@media (min-width:1500px){.marquee{--bscale:1.16}}
@media (min-width:1900px){.marquee{--bscale:1.3}}
@media (min-width:2300px){.marquee{--bscale:1.42}}
.brand{height:calc(72px * var(--bscale,1))}
.brand img{
  height:calc(var(--bh,26px) * var(--bscale,1));
  max-width:calc(180px * var(--bscale,1));
}
/* restated after the scaling rules above, because the phone values are
   written earlier in the file and equal weight is settled by order */
@media (max-width:640px){
  .brand{height:62px}
  .brand img{max-width:132px}
}
#process{padding-top:clamp(32px,3.8vw,54px)}
/* The four step strip and the three service cards are a layout, not prose,
   so they follow the window rather than the reading measure. */
#process>.wrap{max-width:var(--maxw-wide)}

/* ---------- process: gradient bento cards ---------- */
.bento{display:grid;grid-template-columns:repeat(6,1fr);gap:clamp(12px,1.6vw,18px)}
.bento-card{
  position:relative;overflow:hidden;isolation:isolate;
  border-radius:var(--r-lg);padding:clamp(22px,2.4vw,30px);
  min-height:216px;display:flex;flex-direction:column;color:#fff;
  transition:transform .55s var(--ease), box-shadow .55s var(--ease);
  /* the card is promoted from the start. Letting the hover transform create
     the layer instead made the browser re-rasterise mid animation, and the
     diagonal pattern dropped out along the rounded edges while it did. */
  will-change:transform;backface-visibility:hidden;
}
.bento-card:nth-child(1),.bento-card:nth-child(2){grid-column:span 3}
.bento-card:nth-child(3){grid-column:span 2}
.bento-card:nth-child(4){grid-column:span 4}
@media (max-width:860px){
  .bento{grid-template-columns:1fr}
  .bento-card:nth-child(1),.bento-card:nth-child(2),
  .bento-card:nth-child(3),.bento-card:nth-child(4){grid-column:auto}
  .bento-card{min-height:0}
}
.bento-card::before{
  content:"";position:absolute;inset:-6px;z-index:0;
  /* a little past the box, so the rotation on hover never swings a bare
     corner into view and the antialiased edge stays covered */
  background:repeating-linear-gradient(112deg, rgba(255,255,255,.10) 0 2px, transparent 2px 15px);
}
.bento-card::after{
  content:"";position:absolute;z-index:0;right:-26%;top:-42%;width:66%;aspect-ratio:1;border-radius:50%;
  pointer-events:none;
  background:radial-gradient(circle, rgba(255,255,255,.24), transparent 64%);
}
.bento-card:hover{transform:translateY(-5px);box-shadow:var(--shadow-lift)}
.bc-orange{background:linear-gradient(146deg,#FF8E45 0%,#EF3D00 100%)}
.bc-green {background:linear-gradient(146deg,#95DC6E 0%,#2A9550 100%)}
.bc-violet{background:linear-gradient(146deg,#BE93FF 0%,#6636D6 100%)}
.bc-blue  {background:linear-gradient(146deg,#86BAFF 0%,#2A56DF 100%)}

.bento-tag{
  position:relative;z-index:2;align-self:flex-start;margin-bottom:auto;
  background:var(--ink);color:#F5F0E2;border-radius:var(--pill);
  font-family:var(--mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;
  padding:7px 13px;
}
.bento-card h3{
  position:relative;z-index:2;margin:26px 0 8px;
  font-family:var(--serif);font-weight:400;line-height:1;letter-spacing:-.02em;
  font-size:clamp(26px,3vw,38px);
}
.bento-card p{
  position:relative;z-index:2;margin:0;max-width:44ch;
  font-size:15px;line-height:1.55;color:rgba(255,255,255,.93);
}
.bento-no{
  position:absolute;z-index:1;right:18px;bottom:8px;
  font-family:var(--sans);font-weight:900;font-size:clamp(44px,5vw,64px);line-height:1;
  color:rgba(255,255,255,.2);letter-spacing:-.04em;
}

.services{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:clamp(28px,3.4vw,46px)}
@media (max-width:880px){.services{grid-template-columns:1fr}}
/* The three service cards light up from the edge on hover: a soft orange
   bloom sitting just outside the card, and a thin warm rim just inside it.
   Both are pseudo elements that only change opacity, so the whole thing is
   one composited fade and nothing about the card itself moves. The bloom
   follows the pointer, which is what makes it read as light rather than
   as a border that switched on. */
/* The moving light used to live on the blurred outer bloom, which is a box
   fourteen pixels larger than the card on every side. Its centre was being
   given as a percentage of the card, so the hotspot sat in the wrong place
   and, once the pointer reached a corner, the blurred blob ran out of box
   and was cut into a hard half circle. That was the glitch.

   It has its own layer now, exactly the size of the card and rounded to
   exactly the same radius, so the gradient is clipped by the card's own
   shape and by nothing else. No blur on it, so there is no edge for the
   filter to sample past. The outer bloom stays, but it is fixed in place
   and only fades. --gh is how lit the card is, eased in the script, so the
   fade out on exit is a quarter of a second rather than a switch. */
.svc{
  position:relative;isolation:isolate;
  --gx:50%;--gy:50%;--gh:0;
  background:var(--sand);border-radius:var(--r-lg);padding:26px 24px 24px;
  transition:transform .5s var(--ease), box-shadow .5s var(--ease), background .3s ease;
}
.svc-glow{
  position:absolute;inset:0;z-index:0;border-radius:inherit;pointer-events:none;
  opacity:var(--gh);
  background:radial-gradient(54% 60% at var(--gx) var(--gy),
    rgba(255,105,0,.34), rgba(255,140,40,.14) 44%, rgba(255,169,70,0) 74%);
}
/* the writing sits above the light, not under it */
.svc > h3,.svc > p,.svc > .pill{position:relative;z-index:1}
.svc::before{
  content:"";position:absolute;inset:-14px;z-index:-2;border-radius:calc(var(--r-lg) + 14px);
  opacity:calc(var(--gh) * .92);pointer-events:none;
  background:
    radial-gradient(60% 70% at 50% 120%, rgba(255,169,70,.42), transparent 70%),
    radial-gradient(58% 66% at 50% -20%, rgba(255,81,0,.32), transparent 70%);
  filter:blur(17px);
}
.svc::after{
  content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;
  opacity:var(--gh);pointer-events:none;
  padding:1px;
  background:linear-gradient(135deg, rgba(255,81,0,.75), rgba(255,169,70,.32) 42%,
                             rgba(255,81,0,.1) 60%, rgba(255,105,0,.62));
  /* a gradient that is only the rim: fill it, then knock the middle out */
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;mask-composite:exclude;
}
.svc:hover{transform:translateY(-5px);background:#FDF9EE}
/* a finger has no pointer to follow, so the card carries a little warmth
   from the bottom edge and leaves it at that */
@media (hover:none),(pointer:coarse){
  .svc{--gh:1;--gx:50%;--gy:92%}
  .svc-glow{opacity:.34}
  .svc::before{opacity:0}
  .svc::after{opacity:.45}
}
@media (prefers-reduced-motion:reduce){
  .svc{transition:none}
  .svc:hover{transform:none}
}
.svc h3{margin:0 0 12px}
.svc p{margin:0 0 17px;font-size:15px;color:var(--ink-70);line-height:1.6}
.pill{
  display:inline-flex;align-items:center;gap:7px;
  font-family:var(--mono);font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;
  background:var(--paper);color:var(--ink-70);padding:8px 14px;border-radius:var(--pill);
  box-shadow:inset 0 0 0 1px var(--line);
}
.pill::before{content:"";width:6px;height:6px;border-radius:var(--pill);background:var(--orange)}

/* ---------- soft gradient pill ---------- */
.btn--soft{
  background:linear-gradient(180deg,#FFF7EE 0%,#FFE9D8 100%);
  color:#A13C0A;box-shadow:inset 0 0 0 1px rgba(255,81,0,.2);
}
.btn--soft:hover{transform:translateY(-2px);box-shadow:inset 0 0 0 1px rgba(255,81,0,.3), 0 12px 26px rgba(255,81,0,.14)}

/* ============================================================
   BRIEF CHAT   a glass object rather than a panel. The light around
   it is two blurred radial blobs drifting in opposite directions,
   not a conic sweep, because a conic sweep bands visibly once the
   opacity is low enough to be tasteful. Everything that moves here
   moves by transform or opacity, so the section keeps its frame rate
   with a full bleed photograph behind it.
   ============================================================ */
.brief-chat{position:relative;isolation:isolate;align-self:start}

/* The light does not float behind the panel any more. It is a ring: a conic
   gradient turning inside a mask that only lets a thin band at the very edge
   through, blurred just enough to read as light leaking out from under the
   glass. Two bands, one tight and bright on the border itself and one wider
   and faint just outside it, turning at different speeds so the colour at
   each corner keeps changing without either one reading as a spinner.
   The gradient sits on a square pseudo element larger than the panel's
   diagonal, so turning it is a plain rotate that stays on the compositor
   and never exposes a corner. */
@property --bcp{syntax:'<number>';inherits:true;initial-value:0}
@property --bcpx{syntax:'<percentage>';inherits:true;initial-value:50%}
@property --bcpy{syntax:'<percentage>';inherits:true;initial-value:50%}

.brief-chat{
  transition:--bcp .85s var(--ease), --bcpx .5s ease-out, --bcpy .5s ease-out;
}
.bc-glow{
  position:absolute;inset:0;z-index:-1;pointer-events:none;
  border-radius:var(--r-lg);
  filter:blur(8px);--bcglow:.92;opacity:var(--bcglow);
  transition:opacity 1s var(--ease);
}
.brief-chat:hover .bc-glow,
.brief-chat:focus-within .bc-glow{opacity:1}

.bc-glow i{
  position:absolute;display:block;overflow:hidden;
  /* the mask: paint the whole box, subtract everything inside the padding,
     and what is left is a band of exactly that padding width */
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;
  mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite:exclude;
}
/* the bright band, sitting on the border line */
.bc-glow i:nth-child(1){
  inset:-1px;padding:3.5px;border-radius:calc(var(--r-lg) + 1px);opacity:1;
}
/* the wider, fainter bloom a few pixels further out */
.bc-glow i:nth-child(2){
  inset:-6px;padding:7px;border-radius:calc(var(--r-lg) + 6px);opacity:.5;
}
.bc-glow i::before{
  content:"";position:absolute;left:50%;top:50%;
  width:210%;aspect-ratio:1;
  transform:translate(-50%,-50%) rotate(0deg);
  background:conic-gradient(from 0deg,
    #7C5CFF 0%, #9A6BF5 10%, #C876E8 20%, #EE7FBE 28%,
    #FF9463 35%, #EE7FBE 42%, #8F6BF0 54%,
    #5C8FEF 66%, #46BFC4 77%, #5E7BE8 88%, #7C5CFF 100%);
  animation:bcHalo 24s linear infinite;
  will-change:transform;
}
.bc-glow i:nth-child(2)::before{animation-duration:34s;animation-direction:reverse}
@keyframes bcHalo{
  from{transform:translate(-50%,-50%) rotate(0deg)}
  to{transform:translate(-50%,-50%) rotate(360deg)}
}
/* the pointer's own light, added on top of the drifting colour and clipped
   to the same band, so the nearest stretch of border brightens rather than
   a spotlight landing on the card */
.bc-glow i::after{
  content:"";position:absolute;inset:0;border-radius:inherit;
  background:radial-gradient(170px 170px at var(--bcpx) var(--bcpy),
             rgba(255,255,255,.8), rgba(255,255,255,0) 72%);
  opacity:var(--bcp);
}

.bc-inner{
  position:relative;border-radius:var(--r-lg);overflow:hidden;
  /* the glass itself: a little light from the top, a little body, and a
     saturated backdrop so the field behind it reads as colour through
     glass rather than as grey frost */
  /* Frosted, and dark enough that the glow behind it cannot bleed through
     onto the face. That bleed is what made the panel look blotchy: the
     colour belongs around the edge, not across the text. */
  background:linear-gradient(168deg, rgba(38,33,28,.9) 0%, rgba(22,19,16,.93) 46%,
                             rgba(14,12,10,.95) 100%);
  -webkit-backdrop-filter:blur(30px) saturate(1.5);backdrop-filter:blur(30px) saturate(1.5);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.2),
    inset 0 0 0 1px rgba(255,255,255,.1),
    0 26px 60px rgba(0,0,0,.45);
  /* Fixed height on purpose. The panel used to grow as replies arrived and
     as the chip row came and went, and since it is a grid item the whole
     Let's connect section grew with it and everything below the fold
     shuffled. The log takes whatever room is left instead. */
  display:flex;flex-direction:column;
  height:clamp(430px, 56vh, 545px);
}
/* the bright edge along the top, as light catches a real edge */
.bc-sheen{
  position:absolute;left:8%;right:8%;top:0;height:1px;pointer-events:none;
  background:linear-gradient(90deg, transparent, rgba(255,255,255,.7), transparent);
}
/* light moving across the glass, driven by the pointer */
.bc-trace{
  position:absolute;inset:0;pointer-events:none;opacity:0;
  transition:opacity .6s var(--ease);
  background:radial-gradient(38% 44% at var(--mx,50%) var(--my,50%),
             rgba(255,255,255,.07), transparent 70%);
}
.brief-chat:hover .bc-trace{opacity:1}

.bc-head{
  flex:none;display:flex;align-items:center;gap:9px;flex-wrap:wrap;
  padding:14px 18px 12px;
  border-bottom:1px solid rgba(255,255,255,.1);
}
.bc-head b{
  font-family:var(--sans);font-weight:600;font-size:14.5px;letter-spacing:-.01em;
  color:#fff;
}
.bc-sub{
  flex:1 0 100%;margin-top:4px;
  font-family:var(--mono);font-size:9px;letter-spacing:.15em;
  text-transform:uppercase;color:rgba(255,255,255,.62);
}
.bc-live{
  position:relative;width:7px;height:7px;border-radius:50%;flex:none;
  background:#6FE3A0;box-shadow:0 0 9px rgba(111,227,160,.8);
}
.bc-live::after{
  content:"";position:absolute;inset:-4px;border-radius:50%;
  border:1px solid rgba(111,227,160,.5);
  animation:bcBreathe 3.4s ease-in-out infinite;
}
@keyframes bcBreathe{
  0%,100%{transform:scale(.7);opacity:.8}
  50%{transform:scale(1.25);opacity:0}
}

.bc-log{
  padding:18px;display:flex;flex-direction:column;gap:11px;
  flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;
  scrollbar-width:thin;scrollbar-color:rgba(245,240,226,.2) transparent;
}
.bc-log::-webkit-scrollbar{width:5px}
.bc-log::-webkit-scrollbar-thumb{background:rgba(245,240,226,.2);border-radius:99px}

.bc-msg{
  max-width:86%;padding:11px 14px;border-radius:16px;
  font-size:14.5px;line-height:1.5;
  animation:bcIn .4s var(--ease) both;
}
@keyframes bcIn{from{opacity:0;transform:translateY(7px)}to{opacity:1;transform:none}}
/* the reply sits on its own darker pane, because the glass behind it is
   bright wherever the photograph is bright and the text has to hold */
.bc-msg--bot{
  align-self:flex-start;border-bottom-left-radius:5px;
  background:rgba(255,255,255,.08);color:#fff;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.09);
}
.bc-msg--me{
  align-self:flex-end;border-bottom-right-radius:5px;
  background:linear-gradient(135deg, var(--orange), #FF7A2E);color:#fff;
}
.bc-msg a{color:inherit;text-decoration:underline;text-underline-offset:3px}

/* ---------- the thinking state ----------
   An orb rather than a spinner: three radial gradients inside one blurred
   sphere, each drifting at its own pace, so the colour inside it keeps
   moving without anything spinning. Two rings breathe out from behind it.
   It exists only while the answer is being put together. */
.bc-think{
  align-self:stretch;display:flex;flex-direction:column;align-items:center;
  gap:12px;padding:20px 12px 16px;
  animation:bcIn .45s var(--ease) both;
  transition:opacity .45s var(--ease), transform .45s var(--ease);
}
.bc-think.is-out{opacity:0;transform:scale(.94)}

.bc-orb{position:relative;width:62px;height:62px;flex:none;display:grid;place-items:center}
.bc-orb b{
  position:relative;z-index:2;width:44px;height:44px;border-radius:50%;
  background:
    radial-gradient(42% 44% at 32% 30%, rgba(255,180,90,.95), transparent 68%),
    radial-gradient(44% 46% at 72% 40%, rgba(214,120,255,.9), transparent 70%),
    radial-gradient(48% 50% at 50% 78%, rgba(255,110,160,.9), transparent 70%),
    radial-gradient(60% 60% at 50% 50%, rgba(255,120,40,.7), rgba(120,70,190,.55) 70%);
  filter:blur(3px);
  animation:bcOrb 7s ease-in-out infinite;
}
.bc-orb::before,.bc-orb::after{
  content:"";position:absolute;inset:0;border-radius:50%;
  border:1px solid rgba(255,190,140,.4);
  animation:bcRing 3.6s ease-out infinite;
}
.bc-orb::after{animation-delay:1.8s;border-color:rgba(200,150,255,.35)}
@keyframes bcOrb{
  0%,100%{transform:scale(1) rotate(0deg);border-radius:50% 50% 50% 50%}
  33%{transform:scale(1.07) rotate(120deg);border-radius:54% 46% 48% 52%}
  66%{transform:scale(.96) rotate(240deg);border-radius:46% 54% 52% 48%}
}
@keyframes bcRing{
  0%{transform:scale(.62);opacity:.75}
  100%{transform:scale(1.5);opacity:0}
}
.bc-think-t{
  font-family:var(--sans);font-size:14px;color:#fff;
  text-align:center;margin:0;
}
.bc-think-s{
  font-family:var(--mono);font-size:9px;letter-spacing:.14em;text-transform:uppercase;
  color:rgba(255,255,255,.58);text-align:center;margin:0;min-height:1em;
  transition:opacity .4s ease;
}
@media (prefers-reduced-motion:reduce){
  .bc-orb b{animation:none;filter:blur(2px)}
  .bc-orb::before,.bc-orb::after{animation:none;opacity:.3}
  .bc-glow i::before{animation:none}
  .brief-chat{transition:none}
  .bc-live::after{animation:none;opacity:.4}
}

/* a real clip from the strip above, offered inside the conversation */
.bc-clip{
  align-self:flex-start;max-width:86%;display:flex;gap:12px;align-items:center;
  padding:10px;border-radius:16px;border-bottom-left-radius:5px;
  background:rgba(255,255,255,.07);box-shadow:inset 0 0 0 1px rgba(255,255,255,.09);
  animation:bcIn .4s var(--ease) both;
}
.bc-clip-thumb{
  width:52px;height:68px;flex:none;border-radius:10px;overflow:hidden;position:relative;
  background:rgba(245,240,226,.12);display:grid;place-items:center;
}
.bc-clip-thumb svg{width:17px;height:17px;fill:#fff;opacity:.9}
.bc-clip-txt{min-width:0}
.bc-clip-txt b{display:block;font-size:13.5px;color:#fff;font-weight:600}
.bc-clip-txt span{
  display:block;font-family:var(--mono);font-size:9px;letter-spacing:.12em;
  text-transform:uppercase;color:rgba(255,255,255,.62);margin-top:3px;
}
.bc-clip button{
  margin-top:8px;border:0;cursor:pointer;border-radius:var(--pill);
  padding:6px 13px;font-family:var(--sans);font-size:12px;font-weight:500;
  background:rgba(255,81,0,.9);color:#fff;
  transition:background .3s ease, transform .3s var(--ease);
}
.bc-clip button:hover{background:var(--orange);transform:translateY(-1px)}

.bc-chips{flex:none;display:flex;flex-wrap:wrap;gap:7px;padding:0 18px 4px}
.bc-chips:empty{display:none}
.bc-chip{
  border:0;cursor:pointer;border-radius:var(--pill);
  padding:8px 14px;font-family:var(--sans);font-size:13px;
  background:rgba(255,255,255,.09);color:#fff;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.14);
  transition:background .25s ease, transform .25s var(--ease), box-shadow .25s ease;
  animation:bcIn .35s var(--ease) both;
}
.bc-chip:hover{background:rgba(255,81,0,.92);transform:translateY(-2px);box-shadow:inset 0 0 0 1px rgba(255,255,255,.22)}

.bc-bar{
  flex:none;display:flex;gap:9px;align-items:center;padding:12px 13px;
  border-top:1px solid rgba(255,255,255,.1);
}
/* a glass capsule, lit from the top edge like the panel itself */
.bc-bar input{
  flex:1;min-width:0;border:0;border-radius:var(--pill);
  padding:12px 17px;font-family:var(--sans);font-size:14.5px;
  background:linear-gradient(180deg, rgba(255,255,255,.12), rgba(255,255,255,.05));
  color:#fff;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.28), inset 0 0 0 1px rgba(255,255,255,.12);
  transition:box-shadow .35s var(--ease), background .35s ease;
}
.bc-bar input::placeholder{color:rgba(245,240,226,.45)}
.bc-bar input:focus{
  outline:none;
  background:linear-gradient(180deg, rgba(255,255,255,.16), rgba(255,255,255,.07));
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.34),
    inset 0 0 0 1px rgba(255,150,90,.45),
    0 0 0 4px rgba(255,120,40,.1),
    0 0 18px rgba(190,120,255,.16);
}

/* the send key: warm core, a cooler bloom under it, both restrained */
.bc-send{
  position:relative;width:42px;height:42px;flex:none;border:0;border-radius:50%;
  cursor:pointer;display:grid;place-items:center;color:#fff;
  background:
    radial-gradient(70% 70% at 38% 26%, rgba(255,205,150,.95), transparent 62%),
    linear-gradient(150deg, #FF7A2E 0%, var(--orange) 52%, #C24BE8 140%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.45),
    0 6px 16px rgba(255,81,0,.3),
    0 2px 22px rgba(170,90,230,.22);
  transition:transform .3s var(--ease), box-shadow .3s var(--ease),
             filter .3s ease, opacity .3s ease;
}
.bc-send svg{position:relative;z-index:1;width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.bc-send:hover{
  transform:translateY(-2px) scale(1.05);filter:brightness(1.08);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.5),
    0 8px 22px rgba(255,81,0,.38),
    0 3px 30px rgba(170,90,230,.32);
}
.bc-send:active{transform:translateY(0) scale(.94);transition-duration:.12s}
.bc-send[disabled]{opacity:.4;cursor:default;transform:none;box-shadow:none}

@media (max-width:640px){
  .bc-inner{height:clamp(390px, 62vh, 470px)}
  .bc-log{padding:15px}
  .bc-msg{max-width:92%;font-size:14px}
  /* a phone pays for blur in frames, so it gets less of it */
  .bc-inner{-webkit-backdrop-filter:blur(16px) saturate(1.3);backdrop-filter:blur(16px) saturate(1.3)}
  .bc-glow{filter:blur(6px);--bcglow:.85}
  .bc-glow i:nth-child(2){inset:-5px;padding:6px;border-radius:calc(var(--r-lg) + 5px);opacity:.36}
  .bc-glow i::after{display:none}
  .bc-trace{display:none}
  .bc-orb{width:54px;height:54px}
  .bc-orb b{width:38px;height:38px}
}
@media (hover:none){
  /* nothing to follow without a cursor, so only the ambient ring runs */
  .brief-chat:hover .bc-glow{opacity:var(--bcglow)}
  .bc-glow i::after{display:none}
  .bc-trace{display:none}
}

/* ---------- footer ---------- */
.foot{padding-block:clamp(26px,3vw,40px) 0;background:var(--paper)}
.foot-cols{display:grid;grid-template-columns:1.4fr 1fr 1fr;gap:34px 40px;align-items:start}
@media (max-width:760px){.foot-cols{grid-template-columns:1fr 1fr}.foot-brand{grid-column:1/-1}}
.foot img{height:54px;width:auto;margin-bottom:16px}
.foot-brand p{margin:0;font-size:13.5px;color:var(--ink-45);max-width:30ch}
.foot-k{
  font-family:var(--mono);font-size:10px;letter-spacing:.15em;text-transform:uppercase;
  color:var(--ink-45);margin:0 0 16px;
}
.foot ul{list-style:none;margin:0;padding:0;display:grid;gap:11px}
.foot li{display:flex;align-items:baseline;gap:10px}
.foot li .ix{font-family:var(--mono);font-size:9.5px;color:#B5AE9F;flex:none}
.foot a{font-size:14px;text-decoration:none;color:var(--ink-70);transition:color .25s ease}
.foot a:hover{color:var(--orange)}
.foot-base{
  display:flex;flex-wrap:wrap;gap:12px 26px;justify-content:space-between;align-items:center;
  margin-top:clamp(18px,2.2vw,28px);
}
.foot-base p,.foot-base a{margin:0;font-family:var(--mono);font-size:10.5px;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-45)}

/* ---------- soft reveals (JS-gated so no-JS shows everything) ---------- */
html.armed .reveal{
  opacity:0;transform:translateY(16px);filter:blur(9px);
  transition:opacity .85s var(--ease), transform .85s var(--ease), filter .85s var(--ease);
}
html.armed .reveal.in{opacity:1;transform:none;filter:blur(0)}

/* ---------- footer scene: the machines sit at the very bottom of the page ---------- */
.foot-scene{position:relative;line-height:0;background:var(--paper)}
.foot-scene img{
  display:block;width:100%;height:auto;
  /* the last row blends with whatever is behind it when the image scales to a
     fractional height, which showed up as a pale hairline. Clip that row. */
  margin-bottom:-1px;
  -webkit-mask-image:linear-gradient(180deg, transparent 0%, #000 18%);
          mask-image:linear-gradient(180deg, transparent 0%, #000 18%);
}

/* ---------- footer sparkles: every one spins its own way ---------- */
.sparkles{
  display:flex;flex-wrap:wrap;justify-content:center;align-items:center;
  gap:clamp(16px,3.2vw,44px);margin-top:clamp(26px,3.4vw,46px);
}
.spark{width:clamp(24px,3vw,40px);height:auto;flex:none}
.spark path,.spark rect,.spark circle{fill:currentColor}
@keyframes spin{to{transform:rotate(360deg)}}
.sp1{color:#F5C518;animation:spin 9s linear infinite}
.sp2{color:#8B5CF6;animation:spin 7s linear infinite reverse}
.sp3{color:#4ADE80;animation:spin 12s linear infinite}
.sp4{color:#FF5100;animation:spin 8s linear infinite reverse}
.sp5{color:#EC4899;animation:spin 11s linear infinite}
.sp6{color:#2F45DC;animation:spin 6.5s linear infinite reverse}
.sp7{color:#10B981;animation:spin 10s linear infinite}
.sp8{color:#EF4444;animation:spin 13s linear infinite reverse}
.sp9{color:#38BDF8;animation:spin 15s linear infinite}


/* ---------- the reels section sits on its own sand surface ----------
   Two painted layers sit between that surface and the content: a warm
   ambient wash that keeps the middle lit, and a grid drawn in white so
   faint it reads as a weave rather than as ruling. Both are masked to a
   soft oval so nothing meets the rounded corners as a hard line, and both
   are pseudo elements at a negative z index, which puts them above the
   surface colour and below everything written on it. The section above
   this one has the dot field. This one is deliberately not that. */
.band-sand{
  position:relative;isolation:isolate;
  background:var(--sand);
  border-radius:var(--r-xl);
  margin-inline:var(--band-gut);
  padding-block:clamp(38px,4.4vw,66px);
}
.band-sand::before,
.band-sand::after{
  content:"";position:absolute;inset:0;z-index:-1;
  border-radius:inherit;pointer-events:none;
}
/* the warm light, strongest along the top and bleeding away downward */
.band-sand::before{
  background:
    radial-gradient(130% 78% at 50% -14%, rgba(255,169,70,.26), rgba(255,169,70,0) 64%),
    radial-gradient(86% 64% at 8% 104%, rgba(255,81,0,.09), rgba(255,81,0,0) 68%),
    radial-gradient(76% 58% at 96% 88%, rgba(247,212,76,.10), rgba(247,212,76,0) 70%);
}
/* the grid, white on sand so the contrast is almost nothing */
.band-sand::after{
  background-image:
    linear-gradient(to right, rgba(255,255,255,.62) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255,255,255,.62) 1px, transparent 1px);
  background-size:76px 76px;
  background-position:center top;
  -webkit-mask:radial-gradient(74% 58% at 50% 40%, #000 18%, rgba(0,0,0,0) 76%);
  mask:radial-gradient(74% 58% at 50% 40%, #000 18%, rgba(0,0,0,0) 76%);
}
/* A phone column is narrow and tall, so the same grid starts to read as
   graph paper. It keeps a lighter line and is pulled up near the heading,
   where it is doing the work, instead of running the length of the band. */
@media (max-width:640px){
  .badge--glow{padding:8px 16px;font-size:10px;letter-spacing:.12em}
  /* the long form label carries three words more than the other one, so it
     steps down a little further rather than wrapping onto a second line */
  #longBadge{font-size:9px;letter-spacing:.09em;padding-inline:13px}
  .band-sand::after{
    background-image:
      linear-gradient(to right, rgba(255,255,255,.44) 1px, transparent 1px),
      linear-gradient(to bottom, rgba(255,255,255,.44) 1px, transparent 1px);
    background-size:64px 64px;
    -webkit-mask:radial-gradient(88% 34% at 50% 19%, #000 8%, rgba(0,0,0,0) 78%);
    mask:radial-gradient(88% 34% at 50% 19%, #000 8%, rgba(0,0,0,0) 78%);
  }
}
.band-sand .card{background:transparent}
.band-sand .card-media{background:var(--sand-2)}
.band-sand .tag{background:var(--paper)}

/* ---------- bento cards, made playful on hover ---------- */
.bento-card{cursor:pointer}
.bento-card::before{transition:transform .9s var(--ease)}
.bento-card::after{transition:transform .8s var(--ease)}
.bento-tag,.bento-card h3,.bento-no{transition:transform .55s var(--ease), color .45s ease}
.bento-card:hover{transform:translateY(-9px) rotate(-.7deg)}
.bento-card:nth-child(even):hover{transform:translateY(-9px) rotate(.7deg)}
/* the diagonal pattern used to slide 16px sideways on hover, on top of the
   card lifting and turning. Two things moving at once read as the line
   coming loose from the card, so the pattern now simply travels with it. */
.bento-card:hover::after{transform:scale(1.3) translate(-6%,6%)}
.bento-card:hover .bento-tag{transform:translateY(-4px) rotate(-1.5deg)}
.bento-card:hover h3{transform:translateX(5px)}
.bento-card:hover .bento-no{transform:translateY(-7px) scale(1.14) rotate(-5deg);color:rgba(255,255,255,.36)}
.bento-card:active{transform:translateY(-3px) scale(.995)}


/* ---------- custom pointer (fine pointers only) ---------- */
.cursor{display:none}
@media (hover:hover) and (pointer:fine){
  html.cursor-on,html.cursor-on *{cursor:none}
  html.cursor-on input,html.cursor-on textarea,html.cursor-on select{cursor:text}
  html.cursor-on .nav,html.cursor-on .nav *{cursor:pointer}
  html.cursor-over-nav .cursor{opacity:0}
  .cursor{
    display:block;position:fixed;left:0;top:0;z-index:200;pointer-events:none;opacity:0;
    width:26px;height:26px;margin:-13px 0 0 -13px;border-radius:50%;
    /* A blend mode turned this into a black blob over the light pill, so the
       ring is drawn plainly instead: a dark hairline with a light halo, which
       reads on both the photographs and the cream. */
    box-shadow:inset 0 0 0 1.2px rgba(20,18,14,.55), 0 0 0 1px rgba(255,255,255,.35);
    transition:width .3s var(--ease),height .3s var(--ease),margin .3s var(--ease),background .3s ease,opacity .25s ease;
  }
  .cursor-dot{
    position:absolute;left:50%;top:50%;width:3px;height:3px;margin:-1.5px 0 0 -1.5px;
    border-radius:50%;background:rgba(20,18,14,.6);transition:opacity .25s ease;
  }
  html.cursor-hot .cursor{width:44px;height:44px;margin:-22px 0 0 -22px;background:rgba(255,81,0,.10);box-shadow:inset 0 0 0 1.2px rgba(255,81,0,.55)}
  html.cursor-hot .cursor-dot{opacity:0}
  html.cursor-live .cursor{opacity:1}
  html.cursor-hide .cursor{opacity:0!important}
}
@media (prefers-reduced-motion:reduce){
  html.cursor-on,html.cursor-on *{cursor:auto!important}
  .cursor{display:none!important}
}

/* ============================================================
   CAPTURE MODE   ?capture=1
   Everything at rest and fully visible, so a design tool imports
   the page as it is meant to look rather than mid animation.
   ============================================================ */
html.capture .loader{display:none!important}
html.capture .nav-pill{opacity:1!important;transform:none!important;animation:none!important}
html.capture .lg-sheen{opacity:0!important}
html.capture .reveal,html.capture .reveal:not(.in){opacity:1!important;transform:none!important;filter:none!important}
html.capture .statement .w{opacity:1!important;filter:none!important}
html.capture #heroLede{filter:none!important;opacity:1!important}
html.capture .cursor{display:none!important}
html.capture,html.capture *{cursor:auto!important}
/* the headline has to be already assembled for a design tool to read it */
html.capture .px-sharp{animation:none!important;--pxa:1!important;--wp:130%!important}
html.capture .px-ghost{display:none!important}
html.capture .px-mark{animation:none!important;opacity:var(--mo,1)!important}
html.capture .hero-lede,html.capture .cue{animation:none!important;opacity:1!important;transform:none!important}
html.capture .hero-bg{opacity:1!important;animation:none!important}
html.capture .spark,html.capture .cv,html.capture .pb,
html.capture .px-mark--star,html.capture .px-mark--face,
html.capture .rmq-track,html.capture .rmq-cta svg,html.capture .bg-stars i,
html.capture .marquee-track,html.capture .rev-track,
html.capture .rev-cat img{animation-play-state:paused!important}
html.capture .hero-bg,html.capture .hero-text,html.capture .scene-bg{transform:none!important}
html.capture .hero-bg img{transform:scale(1.06)!important}

/* ============================================================
   CONNECT BAND   the photograph runs full bleed, copy sits in the
   clear field on the left, the form floats on the right, and the
   monitor stays readable in the middle where nothing is written
   ============================================================ */
.cband{
  position:relative;overflow:hidden;background:var(--night);
  display:flex;align-items:center;
  min-height:clamp(620px,84vh,880px);
  padding-block:clamp(58px,7vw,104px);
}
.cband-bg{
  position:absolute;inset:0;z-index:0;
  width:100%;height:100%;object-fit:cover;object-position:50% 56%;
}
.cband-veil{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    linear-gradient(90deg, rgba(8,10,6,.90) 0%, rgba(8,10,6,.58) 23%, rgba(8,10,6,.06) 43%,
                           rgba(8,10,6,.06) 57%, rgba(8,10,6,.58) 77%, rgba(8,10,6,.90) 100%),
    linear-gradient(180deg, rgba(8,10,6,.50) 0%, rgba(8,10,6,0) 24%,
                            rgba(8,10,6,0) 68%, rgba(8,10,6,.55) 100%);
}
.cband-grid{
  position:relative;z-index:2;width:100%;
  max-width:1560px;margin:0 auto;padding-inline:clamp(20px,4vw,56px);
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,396px);
  gap:clamp(34px,7vw,120px);align-items:center;
}
.cband .display,.cband-copy h2{color:var(--on-night)}
/* The connect heading is the one place on the page that speaks in a heavy
   modern sans instead of the serif. First line stays plain white so it holds
   its own against the photograph, second line carries the colour. The two
   custom properties below are registered so the browser can interpolate them,
   which is what lets the gradient follow the cursor on a transition instead
   of a per frame write. */
@property --cbx{syntax:'<percentage>';inherits:false;initial-value:50%}
@property --cbp{syntax:'<percentage>';inherits:false;initial-value:50%}
@property --cbh{syntax:'<number>';inherits:false;initial-value:0}

.cband-h{
  --cbx:50%;--cbp:50%;--cbh:0;
  font-family:var(--sans);font-weight:800;
  font-size:clamp(31px,3.9vw,55px);line-height:1.03;letter-spacing:-.042em;
  margin:0 0 20px;
}
.ch-l1,.ch-l2{display:block}
.ch-l1{color:#fff}
.ch-l2{margin-top:.04em;color:#fff}

/* Two stacked backgrounds, both clipped to the letters. The linear one is the
   colour and sits at twice the width so there is something to slide. The
   radial one is a soft highlight that only exists while a cursor is on the
   words. Without background-clip support the line just stays white. */
@supports ((-webkit-background-clip:text) or (background-clip:text)){
  .ch-l2{
    background-image:
      radial-gradient(54% 260% at var(--cbx) 50%,
        rgba(255,255,255,calc(.55 * var(--cbh))) 0%,
        rgba(255,255,255,0) 62%),
      linear-gradient(96deg,
        #FFC99C 0%, #FFA878 12%, #FF8E6E 26%,
        #EE7E99 42%, #B98DC8 58%, #8EA7D4 74%,
        #86C4BD 88%, #AAD2C6 100%);
    /* only a little wider than the words, so the visible slice still runs the
       whole way from the warm end to the cool one */
    background-size:100% 100%, 130% 100%;
    background-position:0 50%, var(--cbp) 50%;
    background-repeat:no-repeat;
    -webkit-background-clip:text;background-clip:text;
    color:transparent;-webkit-text-fill-color:transparent;
    transition:--cbx .55s ease-out, --cbp .7s ease-out, --cbh .4s ease;
  }
}
.cband-copy{max-width:540px}
.cband-copy .lede{color:#E9E1D0}
.cband-copy h2{margin:0 0 20px}
.cband-copy .lede{max-width:40ch}
.cband-reach{list-style:none;margin:30px 0 0;padding:0}
.cband-reach li{padding-block:13px;border-bottom:1px solid var(--line-night)}
.cband-reach li:first-child{border-top:1px solid var(--line-night)}
.cband-reach .k{
  display:block;font-family:var(--mono);font-size:10px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--on-night-60);margin-bottom:5px;
}
.cband-reach a{font-size:17px;text-decoration:none;color:var(--on-night);transition:color .25s ease}
.cband-reach a:hover{color:var(--amber)}
.cband-hours{
  margin:18px 0 0;font-family:var(--mono);font-size:11px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--on-night-60);
}
@media (max-width:980px){
  .cband{min-height:0;padding-block:clamp(50px,8vw,80px)}
  .cband-grid{grid-template-columns:1fr;gap:32px}
  .cband-copy{max-width:none}
  .cband-bg{object-position:50% 42%}
  .cband-veil{background:linear-gradient(180deg, rgba(8,10,6,.84) 0%, rgba(8,10,6,.70) 42%, rgba(8,10,6,.92) 100%)}
  .cband-h{letter-spacing:-.036em}
}

/* A finger has no hover, so the gradient just sits at its resting position and
   nothing listens for a pointer. It reads the same, only still. */
@media (hover:none),(pointer:coarse){
  .ch-l2{transition:none}
}
@media (prefers-reduced-motion:reduce){
  .ch-l2{transition:none}
}

/* ============================================================
   WORK GRIDS   shorts read first, in a four up staggered grid.
   Long form runs as a wider drag rail on the dark panel.
   ============================================================ */
/* Reels: four to a page, same paging behaviour as the long form rail.
   The staggered drop repeats every four cards so each page reads the
   same way rather than the offsets drifting across the whole strip. */
.rail-wrap{position:relative}

/* ============================================================
   RAIL PAGING   On a pointer device the strip is not a scroller
   at all: the clip holds the window and the strip itself is moved
   with one transform, which the compositor animates. That is the
   difference between a page change that glides and one that
   stutters, because writing scrollLeft every frame is main thread
   work and everything else on the page is competing for it.
   A touch device keeps the native scroller, since its own momentum
   swipe is already smoother than anything scripted.
   ============================================================ */
.rail-clip{position:relative;min-width:0}

/* The reels break out of the 1160px column on a wide screen, because the
   page was leaving 390px of empty paper either side of them while the cards
   stayed small. Capped so they never run edge to edge. */
.rail-wrap--wide{
  --reel-w:min(calc(100vw - 72px), 1560px);
  width:var(--reel-w);
  margin-inline:calc(50% - var(--reel-w) / 2);
}
@media (max-width:1180px){
  .rail-wrap--wide{--reel-w:100%;margin-inline:0}
}

/* The strip has to end somewhere, but it does not have to end in a straight
   chop. The edges fade instead, so the card leaving and the card arriving
   dissolve rather than being sliced. Vertical padding keeps the mask clear
   of the hover lift and the card shadows. */
.rail-clip--fade{
  /* One number drives both edge treatments, so the fade and the haze always
     agree. It used to be a share of the strip, which grew with the strip and
     at 1920 put 170px of blur on each side. It is now a small band measured
     against the window instead: about 35px on a tablet, 63px on a laptop,
     88px at 1920, 100px at the top. The middle of the strip stays sharp. */
  --edge:clamp(34px, 4.6vw, 100px);
  padding-block:44px;margin-block:-44px;
  /* Not a straight ramp. The extra stops hold the card near full opacity
     well into the zone and then let it go quickly at the very edge, which
     reads as dissolving rather than as a gradient laid over the top. */
  -webkit-mask-image:linear-gradient(90deg,
      transparent 0,
      rgba(0,0,0,.26) calc(var(--edge) * .36),
      rgba(0,0,0,.8) calc(var(--edge) * .74),
      #000 var(--edge),
      #000 calc(100% - var(--edge)),
      rgba(0,0,0,.8) calc(100% - var(--edge) * .74),
      rgba(0,0,0,.26) calc(100% - var(--edge) * .36),
      transparent 100%);
          mask-image:linear-gradient(90deg,
      transparent 0,
      rgba(0,0,0,.26) calc(var(--edge) * .36),
      rgba(0,0,0,.8) calc(var(--edge) * .74),
      #000 var(--edge),
      #000 calc(100% - var(--edge)),
      rgba(0,0,0,.8) calc(100% - var(--edge) * .74),
      rgba(0,0,0,.26) calc(100% - var(--edge) * .36),
      transparent 100%);
}

/* The haze. Two panes pinned to the clip, blurring whatever is behind them
   rather than painting anything of their own, so they take the colour of
   the section instead of laying a white block over it. They never move: the
   strip slides underneath, which is why the cost does not grow with the
   number of reels and why nothing has to be animated per card. Strongest a
   little inside the edge, where the card is still solid enough to show the
   softening, and gone by the time it reaches the reading area. */
.rail-haze{
  position:absolute;top:0;bottom:0;width:var(--edge,0px);
  z-index:3;pointer-events:none;
}
.rail-haze--l{left:0}
.rail-haze--r{right:0}
@supports ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){
  .rail-haze{-webkit-backdrop-filter:blur(7px);backdrop-filter:blur(7px)}
  .rail-haze--l{
    -webkit-mask-image:linear-gradient(90deg, rgba(0,0,0,.65) 0, #000 26%,
                                       rgba(0,0,0,.5) 66%, transparent 100%);
            mask-image:linear-gradient(90deg, rgba(0,0,0,.65) 0, #000 26%,
                                       rgba(0,0,0,.5) 66%, transparent 100%);
  }
  .rail-haze--r{
    -webkit-mask-image:linear-gradient(270deg, rgba(0,0,0,.65) 0, #000 26%,
                                       rgba(0,0,0,.5) 66%, transparent 100%);
            mask-image:linear-gradient(270deg, rgba(0,0,0,.65) 0, #000 26%,
                                       rgba(0,0,0,.5) 66%, transparent 100%);
  }
}
/* A phone cannot spare either the blur or the width. The fade stays, so the
   strip still ends softly, and the haze steps down rather than disappearing. */
@media (max-width:620px){
  .rail-clip--fade{--edge:clamp(16px, 5vw, 34px)}
  .rail-haze{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}
}
@media (prefers-reduced-motion:reduce){
  .rail-haze{-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px)}
}

/* ============================================================
   REEL MARQUEE   small covers travelling right to left, and one
   player they open into. The track holds two copies of the set and
   the animation moves it exactly one copy's width, so the seam
   never arrives. Hovering anywhere over the strip pauses the
   animation, which means it carries on from the same place rather
   than restarting. Nothing is animated per card, so twenty reels
   cost what seven do.
   ============================================================ */
.rmq{
  position:relative;
  /* The strip runs the width of the card it sits in, less a small inset, so
     the covers travel almost the whole window and the fade is the only thing
     ending them. It used to stop at 1120px, which on a wide screen left 400px
     of empty sand either side before the fade had even started.

     The card size is one ramp rather than a set of steps: a card grows with
     the window, and because it grows more slowly than the window does, a
     wider screen also ends up showing more of them. Roughly three across a
     tablet, four and a half on a laptop, five and a half at 1920, six and a
     half on a 27 inch. No count is hard coded anywhere. */
  --rmq-w:min(calc(100vw - (var(--band-gut) + var(--strip-in)) * 2), 2600px);
  --reel-cw:clamp(200px, calc(150px + 8vw), 360px);
  --reel-gap:clamp(12px, 1.1vw, 22px);
  --rmq-ar:9 / 16;
  width:var(--rmq-w);
  margin-inline:calc(50% - var(--rmq-w) / 2);
}
.rmq-clip{overflow:hidden}
@supports (overflow-x:clip){
  .rmq-clip{overflow-x:clip;overflow-y:visible}
}
.rmq-track{
  display:flex;align-items:flex-start;gap:var(--reel-gap);
  width:max-content;
  transform:translate3d(0,0,0);
  animation:rmqRun var(--rmq-dur, 70s) linear infinite;
  will-change:transform;
}
@keyframes rmqRun{
  from{transform:translate3d(0,0,0)}
  to{transform:translate3d(calc(var(--shift, 0px) * -1),0,0)}
}
/* held while a reel is open, and while the section is off screen */
.rmq.is-held .rmq-track,
.rmq.is-away .rmq-track{animation-play-state:paused}

.rmq-card{
  position:relative;flex:none;width:var(--reel-cw);
  cursor:pointer;
  transform:translate3d(0,0,0);
  transition:transform .4s var(--ease);
}
.rmq-card:focus{outline:none}
/* each cover is its own object: a ring, a radius and a little lift */
.rmq-media{
  position:relative;aspect-ratio:var(--rmq-ar, 9 / 16);
  border-radius:var(--r);overflow:hidden;
  background:var(--sand-2);
  box-shadow:
    inset 0 0 0 1px rgba(26,26,26,.1),
    0 1px 2px rgba(26,26,26,.05),
    0 10px 26px rgba(26,26,26,.09);
  transition:box-shadow .4s var(--ease);
}
.rmq-media video{width:100%;height:100%;object-fit:cover;display:block}
/* a reel with no file yet still reads as a slot rather than as a gap */
.rmq-slot{
  position:absolute;inset:0;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:5px;text-align:center;
  background:linear-gradient(168deg, rgba(255,169,70,.16), rgba(234,225,201,.5));
  font-family:var(--mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;
}
.rmq-slot b{color:var(--ink-70);font-weight:400}
.rmq-slot span{color:var(--ink-45)}

.rmq-cta{
  position:absolute;inset:0;z-index:2;display:grid;place-items:center;
  background:rgba(12,10,8,.26);
  opacity:0;transition:opacity .3s var(--ease);
}
.rmq-cta b{
  display:inline-flex;align-items:center;gap:8px;
  font-family:var(--mono);font-size:9.5px;letter-spacing:.15em;text-transform:uppercase;
  font-weight:400;color:#fff;padding:9px 14px 9px 11px;border-radius:var(--pill);
  background:rgba(20,18,14,.5);
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.2);
}
/* the little arrow cursor, the same mark the page uses for its own pointer */
.rmq-cta svg{
  width:13px;height:13px;flex:none;fill:var(--amber);
  transform:rotate(-6deg);
  animation:rmqPoke 2.6s var(--ease) infinite;
}
@keyframes rmqPoke{
  0%,68%,100%{transform:translate3d(0,0,0) rotate(-6deg)}
  78%{transform:translate3d(2px,2px,0) rotate(-6deg)}
  88%{transform:translate3d(0,0,0) rotate(-6deg)}
}
.rmq-hint{
  margin:clamp(22px,2.4vw,34px) 0 0;text-align:center;
  display:flex;align-items:center;justify-content:center;gap:8px;
  font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-45);
}
.rmq-hint svg{
  width:11px;height:11px;flex:none;fill:currentColor;opacity:.75;
  transform:rotate(-6deg);
  animation:rmqPoke 2.6s var(--ease) infinite;
}

@media (hover:hover) and (pointer:fine){
  .rmq:hover .rmq-track{animation-play-state:paused}
  .rmq:has(:focus-visible) .rmq-track{animation-play-state:paused}
  /* the lift is deliberately small. This is still the browsing state. */
  .rmq-card:hover,
  .rmq-card:focus-visible{transform:translate3d(0,-5px,0) scale(1.045);z-index:5}
  .rmq-card:hover .rmq-media,
  .rmq-card:focus-visible .rmq-media{
    box-shadow:
      inset 0 0 0 1px rgba(255,81,0,.4),
      0 14px 34px rgba(26,26,26,.16);
  }
  .rmq-card:hover .rmq-cta,
  .rmq-card:focus-visible .rmq-cta{opacity:1}
}
/* ---------- the long form strip: landscape, and in the dark ---------- */
/* Same idea on the night panel, with 16:9 cards, which means fewer of them
   and each one considerably wider: about two and a half on a tablet, three
   on a laptop, three and three quarters at 1920, four on a 27 inch. */
.rmq--long{
  --rmq-w:min(calc(100vw - (var(--band-gut) + var(--strip-in)) * 2), 2600px);
  --reel-cw:clamp(280px, calc(180px + 15vw), 620px);
  --reel-gap:clamp(14px, 1.3vw, 26px);
  --rmq-ar:16 / 9;
}
.rmq--long .rmq-media{
  border-radius:var(--r);
  background:#191512;
  box-shadow:
    inset 0 0 0 1px rgba(245,240,226,.13),
    0 16px 42px rgba(0,0,0,.42);
}
.rmq--long .rmq-slot{
  background:linear-gradient(168deg, rgba(255,81,0,.14), rgba(20,18,14,.92));
}
.rmq--long .rmq-slot b{color:rgba(245,240,226,.72)}
.rmq--long .rmq-slot span{color:rgba(245,240,226,.4)}
.rmq--long .rmq-hint{color:var(--on-night-60)}
@media (hover:hover) and (pointer:fine){
  .rmq--long .rmq-card:hover .rmq-media,
  .rmq--long .rmq-card:focus-visible .rmq-media{
    box-shadow:
      inset 0 0 0 1px rgba(255,81,0,.5),
      0 22px 54px rgba(0,0,0,.5);
  }
}
/* A phone is the one width where the ramp gives the wrong answer: it would
   leave three small covers side by side on a screen held in one hand. One
   card and a slice of the next reads far better, so the phone gets its own
   number rather than a share of the window. */
@media (max-width:560px){
  .rmq{--reel-cw:min(58vw, 244px);--reel-gap:12px}
}
@media (max-width:640px){
  .rmq.rmq--long{--reel-cw:min(84vw, 420px);--reel-gap:14px}
}

@media (prefers-reduced-motion:reduce){
  .rmq-track{animation:none}
  .rmq-cta svg{animation:none}
  .rmq-clip{overflow-x:auto;-webkit-overflow-scrolling:touch}
  .rmq-card{transition:none}
  .rmq-card:hover{transform:none}
}

/* ---------- the focused player ---------- */
.rplay{
  position:fixed;inset:0;z-index:95;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:14px;
  padding:calc(18px + env(safe-area-inset-top,0px)) 20px calc(18px + env(safe-area-inset-bottom,0px));
}
.rplay[hidden]{display:none}
.rplay-scrim{
  position:absolute;inset:0;
  background:rgba(12,10,8,.74);
  -webkit-backdrop-filter:blur(16px) saturate(1.1);backdrop-filter:blur(16px) saturate(1.1);
  opacity:0;transition:opacity .45s var(--ease);
}
.rplay.is-on .rplay-scrim{opacity:1}

/* The column carries the width now, so the control bar above the video is
   exactly as wide as the video and the two buttons land on its corners. The
   box keeps its own transform origin, so the flight is untouched. */
.rplay-col{
  position:relative;z-index:1;display:flex;flex-direction:column;
  width:min(calc(100vw - 48px), calc((100svh - 252px) * 0.5625), 392px);
}
.rplay.is-wide .rplay-col{
  width:min(calc(100vw - 48px), calc((100svh - 252px) * 1.7778), 1000px);
}
.rplay-bar{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  margin-bottom:12px;
}
.rplay-box{
  position:relative;width:100%;
  transform-origin:top left;
}
.rplay.is-wide .rplay-stage{aspect-ratio:16 / 9}
.rplay.is-wide .rplay-nav--prev{left:max(20px, calc(50% - 570px))}
.rplay.is-wide .rplay-nav--next{right:max(20px, calc(50% - 570px))}
.rplay-stage{
  position:relative;aspect-ratio:9 / 16;
  border-radius:var(--r-lg);overflow:hidden;background:#0B0A08;
  box-shadow:0 30px 80px rgba(0,0,0,.5), inset 0 0 0 1px rgba(255,255,255,.1);
}
.rplay-stage video{width:100%;height:100%;object-fit:cover;display:block}
/* the shared chrome is hidden until a card asks for it, so the stage asks */
.rplay-stage .vid-pp{display:grid;opacity:0}
.rplay-stage:hover .vid-pp,
.rplay-stage.is-paused .vid-pp{opacity:1}
.rplay-stage .vid-prog{display:flex}
/* a slot with no file yet says so, instead of opening onto a black hole */
.rplay-stage.is-empty{background:linear-gradient(168deg, #241d18, #0E0C0A)}
.rplay-stage.is-empty .vid-pp,
.rplay-stage.is-empty .vid-prog{display:none}
.rplay-stage.is-empty::after{
  content:"This slot is waiting for its file";
  position:absolute;inset:0;display:grid;place-items:center;padding:0 28px;
  text-align:center;
  font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;
  color:rgba(245,240,226,.45);
}

/* everything that is not the stage fades in after the flight, so the flight
   itself is one clean rectangle growing out of the card */
.rplay-meta,.rplay-x,.rplay-nav,.rplay-sound{
  opacity:0;transition:opacity .35s ease .14s;
}
.rplay.is-on .rplay-meta,
.rplay.is-on .rplay-x,
.rplay.is-on .rplay-nav,
.rplay.is-on .rplay-sound{opacity:1}

.rplay-meta{margin-top:14px;text-align:center}
.rplay-t{
  margin:0;font-family:var(--serif);font-size:clamp(17px,1.5vw,21px);
  color:var(--on-night);line-height:1.2;
}
.rplay-w{margin:4px 0 0;font-size:13px;color:var(--on-night-60)}
.rplay-n{
  margin:7px 0 0;font-family:var(--mono);font-size:10px;letter-spacing:.16em;
  color:rgba(245,240,226,.45);
}

.rplay-x{
  display:inline-flex;align-items:center;gap:7px;
  padding:9px 15px 9px 11px;border:0;border-radius:var(--pill);cursor:pointer;
  background:rgba(245,240,226,.12);color:var(--on-night);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  box-shadow:inset 0 0 0 1px rgba(245,240,226,.2);
  font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;
  transition:background .3s ease, opacity .35s ease .14s;
}
.rplay-x svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.rplay-x:hover{background:rgba(245,240,226,.2)}

.rplay-sound{
  display:inline-flex;align-items:center;gap:7px;
  padding:9px 15px;border:0;border-radius:var(--pill);cursor:pointer;
  background:rgba(245,240,226,.12);color:var(--on-night);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  box-shadow:inset 0 0 0 1px rgba(245,240,226,.2);
  font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;
  transition:background .3s ease, opacity .35s ease .14s;
}
.rplay-sound svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.rplay-sound svg path:first-child{fill:currentColor;stroke:none}
.rplay-sound:hover{background:rgba(245,240,226,.2)}
.rplay-sound.is-on{background:rgba(255,81,0,.9);box-shadow:inset 0 0 0 1px rgba(255,255,255,.22)}
/* nothing to unmute on a slot with no file */
.rplay-sound[disabled]{display:none}

.rplay-nav{
  position:absolute;z-index:2;top:50%;translate:0 -50%;
  width:46px;height:46px;border:0;border-radius:var(--pill);cursor:pointer;
  display:grid;place-items:center;
  background:rgba(245,240,226,.12);color:var(--on-night);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  box-shadow:inset 0 0 0 1px rgba(245,240,226,.2);
  transition:background .3s ease, transform .35s var(--ease), opacity .35s ease .14s;
}
.rplay-nav svg{width:19px;height:19px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.rplay-nav:hover{background:rgba(245,240,226,.22)}
.rplay-nav--prev{left:max(20px, calc(50% - 300px))}
.rplay-nav--next{right:max(20px, calc(50% - 300px))}
.rplay-nav--prev:hover{transform:translateX(-3px)}
.rplay-nav--next:hover{transform:translateX(3px)}

@media (max-width:640px){
  /* the phone cover size lives with the other strip rules now, further up:
     it was being reset here, after them, and equal weight goes to whichever
     comes last */
  .rplay-col{width:min(calc(100vw - 40px), calc((100svh - 230px) * 0.5625))}
  .rplay.is-wide .rplay-col{width:min(calc(100vw - 40px), calc((100svh - 230px) * 1.7778))}
  .rplay-nav{width:42px;height:42px;top:auto;bottom:calc(20px + env(safe-area-inset-bottom,0px));translate:0 0}
  .rplay-nav--prev{left:22px}
  .rplay-nav--next{right:22px}
  .rplay-x,.rplay-sound{padding:8px 13px;font-size:9.5px}
}
@media (max-height:560px) and (orientation:landscape){
  .rplay-col{width:calc((100svh - 112px) * 0.5625)}
  .rplay.is-wide .rplay-col{width:min(calc(100vw - 40px), calc((100svh - 112px) * 1.7778))}
  .rplay-meta{display:none}
  .rplay-bar{margin-bottom:8px}
}
@media (prefers-reduced-motion:reduce){
  .rplay-scrim,.rplay-meta,.rplay-x,.rplay-nav,.rplay-sound{transition:none}
}
@media (hover:hover) and (pointer:fine){
  .rail-clip{overflow-x:clip;overflow-y:visible;padding-block:14px;margin-block:-14px}
  .rail-clip--fade{padding-block:44px;margin-block:-44px}
  .rail{
    overflow:visible;padding:0;margin:0;
    /* stays the width of the clip on purpose: the column width is a
       percentage of it, and the extra columns simply spill out of the box
       for the clip to trim. max-content here would make that percentage
       circular and collapse the tracks. */
    transform:translate3d(0,0,0);
    transition:transform .62s cubic-bezier(.22,1,.36,1);
    will-change:transform;
  }
  .rail.no-anim{transition:none}
}
@media (prefers-reduced-motion:reduce){
  .rail{transition:none!important}
}

/* arrows sit in the margin either side of the strip, vertically centred */
.rail-arrow{
  position:absolute;top:calc(50% - 34px);z-index:4;
  width:46px;height:46px;border:0;border-radius:var(--pill);cursor:pointer;
  display:grid;place-items:center;
  background:rgba(20,18,14,.55);color:var(--on-night);
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
  box-shadow:0 6px 18px rgba(0,0,0,.22), inset 0 0 0 1px rgba(245,240,226,.16);
  transition:opacity .3s ease, transform .35s var(--ease), background .3s ease;
}
.rail-arrow svg{width:19px;height:19px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.rail-arrow--prev{left:-6px}
.rail-arrow--next{right:-6px}
.rail-arrow:hover{transform:scale(1.06)}
.rail-arrow--prev:hover{transform:translateX(-3px) scale(1.06)}
.rail-arrow--next:hover{transform:translateX(3px) scale(1.06)}
.rail-arrow[disabled]{opacity:0;pointer-events:none;transform:none}
/* on paper, ink rather than night */
.rail-arrow--light{
  background:rgba(252,245,226,.78);color:var(--ink);
  box-shadow:0 6px 18px rgba(26,26,26,.12), inset 0 0 0 1px rgba(26,26,26,.1);
}
.rail-arrow--light:hover{background:rgba(255,255,255,.92)}
@media (max-width:620px){
  /* a phone swipes, so the arrows only take up room */
  .rail-arrow{display:none}
}
.rail--wide{
  --rail-gap:clamp(16px,2vw,24px);
  gap:var(--rail-gap);
  grid-auto-columns:calc((100% - 2*var(--rail-gap)) / 3);
  scroll-snap-type:x proximity;
}
@media (max-width:900px){.rail--wide{grid-auto-columns:calc((100% - var(--rail-gap)) / 2)}}
@media (max-width:620px){.rail--wide{grid-auto-columns:100%}}
/* no filter while a page travels. A blur on twelve cards is a repaint of
   every one of them on every frame of the move, which is exactly the work
   that made the change feel like it was catching. */

.rail-nav{display:flex;align-items:center;justify-content:center;gap:16px;margin-top:clamp(18px,2.4vw,30px)}
.rail-dots{display:flex;align-items:center;gap:9px}
.rail-dot{
  width:8px;height:8px;border:0;padding:0;border-radius:var(--pill);cursor:pointer;
  background:rgba(245,240,226,.26);transition:background .3s ease, width .35s var(--ease);
}
.rail-dot.on{background:var(--orange);width:24px}

/* too many pages for dots: a counter in the same mono as every other label */
.rail-count{
  font-family:var(--mono);font-size:11px;letter-spacing:.14em;
  color:var(--on-night-60);min-width:7ch;text-align:center;
  font-variant-numeric:tabular-nums;
}
.rail-nav--light .rail-count{color:var(--ink-45)}

/* the reels sit on paper, so the dots in ink rather than light */
.rail-nav--light .rail-dot{background:rgba(26,26,26,.16)}
.rail-nav--light .rail-dot.on{background:var(--orange)}

/* ============================================================
   TWO INK DEVICES, used only where a line needs the emphasis:
   a drawn underline and a marker highlight. Both settle into
   their finished state without JS, in capture mode, and under
   reduced motion.
   ============================================================ */
.pen{position:relative;display:inline-block}
.pen-line{
  position:absolute;left:-1%;right:-1%;bottom:-.17em;
  width:102%;height:.34em;overflow:visible;pointer-events:none;
}
.pen-line path{
  fill:none;stroke:var(--orange);stroke-width:4;stroke-linecap:round;
  stroke-dasharray:210;stroke-dashoffset:0;
}
.on-night .pen-line path,.hero .pen-line path{stroke:var(--sun)}
html.js .pen-line path{stroke-dashoffset:210}
html.js .pen.drawn .pen-line path{animation:penDraw .95s var(--ease) .1s forwards}
@keyframes penDraw{to{stroke-dashoffset:0}}

.hl{position:relative;display:inline-block;isolation:isolate}
.hl::before{
  content:"";position:absolute;z-index:-1;
  left:-.14em;right:-.14em;bottom:.04em;height:.5em;border-radius:3px;
  background:var(--sun);opacity:.45;
  transform:skewX(-9deg) scaleX(1);transform-origin:left center;
}
.hl--warm::before{background:var(--amber);opacity:.32;height:.44em}
html.js .hl::before{transform:skewX(-9deg) scaleX(0)}
html.js .hl.drawn::before{animation:hlIn .65s var(--ease) .15s forwards}
/* inside a scroll told line the marker is driven by scroll position instead,
   so it grows with the words rather than firing once on its own */
html.js .hl--scroll::before{
  animation:none!important;
  transform:skewX(-9deg) scaleX(var(--hl-x,0));
}
@keyframes hlIn{to{transform:skewX(-9deg) scaleX(1)}}

html.capture .pen-line path{stroke-dashoffset:0!important;animation:none!important}
html.capture .hl::before{transform:skewX(-9deg) scaleX(1)!important;animation:none!important}

/* ============================================================
   DECORATIVE SHAPES   a few small marks drifting in the empty
   margins, so the plain sections stop reading as blank
   ============================================================ */
.has-deco{position:relative}
.deco{position:absolute;z-index:0;pointer-events:none;color:var(--orange)}
.deco svg{width:100%;height:auto;display:block}
.deco svg path{fill:currentColor}
.deco-1{width:clamp(32px,3.8vw,58px);left:5%;top:15%;color:var(--sun);opacity:.55;animation:floaty 9s ease-in-out infinite}
.deco-2{width:clamp(24px,2.8vw,44px);right:7%;bottom:16%;color:var(--orange);opacity:.3;animation:floaty 11.5s ease-in-out infinite reverse}
.deco-3{width:clamp(28px,3.2vw,50px);left:3.5%;top:22%;color:#6636D6;opacity:.22;animation:spin 28s linear infinite}
.deco-4{width:clamp(22px,2.6vw,40px);right:4.5%;top:11%;color:#2A9550;opacity:.26;animation:floaty 10.5s ease-in-out infinite}
@keyframes floaty{0%,100%{transform:translateY(0) rotate(0deg)}50%{transform:translateY(-14px) rotate(14deg)}}
@media (max-width:760px){.deco{display:none}}

/* the hero's trailing dots should not shout */


/* ============================================================
   PULL QUOTE   one line that earns its size, with the meme
   photograph sitting beside it at a slight angle
   ============================================================ */
.quote-band{position:relative}
.quote-grid{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.14fr);
  gap:clamp(24px,3.4vw,52px);align-items:center;
}
/* the caption keeps the photograph company instead of sitting a screen away */
.deck-wrap{
  display:grid;grid-template-columns:minmax(158px,.7fr) minmax(0,1fr);
  gap:clamp(14px,1.8vw,26px);align-items:center;
}
@media (max-width:1040px){
  .quote-grid{grid-template-columns:minmax(0,.92fr) minmax(0,1.2fr)}
  .deck-wrap{grid-template-columns:minmax(118px,.7fr) minmax(0,1fr)}
}
@media (max-width:860px){
  .quote-grid{grid-template-columns:1fr;gap:26px}
  .deck-wrap{grid-template-columns:1fr;gap:18px;justify-items:center}
  .deck{margin-inline:auto;max-width:340px}
}
.quote-copy{margin:0;position:relative}
.quote-mark{
  display:block;font-family:var(--serif);font-weight:500;line-height:.55;
  font-size:clamp(66px,8.4vw,124px);color:var(--orange);opacity:.2;
  margin-bottom:-.14em;
}
.quote-text{
  font-family:var(--serif);font-weight:400;margin:0;
  font-size:clamp(27px,4vw,50px);line-height:1.08;letter-spacing:-.025em;
  text-wrap:balance;
}
.quote-text em{font-style:italic}
.quote-by i{font-style:italic}
.quote-by{
  margin-top:clamp(14px,1.8vw,22px);
  font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-45);
}

/* ============================================================
   BRANDS   soft colour behind the wall, and shapes that drift
   away from the pointer at different depths
   ============================================================ */
/* the story above it already ends in a lot of air, so this one starts sooner */
/* No overflow clip on this one. The colour here is three blurred discs, and
   clipping them at the section edge ended the whole wash on a hard line
   straight across the page under the numbers. Left to run, each disc fades
   out on its own radius and the warmth carries into the section below.
   Sideways bleed is already held by overflow-x on the body. */
.brands-band{position:relative;overflow-x:clip;overflow-y:visible;
  padding-top:clamp(18px,2.2vw,32px);padding-bottom:clamp(24px,2.8vw,38px)}
.brands-band>.wrap,.brands-band>.marquee{position:relative;z-index:2}
.blob{position:absolute;z-index:0;border-radius:50%;pointer-events:none;filter:blur(64px)}
.blob-a{width:46vw;aspect-ratio:1;left:-12%;top:2%;
        background:radial-gradient(circle, rgba(255,169,70,.36), rgba(255,169,70,.08) 52%, rgba(255,169,70,0) 76%)}
.blob-b{width:40vw;aspect-ratio:1;right:-9%;bottom:-10%;
        background:radial-gradient(circle, rgba(110,80,220,.22), rgba(110,80,220,.05) 52%, rgba(110,80,220,0) 76%)}
.blob-c{width:34vw;aspect-ratio:1;left:34%;top:40%;
        background:radial-gradient(circle, rgba(42,149,80,.16), rgba(42,149,80,.04) 50%, rgba(42,149,80,0) 74%)}
.drift{
  position:absolute;left:var(--x);top:var(--y);z-index:1;pointer-events:none;
  width:clamp(20px,2.4vw,38px);will-change:transform;
}
.drift svg{width:100%;height:auto;display:block}
.drift svg path,.drift svg circle{fill:currentColor}
.d1{color:var(--sun);opacity:.85}
.d2{color:var(--orange);opacity:.6}
.d3{color:#EC4899;opacity:.5}
.d4{color:#38BDF8;opacity:.6}
.d5{color:#2A9550;opacity:.55}
.d1 svg{animation:floaty 11s ease-in-out infinite}
.d2 svg{animation:floaty 14s ease-in-out infinite reverse}
.d3 svg{animation:spin 30s linear infinite}
.d4 svg{animation:floaty 12s ease-in-out infinite}
.d5 svg{animation:floaty 16s ease-in-out infinite reverse}
@media (max-width:760px){.drift{display:none}.blob{filter:blur(48px);opacity:.7}}

/* ---------- a faint dot screen, so the plain cream sections read as paper ---------- */
.paper-dots{
  background-image:radial-gradient(rgba(26,26,26,.055) 1px, transparent 1px);
  background-size:18px 18px;
  background-position:0 0;
}

/* ============================================================
   STORY   three scenes, told as you scroll. The photograph is
   sticky, the copy steps past it, and the image crossfades.
   ============================================================ */
.story{position:relative;padding-block:clamp(36px,4.4vw,64px) clamp(8px,1.2vw,20px)}
/* This section is a photograph next to a story, so it is given the wide
   container rather than the reading column. On a 27 inch the picture was
   441px across with 380px of empty paper on either side of the whole thing. */
.story>.wrap{max-width:var(--maxw-wide)}
.story-grid{
  display:grid;grid-template-columns:.9fr 1.05fr 44px;
  gap:clamp(24px,3.4vw,76px);align-items:start;
}
.story-media{position:sticky;top:clamp(96px,14vh,130px)}
.story-stack{
  position:relative;aspect-ratio:4/3;overflow:hidden;
  border-radius:var(--squish);box-shadow:var(--shadow-lift);background:var(--sand-2);
}
.story-img{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:0;transform:scale(1.04);
  transition:opacity .7s var(--ease), transform 1.2s var(--ease);
}
.story-img.is-on{opacity:1;transform:scale(1)}
/* the aura card is flat artwork, so it is contained rather than cropped */
.story-img.is-flat{object-fit:contain;background:#fff}
.story-cap{
  margin:14px 2px 0;
  font-family:var(--mono);font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--ink-45);transition:opacity .4s ease;
}
.story-steps{display:grid}
/* Each step needs enough scroll for the photograph to change under it, and
   no more. At 72vh a 27 inch monitor gave every one of them 780px of height
   for two short paragraphs, which is where the emptiness came from. Capped,
   so a taller screen stops adding blank space. */
.story-step{
  min-height:clamp(360px, 60vh, 600px);
  display:flex;flex-direction:column;justify-content:center;
  opacity:.22;filter:blur(4px);transform:translateY(10px) rotate(0deg);
  transition:opacity .6s var(--ease), filter .6s var(--ease), transform .6s var(--ease);
}
.story-step.is-on{opacity:1;filter:blur(0);transform:none}
/* a little off axis, so the sequence reads as a strip rather than a form */
.story-step:nth-child(odd) h2{transform:rotate(-.55deg)}
.story-step:nth-child(even) h2{transform:rotate(.6deg)}

/* comic sticker label */
.badge--sticker{
  transform:rotate(-1.6deg);
  box-shadow:inset 0 0 0 1px rgba(255,81,0,.24), 2px 2px 0 rgba(255,81,0,.16);
}
.story-step:nth-child(even) .badge--sticker{transform:rotate(1.4deg)}

/* handwritten margin note */
.scribble{
  font-family:"Caveat", ui-rounded, cursive;
  font-size:clamp(17px,1.7vw,21px);color:var(--orange);
  margin:14px 0 0;transform:rotate(-1.8deg);transform-origin:left center;
  opacity:.9;
}
.story-step:nth-child(even) .scribble{transform:rotate(1.6deg)}
.story-step h2{margin:0 0 16px}
.story-step .lede{max-width:46ch}
.story-step:last-child{min-height:clamp(240px, 38vh, 380px)}
html:not(.js) .story-step{opacity:1;transform:none}
html:not(.js) .story-img{opacity:1}
@media (max-width:860px){
  /* The story stays scroll told on a phone, it just changes shape: the
     photograph sticks under the nav, the progress bar goes horizontal under
     it, and the steps run past underneath. Flattening it into a plain list
     was throwing away the whole point of the section. */
  .story-grid{grid-template-columns:1fr;gap:14px}
  /* The sticky photograph needs the page colour behind it, or the step text
     scrolls up through the gaps and reads as two things printed on top of
     each other. It also gets a short fade below, so text leaves rather than
     being sliced off at a hard edge. */
  .story-media{
    position:sticky;top:calc(84px + env(safe-area-inset-top,0px));z-index:2;
    background:var(--paper);padding-bottom:10px;
  }
  .story-media::after{
    content:"";position:absolute;left:0;right:0;top:100%;height:26px;
    background:linear-gradient(180deg,var(--paper),rgba(252,245,226,0));
    pointer-events:none;
  }
  .story-stack{max-height:38vh}
  .story-stack .story-img{object-position:50% 42%}
  .story-step{
    min-height:56vh;padding-block:12px;
    display:flex;flex-direction:column;justify-content:center;
  }
  .story-step h2{transform:none !important}
  .story-step:last-child{min-height:40vh}
  .story-stack{aspect-ratio:16/10}

}

/* ---------- story progress rail ---------- */
.story-rail{position:sticky;top:clamp(120px,20vh,190px);justify-self:end}
.story-rail ol{list-style:none;margin:0;padding:0;display:grid;gap:0}
.story-rail li{display:grid;justify-items:center;gap:8px}
.story-rail .rn{
  font-family:var(--mono);font-size:10px;letter-spacing:.1em;
  color:var(--ink-45);opacity:.5;transition:color .4s ease, opacity .4s ease;
}
.story-rail .rl{
  width:1px;height:clamp(26px,4vh,44px);background:var(--line);
  position:relative;overflow:hidden;
}
.story-rail .rl::after{
  content:"";position:absolute;inset:0;background:var(--orange);
  transform:scaleY(0);transform-origin:top;transition:transform .5s var(--ease);
}
.story-rail li:last-child .rl{display:none}
.story-rail li.is-done .rl::after,.story-rail li.is-on .rl::after{transform:scaleY(1)}
.story-rail li.is-on .rn{color:var(--orange);opacity:1;font-weight:500}
.story-rail li.is-done .rn{opacity:.75}

/* On a phone the rail lies down and travels with the photograph: three short
   bars filling left to right rather than a column of numbers. It has to come
   after the rules above to beat them, since they carry the same weight. */
@media (max-width:900px){
  .story-rail{
    display:block;position:sticky;top:calc(68px + env(safe-area-inset-top,0px));
    justify-self:stretch;order:-1;z-index:3;
    background:var(--paper);padding-block:7px 5px;margin-bottom:-4px;
  }
  .story-rail ol{display:flex;gap:7px;justify-content:center}
  .story-rail li{display:block}
  .story-rail .rn{display:none}
  /* display:block matters here: the bars are spans, and once the list item
     stops being a grid they fall back to inline and take no size at all */
  .story-rail .rl,
  .story-rail li:last-child .rl{
    display:block;width:36px;height:3px;border-radius:99px;
    background:rgba(26,26,26,.16);
  }
  .story-rail .rl::after{transform-origin:left;transform:scaleX(0)}
  .story-rail li.is-done .rl::after,
  .story-rail li.is-on .rl::after{transform:scaleX(1)}
}

/* ============================================================
   TEAM DECK   a physical stack of photographs. The top card
   deals away and the next one is already waiting underneath.
   ============================================================ */
.deck{margin:0 0 0 auto;position:relative;width:100%;max-width:clamp(290px,30vw,400px)}
.deck-stack{
  position:relative;aspect-ratio:1;
  /* no perspective and a centred origin, so a scaled card never drifts
     out of its own box and gets clipped at the top */
  overflow:visible;
}
.deck-card{
  position:absolute;inset:0;cursor:pointer;
  border-radius:var(--squish);overflow:hidden;background:var(--sand-2);
  box-shadow:0 10px 30px rgba(26,26,26,.14), 0 2px 6px rgba(26,26,26,.08);
  transform-origin:50% 50%;
  transition:transform .55s var(--ease), opacity .45s var(--ease), box-shadow .55s var(--ease);
  will-change:transform;
}
.deck-card img{width:100%;height:100%;object-fit:cover;object-position:center;display:block;pointer-events:none}
/* JS writes --ty / --rot / --sc and the z-index; the transform is composed
   here so hover and the deal-away can layer on top of it. Any number of
   cards works: add one more <article> and nothing else changes. */
.deck-card{
  transform:translateY(var(--ty,0px)) rotate(var(--rot,0deg)) scale(var(--sc,1));
}
.deck-card.is-top:hover{
  transform:translateY(calc(var(--ty,0px) - 6px))
            rotate(calc(var(--rot,0deg) * .55))
            scale(calc(var(--sc,1) * 1.012));
}
.deck-card.is-top:hover{box-shadow:0 18px 44px rgba(26,26,26,.2)}
.deck-card:not(.is-top){pointer-events:none}
.deck-card.is-out{
  transform:translate(62%,-8%) rotate(14deg) scale(.96) !important;
  opacity:0 !important;
  transition:transform .5s cubic-bezier(.4,0,.3,1), opacity .42s ease;
}

.deck-meta{display:grid;gap:clamp(13px,1.6vw,20px);justify-items:end;text-align:right}
/* reserves the tallest caption, so switching teammates never nudges the controls */
.deck-cap{margin:0;display:grid;gap:5px;min-height:5.6em}
.deck-cap b{
  font-family:var(--serif);font-weight:500;font-size:clamp(20px,2.1vw,26px);
  letter-spacing:-.02em;color:var(--ink);text-wrap:balance;
}
.deck-cap span{font-size:14.5px;color:var(--ink-70);line-height:1.5;text-wrap:pretty}
/* narrow column, so the numbers and the button stack under the name */
.deck-ctl{display:grid;gap:clamp(10px,1.2vw,14px);justify-items:end}
.deck-btn{justify-self:end}
@media (max-width:860px){
  .deck-meta{justify-items:center;text-align:center;order:2}
  .deck-ctl{justify-items:center}
  .deck-btn{justify-self:center}
  .deck-cap{min-height:0}
  .deck{order:1}
}

.deck-btn{
  display:inline-flex;align-items:center;gap:9px;cursor:pointer;border:0;
  font-family:var(--sans);font-size:13.5px;font-weight:500;
  padding:11px 18px;border-radius:var(--pill);
  background:linear-gradient(180deg,#FFF7EE 0%,#FFE9D8 100%);color:#A13C0A;
  box-shadow:inset 0 0 0 1px rgba(255,81,0,.2);
  transition:transform .35s var(--ease), box-shadow .35s var(--ease);
}
.deck-btn svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;transition:transform .5s var(--ease)}
.deck-btn:hover{transform:translateY(-2px);box-shadow:inset 0 0 0 1px rgba(255,81,0,.3), 0 10px 24px rgba(255,81,0,.15)}
.deck-btn:hover svg{transform:rotate(-90deg)}


/* ============================================================
   DOT GRID   a canvas port of React Bits DotGrid. Sits behind the
   section, never takes pointer events, dots warm to orange near
   the cursor and get pushed on a click.
   ============================================================ */
.dot-field{position:relative}
.dot-field>*{position:relative;z-index:1}
.dotgrid{
  position:absolute;inset:0;width:100%;height:100%;
  pointer-events:none;z-index:0;
  /* fades in around the turnaround cards rather than switching on */
  /* fades in around the turnaround cards, then thins out again so the
     review cards are the loudest thing in their own section */
  -webkit-mask-image:linear-gradient(180deg, transparent 0 8%, rgba(0,0,0,.45) 20%, #000 34%, #000 62%, rgba(0,0,0,.5) 80%, rgba(0,0,0,.28) 100%);
          mask-image:linear-gradient(180deg, transparent 0 8%, rgba(0,0,0,.45) 20%, #000 34%, #000 62%, rgba(0,0,0,.5) 80%, rgba(0,0,0,.28) 100%);
}
.quote-band{position:relative;padding-top:clamp(8px,1.2vw,18px);padding-bottom:clamp(22px,3vw,44px)}
.quote-band>.wrap{position:relative;z-index:1}
@media (prefers-reduced-motion:reduce){.dotgrid{display:none}}

/* deck: without JS the stack has no indices, so show only the first photo */
html:not(.js) .deck-card:not(:first-child){display:none}
html:not(.js) .deck-card{position:relative}
.deck-card.no-anim{transition:none !important}

/* ============================================================
   REVIEWS   rows of notes drifting in opposite directions over
   the dot field. Each row's shift distance is measured in JS so
   the loop has no visible reset.
   ============================================================ */
.reviews{position:relative;padding-top:clamp(14px,2vw,30px);padding-bottom:clamp(30px,4vw,56px)}
/* a soft paper veil between the dot field and the cards, so the dots read as
   texture here rather than as a second thing to look at */
.reviews::before{
  content:"";position:absolute;inset:auto 0 0;height:74%;z-index:0;pointer-events:none;
  background:linear-gradient(180deg, rgba(252,245,226,0) 0%, rgba(252,245,226,.34) 40%, rgba(252,245,226,.5) 100%);
}
.reviews>*{position:relative;z-index:1}

/* Headline broken over two lines with the letter sitting right next to it.
   Flex rather than a grid on purpose: the copy takes only the width its own
   longest line needs, so the letter lands beside the text instead of being
   pushed out to the far edge of the page. */
.rev-head{
  display:flex;align-items:center;flex-wrap:wrap;
  gap:clamp(14px,2.4vw,42px);
}
.rev-head-copy{flex:0 1 auto;min-width:0}
.rev-head-copy .badge{margin-bottom:12px}
/* ---------- the kind words heading ----------
   Geometric sans in lower case, set against the Playfair quote directly
   above it. Two lines, the second one stepped in, and the personality
   carried by three marks rather than by another font file: a starburst
   standing in for an o, a drawn arrow, and a rough ring around the last
   two words. All three wake up together on hover, gently. */
.rev-title{
  margin:0;cursor:default;
  font-family:var(--sans);font-weight:600;
  font-size:clamp(34px,5.2vw,62px);line-height:1.02;
  letter-spacing:-.035em;color:var(--ink);
}
.rt-l1,.rt-l2{display:block}
.rt-l2{padding-left:.9em}
.rt-l2{margin-top:.06em}

/* the starburst sitting where an o would be */
.rt-star{
  display:inline-block;width:.62em;height:.62em;vertical-align:-.03em;
  margin:0 .02em;
  transition:transform .7s var(--ease);
}
.rt-star svg{width:100%;height:100%;display:block;fill:var(--orange)}
.rev-title:hover .rt-star{transform:rotate(105deg) scale(1.08)}

/* a small drawn arrow between the words */
.rt-arrow{
  display:inline-block;width:.86em;height:.24em;vertical-align:.14em;
  margin:0 .12em 0 .06em;opacity:.55;
  transition:transform .6s var(--ease), opacity .6s ease;
}
.rt-arrow svg{width:100%;height:100%;display:block;fill:none;
  stroke:var(--ink);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;
  vector-effect:non-scaling-stroke}
.rev-title:hover .rt-arrow{transform:translateX(.12em);opacity:.9}

/* the rough ring, drawn on as the pointer arrives */
.rt-ring{position:relative;display:inline-block;white-space:nowrap}
.rt-ring-svg{
  position:absolute;left:-.16em;top:-.18em;width:calc(100% + .32em);height:calc(100% + .36em);
  overflow:visible;pointer-events:none;
  fill:none;stroke:var(--orange);stroke-width:2;stroke-linecap:round;
  vector-effect:non-scaling-stroke;
  stroke-dasharray:640;stroke-dashoffset:640;opacity:.75;
  transition:stroke-dashoffset 1.1s var(--ease);
}
.rev-title:hover .rt-ring-svg{stroke-dashoffset:0}
@media (prefers-reduced-motion:reduce){
  .rt-star,.rt-arrow,.rt-ring-svg{transition:none}
  .rt-ring-svg{stroke-dashoffset:0}
}
html.capture .rt-ring-svg{stroke-dashoffset:0}
.rev-head-copy .lede{margin-top:14px;max-width:44ch}

.rev-cat{margin:-6px 0 0;flex:0 0 auto;width:clamp(148px,16vw,212px)}
.rev-cat img{
  display:block;width:100%;height:auto;
  transform:rotate(-4deg);
  filter:drop-shadow(0 8px 16px rgba(26,26,26,.1));
  transition:transform .8s var(--ease);
}
.rev-cat img:hover{transform:rotate(-1.4deg) translateY(-4px) scale(1.02)}
/* the letter leans toward the pointer while it is near, which is written
   from JS as two numbers and composed here so the float keeps running */
.rev-cat.is-tilting img{
  animation:none;
  transform:rotate(calc(-4deg + var(--lean-r, 0deg)))
            translate3d(var(--lean-x, 0px), var(--lean-y, 0px), 0);
  transition:transform .35s var(--ease);
}
@media (min-width:861px){
  /* a slow drift so the letter feels held rather than pasted on */
  .rev-cat img{animation:catFloat 9s ease-in-out infinite}
}
@keyframes catFloat{
  0%,100%{transform:rotate(-4deg) translateY(0)}
  50%{transform:rotate(-2.6deg) translateY(-9px)}
}
@media (max-width:860px){
  .rev-head{gap:14px}
  .rev-cat{margin:0;width:min(172px,44vw)}
}
@media (max-width:560px){
  .rev-head{flex-direction:column;align-items:flex-start}
  .rev-cat{align-self:center;width:min(190px,52vw)}
}

/* ============================================================
   REVIEW ROWS   two rows, opposite directions, very slow. The
   shift distance is measured in JS from one set of cards plus one
   gap, so the loop has no seam. Duration is derived from that
   distance, which keeps both rows at the same reading speed.
   ============================================================ */
.rev-rows{
  display:grid;gap:clamp(20px,2.6vw,34px);
  margin-top:clamp(20px,2.6vw,34px);
}
/* The track only ever moves sideways, so only the x axis needs clipping.
   overflow:clip can be set per axis without forcing the other one to auto,
   which lets rotation, the vertical nudge and the shadows sit outside the
   row box instead of being chopped at its edge. Older engines fall back to
   hidden with enough padding that nothing reaches the edge. */
/* min-width:0 is load bearing: these rows are grid items, and once the y axis
   is visible the item goes back to a content based minimum size, which would
   stretch the row to the full width of its track and put a horizontal
   scrollbar on the page. */
.rev-row{overflow:hidden;min-width:0;padding-block:30px;margin-block:-16px}
@supports (overflow-x:clip){
  .rev-row{overflow-x:clip;overflow-y:visible;padding-block:12px;margin-block:0}
}
.rev-track{
  display:flex;width:max-content;gap:clamp(16px,1.8vw,26px);
  align-items:flex-start;
  will-change:transform;
  animation:revShift 150s linear infinite;
}
.rev-row[data-dir="right"] .rev-track{animation-direction:reverse}
/* Pointer anywhere over the rows holds both of them, and letting go resumes
   from exactly where it stopped: a paused animation keeps its own progress,
   so there is nothing to reset. On touch a press does the same for as long
   as the finger is down, and a tap latches it. */
@media (hover:hover){
  .rev-rows:hover .rev-track{animation-play-state:paused}
}
.rev-rows.is-held .rev-track,
.rev-rows.is-pressed .rev-track{animation-play-state:paused}
@keyframes revShift{
  from{transform:translate3d(0,0,0)}
  to{transform:translate3d(calc(-1 * var(--shift,1200px)),0,0)}
}

.rev-card{
  flex:none;width:clamp(292px,26vw,366px);
  padding:16px 18px 20px;
  border-radius:var(--squish-tall);
  background:var(--paper);cursor:pointer;
  /* deliberately light: ten of these side by side used to add up to a dark
     band under the row, which read as haze over the dot field */
  box-shadow:0 1px 1px rgba(26,26,26,.035), 0 4px 10px rgba(26,26,26,.045);
  transform:rotate(var(--rc-rot,0deg)) translateY(var(--rc-ty,0px));
  transition:transform .5s var(--ease), box-shadow .5s var(--ease);
}
.rev-card:hover,
.rev-card:focus-visible{
  transform:rotate(0deg) translateY(calc(var(--rc-ty,0px) - 5px));
  box-shadow:0 2px 3px rgba(26,26,26,.05), 0 10px 22px rgba(26,26,26,.08);
  outline:none;
}

/* the pill that carries who said it, as in the reference */
.rev-top{
  display:flex;align-items:center;gap:12px;
  padding:10px 14px 10px 10px;border-radius:var(--pill);
  background:var(--rc-pill,rgba(26,26,26,.05));
}
.rev-av{
  flex:none;position:relative;width:42px;height:42px;border-radius:50%;
  display:grid;place-items:center;overflow:hidden;
  background:var(--rc-av,rgba(255,255,255,.75));
}
.rev-av img{width:100%;height:100%;object-fit:cover;display:block}
.rev-av .rev-burst{
  position:absolute;inset:4px;width:auto;height:auto;
  fill:var(--orange);opacity:.22;
}
.rev-av b{
  position:relative;font-family:var(--serif);font-weight:500;font-size:15px;
  letter-spacing:.01em;color:#6B3416;
}
.rev-who{display:grid;gap:2px;min-width:0;flex:1}
.rev-name{
  font-family:var(--sans);font-weight:600;font-size:15px;letter-spacing:-.005em;
  color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.rev-line{display:flex;align-items:center;justify-content:space-between;gap:10px}
.rev-meta{
  font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink-45);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
/* five stars from one masked element, so there is no icon markup per card */
.rev-stars{
  flex:none;display:block;width:68px;height:13px;background:var(--orange);opacity:.85;
  -webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M10 1.6l2.4 5.3 5.8.6-4.3 3.9 1.2 5.7L10 14.2 4.9 17.1l1.2-5.7L1.8 7.5l5.8-.6z'/%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M10 1.6l2.4 5.3 5.8.6-4.3 3.9 1.2 5.7L10 14.2 4.9 17.1l1.2-5.7L1.8 7.5l5.8-.6z'/%3E%3C/svg%3E");
  -webkit-mask-size:13.6px 13px;mask-size:13.6px 13px;
  -webkit-mask-repeat:repeat-x;mask-repeat:repeat-x;
}
.rev-quote{
  margin:15px 4px 0;
  font-family:var(--serif);font-weight:400;font-size:clamp(17px,1.35vw,19px);
  line-height:1.38;letter-spacing:-.012em;color:var(--ink);
  text-wrap:pretty;
}

/* Controlled palette: card tone, pill tone, avatar tone. The rotation, the
   vertical nudge and the width all hang off the tone class rather than
   :nth-child, because the loop clones whole sets: a positional rule would
   give a clone different widths from its original and put a jump in the seam. */
.rc-cream {background:#FBF3DC;--rc-pill:#F2E6C6;--rc-av:#FFFCF2;--rc-rot:-.7deg}
.rc-orange{background:#FDE7D6;--rc-pill:#F8D5BB;--rc-av:#FFF6EE;--rc-rot:.8deg;--rc-ty:11px;width:clamp(272px,23.5vw,332px)}
.rc-green {background:#E6EFDF;--rc-pill:#D5E4CA;--rc-av:#F6FBF2;--rc-rot:-.5deg;--rc-ty:5px}
.rc-blue  {background:#E4EAF4;--rc-pill:#D3DDEE;--rc-av:#F5F8FD;--rc-rot:.6deg;--rc-ty:14px}
.rc-pink  {background:#F7E3E6;--rc-pill:#EFD0D5;--rc-av:#FEF7F8;--rc-rot:-.9deg;width:clamp(268px,23vw,324px)}

.rev-hint{
  margin:clamp(16px,2vw,24px) 0 0;text-align:center;
  font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-45);transition:color .3s ease;
}
.rev-rows.is-held + .wrap .rev-hint{color:var(--orange)}
@media (hover:hover){
  .rev-rows:hover + .wrap .rev-hint{color:var(--orange)}
}

@media (max-width:860px){
  /* one width, no rotation, no offsets: phones have no room for the flourish */
  .rev-card,
  .rc-orange,
  .rc-pink{width:clamp(256px,74vw,300px);padding:14px 15px 18px}
  .rev-card{--rc-rot:0deg;--rc-ty:0px}
  .rev-quote{font-size:16.5px;margin-top:13px}
  .rev-rows{gap:14px}
}
@media (prefers-reduced-motion:reduce){
  .rev-track{animation:none;width:auto}
  /* both axes named, or auto next to the visible y from @supports would
     resolve to auto and put a vertical scrollbar inside the row */
  .rev-row{overflow-x:auto;overflow-y:hidden;padding-block:16px;-webkit-overflow-scrolling:touch}
  .rev-card{--rc-rot:0deg;--rc-ty:0px}
  .rev-cat img{animation:none;transition:none}
  .rev-cat img:hover{transform:rotate(-4deg)}
  .rev-hint{display:none}
}

/* A phone on its side has almost no height to give. Everything that was
   sized against the viewport gets a shorter ceiling here, so nothing ends up
   taller than the screen it has to sit on. */
@media (max-height:540px) and (orientation:landscape){
  .bc-inner{height:clamp(260px, 84vh, 380px)}
  .story-step{min-height:78vh}
  .story-stack{max-height:52vh}
  .story-media{top:calc(58px + env(safe-area-inset-top,0px))}
  .story-rail{top:calc(44px + env(safe-area-inset-top,0px))}
  .hero{min-height:auto;padding-block:84px 56px}
  .reel-card{--card-h:auto}
}
