/* ==========================================================================
   Biancardi Luxury Events — v2
   Built to Brand Book Edition 01 (September 2026).

   Departures from the book, each deliberate:
   1. Forest is out. Midnight is the only dark ground; Champagne accents it.
   2. The reading face is Libre Baskerville, not Baskervville — the revival's
      hairlines are too fine to read on screen (§04 warns about this itself).
   3. Type and space are FLUID: every size interpolates between a 360px floor
      and a 1600px ceiling and then stops. §04's values are the ceiling.
   4. Eyebrow labels are used sparingly rather than above every heading.
   5. The wordmark is the supplied PNG, not type set in the display face.

   Everything else holds: square corners, no shadows, hairline separators,
   Champagne never as text on a light ground.
   ========================================================================== */

:root{
  /* ---------- colour ---------- */
  --ivory:#F7F4EF;
  --ivory-deep:#EFEAE1;
  --midnight:#11141D;
  --midnight-lift:#191D28;
  --ink-black:#080A10;
  --champagne:#D1AC6B;
  --champagne-ink:#5C4517;   /* the only gold that may carry text on light */
  --stone:#D9D2C8;
  --ink-60:#5F5A51;
  --ink-40:#837D72;
  --on-dark:rgba(247,244,239,.93);
  --on-dark-dim:rgba(247,244,239,.74);

  /* ---------- type families ---------- */
  --font-display:"Bodoni Moda",Didot,"Times New Roman",serif;
  /* The reading face. EB Garamond carries noticeably less ink than Libre
     Baskerville at the same size — lighter on the page without going to the
     hairlines that made §04's own Baskervville unreadable on screen. Its
     x-height is smaller, so the body step below is set ~12% larger to keep
     the apparent reading size identical. To go back, put Libre Baskerville
     first here and drop --t-0 to 1.0625/1.1875rem. */
  --font-body:"EB Garamond","Libre Baskerville",Georgia,serif;
  --font-label:"Jost",Futura,"Century Gothic",sans-serif;

  /* ---------- fluid type ----------
     clamp(floor, rem + vw, ceiling). The rem term keeps the scale responsive
     to the reader's own font-size setting and to zoom, which a pure-vw scale
     ignores. The ceiling stops an ultrawide monitor rendering 90px body copy.
     The display steps carry an extra min(…,vw) so an enlarged default font on
     a small phone cannot push a headline wider than the screen. */
  --t-label:clamp(0.8125rem, 0.7943rem + 0.081vw, 0.875rem);      /* 13 -> 14px */
  --t--1:clamp(1.0625rem, 1.0262rem + 0.161vw, 1.1875rem);        /* 17 -> 19px */
  --t-0:clamp(1.28125rem, 1.2359rem + 0.202vw, 1.4375rem);  /* EB Garamond runs small; see --font-body */
  --t-1:clamp(1.3125rem, 1.2218rem + 0.403vw, 1.625rem);
  --t-2:min(clamp(1.6875rem, 1.4516rem + 1.048vw, 2.5rem), 9vw);
  --t-3:min(clamp(2.125rem, 1.6895rem + 1.935vw, 3.625rem), 12vw);

  /* ---------- fluid space ---------- */
  --sp-2xs:0.5rem;
  --sp-xs:clamp(0.75rem, 0.7097rem + 0.179vw, 1rem);
  --sp-s:clamp(1rem, 0.8548rem + 0.645vw, 1.5rem);
  --sp-m:clamp(1.5rem, 1.2097rem + 1.290vw, 2.5rem);
  --sp-l:clamp(2.5rem, 2.0645rem + 1.935vw, 4rem);
  --sp-xl:clamp(4rem, 3.4194rem + 2.581vw, 6rem);
  --sp-2xl:clamp(6rem, 5.1290rem + 3.871vw, 9rem);
  --gutter:clamp(1.25rem, 0.4516rem + 3.548vw, 4rem);

  --track-label:0.2em;
  --measure:62ch;
  --maxw:75rem;
  --nav-h:clamp(4.25rem, 4rem + 1.1vw, 5.75rem);
  --ease:cubic-bezier(.22,.61,.36,1);
}

/* ---------- self-hosted brand faces ----------
   Free under the SIL Open Font License, served from this folder, so no font
   request leaves the visitor's browser. Bodoni Moda is the VARIABLE cut; its
   optical-size axis is set by hand per role, never left to the browser, which
   drives it from the pixel size and thins hairlines until they break apart. */
@font-face{font-family:"Bodoni Moda";src:url("../fonts/bodoni-moda-var.woff2") format("woff2");font-weight:400 900;font-style:normal;font-display:swap}
@font-face{font-family:"Libre Baskerville";src:url("../fonts/libre-baskerville-400.woff2") format("woff2");font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"Libre Baskerville";src:url("../fonts/libre-baskerville-400-italic.woff2") format("woff2");font-weight:400;font-style:italic;font-display:swap}
@font-face{font-family:"Libre Baskerville";src:url("../fonts/libre-baskerville-700.woff2") format("woff2");font-weight:700;font-style:normal;font-display:swap}
@font-face{font-family:"EB Garamond";src:url("../fonts/eb-garamond-400.woff2") format("woff2");font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"EB Garamond";src:url("../fonts/eb-garamond-400-italic.woff2") format("woff2");font-weight:400;font-style:italic;font-display:swap}
@font-face{font-family:"EB Garamond";src:url("../fonts/eb-garamond-600.woff2") format("woff2");font-weight:600 700;font-style:normal;font-display:swap}
@font-face{font-family:"Jost";src:url("../fonts/jost-300.woff2") format("woff2");font-weight:300;font-style:normal;font-display:swap}
@font-face{font-family:"Jost";src:url("../fonts/jost-500.woff2") format("woff2");font-weight:500;font-style:normal;font-display:swap}

/* ==========================================================================
   RESET + RESILIENCE
   The overflow rules are not housekeeping: a long word, a pasted URL or a
   translated string is the usual cause of a page that scrolls sideways on a
   phone. Text may break; every flex/grid child may be narrower than content.
   ========================================================================== */
*,*::before,*::after{box-sizing:border-box;min-inline-size:0}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;scroll-padding-block-start:calc(var(--nav-h) + 1rem)}
body{
  margin:0;background:var(--ivory);color:var(--midnight);
  font-family:var(--font-body);font-size:var(--t-0);line-height:1.75;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  font-optical-sizing:none;overflow-wrap:break-word;
}
h1,h2,h3,h4,p,blockquote,figure{margin:0;overflow-wrap:anywhere}
img,video,svg{max-inline-size:100%;display:block}
button{font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer}
a{color:inherit;text-decoration:none}
ul{margin:0;padding:0;list-style:none}
:focus-visible{outline:2px solid var(--champagne);outline-offset:3px}
::selection{background:var(--champagne);color:var(--midnight)}
/* display on a component otherwise overrides the hidden attribute */
[hidden]{display:none!important}

/* ==========================================================================
   TYPE ROLES
   ========================================================================== */
.statement{font-family:var(--font-display);font-weight:400;font-size:var(--t-3);line-height:1.08;letter-spacing:-0.012em;font-variation-settings:"opsz" 14,"wght" 450}
.section-head{font-family:var(--font-display);font-weight:400;font-size:var(--t-2);line-height:1.16;font-variation-settings:"opsz" 13,"wght" 450;text-wrap:balance}
.sub-head{font-family:var(--font-display);font-weight:400;font-size:var(--t-1);line-height:1.3;font-variation-settings:"opsz" 11,"wght" 500}
.body{font-size:var(--t-0);line-height:1.75;max-inline-size:var(--measure)}
.note{font-size:var(--t--1);line-height:1.7;color:var(--ink-60)}
.label{font-family:var(--font-label);font-weight:500;font-size:var(--t-label);line-height:1.4;letter-spacing:var(--track-label);text-transform:uppercase;color:var(--midnight)}
em,i{font-style:italic}

/* No copy uses emphasis at the moment, but the 700 cut is served rather than
   synthesised, so a <strong> added later renders properly instead of smeared. */
strong,b{font-weight:700;color:var(--midnight)}
.band--dark strong,.band--dark b{color:var(--ivory)}
.band--dark .quote strong{color:var(--ivory)}
.note strong,.invite__note strong{color:inherit;font-weight:700}
.band--dark .note strong{color:var(--on-dark)}

.band--dark .statement,.band--dark .section-head{font-variation-settings:"opsz" 12,"wght" 500}
.band--dark .sub-head{font-variation-settings:"opsz" 10,"wght" 500}

/* ==========================================================================
   BANDS
   ========================================================================== */
.band{position:relative}
.band--ivory{background:var(--ivory);color:var(--midnight)}
.band--deep{background:var(--ivory-deep);color:var(--midnight)}
.band--dark{background:var(--midnight);color:var(--ivory);position:relative}
/* ------------------------------------------------------ the sheen ---
   Midnight on its own is a flat field. This is the light off a bolt of silk
   laid over it: three broad diagonal bands of ivory at three to six percent,
   with soft stops so there is not a hard edge anywhere on them. It reads as a
   sheen rather than as a graphic — no lines, no pattern, nothing to notice,
   just a ground that is no longer one tone. */
.sheen{
  position:absolute;inset:0;z-index:0;pointer-events:none;
  background:
    linear-gradient(116deg, transparent 6%,  rgba(247,244,239,.052) 24%, transparent 44%),
    linear-gradient(116deg, transparent 42%, rgba(247,244,239,.098) 61%, transparent 80%),
    linear-gradient(116deg, transparent 68%, rgba(247,244,239,.142) 88%, transparent 100%);
  /* weighted to the right: the copy holds the left of every one of these bands
     and reads best on plain Midnight, so the light is turned down to about a
     tenth over there and comes up to full across the right half */
  -webkit-mask-image:linear-gradient(90deg, rgba(0,0,0,.14) 0%, rgba(0,0,0,.40) 38%, #000 74%);
  mask-image:linear-gradient(90deg, rgba(0,0,0,.14) 0%, rgba(0,0,0,.40) 38%, #000 74%);
}
.band--dark > .wrap,.band--dark > .hero__stage{position:relative;z-index:1}
.band--dark .label{color:var(--champagne)}
.band--dark .note{color:var(--on-dark-dim)}
.band--dark .body{color:var(--on-dark)}

.wrap{max-inline-size:var(--maxw);margin-inline:auto;padding-inline:var(--gutter)}
.section{padding-block:var(--sp-2xl)}
.section--tight{padding-block:var(--sp-xl)}
.tick{display:block;inline-size:2.75rem;block-size:1px;background:var(--champagne)}
.tick--c{margin-inline:auto}

/* ==========================================================================
   SECTION ENTRANCES
   Each section announces itself once, in a way particular to its content —
   the copy arrives from the side, the films rise in sequence, the triangle
   draws itself. Reduced motion turns all of it off and shows the finished
   state. A section animates once and is then still.
   ========================================================================== */
.enter{--d:0ms}
.js .enter-up{opacity:0;transform:translateY(1.75rem)}
.js .enter-left{opacity:0;transform:translateX(-1.5rem)}
.js .enter-rise{opacity:0;transform:translateY(2.5rem) scale(.985)}
.js .enter-fade{opacity:0}
.is-in .enter-up,.is-in .enter-left,.is-in .enter-rise,.is-in .enter-fade,
.is-in.enter-up,.is-in.enter-left,.is-in.enter-rise,.is-in.enter-fade{
  opacity:1;transform:none;
  transition:opacity .85s ease var(--d), transform 1s var(--ease) var(--d);
}
/* a champagne hairline that draws itself across the head of a section */
.draw-rule{transform-origin:left center}
.js .draw-rule{transform:scaleX(0)}
.is-in .draw-rule{transform:scaleX(1);transition:transform 1.1s var(--ease) var(--d)}
.draw-rule--c{transform-origin:center}

/* ==========================================================================
   BUTTONS — 44px minimum target everywhere
   ========================================================================== */
.btn{
  display:inline-flex;align-items:center;justify-content:center;min-block-size:3rem;
  font-family:var(--font-label);font-weight:500;font-size:var(--t-label);
  letter-spacing:var(--track-label);text-transform:uppercase;
  /* the side padding is rem-based so it grows with the reader's font size,
     but capped against the viewport: at 24px default on a 320px screen the
     old fixed 2.1rem pushed the button past the edge of the page */
  padding:0.95rem clamp(1.1rem, 0.6rem + 3vw, 2.1rem);max-inline-size:100%;
  border:1px solid var(--midnight);
  background:var(--midnight);color:var(--ivory);text-align:center;
  transition:background .25s ease,color .25s ease,border-color .25s ease;
}
.btn:hover{background:transparent;color:var(--midnight)}
.btn--onDark{background:var(--champagne);color:var(--midnight);border-color:var(--champagne)}
.btn--onDark:hover{background:transparent;color:var(--champagne)}
.btn--ghost{background:transparent;color:var(--midnight)}
.btn--ghost:hover{background:var(--midnight);color:var(--ivory)}
.btn--quiet{background:transparent;color:var(--ink-60);border-color:var(--stone)}
.btn--quiet:hover{background:transparent;color:var(--midnight);border-color:var(--midnight)}
.btn[disabled]{border-color:var(--stone);background:var(--stone);color:#fff;cursor:not-allowed}

/* ==========================================================================
   NAVIGATION — the supplied wordmark, not type
   ========================================================================== */
.nav{
  position:sticky;inset-block-start:0;z-index:60;
  background:var(--midnight);color:var(--ivory);
  border-block-end:1px solid transparent;
  transition:border-color .3s ease,box-shadow .3s ease;
}
/* once it has left the top of the page it stops pretending to be part of the
   hero: a champagne hairline, and a shadow deep enough to separate it from a
   film running underneath */
.nav.is-stuck{border-block-end-color:rgba(209,172,107,.35);box-shadow:0 12px 28px -18px rgba(0,0,0,.9)}
.nav__inner{max-inline-size:var(--maxw);margin-inline:auto;padding-inline:var(--gutter);min-block-size:var(--nav-h);display:flex;align-items:center;justify-content:space-between;gap:var(--sp-m)}

.mark{display:flex;align-items:center;flex:0 0 auto;padding-block:0.55rem}
.mark img{block-size:clamp(1.75rem, 1.45rem + 1.35vw, 2.75rem);inline-size:auto;max-inline-size:min(52vw,18rem);object-fit:contain}
.mark--lg img{block-size:clamp(2rem, 1.4rem + 2.6vw, 3.25rem);max-inline-size:min(72vw,24rem)}

.nav__menu{display:flex;align-items:center;gap:var(--sp-m)}
.nav__link{
  position:relative;
  font-family:var(--font-label);font-weight:300;font-size:var(--t-label);
  letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--on-dark);display:inline-flex;align-items:center;min-block-size:2.75rem;
  transition:color .25s ease;
}
.nav__link:hover{color:var(--ivory)}
.nav__link[aria-current="page"]{color:var(--ivory)}
/* the rule draws itself in from the left rather than appearing whole */
.nav__link::after{
  content:"";position:absolute;inset-block-end:0.55rem;inset-inline:0;block-size:1px;
  background:var(--champagne);transform:scaleX(0);transform-origin:left;
  transition:transform .4s var(--ease);
}
.nav__link:hover::after,.nav__link[aria-current="page"]::after{transform:scaleX(1)}
.nav__link:focus-visible{outline:2px solid var(--champagne);outline-offset:4px}

/* a hairline between the places you can go and the thing we want you to do */
.nav__sep{inline-size:1px;block-size:1.4rem;background:rgba(247,244,239,.20);flex:0 0 auto}

/* the call to action is the one lit object in the bar, so it gets a little
   more presence than a flat fill: a soft champagne halo that grows on hover */
.nav__menu .btn--onDark{box-shadow:0 0 0 0 rgba(209,172,107,0);transition:background .3s ease,color .3s ease,box-shadow .4s var(--ease)}
.nav__menu .btn--onDark:hover{box-shadow:0 0 0 1px var(--champagne),0 8px 24px -10px rgba(209,172,107,.55)}

.nav__burger{display:none;inline-size:2.75rem;block-size:2.75rem;position:relative;flex:0 0 auto}
.nav__burger span{position:absolute;inset-inline:0.35rem;block-size:1px;background:var(--ivory);transition:transform .35s var(--ease),opacity .2s ease,inline-size .3s ease,background .25s ease}
.nav__burger span:nth-child(1){inset-block-start:0.95rem}
.nav__burger span:nth-child(2){inset-block-start:1.35rem}
.nav__burger span:nth-child(3){inset-block-start:1.75rem;inset-inline-end:0.95rem}
.nav__burger:hover span{background:var(--champagne)}
.nav__burger:hover span:nth-child(3){inset-inline-end:0.35rem}
body.nav-open .nav__burger span:nth-child(3){inset-inline-end:0.35rem}
body.nav-open .nav__burger span:nth-child(1){transform:translateY(0.4rem) rotate(45deg)}
body.nav-open .nav__burger span:nth-child(2){opacity:0}
body.nav-open .nav__burger span:nth-child(3){transform:translateY(-0.4rem) rotate(-45deg)}

/* ==========================================================================
   HERO
   The film is a 9:16 clip, so it gets a vertical home: a column at the right
   on wide screens, capped in px so a large monitor never upscales a 760px
   source, its left edge masked so there is no seam. On a phone the film and
   the screen are the same shape, so it takes the whole frame.
   ========================================================================== */
/* The hero is two columns now: the copy on the left, the film in its own
   frame on the right. It is no longer a background and no longer a scroll
   takeover — the film simply plays, muted, from the moment the page opens.

   The whole block has to be readable without scrolling, eyebrow to footnote,
   so the section sizes itself to its content and only caps at the screen. */
.hero__grid{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.2fr);
  gap:var(--sp-l);align-items:center;
}
/* THE TRACK. Its height is the length of the takeover: one screen of scroll
   above the screen the stage occupies. Without JS, or under reduced motion, it
   collapses to a single screen and the film stays in its card. */
.hero{position:relative;background:var(--midnight);--p:0}
.js .hero{block-size:200svh}
.hero__stage{position:relative;overflow:clip;padding-block:var(--sp-xl)}
.js .hero__stage{
  position:sticky;inset-block-start:0;
  block-size:100svh;padding-block:0;
  display:flex;align-items:center;
}
/* The nav offset lives on the grid, so the stage box itself is the full
   screen and the film can grow to cover every pixel of it. The width is
   explicit because the stage is a flex container and `.wrap`'s auto margins
   would otherwise take every spare pixel and leave the grid at nothing. */
/* The block is centred in what you can actually SEE, which is not the same as
   centred in the stage. The navigation is sticky, so the hero starts below it
   and the 100svh stage hangs its last nav-height below the fold. Padding the
   grid at the bottom by exactly that lifts the content back by half of it, and
   the gap above the copy then equals the gap below it on screen. */
.js .hero__grid{
  padding-block-end:var(--nav-h);
  inline-size:100%;
}

/* The hero film's shape lives here, once. The slot that holds its place in
   the grid and the tile itself both read it, so changing the film's aspect
   ratio is two numbers rather than a hunt through the stylesheet. Keep it in
   step with the --arw/--arh on #heroFilm, which is what site.js measures. */
.hero{--hero-arw:16;--hero-arh:9}
.hero__slot{aspect-ratio:var(--hero-arw)/var(--hero-arh);inline-size:100%}
.hero__film{aspect-ratio:var(--hero-arw)/var(--hero-arh)}

/* At rest the film sits exactly in its slot. As --p runs 0 → 1 site.js writes
   the four numbers below, interpolating that box out to the whole stage, so
   the crop is right the whole way rather than snapping at the end. */
.js .hero__film{
  position:absolute;z-index:2;
  inset-inline-start:var(--fx,0px);inset-block-start:var(--fy,0px);
  inline-size:var(--fw,100%);block-size:var(--fh,100%);
  aspect-ratio:auto;
}
/* The hero's player keeps ONE pixel size — the open box — and is scaled to
   whatever the tile currently is. site.js writes --pw/--ph when the layout
   changes and --pscale on every frame. Resizing an iframe sixty times a
   second reflows the document inside it and the picture lags behind its own
   frame; a transform is composited and does not. `inset` is unset on the
   trailing edges so the explicit size wins rather than fighting it. */
.js .hero__film .film__player{
  inset-inline-end:auto;inset-block-end:auto;
  inline-size:var(--pw,100%);block-size:var(--ph,100%);
  transform-origin:0 0;transform:scale(var(--pscale,1));
  will-change:transform;
}

/* the copy lifts away and hands the screen over */
.hero__copy{max-inline-size:34rem;container-type:inline-size}
.js .hero__copy{
  transform:translateY(calc(var(--p) * -5rem));
  opacity:clamp(0, calc(1 - var(--p) * 2.6), 1);
}
.js .hero__copy[data-gone]{pointer-events:none}

/* the ladder down the left column: label, headline, paragraph, button, note */
.hero__eyebrow{
  display:flex;align-items:flex-start;gap:0.9rem;
  margin-block-end:var(--sp-m);
}
/* the rule sits on the first line's centre, so it stays put if the label
   wraps on a narrow screen instead of drifting to the middle of two lines */
.hero__eyebrow .tick{margin-block-start:0.62em;flex:0 0 auto}

/* once the film has the screen it runs under the fixed navigation */
.hero__topfade{
  position:absolute;inset-block-start:0;inset-inline:0;block-size:11rem;z-index:3;
  background:linear-gradient(180deg,rgba(8,10,16,.78),transparent);
  opacity:var(--p);pointer-events:none;
}
/* The scroll cue. It sits at the foot of the stage and says the only thing
   the hero cannot say for itself: that the screen moves. Its opacity is a
   function of --p, so it is gone within the first tenth of the track and
   returns if the reader scrolls back up — no listener, no state.

   It exists only where the takeover does. Without JS, on a portrait screen
   and under reduced motion the hero is one ordinary screen with the film
   below the copy, and an instruction to scroll would be telling somebody
   something they can already see. */
/* champagne belongs to the eyebrow at the top of the hero, which is a
   statement; this is an instruction and should be quieter than the thing it
   is pointing away from. The one accent is the dot on the rule. */
.band--dark .hero__cue{color:var(--on-dark-dim)}
.hero__cue{
  display:none;
  /* The stage is a full 100svh and the navigation is sticky above it, so at
     rest the stage hangs its last nav-height below the fold — the same reason
     the grid carries padding-block-end:var(--nav-h). Without that offset here
     the cue would sit just off the bottom of the screen, which is a cruel
     place to put an instruction to scroll. */
  position:absolute;inset-inline:0;
  inset-block-end:calc(var(--nav-h) + var(--sp-s));
  z-index:4;pointer-events:none;margin:0;
  flex-direction:column;align-items:center;gap:0.7rem;
  color:var(--on-dark-dim);text-align:center;
  opacity:clamp(0, calc(1 - var(--p) * 14), 1);
}
.js .hero__cue{display:flex}
.hero__cue-rule{
  position:relative;display:block;overflow:hidden;
  inline-size:1px;block-size:3rem;
  background:linear-gradient(180deg,rgba(247,244,239,.05),rgba(247,244,239,.22));
}
.hero__cue-dot{
  position:absolute;inset-inline-start:0;inset-block-start:0;
  inline-size:1px;block-size:1.1rem;background:var(--champagne);
  animation:cue-fall 2.6s var(--ease) infinite;
}
@keyframes cue-fall{
  0%   {transform:translateY(-1.1rem);opacity:0}
  22%  {opacity:1}
  78%  {opacity:1}
  100% {transform:translateY(3rem);opacity:0}
}

/* Three lines, always. The size is capped against the COLUMN, not the
   viewport — a 1024px screen gives the copy a 440px column and the full
   display step would spill that headline onto five lines. text-wrap:balance
   then evens the three. */
.hero__statement{
  margin-block-end:var(--sp-m);color:var(--ivory);
  font-size:min(var(--t-3), 9.2cqi);text-wrap:balance;
}
.hero__body{margin-block-end:var(--sp-l);color:var(--on-dark)}

/* A laptop screen is around 780-820px tall with the browser chrome taken off,
   and the whole hero block — eyebrow down to the footnote under the button —
   has to be readable the moment the page opens. So the spacing tightens by a
   step on anything shorter than 896px, which covers every common laptop. */
@media (max-height: 56rem){
  .hero__stage:not(.js *){padding-block:var(--sp-l)}
  /* the whole ladder compresses together, or the label ends up with more air
     under it than the headline has */
  .hero__eyebrow{margin-block-end:var(--sp-s)}
  .hero__statement{margin-block-end:var(--sp-s)}
  .hero__body{margin-block-end:var(--sp-m)}
  .hero__grid{gap:var(--sp-l)}
}

/* A short window (a laptop with a small screen, or a preview pane) has less
   than 560px under the navigation. The hero copy is built for 800; without
   this it is taller than the stage and gets clipped at both ends. */
@media (max-height: 46rem){
  .hero__stage:not(.js *){padding-block:var(--sp-l)}
  .hero__statement{font-size:var(--t-2);margin-block-end:var(--sp-s)}
  .hero__eyebrow{margin-block-end:var(--sp-xs)}
  .hero__body{margin-block-end:var(--sp-m)}
}
@media (max-height: 34rem){
  .hero__statement{font-size:var(--t-1)}
  .hero__body{margin-block-end:var(--sp-s)}
}

/* the one orchestrated load */
.js .seq{opacity:0}
.is-ready .seq{animation:rise .9s var(--ease) forwards}
.is-ready .seq--1{animation-delay:.05s}
.is-ready .seq--2{animation-delay:.18s}
.is-ready .seq--3{animation-delay:.31s}
.is-ready .seq--4{animation-delay:.44s}
.is-ready .seq--5{animation-delay:.6s}
@keyframes rise{from{opacity:0;transform:translateY(0.9rem)}to{opacity:1;transform:none}}
.is-ready .hero__film{animation:filmIn 1.6s ease forwards}
@keyframes filmIn{from{opacity:0}to{opacity:1}}
/* the one draw-on used by every hairline that inks itself in: the invitation
   card's double keyline and the three curves under the plates */
@keyframes draw{to{stroke-dashoffset:0}}

/* rotating word — locked to the widest phrase, each phrase carrying its own
   full stop, so the hero cannot change height as it cycles */
/* The masking window must be exactly as tall as the line it sits in, with the
   same line-height, so the inner line box coincides with the outer one and the
   rotating word shares the baseline of the text around it. A shorter window
   bottom-aligned in a taller line box is what makes the word sit low. */
/* "businesses with" must stay on the same line as the rotating word: an
   inline-block is a break opportunity of its own, so a non-breaking space
   in front of it is not enough — the pair has to be one nowrap unit. */
.nb{white-space:nowrap}
.swap{display:inline-block;position:relative;overflow:hidden;vertical-align:bottom;block-size:1.75em;line-height:1.75;color:var(--champagne);white-space:nowrap}
.swap__track{display:block;position:relative}
.swap__word{display:block;white-space:nowrap;position:absolute;inset-block-start:0;inset-inline-start:0;transform:translateY(110%);opacity:0}
.swap__word.is-in{transform:translateY(0);opacity:1;transition:transform .52s var(--ease),opacity .34s ease}
.swap__word.is-out{transform:translateY(-110%);opacity:0;transition:transform .52s var(--ease),opacity .34s ease}

/* ==========================================================================
   THE EXPERIENCE — copy holds the left, the landscape film holds the right
   ========================================================================== */
.experience__grid{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.1fr);
  gap:var(--sp-xl);align-items:center;
}
/* Three lines, always — the same rule the hero headline keeps. The size is
   capped against the COLUMN rather than the viewport, so a narrow column gets
   a smaller headline instead of a fourth line, and text-wrap:balance evens
   whatever lines are left. */
.experience__copy{container-type:inline-size}
.experience__copy .section-head{
  margin-block:var(--sp-s);
  font-size:min(var(--t-2), 8.6cqi);text-wrap:balance;
}
.experience__copy .body{margin-block-end:0}


/* ---------------------------------------------------- the masthead ---
   The section had a small uppercase label on a hairline, which is correct for
   an eyebrow and far too quiet for the door into the work. This is an engraved
   plate instead: a champagne diamond, the name in the display face in caps on
   wide tracking, and a tapered double rule running out either side — the long
   line over a shorter one, the way a rule is cut on an invitation.

   It is set at the same size as the gathering names below and still reads
   above them, because caps and tracking do the ranking rather than scale. */
.masthead{text-align:center;margin-block-end:var(--sp-l)}
.masthead__gem{
  display:block;inline-size:0.4375rem;block-size:0.4375rem;
  background:var(--champagne);transform:rotate(45deg);
  margin-inline:auto;margin-block-end:var(--sp-s);
}
.masthead__title{
  display:flex;align-items:center;justify-content:center;gap:clamp(1rem,3vw,2.25rem);
  font-family:var(--font-display);font-weight:400;
  font-size:var(--t-2);line-height:1.1;
  font-variation-settings:"opsz" 13,"wght" 420;
}
.masthead__title > span{
  text-transform:uppercase;letter-spacing:0.1em;
  /* caps tracked this wide leave a hole after the last letter; pull it back */
  margin-inline-end:-0.1em;
  white-space:nowrap;
}
/* the tapered double rule: a full-width hairline over a shorter one */
.masthead__title::before,.masthead__title::after{
  content:"";flex:1 1 0;max-inline-size:9rem;block-size:0.3125rem;
  background:
    linear-gradient(var(--champagne),var(--champagne)) 50% 0 / 100% 1px no-repeat,
    linear-gradient(var(--champagne),var(--champagne)) 50% 100% / 52% 1px no-repeat;
}
.masthead__note{
  font-family:var(--font-label);font-weight:300;font-size:var(--t--1);
  letter-spacing:0.04em;line-height:1.5;color:var(--ink-60);
  margin-block-start:var(--sp-s);text-wrap:balance;
}

/* ==========================================================================
   THE INLINE PLAYER

   Every film on the site is one of these, the hero included. Nothing opens a
   lightbox any more: the poster, the cue and the video are the same box, and
   pressing the cue starts the film in place at the size it was already being
   shown. preload="none" means a frame of it is a poster image and nothing
   else until somebody actually asks for it.
   ========================================================================== */
.film{position:relative;background:var(--midnight);overflow:hidden;aspect-ratio:9/16;container-type:size}
.film--wide{aspect-ratio:16/9}
.film__poster{
  display:block;inline-size:100%;block-size:100%;object-fit:cover;background:var(--ink-black);
  /* held back a little until it is asked for, so the copy leads and the cue
     reads cleanly over it */
  filter:brightness(.82) saturate(.94);
  transition:filter .5s ease,opacity .35s ease;
}
.film:hover .film__poster{filter:brightness(.9) saturate(1)}
.film.is-playing .film__poster{opacity:0}

/* ------------------------------------------------ the Vimeo player ---
   The films are hosted on Vimeo. Nothing but a poster image is in the page
   until the cue is pressed — the iframe is built on the click, which is what
   keeps twenty-six films off the initial load entirely.

   The iframe is given the FILM's own aspect ratio (--ar) and then scaled to
   cover its tile, because a player letterboxes its video to the box it is
   handed: matching the box to the source first means there are no bars, and
   covering after means the tile is filled exactly as the old <video> did. */
.film__player{
  position:absolute;inset:0;z-index:1;
  /* The player is the tile, exactly — and VIMEO does the fitting inside it.
     It never crops: whatever shape the film really is, the whole frame is
     shown and the difference reads as midnight, which is the tile's own
     ground. We used to size this box to the source's ratio and cover the
     tile with it, which filled the tile perfectly when the declared ratio
     was right and quietly cut the sides or the ends off a film when it was
     not. A ratio written down by hand is a ratio that will be wrong one day;
     this needs no ratio at all. */
  inline-size:100%;block-size:100%;
}
.film__player iframe{position:absolute;inset:0;inline-size:100%;block-size:100%;border:0}

/* While a film plays, its iframe swallows every pointer event, so the row
   underneath cannot be dragged. This takes the top of the tile back: a
   transparent layer that turns a drag into a row scroll and a tap into
   play/pause. The bottom of the tile is left alone, which is where Vimeo
   keeps its own controls. */
/* The mouse's grab handle on a playing film — a band across the middle of the
   tile, and only the middle. Vimeo draws its own buttons along the top of the
   player and its control bar along the bottom; a shield that reached either
   edge would swallow the clicks meant for them, which is a worse fault than a
   row that is slightly harder to drag. */
.film__drag{
  position:absolute;inset-inline:0;
  inset-block-start:clamp(2.5rem, 16%, 5rem);
  inset-block-end:38%;
  z-index:2;cursor:grab;touch-action:pan-y;
}
.film__drag.is-grabbing{cursor:grabbing}
/* for the length of a drag only: no iframe may take the pointer */
.is-film-dragging .film__player{pointer-events:none}
.is-film-dragging{user-select:none}
/* the champagne keyline the brand uses everywhere it frames something */
.film__frame{
  position:absolute;inset:0.5rem;border:1px solid rgba(209,172,107,0);
  transition:border-color .45s ease;pointer-events:none;z-index:2;
}
.film:hover .film__frame{border-color:rgba(209,172,107,.85)}
/* the hero's frame is always drawn: it is the only film on a dark ground and
   without a keyline it reads as a hole cut in the band rather than an object */
.film--onDark .film__frame{border-color:rgba(209,172,107,.4)}
.film.is-playing .film__frame{border-color:transparent}

/* The cue. It covers the whole frame, so the film is one large target rather
   than a small button somebody has to aim at. */
.film__cue{
  position:absolute;inset:0;z-index:3;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:var(--sp-s);cursor:pointer;border:0;padding:var(--sp-s);
  background:linear-gradient(180deg,rgba(8,10,16,.1),rgba(8,10,16,.42));
  transition:opacity .35s ease,background .4s ease;
}
.film:hover .film__cue{background:linear-gradient(180deg,rgba(8,10,16,.18),rgba(8,10,16,.56))}
.film.is-playing .film__cue{opacity:0;pointer-events:none}
.film__glyph{
  flex:0 0 auto;inline-size:3.25rem;aspect-ratio:1;border:1px solid rgba(247,244,239,.8);
  display:grid;place-items:center;background:rgba(17,20,29,.3);
  transition:background .35s ease,border-color .35s ease,transform .5s var(--ease);
}
.film__glyph svg{inline-size:0.875rem;block-size:1rem;fill:var(--ivory);transition:fill .3s ease}
.film:hover .film__glyph{background:var(--champagne);border-color:var(--champagne);transform:scale(1.08)}
.film:hover .film__glyph svg{fill:var(--midnight)}
.film__label{
  font-family:var(--font-label);font-weight:500;font-size:var(--t-label);
  letter-spacing:var(--track-label);text-transform:uppercase;
  color:var(--ivory);text-align:center;text-shadow:0 1px 10px rgba(8,10,16,.6);
}

/* ==========================================================================
   THE STRIP — a row of films you drag or swipe

   No buttons and no pagination: the row scrolls. Touch and trackpad get that
   for free; a mouse gets click-and-drag, which is why the cursor is a grab
   hand. The mask on the trailing edge is the affordance — a film half in
   frame says there is more of the row without a word of instruction.
   ========================================================================== */
.strip{
  --tile:clamp(13rem, 21vw, 17.5rem);
  display:flex;gap:var(--sp-xs);
  overflow-x:auto;overscroll-behavior-x:contain;
  scroll-snap-type:x proximity;scroll-padding-inline:var(--gutter);
  scrollbar-width:none;-ms-overflow-style:none;
  padding-block:1px;cursor:grab;
  /* bleed to the page edge so a film can sit half in frame */
  margin-inline:calc(var(--gutter) * -1);padding-inline:var(--gutter);
}
.strip::-webkit-scrollbar{display:none}
.strip.is-dragging{cursor:grabbing;scroll-snap-type:none}
/* the glide that follows a drag; snapping stays out of its way until it lands */
.strip.is-settling{scroll-snap-type:none}
.strip.is-dragging .film__cue{pointer-events:none}
.strip > .film{
  flex:0 0 auto;scroll-snap-align:start;
  inline-size:var(--tile);
}
/* a dragged strip must not hand the browser a native image drag instead */
.strip img,.strip video{user-select:none;-webkit-user-drag:none}

/* ==========================================================================
   THE EVENTS — an index of gatherings, each one a strip

   The name and its leader rule head the row; the films run underneath at a
   size you can actually watch, and the row scrolls sideways. Only the list of
   gatherings is folded — three show, all six on request — and that control is
   a bordered button, not another tracked-caps line, so it cannot be mistaken
   for the section titles around it.
   ========================================================================== */
.events{margin-block-start:var(--sp-xl)}

/* Three gatherings across. Each column is a name, a rule and one film at the
   size it is watched, with the next film of that event showing at the edge —
   a fifth of it, which is enough to say "this row moves" without a control.
   Six columns when the list is open, in two rows of three. */
.index{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:var(--sp-l) var(--sp-m);
}
/* display:contents, so the hidden three drop into the same grid rather than
   forming a second one under it */
.index__more{display:none}
.index.is-open .index__more{display:contents}

/* The heading reserves two lines whether or not it needs them, so the films
   in a row all start at the same height. Names are editorial and will not all
   be the same length; the films lining up is not negotiable. The rule sits on
   the first line rather than centred, so it stays put when a name wraps. */
.ev__head{display:flex;align-items:flex-start;gap:var(--sp-xs);margin-block-end:var(--sp-2xs);min-block-size:2.3em}
.ev__name{
  font-family:var(--font-display);font-weight:400;
  font-size:var(--t-1);line-height:1.15;
  font-variation-settings:"opsz" 11,"wght" 430;
  transition:color .4s ease;text-wrap:balance;
}
.ev__head{font-size:var(--t-1)}
.ev__name{font-size:1em}
/* the leader rule runs from the name out to the edge of its own column */
.ev__lead{flex:1 1 1.5rem;min-inline-size:1.5rem;block-size:1px;margin-block-start:0.57em;background:var(--stone);transition:background .45s ease}
.ev:hover .ev__lead,.ev:focus-within .ev__lead{background:var(--champagne)}
.ev:hover .ev__name,.ev:focus-within .ev__name{color:var(--champagne-ink)}

/* The record of the room, under the name. Two figures — how many came and
   what the house was worth — set as a small ruled block: the figure in the
   display face, its name beneath in tracked caps.

   It is evidence, not a headline. The figures are deliberately SMALLER and
   LIGHTER than the event name above them, because the name is what a reader
   is scanning for and the numbers are what makes them stop; a bold number
   competes with the name instead of supporting it. They sit side by side in
   a flex row, so the one event with a single figure simply shows one. */
.ev__stats{
  /* The figures sit beside each other rather than spreading across the card:
     a stretched grid put half a column of empty space between the guest count
     and the property value, which read as two unrelated numbers. */
  display:flex;flex-wrap:wrap;
  gap:var(--sp-xs) var(--sp-m);
  margin-block-end:var(--sp-s);padding-block-start:0.7rem;
  border-block-start:1px solid var(--stone);
  transition:border-color .45s ease;
}
.ev:hover .ev__stats,.ev:focus-within .ev__stats{border-block-start-color:var(--champagne)}
.ev__stats li{display:flex;flex-direction:column;gap:0.15rem;min-inline-size:0}
.ev__stat-v{
  font-family:var(--font-display);font-weight:400;font-size:var(--t-0);
  font-variation-settings:"opsz" 11,"wght" 400;
  line-height:1.05;color:var(--midnight);font-variant-numeric:tabular-nums;
}
.ev__stat-l{
  font-family:var(--font-label);font-weight:500;font-size:var(--t-label);
  letter-spacing:var(--track-label);text-transform:uppercase;
  line-height:1.3;color:var(--ink-40);
}

/* Inside a column the strip does not bleed to the page edge: the film is a
   fixed share of the column, so the sliver of the next one is the same width
   on every screen and on every event. */
.ev .strip{
  /* 78% of the column, capped: past 20rem a vertical film stops being a film
     you watch in a row and starts being a wall. */
  --tile:min(78%, 20rem);
  margin-inline:0;padding-inline:0;scroll-padding-inline:0;
}

/* ------------------------------------------------- the scroll cue ---
   No words. Under each row runs the row's own scrollbar, drawn the way the
   rest of the page is drawn: a stone track the width of the column and a
   champagne thumb whose LENGTH is how much of the row you can see and whose
   POSITION is where you are in it. Eight films give a short thumb, two give a
   long one — the control states the size of the thing before it is touched.

   Until the row is moved the thumb travels the track and returns, and a pair
   of chevrons breathes beside it. Both stop the moment it is moved, and from
   then on the thumb is simply the truth about that row. */
.ev__hint{
  display:flex;align-items:center;gap:0.75rem;
  margin-block-start:var(--sp-s);
}
.ev__hint--c{max-inline-size:26rem;margin-inline:auto;margin-block-start:var(--sp-m)}
/* The rail is a real control, not a picture of one. It is 2px of ink with a
   finger-sized invisible hit area around it, so it can be grabbed and dragged
   on a trackpad or a phone; `pan-y` keeps the page itself scrollable through
   it, while horizontal gestures come to us. */
.ev__track{
  position:relative;flex:1 1 auto;block-size:2px;background:var(--stone);
  cursor:grab;touch-action:pan-y;
}
.ev__track::before{content:"";position:absolute;inset-block:-0.85rem;inset-inline:-0.25rem}
.ev__track:hover .ev__thumb{block-size:6px;inset-block:-2px}
.ev__track.is-grabbing{cursor:grabbing}
.ev__track.is-grabbing .ev__thumb{block-size:6px;inset-block:-2px}
.ev__thumb{
  position:absolute;inset-block:-1px;inset-inline-start:0;
  inline-size:var(--w,36%);block-size:4px;background:var(--champagne);
  transform:translateX(var(--x,0));
  transition:block-size .18s ease,inset-block .18s ease;
}
/* The demonstration runs ONCE, when the section arrives, and then hands the
   rail over to the row. Repeating it made the page look like it was waiting
   for something; shown once it reads as an instruction and then gets out of
   the way. */
.is-in .ev__thumb{animation:thumb-travel 3.2s var(--ease) .9s 1}
/* the travel is expressed against the thumb's own width, so a long thumb
   moves a short way and a short thumb moves a long way — exactly as the real
   scroll would */
@keyframes thumb-travel{
  0%,10%   {transform:translateX(0)}
  45%,58%  {transform:translateX(calc((100cqw - 100%) * 1))}
  95%,100% {transform:translateX(0)}
}
.ev__track{container-type:inline-size}
.ev__chev{display:flex;flex:0 0 auto;opacity:.35}
.is-in .ev__chev{animation:chev-breathe 2.3s ease-in-out .9s 2;animation-fill-mode:both}
.ev__chev svg{
  inline-size:0.9rem;block-size:0.5625rem;overflow:visible;
  fill:none;stroke:var(--champagne);stroke-width:1.4;stroke-linecap:round;stroke-linejoin:round;
}
@keyframes chev-breathe{
  0%,100%{opacity:.35;transform:translateX(0)}
  50%    {opacity:1;  transform:translateX(0.2rem)}
}
/* moved: the demonstration ends and the thumb tells the truth */
.ev__hint.is-done .ev__thumb{animation:none;transition:transform .1s linear,inline-size .3s ease}
.ev__hint.is-done .ev__chev{animation:none;opacity:0;transition:opacity .4s ease}

/* The nudge. The row eases left and settles back, the way it would if a thumb
   had pushed it — enough to show the next film move, not enough to be a
   carousel. It happens ONCE, when the section arrives, and never again: a row
   that keeps twitching reads as a fault rather than as an invitation. It
   pauses under the cursor so it never shifts under a click, and it is off
   entirely while the row is being dragged. */
@keyframes strip-nudge{
  0%   {transform:translateX(0)}
  26%  {transform:translateX(-1.15rem)}
  62%  {transform:translateX(-1.15rem)}
  100% {transform:translateX(0)}
}
.is-in .strip.can-scroll:not(.is-scrolled) > .film{
  animation:strip-nudge 2.3s var(--ease) 1.1s 1;
}
.strip:hover > .film{animation-play-state:paused}
/* nothing animates under a hand that is holding the row */
.strip.is-dragging > .film{animation:none}

.events__more{margin-block-start:var(--sp-l);text-align:center}

/* the guests' own films: one line, on the deep band, nothing to press open */
/* ==========================================================================
   THE KINDS OF DAY — a row of tags under the opening claim

   The headline says "more than another event"; this says what kind of event.
   Squared rather than rounded on purpose: nothing else on the site carries a
   radius, and a row of round tags would read as borrowed from elsewhere. The
   last item is not a tag — no border, dimmer, italic — because it is a note
   about the list rather than another item in it.
   ========================================================================== */
.kinds{
  display:flex;flex-wrap:wrap;justify-content:center;align-items:center;
  gap:0.7rem 0.75rem;margin-block-start:var(--sp-l);
}
.kinds li{
  font-family:var(--font-label);font-weight:500;font-size:var(--t-label);
  letter-spacing:var(--track-label);text-transform:uppercase;line-height:1;
  color:var(--midnight);border:1px solid var(--stone);
  padding:0.72rem 1.15rem;
  transition:border-color .35s ease,color .35s ease,background .35s ease;
}
.kinds li:hover{border-color:var(--champagne);color:var(--champagne-ink);background:var(--ivory)}
/* the type selector in `.kinds li` outranks a bare class, so this one has to
   carry both to win — otherwise the note renders in tracked capitals like the
   tags it is meant to sit apart from */
.kinds li.kinds__more{
  border:0;background:none;padding:0;
  color:var(--midnight);text-transform:none;letter-spacing:0;
  font-family:var(--font-body);font-weight:400;font-style:italic;
  font-size:var(--t--1);line-height:1.4;
}
.kinds li.kinds__more:hover{color:var(--midnight);background:none;border-color:transparent}
@media (max-width: 32rem){
  .kinds{gap:0.55rem}
  .kinds li{padding:0.62rem 0.85rem}
}

/* ==========================================================================
   WHAT WE HANDLE — the work, set as a spec sheet

   Seven rows on one hairline grid: the number and the name hold the left,
   the plain list holds the right. Not an accordion, because the FAQ directly
   below is one and two in a row read as a page that is hiding from you. This
   is meant to be read at a glance, without being opened.
   ========================================================================== */
.svc__head{text-align:center;margin-block-end:var(--sp-l)}
.svc__intro{margin-inline:auto;color:var(--ink-60)}
.svc{
  /* An asymmetric mosaic, not a table. Seven spans across twelve columns,
     arranged so no two rows break in the same place — the eye is given a
     reason to travel down the section instead of scanning a column of
     identical cells. Every card is a photograph first and a caption second,
     which is the honest order: the proof of this work is what it looked
     like, and we have the pictures. */
  max-inline-size:84rem;margin-inline:auto;
  display:grid;grid-template-columns:repeat(12,minmax(0,1fr));
  gap:clamp(0.75rem, 1.4vw, 1.25rem);
}
.svc__card:nth-child(1){grid-column:span 7}
.svc__card:nth-child(2){grid-column:span 5}
.svc__card:nth-child(3){grid-column:span 4}
.svc__card:nth-child(4){grid-column:span 4}
.svc__card:nth-child(5){grid-column:span 4}
.svc__card:nth-child(6){grid-column:span 5}
.svc__card:nth-child(7){grid-column:span 7}

.svc__card{
  position:relative;overflow:hidden;isolation:isolate;
  min-block-size:clamp(20rem, 29vw, 29rem);
  background:var(--midnight);
  display:flex;
}
.svc__shot{position:absolute;inset:0;margin:0;overflow:hidden;z-index:0}
.svc__shot img{
  inline-size:100%;block-size:100%;object-fit:cover;display:block;
  transition:transform 1.4s var(--ease), filter .7s ease;
  filter:saturate(.9) contrast(1.02);
}
/* the wash is what makes seven different photographs read as one set: they
   are all pulled down into Midnight, and only the picture's own light gets
   through */
.svc__wash{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    linear-gradient(180deg, rgba(17,20,29,.66) 0%, rgba(17,20,29,.16) 30%, rgba(17,20,29,.66) 62%, rgba(17,20,29,.95) 100%);
  transition:opacity .6s ease;
}
.svc__key{
  position:absolute;inset:0.85rem;z-index:2;pointer-events:none;
  border:1px solid rgba(209,172,107,0);
  transition:border-color .6s ease, inset .6s var(--ease);
}
.svc__face{
  position:relative;z-index:3;inline-size:100%;
  display:flex;flex-direction:column;justify-content:space-between;
  padding:clamp(1.25rem, 2.2vw, 2rem);
  color:var(--ivory);
}
.svc__n{
  font-family:var(--font-display);font-weight:400;
  font-size:var(--t-1);line-height:1;
  font-variation-settings:"opsz" 11,"wght" 400;
  font-variant-numeric:tabular-nums;
  color:var(--champagne);opacity:.8;
  transition:opacity .5s ease;
}
.svc__t{margin:0;color:var(--ivory);text-wrap:balance}
.svc__lead{
  margin-block-start:0.5rem;
  font-size:var(--t--1);line-height:1.6;color:var(--on-dark);
  max-inline-size:38ch;
}

/* The detail opens on the card rather than living on it. A list of four
   under every one of seven photographs is a wall of small type; held back
   until the card is asked for, the section reads as seven pictures and
   opens into a spec sheet exactly where the visitor is looking. */
/* three children — name, lead, list — so three tracks, and it is the LAST
   that is held at zero. Declaring two leaves the list in an implicit auto
   row, which is the whole block sitting mid-card with its detail already
   open behind an overflow:hidden. */
.svc__foot{display:grid;grid-template-rows:auto auto 0fr;transition:grid-template-rows .65s var(--ease)}
.svc__list{
  overflow:hidden;min-block-size:0;
  opacity:0;transition:opacity .4s ease;
}
.svc__list li{
  position:relative;padding-inline-start:1rem;
  font-size:var(--t-label);line-height:1.5;color:var(--on-dark);
  margin-block-start:0.38rem;
}
.svc__list li:first-child{margin-block-start:var(--sp-xs)}
.svc__list li::before{
  content:"";position:absolute;inset-inline-start:0;inset-block-start:0.56em;
  inline-size:0.3rem;block-size:0.3rem;background:var(--champagne);
  transform:rotate(45deg);
}

.svc__card:hover .svc__foot,
.svc__card:focus-within .svc__foot{grid-template-rows:auto auto 1fr}
.svc__card:hover .svc__list,
.svc__card:focus-within .svc__list{opacity:1;transition-delay:.14s}
.svc__card:hover .svc__shot img,
.svc__card:focus-within .svc__shot img{transform:scale(1.06);filter:saturate(1) contrast(1)}
.svc__card:hover .svc__key,
.svc__card:focus-within .svc__key{border-color:rgba(209,172,107,.7);inset:0.6rem}
/* the numeral steps back as the detail opens: at full strength it sits
   behind the title of a card whose copy has just grown up the frame */
.svc__card:hover .svc__n,
.svc__card:focus-within .svc__n{opacity:.3}
.svc__card:hover .svc__wash,
.svc__card:focus-within .svc__wash{opacity:.92}

/* THE ENTRANCE. One move, not four: the card settles into place while its
   photograph comes down out of an oversize crop, the way a lens racks into
   focus. No hairline sweeping the width, no list items arriving one after
   another — those read as effects. This reads as the picture arriving. */
.js .svc__card{opacity:0;transform:translate3d(0, 2rem, 0)}
.js .svc__card .svc__shot img{transform:scale(1.18)}
.js .svc__card.is-in{
  opacity:1;transform:none;
  transition:opacity 1s ease var(--d, 0ms), transform 1.1s var(--ease) var(--d, 0ms);
}
.js .svc__card.is-in .svc__shot img{
  transform:scale(1);
  transition:transform 1.9s var(--ease) var(--d, 0ms), filter .7s ease;
}
/* the stagger runs along each row of the mosaic, not down the whole list */
.svc__card:nth-child(2),.svc__card:nth-child(4),.svc__card:nth-child(7){--d:110ms}
.svc__card:nth-child(5){--d:220ms}

/* ---- the closing line ---------------------------------------------------
   The seven cards are the work we are asked for most, not a closed list, so
   the mosaic ends on the same note the pillar lists do: a quiet italic line,
   centred under the grid, in the band's own ink rather than a heading colour.
   It is a sentence, not an eighth card — it must not read as something to
   click.
   ------------------------------------------------------------------------ */
.svc__more{
  margin-block-start:var(--sp-l);margin-block-end:0;text-align:center;
  font-family:var(--font-body);font-style:italic;
  font-size:var(--t-0);color:var(--ink-60);letter-spacing:0;
}
.svc__more::before{
  content:"";display:block;inline-size:2.5rem;block-size:1px;
  margin:0 auto var(--sp-s);background:var(--champagne);opacity:.5;
}
@media (max-width: 46rem){
  .svc__more{margin-block-start:var(--sp-m);font-size:var(--t--1)}
}

/* ---- tablet: two across, then the mosaic gives up its asymmetry -------- */
@media (max-width: 62rem){
  .svc__card:nth-child(n){grid-column:span 6}
  .svc__card{min-block-size:clamp(17rem, 34vw, 22rem)}
}

/* ---- no hover: the card comes apart ------------------------------------
   The trigger here is (hover: none), not a width. A tablet at 820px is a
   touch device with no pointer: on a width rule it would keep the desktop
   card and its detail would be unreachable — four bullets per service that
   nobody on an iPad could ever open. So the split follows the INPUT, not the
   screen. The photograph keeps only its numeral, and the name and the detail
   sit below it in ink on the band, always open. Nothing has to be tapped to
   find, and white type never has to hold up over a busy frame.
   ------------------------------------------------------------------------ */
@media (max-width: 46rem){
  .svc{grid-template-columns:minmax(0,1fr);gap:var(--sp-l)}
  .svc__card:nth-child(n){grid-column:span 1;--d:0ms}
}
@media (hover: none){
  .svc{gap:var(--sp-l)}
  .svc__card{display:block;min-block-size:0;background:transparent;overflow:visible}
  .svc__shot{position:relative;aspect-ratio:16/10;overflow:hidden}
  .svc__wash{
    inset-block-end:auto;aspect-ratio:16/10;
    background:linear-gradient(180deg, rgba(17,20,29,.62) 0%, rgba(17,20,29,.10) 46%, rgba(17,20,29,.22) 100%);
  }
  .svc__key{inset:0.6rem;inset-block-end:auto;aspect-ratio:16/10;border-color:rgba(209,172,107,.38)}
  .svc__face{display:contents}
  .svc__n{
    position:absolute;z-index:3;
    inset-block-start:clamp(1rem, 4vw, 1.5rem);inset-inline-start:clamp(1rem, 4vw, 1.5rem);
    opacity:1;
  }
  .svc__foot{display:block;padding-block-start:var(--sp-s)}
  /* the lead moved up to reading size, so the name has to move up with it or
     the card loses its heading — 21px over 20.5px is not a hierarchy */
  .svc__t{color:var(--midnight);font-size:var(--t-2)}
  .svc__lead{color:var(--ink-60);max-inline-size:46ch}
  .svc__list{opacity:1;overflow:visible}
  /* on the desktop card these sit inside a hover reveal, where a small size
     reads as a detail line under the name. Here the card has come apart and
     the list is just text on the band — at --t-label it was 13px, which is
     caption size, not reading size. The lead moves up with it so the two do
     not end up level. */
  .svc__lead{font-size:var(--t-0);line-height:1.6}
  .svc__list li{
    color:var(--ink-60);font-size:var(--t--1);line-height:1.5;
    margin-block-end:0.4rem;
  }
  .svc__list li:first-child{margin-block-start:var(--sp-s)}
}

/* ==========================================================================
   PARTNERS — a measured wall, four to a row

   Eight marks of eight different shapes cannot be packed into one line: they
   bunch, the gaps between them read as accidental, and at the widths where the
   line wraps one mark is left alone on a row of its own. So the wall is a grid
   instead — each mark gets a cell of exactly the same size, centred in it, and
   the column count only ever halves (4 → 2), so a row is never left with an
   orphan. The dividers are gone with the line; even spacing separates them now.
   ========================================================================== */
/* the marks close the opening block of section two, on their own hairline,
   between the film and the gatherings */
/* the marks sit in their own band between two hairlines: one closes the
   block above them, one opens Signature Experiences below */
.partners{
  margin-block-start:var(--sp-l);
  padding-block:var(--sp-l);
  border-block:1px solid var(--stone);
}
.partners__inner{display:grid;justify-items:center;gap:var(--sp-m)}
.partners__label{
  color:var(--ink-60);display:flex;align-items:center;gap:0.9rem;
}
.partners__label::before,.partners__label::after{content:"";inline-size:1.5rem;block-size:1px;background:var(--champagne)}
.partners__row{
  /* One knob for the whole wall. The optical heights below are relative to
     it, so dropping to two columns can scale every mark up together without
     disturbing the balance between them. */
  --k:1;
  inline-size:100%;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  column-gap:var(--sp-m);row-gap:var(--sp-l);
}
/* one cell, one height: the marks share a box rather than each sitting at
   whatever height its own artwork happens to be */
.partners__row li{display:grid;place-items:center;block-size:calc(3.4rem * var(--k));inline-size:100%}
.partners__row img{
  max-block-size:calc(var(--h,1.5rem) * var(--k));
  max-inline-size:min(92%, calc(9.5rem * var(--k)));
  inline-size:auto;block-size:auto;object-fit:contain;
  opacity:.82;transition:opacity .35s ease;
}
.partners__row img:hover{opacity:1}

/* Optical sizing, not mathematical. Every source file is 180px tall, so equal
   heights would make a single-line wordmark tower over a stacked lockup and a
   two-line mark shrink to nothing. These are set by eye, mark by mark, so the
   eight read as one weight across the wall — the numbers will look uneven,
   which is the point; matching them is what makes a logo wall look wrong. */
.partners__row img[data-logo="10x-health"]{--h:1.375rem}
.partners__row img[data-logo="ag1"]{--h:1.875rem}
.partners__row img[data-logo="im8"]{--h:1.5rem}
.partners__row img[data-logo="mph-club"]{--h:1.625rem}
.partners__row img[data-logo="house-of-wellness"]{--h:3.125rem}
.partners__row img[data-logo="hotel-collection"]{--h:2rem}
.partners__row img[data-logo="pura-vida"]{--h:2.125rem}
.partners__row img[data-logo="super-luxury-group"]{--h:2.375rem}

/* ==========================================================================
   THE MODEL — three pillars, told one at a time

   The old layout set the three side by side and let the eye choose. That is
   a diagram, not an argument. Here the section takes the scroll for the
   length of its track and spends it: each pillar arrives centred, steps
   aside into its column, and opens a film in the space it has just left.
   Scroll on and the film wipes shut across the frame, the pillar lifts
   away, and the next one walks on. Three pillars, three films, one gesture
   repeated — the repetition is what makes it read as a system rather than
   as three unrelated flourishes.

   EVERY movement below is a function of two numbers per pillar, which
   site.js writes to the element each frame:

     --enter  0 → 1 as the pillar walks on
     --exit   0 → 1 as it leaves

   Nothing else is animated, there are no transitions to fight the scroll,
   and retiming the whole sequence is a matter of editing the calc()s here.

   Without JavaScript the track has no height, the stage does not stick, and
   the three pillars stack as ordinary articles with their poster frames —
   the section still says what it has to say, it just does not perform.
   ========================================================================== */
.model{padding-block:0}
.model__track{position:relative}
/* A pillar used to get about one screen of scroll, of which the walk-on was
   a third — roughly 240 pixels. One flick of a trackpad is more than that,
   so a single gesture threw the whole section forward and the visitor never
   felt in control of it. At 170svh a pillar gets nearly two screens and its
   walk-on takes over 400 pixels: the same choreography, spread across enough
   distance to be steered rather than triggered. */
.pillars-on .model__track{block-size:calc(100svh + 3 * 170svh)}

.model__stage{
  display:grid;grid-template-rows:auto minmax(0,1fr) auto;
  /* three things share one screen — the title, the pillar, the rail — and
     each needs air around it or the stage reads as a crowded slide. The gaps
     are deliberately larger than the section rhythm elsewhere on the page. */
  gap:clamp(1.5rem, 4svh, 3rem);
  padding-block:calc(var(--nav-h) + var(--sp-xs)) var(--sp-l);
  padding-inline:var(--gutter);
}
.pillars-on .model__stage{
  position:sticky;inset-block-start:0;
  block-size:100svh;
  /* overflow:hidden makes this a SCROLL CONTAINER — it has no overflow to
     scroll, but the browser still treats a gesture over it as belonging to
     it, and Safari then refuses to chain that gesture on to the page: the
     visitor puts the pointer on the pinned stage and the site stops dead.
     overflow:clip crops exactly the same way without creating a scroll
     container at all, so nothing can be trapped. hidden stays as the
     fallback for the browsers that predate clip. */
  overflow:hidden;
}
@supports (overflow: clip){
  .pillars-on .model__stage{overflow:clip}
}
.model__stage > *{inline-size:100%;max-inline-size:var(--maxw);margin-inline:auto;position:relative;z-index:1}

/* ---- the masthead ------------------------------------------------------
   It opens as the section's title, centred on an empty stage, and is then
   lifted and set down small at the top for the rest of the sequence. The
   lift is --head, written by the script. */
.model__head{text-align:center;max-inline-size:45rem}
/* this section never receives .is-in — the stage is its own entrance — so
   the rule is simply drawn rather than waiting for one */
.pillars-on .model__head .draw-rule{transform:scaleX(1)}
/* The title is SET at its docked size and scaled UP for the opening, never
   the other way round. A transform does not reflow, so a headline set large
   and shrunk to 0.6 still reserves its full height in the grid — sixty-odd
   pixels of dead layout above the pillar for the whole sequence, which is
   what was pushing the copy down the stage. Set small and scaled up, the
   row only ever reserves what the docked title actually needs. */
.pillars-on .model__head{
  transform:translate3d(0, calc((1 - var(--head, 0)) * 30svh), 0)
            scale(calc(1.95 - 0.95 * var(--head, 0)));
  transform-origin:50% 0;
}
.model__head .section-head{margin-block:var(--sp-s) 0}
.pillars-on .model__head .section-head{font-size:var(--t-1)}
/* docked, it is a running header and nothing more: the pillar's own numeral
   and the rail carry the position, so the title gets out of their way */
.pillars-on .model__head .section-head{opacity:calc(1 - 0.58 * var(--head, 0))}
.pillars-on .model__head .tick{opacity:calc(1 - var(--head, 0))}
.pillars-on .model__cue{transform:scale(calc(1 / (1.95 - 0.95 * var(--head, 0))))}

.model__cue{
  margin-block-start:var(--sp-m);
  font-family:var(--font-ui);font-size:var(--t-label);
  text-transform:uppercase;letter-spacing:.24em;
  color:var(--on-dark-dim);
  display:none;
}
/* the cue is lifted out of the flow: at opacity zero it was still reserving
   its own height at the top of every pillar for the rest of the sequence */
.pillars-on .model__cue{
  display:block;opacity:calc(1 - var(--head, 0));
  position:absolute;inset-inline:0;inset-block-start:100%;
  margin-block-start:var(--sp-m);pointer-events:none;
}
.model__head{position:relative}
.model__cue span{position:relative;display:inline-block}
.model__cue span::after{
  content:"";position:absolute;inset-block-start:calc(100% + 0.7rem);inset-inline:50% auto;
  inline-size:1px;block-size:1.6rem;background:linear-gradient(var(--champagne), transparent);
  animation:cue-fall 2.2s ease-in-out infinite;
}
@keyframes cue-fall{
  0%,100%{transform:scaleY(.35);transform-origin:top;opacity:.45}
  50%    {transform:scaleY(1);  transform-origin:top;opacity:1}
}

/* ---- the pillars themselves -------------------------------------------- */
.pillars{position:relative;min-block-size:0}
.pillars-on .pillars{block-size:100%}

.pillar{
  /* Centred is right again now the masthead reserves only what it shows:
     with the row running the full height of the stage, centring puts a
     little more air below the copy than above it, and the rail keeps its
     clearance. */
  display:grid;align-content:center;
  grid-template-columns:minmax(0,0.9fr) minmax(0,1.1fr);
  gap:clamp(2rem, 6vw, 7rem);
  align-items:center;
}
.pillars-on .pillar{
  position:absolute;inset:0;
  visibility:hidden;pointer-events:none;
  /* live opacity: full once it has walked on, gone once it has left */
  opacity:calc(var(--enter, 0) * (1 - var(--exit, 0)));
}
.pillars-on .pillar.is-live{visibility:visible}
.pillar + .pillar{margin-block-start:var(--sp-xl)}
.pillars-on .pillar + .pillar{margin-block-start:0}

/* the copy column. --slide is how far right it has to sit to read as
   centred on an empty stage; it walks back to zero as the film opens. */
.pillar__copy{--slide:58%}
.pillars-on .pillar__copy{
  transform:translate3d(calc(var(--slide) * (1 - var(--enter, 0))),
                        calc(var(--exit, 0) * -2.4rem), 0);
  will-change:transform;
}
.pillar__n{
  display:block;font-family:var(--font-display);font-size:var(--t-1);
  font-variation-settings:"opsz" 11,"wght" 400;
  color:var(--champagne);opacity:.75;line-height:1;
  margin-block-end:var(--sp-xs);
}
.pillar__rule{display:block;inline-size:2.25rem;block-size:1px;background:var(--champagne);opacity:.55;margin-block-end:var(--sp-s)}
.pillar__title{color:var(--ivory);margin-block-end:var(--sp-xs);font-size:var(--t-2)}
.pillar__lede{font-size:var(--t-0);line-height:1.66;color:var(--on-dark);max-inline-size:34ch}
.pillar__label{
  display:block;margin-block:var(--sp-m) var(--sp-xs);
  font-family:var(--font-ui);font-size:var(--t-label);
  text-transform:uppercase;letter-spacing:.2em;color:var(--on-dark-dim);
}
.pillar__list{display:block;columns:2;column-gap:var(--sp-m)}
.pillar__list li{
  position:relative;padding-inline-start:1rem;
  font-size:var(--t--1);line-height:1.5;color:var(--on-dark);
  margin-block-end:0.42rem;break-inside:avoid;
}
.pillar__list li::before{
  content:"";position:absolute;inset-inline-start:0;inset-block-start:0.62em;
  inline-size:0.32rem;block-size:0.32rem;background:var(--champagne);
  transform:rotate(45deg);opacity:.75;
}
.pillar__list li.pillar__more{
  color:var(--on-dark-dim);font-family:var(--font-body);font-style:italic;
  padding-inline-start:1rem;letter-spacing:0;text-transform:none;
}
.pillar__list li.pillar__more::before{display:none}

/* ---- the film ----------------------------------------------------------
   One rectangle that never moves. The picture inside it is revealed by a
   wipe that runs left to right as the pillar walks on, and closes the same
   way as it leaves — so the three films read as one continuous sweep across
   the section rather than as three separate fades. */
.pillar__film{
  position:relative;margin:0;overflow:hidden;
  block-size:min(44svh, 25rem);
  background:#0C0F16;
}
.pillars-on .pillar__film{
  clip-path:inset(0 calc((1 - var(--enter, 0)) * 100%) 0 calc(var(--exit, 0) * 100%));
}
/* The still is a real lazy <img>, not the video's poster attribute: a poster
   is fetched the moment the page parses, and three of them put half a
   megabyte in front of the first paint for a section two screens down. This
   one waits until it is nearly in view, and is what a visitor without
   JavaScript sees. The film, once it is running, simply covers it. */
.pillar__still{
  position:absolute;inset:0;inline-size:100%;block-size:100%;
  object-fit:cover;display:block;
}
.pillars-on .pillar__still{
  /* Two movements, both written by the scroll. The scale settles as the
     pillar walks on and swells again as it leaves, so the frame is never
     quite at rest; the drift carries it slowly up the panel across the whole
     time it is held. Together they are why a photograph here does not read
     as a photograph — the scroll is doing what a film would have done, and
     the visitor is the one moving it. */
  transform:
    scale(calc(1.10 - 0.09 * var(--enter, 0) + 0.06 * var(--exit, 0)))
    translate3d(0, calc((0.5 - var(--t, 0.5)) * 4.5%), 0);
  will-change:transform;
}
.pillar__scrim{
  position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(100deg, rgba(17,20,29,.55), rgba(17,20,29,0) 42%);
}
.pillar__key{
  position:absolute;inset:0.75rem;pointer-events:none;
  border:1px solid rgba(209,172,107,.42);
}

/* ---- the closing line and the rail -------------------------------------
   The payoff is a single line on an empty field, so it is lifted out of the
   grid and centred on the whole stage: at the foot of the section it would
   read as a caption to nothing. */
.pillars-on .model__sum{
  position:absolute;inset:0;margin:0;pointer-events:none;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  max-inline-size:none;
  opacity:var(--sum, 0);
  transform:translate3d(0, calc((1 - var(--sum, 0)) * 1.4rem), 0);
}

/* The cue does not belong only to the opening. A visitor three screens into
   a pinned section needs to know there is more of it and roughly how much is
   left — without that the section reads as a page that has stopped
   responding. So the numerals become a progress bar and the instruction
   stays with them, bowing out only once the last pillar is on. */
.prail__note{
  display:none;
  margin:0 0 var(--sp-xs);text-align:center;
  font-family:var(--font-ui);font-size:var(--t-label);
  text-transform:uppercase;letter-spacing:.24em;color:var(--on-dark-dim);
}
.pillars-on .prail__note{display:block;opacity:var(--cue, 0)}
.prail__note span{position:relative;display:inline-block}
.prail__note span::after{
  content:"";position:absolute;inset-block-start:50%;inset-inline-start:calc(100% + 0.7rem);
  inline-size:1.1rem;block-size:1px;background:var(--champagne);
  transform-origin:left center;
  animation:cue-slide 2.2s ease-in-out infinite;
}
@keyframes cue-slide{
  0%,100%{transform:scaleX(.3);opacity:.4}
  50%    {transform:scaleX(1); opacity:1}
}

.prail{display:flex;justify-content:center;gap:var(--sp-s);margin:0;padding:0;list-style:none}
.prail li{
  display:flex;align-items:center;gap:0.55rem;
  font-family:var(--font-ui);font-size:var(--t-label);
  letter-spacing:.2em;color:var(--on-dark-dim);
  opacity:.45;transition:opacity .5s ease,color .5s ease;
}
.prail li.is-on{opacity:1;color:var(--champagne)}
.prail i{
  display:block;inline-size:clamp(2.5rem, 8vw, 5.5rem);block-size:2px;
  background:rgba(247,244,239,.16);position:relative;overflow:hidden;
}
.prail i::after{
  content:"";position:absolute;inset:0 auto 0 0;
  inline-size:calc(var(--fill, 0) * 100%);
  background:var(--champagne);
}
.prail{display:none}
.pillars-on .prail{display:flex}

/* ---- tablet: the film goes under the copy, the stage keeps its pin ------ */
@media (max-width: 62rem){
  .pillar{grid-template-columns:minmax(0,1fr);gap:var(--sp-m);align-content:center}
  .pillar__copy{--slide:0%}
  .pillars-on .pillar__copy{
    transform:translate3d(0, calc((1 - var(--enter, 0)) * 2.2rem + var(--exit, 0) * -2.2rem), 0);
  }
  .pillar__film{block-size:min(34svh, 20rem)}
  .pillar__list{columns:2}
}

/* ---- phone: the film IS the stage --------------------------------------
   A phone has no room for a column beside a picture, and a small picture
   under a list is not a wow, it is a thumbnail. So the film goes full bleed
   behind the copy and the wipe reveals the whole screen. */
@media (max-width: 46rem){
  .pillars-on .model__track{block-size:calc(100svh + 3 * 140svh)}
  .pillars-on .pillar{position:absolute;inset:0;display:block}
  /* The film bleeds to the page edges and down past the rail, but NOT up:
     bleeding upward put the picture over the masthead, and a title half
     behind a photograph is not a full-bleed effect, it is a mistake. */
  .pillars-on .pillar__film{
    position:absolute;
    inset-inline:calc(var(--gutter) * -1);
    inset-block:0 -7rem;
    block-size:auto;
  }
  /* On a phone the copy sits ON the picture, and a window blowing out
     behind a line of 13px type is the difference between a list you can
     read and one you squint at. Two washes: one down the frame, one from
     the left where every line of type starts. */
  .pillars-on .pillar__scrim{
    background:
      linear-gradient(180deg, rgba(17,20,29,.82) 0%, rgba(17,20,29,.55) 52%, rgba(17,20,29,.86) 100%),
      linear-gradient(90deg, rgba(17,20,29,.68) 0%, rgba(17,20,29,.16) 80%);
  }
  .pillars-on .pillar__key{inset:var(--sp-xs) var(--sp-xs)}
  .pillars-on .pillar__copy{
    position:relative;z-index:2;
    block-size:100%;display:flex;flex-direction:column;justify-content:flex-start;
    padding-block-start:6svh;
  }
  .pillar__lede{font-size:var(--t--1);max-inline-size:30ch}
  .pillar__label{margin-block:var(--sp-s) var(--sp-2xs)}
  .pillar__list{columns:1}
  .pillar__list li{margin-block-end:0.3rem}
  .prail{gap:var(--sp-xs)}
  .prail i{inline-size:clamp(2rem, 14vw, 4rem)}
}

/* A short phone — an SE, or any phone with its browser chrome showing — has
   about a hundred fewer pixels than the stage assumes, and the list is what
   runs off the bottom. Two columns and a tighter setting bring the whole
   pillar back inside one screen rather than cropping the end of it. */
@media (max-width: 46rem) and (max-height: 46rem){
  /* the type scale compresses on a phone — --t-0 is 20.6px and --t-1 only
     21.1px — so a heading set one step above body copy is not a heading at
     all. Both card names take --t-2, which is the first step that reads as
     one. */
  .pillar__title{font-size:var(--t-1)}
  .pillar__lede{font-size:var(--t--1);line-height:1.5;max-inline-size:34ch}
  .pillar__label{margin-block:var(--sp-xs) var(--sp-2xs)}
  .pillar__list{columns:2;column-gap:var(--sp-s)}
  .pillar__list li{font-size:var(--t-label);margin-block-end:0.2rem;padding-inline-start:0.8rem}
  .pillar__n{margin-block-end:var(--sp-2xs)}
  .pillar__rule{margin-block-end:var(--sp-xs)}
}

/* ---- TOUCH: the takeover comes apart -----------------------------------
   The script does not start the engine when (hover: none) matches, so
   .pillars-on is never set and everything above falls away on its own. What
   is left is this: three articles, each a photograph with its words beneath
   it on the midnight band. No copy over a picture, so nothing depends on a
   scrim holding up over a bright sky; no pinned stage, so a resting thumb
   cannot walk the section forward.

   The rules below are what turns that fallback from merely working into the
   intended layout — picture first, a frame that keeps its proportion instead
   of chasing the viewport, and the scrim reduced to the vignette that seats
   the photograph on the band rather than the wash that used to carry text.
   ------------------------------------------------------------------------ */
@media (hover: none){
  .model__stage{
    gap:var(--sp-m);
    padding-block:var(--sp-xl) var(--sp-xl);
  }
  .model__head{margin-inline:auto}
  /* the tick above the title is a draw-rule, and draw-rules wait for an
     .is-in that this section is never given — on the pinned stage the
     takeover drew it instead, so without the takeover it has to be drawn
     here or the title loses its mark */
  .model__head .draw-rule{transform:scaleX(1)}

  .pillars{display:grid;gap:var(--sp-2xl)}
  .pillar{
    display:grid;grid-template-columns:minmax(0,1fr);
    gap:var(--sp-s);align-content:start;align-items:start;
  }
  .pillar + .pillar{margin-block-start:0}

  /* the photograph leads, the way it does on a service card */
  .pillar__film{
    order:-1;
    block-size:auto;aspect-ratio:16/10;
  }
  .pillar__copy{--slide:0%}

  /* seated, not washed: a soft foot so the frame does not float on the band,
     and nothing across the middle, because no text sits there any more */
  .pillar__scrim{
    background:linear-gradient(180deg, rgba(17,20,29,0) 58%, rgba(17,20,29,.42) 100%);
  }
  .pillar__key{inset:0.6rem}

  .pillar__n{margin-block-end:var(--sp-2xs)}
  .pillar__title{font-size:var(--t-2)}
  .pillar__lede{font-size:var(--t-0);line-height:1.6;max-inline-size:42ch}
  /* These lists are the substance of the section on a phone — they are what
     someone actually reads to find out whether we do their kind of thing —
     and they were set at the size they had when they were captions floating
     over a photograph on a pinned stage. Stacked on the band they are body
     copy, so they are set as body copy: one step up the scale, a single
     column, and leading to match. The lede stays a step above them, so the
     hierarchy is carried by leading and measure rather than by making the
     list small. */
  .pillar__list{columns:1}
  .pillar__list li{
    font-size:var(--t-0);line-height:1.5;
    margin-block-end:0.45rem;padding-inline-start:1.1rem;
  }
  .pillar__list li::before{inset-block-start:0.56em}
  .pillar__label{font-size:var(--t-label);margin-block:var(--sp-m) var(--sp-xs)}

  .model__sum{margin-block-start:var(--sp-xl)}
}
/* two across is still comfortable on a tablet in landscape */
@media (hover: none) and (min-width: 46rem){
  .pillar{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--sp-l);align-items:center}
  .pillar__film{order:0;aspect-ratio:4/3}
  .pillar__list{columns:2}
}


/* A visitor who has asked for less movement gets the section as a plain
   stack: no pin, no wipe, no push. The films keep their poster frames. */
@media (prefers-reduced-motion: reduce){
  .pillars-on .model__track{block-size:auto}
  .pillars-on .model__stage{position:static;block-size:auto;overflow:visible}
  .pillars-on .model__head{transform:none}
  .pillars-on .model__cue{display:none}
  .pillars-on .pillars{block-size:auto}
  .pillars-on .pillar{position:relative;inset:auto;visibility:visible;opacity:1;margin-block-end:var(--sp-xl)}
  .pillars-on .pillar__copy,.pillars-on .pillar__still{transform:none}
  .pillars-on .pillar__film{clip-path:none}
  .pillars-on .model__sum{opacity:1;transform:none}
  .pillars-on .prail{display:none}
}

.model__sum{position:relative}
.model__halo{
  position:absolute;inset-block-start:0;inset-inline-start:50%;
  inline-size:7rem;aspect-ratio:1;translate:-50% -46%;
  border-radius:50%;pointer-events:none;
  background:radial-gradient(circle, rgba(209,172,107,.34), transparent 66%);
  opacity:0;
}
.is-in .model__halo{animation:halo-land 6s ease-out 2.3s infinite}
@keyframes halo-land{
  0%,26%  {opacity:0;scale:.7}
  33%     {opacity:1;scale:1}
  52%,100%{opacity:0;scale:1.25}
}
.is-in .model__gem{animation:gem-land 6s ease-out 2.3s infinite}
@keyframes gem-land{
  0%,26%  {transform:rotate(45deg) scale(1)}
  33%     {transform:rotate(45deg) scale(1.55)}
  55%,100%{transform:rotate(45deg) scale(1)}
}

.model__sum{display:flex;flex-direction:column;align-items:center;gap:var(--sp-xs)}
.model__gem{
  inline-size:0.5rem;block-size:0.5rem;background:var(--champagne);
  transform:rotate(45deg);
}
.model__sum .label{color:var(--champagne)}

/* ==========================================================================
   TESTIMONIALS
   One voice at a time, centred, with the others a click away. A carousel that
   hides its content behind a drag gesture asks the reader to discover it; this
   one shows the whole quote and names its controls. Rotation pauses on hover
   and on focus, and does not start at all under reduced motion.
   ========================================================================== */
.testimonial{text-align:center}
.testimonial__head{margin-block-end:var(--sp-l)}
.testimonial__stage{display:grid;max-inline-size:52rem;margin-inline:auto}
.testimonial__item{grid-area:1/1;opacity:0;visibility:hidden;transform:translateY(0.75rem);transition:opacity .6s ease,transform .7s var(--ease),visibility 0s linear .6s;margin:0}
.testimonial__item.is-on{opacity:1;visibility:visible;transform:none;transition:opacity .7s ease .1s,transform .8s var(--ease) .1s,visibility 0s}
.testimonial__mark{
  display:block;font-family:var(--font-display);
  font-size:clamp(2.75rem,1.6rem + 5vw,5rem);line-height:.72;block-size:.44em;overflow:visible;
  color:var(--champagne);margin-block-end:var(--sp-m);
  font-variation-settings:"opsz" 22,"wght" 400;
}
.quote{font-family:var(--font-display);font-weight:400}
.quote--lead{font-size:var(--t-2);line-height:1.34;font-variation-settings:"opsz" 13,"wght" 400;text-wrap:balance}
.quote__attr{display:block;margin-block-start:var(--sp-m);font-style:normal}
.quote__attr::before{content:"";display:block;inline-size:2.25rem;block-size:1px;background:var(--champagne);margin:0 auto var(--sp-s)}
.quote__name{font-family:var(--font-body);font-size:var(--t--1);line-height:1.5;display:block}
.quote__org{font-family:var(--font-label);font-weight:500;font-size:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--ink-60);display:block;margin-block-start:0.4rem}

.testimonial__controls{display:flex;align-items:center;justify-content:center;gap:var(--sp-m);margin-block-start:var(--sp-l)}
.tctl{
  inline-size:3rem;block-size:3rem;border:1px solid var(--stone);
  display:grid;place-items:center;transition:border-color .25s ease,background .25s ease;
}
.tctl:hover{border-color:var(--midnight);background:var(--midnight)}
.tctl:hover svg{stroke:var(--ivory)}
.tctl svg{inline-size:0.8125rem;block-size:0.8125rem;stroke:var(--midnight);fill:none;stroke-width:1.2;transition:stroke .25s ease}
.tdots{display:flex;align-items:center;gap:0.75rem}
.tdot{
  inline-size:2.5rem;block-size:2.75rem;display:grid;place-items:center;
  font-family:var(--font-label);font-weight:500;font-size:var(--t--1);
  letter-spacing:0.1em;color:var(--ink-60);position:relative;
  transition:color .25s ease;
}
.tdot::after{content:"";position:absolute;inset-block-end:0.55rem;inline-size:1.25rem;block-size:1px;background:var(--stone);transition:background .3s ease,inline-size .3s var(--ease)}
.tdot:hover{color:var(--midnight)}
.tdot.is-on{color:var(--midnight)}
.tdot.is-on::after{background:var(--champagne);inline-size:1.75rem}

/* ==========================================================================
   BEFORE YOU APPLY — the questions, on hairlines

   Built on <details>, so it opens and closes with no JavaScript at all and
   stays keyboard- and screen-reader-correct for free. The marker is drawn in
   CSS rather than using the browser's triangle, and the native one is removed
   on both engines.
   ========================================================================== */
.faq__head{text-align:center;margin-block-end:var(--sp-l)}
.faq{max-inline-size:46rem;margin-inline:auto;border-block-start:1px solid var(--stone)}
.faq__item{border-block-end:1px solid var(--stone)}

.faq__q{
  display:flex;align-items:center;gap:var(--sp-s);
  padding-block:var(--sp-s);cursor:pointer;list-style:none;
  font-family:var(--font-display);font-size:var(--t-0);line-height:1.35;
  font-variation-settings:"opsz" 11,"wght" 450;
  transition:color .25s ease;
}
.faq__q::-webkit-details-marker{display:none}
.faq__q:hover{color:var(--champagne-ink)}
.faq__item[open] .faq__q{color:var(--champagne-ink)}

/* the + that becomes a − : two rules, one of which rotates away */
.faq__mark{
  position:relative;flex:0 0 auto;inline-size:0.75rem;block-size:0.75rem;
  margin-inline-start:auto;
}
.faq__mark::before,.faq__mark::after{
  content:"";position:absolute;inset-block-start:50%;inset-inline-start:0;
  inline-size:100%;block-size:1px;background:var(--champagne-ink);
  transition:transform .3s var(--ease);
}
.faq__mark::after{transform:rotate(90deg)}
.faq__item[open] .faq__mark::after{transform:rotate(0deg)}

.faq__a{padding-block-end:var(--sp-s);padding-inline-end:calc(0.75rem + var(--sp-s))}
.faq__a p{font-size:var(--t--1);line-height:1.8;color:var(--ink-60);max-inline-size:66ch}

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

/* ==========================================================================
   REQUEST — the brand's invitation card, drawn on arrival
   ========================================================================== */
.request{padding-block:var(--sp-2xl)}
.invite{position:relative;padding:clamp(2.75rem, 1.5rem + 5.5vw, 9rem) var(--sp-l);text-align:center}
.invite__keyline{position:absolute;inset:0;inline-size:100%;block-size:100%;overflow:visible;pointer-events:none}
.invite__keyline rect{fill:none;stroke:var(--champagne);vector-effect:non-scaling-stroke}
.js .invite__keyline rect{stroke-dasharray:4000;stroke-dashoffset:4000}
.invite__keyline .k-out{stroke-width:1;stroke-opacity:.9}
.invite__keyline .k-in{stroke-width:1;stroke-opacity:.28}
.is-in .invite__keyline .k-out{animation:draw 1.9s var(--ease) .1s forwards}
.is-in .invite__keyline .k-in{animation:draw 1.9s var(--ease) .3s forwards}
.invite__inner{max-inline-size:46rem;margin-inline:auto;position:relative;z-index:1}
/* a single band of light crossing the card every nine seconds, the way it
   would cross engraved metal as you walk past it */
.invite::after{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:linear-gradient(116deg,
    transparent 38%, rgba(247,244,239,.085) 50%, transparent 62%);
  background-size:280% 100%;background-repeat:no-repeat;
  animation:invite-sweep 9s cubic-bezier(.4,0,.2,1) 1.2s infinite;
}
@keyframes invite-sweep{
  0%      {background-position:135% 0}
  42%,100%{background-position:-55% 0}
}
.invite .label{color:var(--champagne)}
.invite .section-head{margin-block:var(--sp-s);color:var(--ivory)}
.invite__body{color:var(--on-dark);margin:0 auto var(--sp-l);max-inline-size:52ch;font-size:var(--t-0)}
.invite__note{margin-block-start:var(--sp-s);font-size:var(--t--1);letter-spacing:0;line-height:1.65;color:var(--on-dark-dim);max-inline-size:52ch;margin-inline:auto}

/* ==========================================================================
   FOOTER
   ========================================================================== */
.footer{padding-block:var(--sp-2xl) var(--sp-m)}
.footer__grid{display:grid;grid-template-columns:minmax(0,4fr) repeat(3,minmax(0,2fr));gap:var(--sp-m);margin-block-end:var(--sp-xl)}
.footer__col h4{margin-block-end:var(--sp-s);color:var(--ink-60)}
.footer__col li{margin-block-end:0.5rem}
.footer__col a{display:inline-flex;align-items:center;min-block-size:2.75rem;font-size:var(--t--1);border-block-end:1px solid transparent;transition:border-color .25s ease}
.footer__col a:hover{border-block-end-color:var(--champagne)}
.footer__cta{border-block-start:1px solid var(--stone);padding-block-start:var(--sp-m);display:flex;align-items:center;justify-content:space-between;gap:var(--sp-s);flex-wrap:wrap}
.footer__legal{font-size:var(--t--1);color:var(--ink-60)}


/* ==========================================================================
   THE FORM AS A FLOW
   One question fills the screen at a time. The steps a visitor is about to go
   through are stated once, condensed, at the top — not parked in a sidebar
   they have to keep glancing at. Enter advances; choosing an option advances
   on its own; Back is always there.
   ========================================================================== */
.flow-head{padding-block:var(--sp-xl) var(--sp-l)}
/* the rule sits beside the label the way it does on every question below,
   rather than stacked hard against it */
.flow-head .label{display:flex;align-items:flex-start;gap:0.9rem}
.flow-head .label .tick{inline-size:2rem;margin-block-start:0.62em;flex:0 0 auto}
.flow-head .section-head{margin-block:var(--sp-m);color:var(--ivory)}
.flow-head .body{color:var(--on-dark);font-size:var(--t--1);max-inline-size:60ch}

/* the three stages, condensed into one line at the top */


/* progress */
.flow-progress{position:sticky;inset-block-start:var(--nav-h);z-index:40;background:var(--ivory);border-block-end:1px solid var(--stone)}
.flow-progress__inner{max-inline-size:var(--maxw);margin-inline:auto;padding:var(--sp-s) var(--gutter);display:flex;align-items:center;gap:var(--sp-s)}
.flow-progress__group{font-family:var(--font-label);font-weight:500;font-size:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--midnight);white-space:nowrap}
.flow-progress__rail{position:relative;flex:1;block-size:1px;background:var(--stone)}
.flow-progress__bar{position:absolute;inset-block-start:-1px;inset-inline-start:0;block-size:3px;inline-size:0;background:var(--champagne);transition:inline-size .5s var(--ease)}
.flow-progress__count{font-family:var(--font-label);font-weight:500;font-size:var(--t-label);letter-spacing:0.1em;color:var(--ink-60);white-space:nowrap;font-variant-numeric:tabular-nums}

/* the viewport holds one question at a time */
.flow{display:block}
.flow__viewport{position:relative;min-block-size:0}
.flow__step{
  position:absolute;inset-block-start:0;inset-inline-start:0;inline-size:100%;
  opacity:0;visibility:hidden;transform:translateY(1.25rem);pointer-events:none;
  transition:opacity .45s ease,transform .55s var(--ease),visibility 0s linear .45s;
}
/* the step on screen is the only one in flow, so the button follows the
   question instead of sitting below the tallest question in the set */
.flow__step.is-active{position:relative;opacity:1;visibility:visible;transform:none;pointer-events:auto;transition:opacity .5s ease .08s,transform .6s var(--ease) .08s,visibility 0s}
.flow__step.is-past{transform:translateY(-1.25rem)}
.no-js-flow .flow__step{opacity:1;visibility:visible;transform:none;pointer-events:auto;position:static;margin-block-end:var(--sp-xl)}

.q{max-inline-size:44rem}
.q__eyebrow{display:flex;align-items:center;gap:0.75rem;margin-block-end:var(--sp-s);color:var(--champagne-ink)}
.q__eyebrow .tick{inline-size:1.5rem}
.q__title{font-family:var(--font-display);font-weight:400;font-size:var(--t-2);line-height:1.2;font-variation-settings:"opsz" 13,"wght" 450;margin-block-end:var(--sp-xs)}
.q__title .opt{font-family:var(--font-label);font-weight:300;font-size:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--ink-40);vertical-align:middle;margin-inline-start:0.75rem}
.q__hint{font-size:var(--t--1);color:var(--ink-60);margin-block-end:var(--sp-m);max-inline-size:52ch}
/* a word held up inside a hint — the real semibold cut, never a synthesised one */
.q__hint strong{font-weight:600;color:var(--midnight)}

/* A phone number is two decisions, so it is two controls: the country from a
   native select — a wheel on a phone, type-ahead on a desktop, and nobody has
   to know their own dial code — and then the number itself. The code sits as
   a fixed prefix beside the field so what is being typed is never in doubt.
   They wrap onto two rows before either gets too narrow to use. */
.phone-field{display:flex;flex-wrap:wrap;gap:0.75rem 1rem;align-items:flex-end;max-inline-size:34rem}
.phone-cc{
  flex:1 1 11rem;min-inline-size:0;
  font-family:var(--font-body);font-size:max(1rem,var(--t-1));line-height:1.5;
  color:var(--midnight);background:transparent;
  border:0;border-block-end:1px solid var(--stone);border-radius:0;
  padding:0.75rem 1.4rem 0.9rem 0;min-block-size:3.25rem;
  appearance:none;cursor:pointer;transition:border-color .25s ease;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6' fill='none' stroke='%2311141D' stroke-width='1.2'%3E%3Cpath d='M1 1l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 0.25rem center;background-size:0.6rem;
}
.phone-cc:hover{border-block-end-color:var(--ink-40)}
.phone-cc:focus{outline:none;border-block-end-color:var(--midnight)}

.phone-num{flex:1 1 13rem;min-inline-size:0;display:flex;align-items:baseline;gap:0.5rem}
.phone-num__pre{
  flex:0 0 auto;font-family:var(--font-body);font-size:max(1rem,var(--t-1));
  color:var(--ink-60);font-variant-numeric:tabular-nums;
}
.phone-num .q-input{flex:1 1 auto;min-inline-size:0}
.q--error .phone-cc{border-block-end-color:var(--champagne-ink)}
.q__field{margin-block-start:var(--sp-s)}

/* a single large line to type on, not a boxed input */
.q-input{
  inline-size:100%;font-family:var(--font-body);font-size:max(1rem,var(--t-1));line-height:1.5;
  color:var(--midnight);background:transparent;border:0;border-block-end:1px solid var(--stone);
  border-radius:0;padding:0.75rem 0 0.9rem;min-block-size:3.25rem;appearance:none;
  transition:border-color .25s ease;
}
.q-input::placeholder{color:var(--ink-40)}
.q-input:hover{border-block-end-color:var(--ink-40)}
.q-input:focus{outline:none;border-block-end-color:var(--midnight)}
textarea.q-input{min-block-size:7rem;resize:vertical;border:1px solid var(--stone);padding:0.9rem 1rem}
textarea.q-input:focus{border-color:var(--midnight)}
.q--error .q-input{border-block-end-color:var(--champagne-ink)}
.q--error textarea.q-input{border-color:var(--champagne-ink)}
.q__error{display:none;font-family:var(--font-label);font-weight:500;font-size:var(--t-label);letter-spacing:0.1em;text-transform:uppercase;color:var(--champagne-ink);margin-block-start:0.75rem}
.q--error .q__error{display:block}

/* options behave like Typeform's: a key letter, click or keyboard, and the
   flow advances on its own once one is chosen */
.opts{display:grid;gap:0.5rem;max-inline-size:34rem}
.opt-row{display:flex;align-items:center;gap:0.9rem;border:1px solid var(--stone);padding:0.85rem 1rem;min-block-size:3.25rem;cursor:pointer;transition:border-color .2s ease,background .2s ease}
.opt-row:hover{border-color:var(--ink-40);background:var(--ivory-deep)}
.opt-row input{position:absolute;opacity:0;pointer-events:none}
.opt-row__key{
  flex:0 0 auto;inline-size:1.75rem;block-size:1.75rem;border:1px solid var(--stone);
  display:grid;place-items:center;font-family:var(--font-label);font-weight:500;
  font-size:var(--t-label);color:var(--ink-60);transition:all .2s ease;
}
.opt-row__t{font-size:var(--t--1);line-height:1.5}
.opt-row:has(input:checked){border-color:var(--midnight);background:var(--ivory-deep)}
.opt-row:has(input:checked) .opt-row__key{background:var(--midnight);border-color:var(--midnight);color:var(--ivory)}
.opt-row:has(input:focus-visible){outline:2px solid var(--champagne);outline-offset:2px}
/* a step on a path the visitor did not take is out of the document entirely */
.flow__step.is-out{display:none}
/* the write-in that a final "Other" reveals */
.opt-other{margin-block-start:0.85rem;max-inline-size:34rem}
/* a step that offers a way out rather than asking a question */
.q__actions{display:flex;flex-wrap:wrap;gap:var(--sp-s);align-items:center;margin-block-start:var(--sp-m)}
.flow--fork #flowNext{background:transparent;color:var(--ink-60);border-color:var(--stone)}
.flow--fork #flowNext:hover{background:transparent;color:var(--midnight);border-color:var(--midnight)}
/* a multi-select says so, and its rows stay chosen together */
.opts--multi .opt-row__key{border-radius:2px}

/* repeatable socials, inside a question */
.social-row{display:grid;grid-template-columns:minmax(min(9rem,32%),1fr) minmax(0,2fr) 3rem;gap:0.5rem;margin-block-end:0.6rem;align-items:center}
.social-row select{font-family:var(--font-label);font-size:var(--t--1);letter-spacing:0.06em;text-transform:uppercase;color:var(--midnight);background:transparent;border:0;border-block-end:1px solid var(--stone);padding:0.7rem 0;min-block-size:3rem;appearance:none}
.social-remove{block-size:3rem;inline-size:3rem;border:1px solid var(--stone);display:grid;place-items:center;color:var(--ink-40);transition:border-color .2s ease,color .2s ease}
.social-remove:hover{border-color:var(--midnight);color:var(--midnight)}
.social-remove svg{inline-size:0.8125rem;block-size:0.8125rem;stroke:currentColor;stroke-width:1.3}
.link-btn{display:inline-flex;align-items:center;min-block-size:2.75rem;font-family:var(--font-label);font-weight:500;font-size:var(--t-label);letter-spacing:0.14em;text-transform:uppercase;border-block-end:1px solid var(--champagne)}
.link-btn:hover{border-block-end-color:var(--midnight)}

/* review */
.review{display:grid;gap:0;max-inline-size:44rem;margin-block-start:var(--sp-m)}
.review__row{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.6fr) auto;gap:var(--sp-s);align-items:baseline;padding-block:0.85rem;border-block-start:1px solid var(--stone)}
.review__k{font-family:var(--font-label);font-weight:500;font-size:var(--t-label);letter-spacing:0.1em;text-transform:uppercase;color:var(--ink-60)}
.review__v{font-size:var(--t--1);line-height:1.6;white-space:pre-line}
.review__v:empty::before{content:"—";color:var(--ink-40)}
.review__edit{font-family:var(--font-label);font-weight:500;font-size:var(--t-label);letter-spacing:0.1em;text-transform:uppercase;color:var(--champagne-ink);border-block-end:1px solid transparent}
.review__edit:hover{border-block-end-color:var(--champagne-ink)}

/* controls */
.flow__nav{display:flex;align-items:center;gap:var(--sp-s);margin-block-start:var(--sp-m);padding-block-start:var(--sp-s);border-block-start:1px solid var(--stone);flex-wrap:wrap}
.flow__hint{font-family:var(--font-label);font-weight:300;font-size:var(--t-label);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--ink-40);margin-inline-start:auto}
.flow__hint kbd{font-family:var(--font-label);font-weight:500;border:1px solid var(--stone);padding:0.15rem 0.45rem;margin-inline:0.25rem}
.flow__status{margin-block-start:var(--sp-s);font-size:var(--t--1);color:var(--ink-60);display:none;inline-size:100%}
.flow__status.is-visible{display:block}
.flow__status--error{color:var(--champagne-ink)}
.hp{position:absolute;inset-inline-start:-9999px;opacity:0;block-size:0;overflow:hidden}

.thanks{display:none;padding-block:var(--sp-2xl);max-inline-size:40rem}
.thanks.is-visible{display:block}
.thanks .section-head{margin-block:var(--sp-s)}

/* legal pages */
.legal{max-inline-size:var(--measure);padding-block:var(--sp-l) var(--sp-2xl)}
.legal h3{font-family:var(--font-display);font-size:var(--t-1);line-height:1.25;margin-block:var(--sp-m) var(--sp-xs);font-weight:400;font-variation-settings:"opsz" 11,"wght" 500}
.legal p{margin-block-end:var(--sp-xs)}
.legal ul{margin-block-end:var(--sp-xs)}
.legal li{padding-inline-start:1.375rem;position:relative;margin-block-end:0.625rem}
.legal li::before{content:"\2014";position:absolute;inset-inline-start:0;color:var(--champagne-ink)}
.page-head{padding-block:var(--sp-2xl)}
.page-head .section-head{margin-block:var(--sp-s);color:var(--ivory)}
.page-head .body{color:var(--on-dark)}
.form-band{padding-block:var(--sp-l) var(--sp-xl);display:flex;flex-direction:column;justify-content:flex-start}

/* ==========================================================================
   BREAKPOINTS — three, each for a structural reason
   ========================================================================== */
@media (max-width: 62rem){
  /* two columns stop being two columns: the copy runs first, the film under
     it at the full width, still in its frame and still playing */
  .hero__grid{grid-template-columns:1fr;gap:var(--sp-l)}
  .hero__copy{max-inline-size:36rem}
  /* stacked, the light follows the film to the bottom of the band — and it
     draws in, so it lifts the ground around the picture without warming the
     headline sitting above it */
  .hero{--g-x:62%;--g-y:80%;--g-a:.24;--g-h:.065;--g-r:24rem}
  /* The line breaks in the headline are set by hand for the desktop column.
     At these widths they leave a stepped rag with a hole down the right, so
     they are dropped and the browser balances the lines to the measure. */
  .hero__statement br{display:none}
  .hero__statement{text-wrap:balance;max-inline-size:17ch}
  .hero__body{max-inline-size:46ch}

  /* the copy and the film stop sitting side by side */
  .experience__grid{grid-template-columns:1fr;gap:var(--sp-l)}
  /* stacked, the column is the whole page: without a measure the headline
     would set on one very long line and lose its shape */
  .experience__copy .section-head{max-inline-size:24ch}
  /* three columns of film stop being watchable; two still are */
  .index{grid-template-columns:repeat(2,minmax(0,1fr))}

  /* three lines converging down a phone is a squiggle, not a diagram */
  .plates{grid-template-columns:minmax(0,1fr);gap:var(--sp-l);max-inline-size:34rem;margin-inline:auto}
  .converge{block-size:var(--sp-l)}
  .converge__svg{display:none}
}

@media (max-width: 54rem){
  .nav__burger{display:block}
  /* Open, the menu is a page of its own, not a dropdown: the destinations set
     in the display face on ruled rows, the request below them, and each row
     arriving a beat after the one above it. */
  .nav__menu{
    position:fixed;inset:var(--nav-h) 0 0;background:var(--midnight);
    flex-direction:column;align-items:stretch;justify-content:flex-start;
    gap:0;padding:var(--sp-m) var(--gutter) var(--sp-xl);
    border-block-start:1px solid rgba(209,172,107,.3);
    opacity:0;pointer-events:none;
    transition:opacity .3s ease;z-index:55;overflow-y:auto;
  }
  body.nav-open .nav__menu{opacity:1;pointer-events:auto}
  body.nav-open{overflow:hidden}

  .nav__menu .nav__link{
    font-family:var(--font-display);font-weight:400;
    font-variation-settings:"opsz" 13,"wght" 400;
    font-size:var(--t-1);text-transform:none;letter-spacing:0;color:var(--ivory);
    min-block-size:3.6rem;inline-size:100%;
    border-block-end:1px solid rgba(247,244,239,.10);
    opacity:0;transform:translateY(0.6rem);
    transition:opacity .45s ease,transform .55s var(--ease);
  }
  .nav__menu .nav__link::after{inset-block-end:-1px;inset-inline-end:auto;inline-size:2.5rem}
  .nav__sep{display:none}
  .nav__menu .btn{
    margin-block-start:var(--sp-l);inline-size:100%;
    opacity:0;transform:translateY(0.6rem);
    transition:opacity .45s ease,transform .55s var(--ease),background .3s ease,color .3s ease;
  }
  body.nav-open .nav__menu .nav__link,
  body.nav-open .nav__menu .btn{opacity:1;transform:none}
  body.nav-open .nav__menu .nav__link:nth-child(2){transition-delay:.07s}
  body.nav-open .nav__menu .nav__link:nth-child(3){transition-delay:.14s}
  body.nav-open .nav__menu .btn{transition-delay:.21s}
  .invite .section-head br{display:none}
  .footer__grid{grid-template-columns:1fr 1fr}
  /* four films to a row stop being watchable; two of them are */
  /* four marks to a row stop fitting; two keeps every row full — and with
     half as many across, every mark is scaled up together so the wall reads
     at the same weight on a phone as it does on a desktop */
  .partners__row{grid-template-columns:repeat(2,minmax(0,1fr));row-gap:var(--sp-m);--k:1.3}
  .flow__viewport{min-block-size:0}
  .flow__hint{display:none}
  .review__row{grid-template-columns:1fr;gap:0.25rem}
}

/* a short laptop screen is the tight case: the head keeps the three stage
   names but drops their prose, so the first question still lands on screen */
@media (max-height: 54rem){
  .flow-head{padding-block:var(--sp-l) var(--sp-m)}
  .flow-head .section-head{margin-block:var(--sp-s)}
  .flow__viewport{min-block-size:0}
}

/* One gathering across. Below this a column cannot hold a film big enough to
   watch, so the grid becomes a stack and each event gets the full width. */
@media (max-width: 40rem){
  /* the keyline plate keeps its inset, but --sp-l on both sides costs a phone
     a fifth of its width and the headline breaks after two words; --sp-m
     leaves the plate reading as a plate and the heading room to set */
  .invite{padding-inline:var(--sp-m)}
  .index{grid-template-columns:minmax(0,1fr);gap:var(--sp-m)}
  .ev__name{font-size:var(--t-2)}
  /* one column is as wide as the page, which a single event does not need:
     the row is held to a card's width so the sliver stays a sliver */
  .ev{max-inline-size:26rem}
}

@media (max-width: 34rem){
  .footer__grid{grid-template-columns:1fr}
  /* the eyebrow is 32 tracked capitals; it is drawn in a little so it holds
     one line on a phone */
  .hero__eyebrow{gap:0.6rem;letter-spacing:0.13em}
  .hero__eyebrow .tick{inline-size:1.25rem}
  .partners__row{--k:1.15}
  .strip{--tile:min(72vw,15rem)}
  /* the plate cannot hold its rules either side of tracked caps at this
     width: the title wraps and the rule moves under it */
  .masthead__title{display:block}
  .masthead__title > span{white-space:normal;display:inline-block}
  .masthead__title::before{display:none}
  .masthead__title::after{
    display:block;inline-size:8rem;max-inline-size:none;
    margin-inline:auto;margin-block-start:var(--sp-s);
  }
}

@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}
  .seq,.enter-up,.enter-left,.enter-rise,.enter-fade{opacity:1!important;transform:none!important}
  .draw-rule{transform:none!important}
  .svc__list li,.svc__lead{opacity:1!important;transform:none!important}
  .conv,.invite__keyline rect{stroke-dashoffset:0!important}
  /* a strip still scrolls under reduced motion; it just does not glide */
  .strip{scroll-behavior:auto}
  .ev__thumb,.ev__chev,.is-in .ev__thumb,.is-in .ev__chev{animation:none!important}
  .conv--pulse,.model__halo,.model__gem,.invite::after{animation:none!important}
  .conv--pulse{stroke-opacity:0}
  .strip > .film{animation:none!important}
}

@media print{.nav,.btn,.film__cue,.strip{display:none}}

/* ===========================================================================
   WHEN THE HERO DOES NOT TAKE THE SCREEN OVER

   Two cases, one behaviour: somebody who asked for less motion, and a screen
   taller than it is wide. The film is 16:9 and it opens WITHOUT being cropped,
   so on a portrait screen the largest honest size for it is a band across the
   middle — a long scroll to earn a small move, with most of the screen empty.
   So on those screens the hero is simply one screen with the film in its card,
   which is where it was going to end up anyway.
   =========================================================================== */
@media (prefers-reduced-motion: reduce), (max-aspect-ratio: 5/4){
  .js .hero{block-size:auto!important}
  /* the stage stops being a flex box, or the film — now a flex item rather
     than a positioned layer — is squeezed to a fraction of the width */
  .js .hero__stage{position:relative!important;block-size:auto!important;padding-block:var(--sp-xl)!important;display:block!important}
  /* relative, never static: the play cue inside is absolutely positioned and
     needs the film itself as its containing block, or it lands over the copy */
  .js .hero__film{position:relative!important;aspect-ratio:var(--hero-arw)/var(--hero-arh)!important;inline-size:100%!important;block-size:auto!important;margin-block-start:var(--sp-l)}
  .js .hero__grid{padding-block-end:0!important}
  .js .hero__slot{display:none}
  .js .hero__copy{transform:none!important;opacity:1!important}
  /* the takeover's player scaling has no meaning here: the tile is simply
     the width of the column and the player is simply the tile */
  .js .hero__film .film__player{
    inset:0!important;inline-size:100%!important;block-size:100%!important;
    transform:none!important;will-change:auto;
  }
  .hero__topfade{display:none!important}
  .hero__cue{display:none!important}
}

