/* ============================================================================
   COFFEE FESTIVAL EUROPE 2027 — Design System
   Content Agency UG
   Motion language reconstructed from the Eirene Cafe reference (Webflow IX2).
   Sections marked "1:1" reproduce the reference's own declarations verbatim.
   ========================================================================= */

/* ---------- 1. FONTS (self-hosted — no third-party request, GDPR-safe) ---- */
@font-face{font-family:'Archivo';font-style:normal;font-display:swap;font-weight:100 900;font-stretch:62% 125%;
  src:url('../../public/fonts/archivo-latin.woff2') format('woff2-variations');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Archivo';font-style:normal;font-display:swap;font-weight:100 900;font-stretch:62% 125%;
  src:url('../../public/fonts/archivo-latin-ext.woff2') format('woff2-variations');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'MonoLabel';font-style:normal;font-display:swap;font-weight:400;
  src:url('../../public/fonts/mono-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2191,U+2193,U+2212,U+2215;}
@font-face{font-family:'MonoLabel';font-style:normal;font-display:swap;font-weight:400;
  src:url('../../public/fonts/mono-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+1E00-1E9F,U+2020,U+20A0-20AB,U+2C60-2C7F;}

/* ---------- 2. TOKENS ---------------------------------------------------- */
:root{
  --grain-url:none;
  --ink:#0B0806; --ink-2:#141210; --ink-3:#1F150D;
  --roast:#6D513F; --roast-deep:#3A2A1E; --espresso:#241710;
  --ivory:#F4EEE4; --bone:#E3D9C9; --muted:#8E8073; --muted-2:#5A5049;
  --ember:#E2551E; --ember-lo:#F08A54; --ember-glow:rgba(226,85,30,.32);
  --bg:var(--ink); --fg:var(--ivory);
  --hairline:rgba(244,238,228,.14); --hairline-dark:rgba(11,8,6,.14);

  --f-display:'Archivo',system-ui,-apple-system,'Segoe UI',sans-serif;
  --f-body:'Archivo',system-ui,-apple-system,'Segoe UI',sans-serif;
  --f-mono:'MonoLabel',ui-monospace,'SF Mono',Menlo,monospace;

  --t-display-xl:clamp(2.7rem,9.6vw,11.4rem);
  --t-display-l:clamp(2.6rem,7.4vw,8rem);
  --t-display-m:clamp(1.9rem,4.6vw,4.2rem);
  --t-display-s:clamp(1.4rem,2.7vw,2.4rem);
  --t-lead:clamp(1.05rem,1.5vw,1.5rem);
  --t-body:clamp(1rem,1.02vw,1.1rem);
  --t-small:clamp(.875rem,.9vw,.95rem);
  --t-label:clamp(.625rem,.72vw,.72rem);

  --gutter:clamp(20px,4.2vw,72px);
  --section-y:clamp(100px,12vw,220px);
  --stack:clamp(28px,3.4vw,56px);
  --maxw:1680px;

  --e-out-quint:cubic-bezier(.22,1,.36,1);
  --e-out-expo:cubic-bezier(.16,1,.3,1);
  --e-in-out-quart:cubic-bezier(.76,0,.24,1);
  --e-out-cubic:cubic-bezier(.33,1,.68,1);
  --d-fast:.24s; --d-mid:.5s; --d-slow:.9s;
  --nav-h:clamp(58px,4.6vw,78px);
}

/* ---------- 3. RESET ----------------------------------------------------- */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;background:var(--ink)}
body{margin:0;background:var(--bg);color:var(--fg);font-family:var(--f-body);
  font-size:var(--t-body);line-height:1.55;font-weight:400;font-stretch:100%;
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;overscroll-behavior:none;}
img,svg,video{display:block;max-width:100%}
img{height:auto}
[hidden]{display:none!important}
h1,h2,h3,h4,p,figure,blockquote,fieldset,legend{margin:0}
fieldset{border:0;padding:0}
ul,ol{margin:0;padding:0;list-style:none}
a{color:inherit;text-decoration:none}
button,input,textarea,select{font:inherit;color:inherit}
button{background:none;border:0;padding:0;cursor:pointer}
:focus-visible{outline:2px solid var(--ember);outline-offset:3px;border-radius:2px}
::selection{background:var(--roast);color:var(--ivory)}

/* ---------- 2b. THE BROWSER'S OWN CHROME --------------------------------
   The parts of the window the page does not draw itself — scrollbar, form
   controls, caret, the ground behind the document — all default to the
   browser's palette unless they are told otherwise. They are brand surfaces
   too, so they get the brand.                                            */
:root{
  color-scheme:dark;              /* dark scrollbars, dark native controls */
  accent-color:var(--ember);      /* checkboxes, radios, range, progress   */
  caret-color:var(--ember);
  scrollbar-color:rgba(226,85,30,.5) var(--ink);
  scrollbar-width:thin}
/* Deliberately NOT ::-webkit-scrollbar on the document. Styling that pseudo
   turns macOS's overlay scrollbar into a permanent 11 px classic bar, which
   costs layout width and reads as heavy on a design like this. `color-scheme`
   already gives Safari and Chrome a dark bar; `scrollbar-color` tints it in
   Firefox and in Chrome 121+. The inner panels that need a visible track keep
   their own rules further down. */
/* the ground behind an over-scrolled document, and behind a page still
   painting its first frame */
html{background:var(--ink)}
::-moz-selection{background:var(--roast);color:var(--ivory)}

/* ---------- 4. LAYOUT ---------------------------------------------------- */
.shell{width:100%;max-width:var(--maxw);margin-inline:auto;padding-inline:var(--gutter)}
.section{padding-block:var(--section-y);position:relative}
.section--light{background:var(--ivory);color:var(--ink)}

/* ---------- 5. TYPOGRAPHY ------------------------------------------------ */
.display{font-family:var(--f-display);font-weight:800;font-stretch:112%;
  text-transform:uppercase;line-height:.86;letter-spacing:-.028em;margin:0}
.display--xl{font-size:var(--t-display-xl)}
.display--l{font-size:var(--t-display-l)}
.display--m{font-size:var(--t-display-m);letter-spacing:-.022em;line-height:.94}
.display--s{font-size:var(--t-display-s);letter-spacing:-.015em;line-height:1}
.editorial{font-family:var(--f-display);font-weight:500;font-stretch:96%;
  font-size:clamp(1.55rem,3.4vw,3.2rem);line-height:1.14;letter-spacing:-.02em}
.lead{font-size:var(--t-lead);line-height:1.45;color:var(--muted);max-width:46ch}
.section--light .lead{color:var(--muted-2)}
.label{font-family:var(--f-mono);font-size:var(--t-label);text-transform:uppercase;
  letter-spacing:.16em;line-height:1;color:var(--muted)}
.label--ember{color:var(--ember)}
.label--ink{color:var(--muted-2)}

.mask{display:block;overflow:hidden;padding-bottom:.08em;margin-bottom:-.08em}
.mask > span{display:block;will-change:transform}
[data-reveal] .mask > span{transform:translate3d(0,110%,0)}

.scrubtext .line{position:relative;display:block}
.scrubtext .line-mask{position:absolute;inset:0 0 0 auto;width:100%;background:currentColor;opacity:.86;pointer-events:none}
.section--light .scrubtext .line-mask{background:var(--ivory)}

/* ---------- 6. PRELOADER — curtain opened by the visitor ---------------- */
.preloader{position:fixed;inset:0;z-index:200;display:flex}
.preloader[hidden]{display:none}
.curtain{width:50%;height:100%;background:var(--ink);position:relative;
  display:flex;align-items:center;will-change:transform}
.curtain--l{justify-content:flex-end}
.curtain--r{justify-content:flex-start}
.curtain__logo{width:clamp(46px,7vw,100px);height:auto;opacity:.96}
.preloader__stage{position:absolute;inset:0;z-index:3;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:clamp(18px,3vw,34px);pointer-events:none;
  padding-top:clamp(170px,29vw,380px)}
.preloader__kicker{color:rgba(244,238,228,.42);opacity:0}

/* enter button — the reference's .curtain-button, given a progress ring */
.enter{
  pointer-events:auto;position:relative;isolation:isolate;
  display:inline-flex;align-items:center;justify-content:center;
  padding:1.05rem 2.3rem;border-radius:999px;
  border:1px solid rgba(244,238,228,.38);color:var(--ivory);opacity:0;overflow:hidden;
  transition:border-color .4s var(--e-out-cubic),color .4s var(--e-out-cubic);
}
.enter__ring{position:absolute;inset:0;z-index:-1;border-radius:inherit;background:var(--ivory);
  transform:translate3d(0,101%,0);transition:transform .62s var(--e-out-expo)}
.enter:not([disabled]):hover{border-color:var(--ivory);color:var(--ink)}
.enter:not([disabled]):hover .enter__ring{transform:translate3d(0,0,0)}
.enter.is-ready::after{
  content:'';position:absolute;inset:-1px;border-radius:inherit;pointer-events:none;
  border:1px solid var(--ember);opacity:0;animation:enterPulse 3s var(--e-out-cubic) infinite}
@keyframes enterPulse{
  0%{transform:scale(1);opacity:.55}70%{transform:scale(1.28);opacity:0}100%{opacity:0}}
.enter__label{position:relative;z-index:2;font-family:var(--f-mono);font-size:var(--t-label);
  text-transform:uppercase;letter-spacing:.16em;line-height:1}
.enter__roll{display:grid;overflow:hidden;height:1.15em;text-align:center;place-items:center}
.enter__roll span{grid-area:1/1;white-space:nowrap;transition:transform .55s var(--e-out-expo)}
.enter__roll span + span{transform:translate3d(0,120%,0)}
.enter.is-ready .enter__roll span{transform:translate3d(0,-120%,0)}
.enter.is-ready .enter__roll span + span{transform:translate3d(0,0,0)}
.enter[disabled]{cursor:progress}
.enter:not([disabled]){cursor:pointer}

.preloader__meta{position:absolute;left:0;right:0;bottom:clamp(28px,4vw,52px);z-index:3;
  display:flex;align-items:center;justify-content:space-between;padding-inline:var(--gutter)}
.preloader__meta .label{color:rgba(244,238,228,.4)}
.preloader__line{position:absolute;left:var(--gutter);right:var(--gutter);z-index:3;
  bottom:clamp(18px,2.6vw,32px);height:1px;background:rgba(244,238,228,.16)}
.preloader__line i{display:block;height:100%;width:100%;background:var(--ember);transform:scaleX(0);transform-origin:0 50%}

/* ---------- 6b. SLOW-LOAD INDICATOR ------------------------------------- */
.loader{position:fixed;inset:0;z-index:400;display:grid;place-items:center;gap:0;
  background:rgba(11,8,6,.94);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
  opacity:0;transition:opacity .5s var(--e-out-cubic)}
.loader.is-on{opacity:1}
.loader[hidden]{display:none!important}
.loader__art{width:clamp(110px,12vw,160px);aspect-ratio:302/348}
.loader__art svg{width:100%;height:100%;display:block;overflow:visible;
  fill:none;stroke-linecap:round;stroke-linejoin:round}
.loader__cup path{stroke-width:10;stroke-dasharray:920;stroke-dashoffset:920;
  animation:brewDraw 2.6s var(--e-in-out-quart) infinite}
.loader__cup .c1{stroke:var(--ember)}
.loader__cup .c2{stroke:#8E6249;animation-delay:.12s}
.loader__cup .c3{stroke:#4A3427;animation-delay:.24s}
.loader__smoke path{stroke:rgba(244,238,228,.6);stroke-width:8;
  stroke-dasharray:130;stroke-dashoffset:130;
  animation:brewSteam 2.6s var(--e-out-cubic) infinite}
.loader__smoke path:nth-child(2){animation-delay:.22s}
.loader__smoke path:nth-child(3){animation-delay:.44s}
@keyframes brewDraw{
  0%{stroke-dashoffset:920}
  46%{stroke-dashoffset:0}
  78%{stroke-dashoffset:0;opacity:1}
  100%{stroke-dashoffset:-920;opacity:.15}
}
@keyframes brewSteam{
  0%{stroke-dashoffset:130;opacity:0}
  22%{opacity:1}
  62%{stroke-dashoffset:0;opacity:1}
  100%{stroke-dashoffset:-130;opacity:0}
}
.loader__label{margin-top:clamp(18px,2.4vw,32px);color:var(--muted);
  align-self:start;grid-row:2}
.loader{grid-template-rows:auto auto;align-content:center}
@media (prefers-reduced-motion:reduce){
  .loader__cup path,.loader__smoke path{animation:none;stroke-dashoffset:0;opacity:1}
}

/* ---------- 6c. LANGUAGE SWAP — a cup being poured -------------------- */
/* Switching language used to be an instant, silent text replacement. Now the
   page is poured over: coffee rises with a wavy crest, the new locale is
   stamped on the surface, and it drains away. ~1.1 s end to end, and the text
   is actually swapped while the screen is covered. */
.brewswap{position:fixed;inset:0;z-index:320;pointer-events:none;overflow:hidden;visibility:hidden}
.brewswap.is-on{visibility:visible}
/* no start transform here: GSAP folds an existing translate into its own base,
   so a CSS `translate3d(0,100%,0)` would make yPercent:100 mean *two* screens */
.brewswap__liquid{position:absolute;left:0;right:0;bottom:0;height:100%;
  background:linear-gradient(180deg,#3A2A1E 0%,#241710 34%,#140C07 100%)}
.brewswap__crest{position:absolute;left:-5%;right:-5%;top:-16px;height:32px;
  background-image:radial-gradient(circle at 50% 100%,#3A2A1E 16px,rgba(0,0,0,0) 16.5px);
  background-size:44px 32px;background-repeat:repeat-x;
  animation:brewSwapCrest 1.1s linear infinite}
@keyframes brewSwapCrest{to{background-position-x:44px}}
.brewswap__bubbles{position:absolute;inset:0;
  background-image:
    radial-gradient(circle,rgba(240,138,84,.5) 3px,rgba(0,0,0,0) 3.6px),
    radial-gradient(circle,rgba(244,238,228,.32) 2px,rgba(0,0,0,0) 2.6px),
    radial-gradient(circle,rgba(240,138,84,.34) 4px,rgba(0,0,0,0) 4.8px);
  background-size:180px 240px,260px 330px,340px 430px;
  background-position:20px 100%,120px 100%,240px 100%;
  animation:brewSwapBubbles 3.4s linear infinite}
@keyframes brewSwapBubbles{
  to{background-position:20px -240px,120px -330px,240px -430px}
}
.brewswap__stage{position:absolute;inset:0;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:clamp(1rem,1.6vw,1.6rem);opacity:0}
.brewswap__cup{width:clamp(96px,9vw,138px);height:auto;overflow:visible;
  fill:none;stroke-linecap:round;stroke-linejoin:round}
.brewswap__pot{stroke:var(--ember);stroke-width:11;
  stroke-dasharray:920;stroke-dashoffset:920}
.brewswap__steam path{stroke:rgba(244,238,228,.7);stroke-width:8;
  stroke-dasharray:130;stroke-dashoffset:130}
/* both a step larger than before: the overlay is on screen long enough to
   read now, so the type has to be worth reading */
.brewswap__code{font-family:var(--f-display);font-weight:800;font-stretch:118%;
  font-size:clamp(4.2rem,13vw,11rem);line-height:.92;letter-spacing:-.045em;color:var(--ivory);
  text-shadow:0 8px 60px rgba(0,0,0,.55)}
.brewswap__word{display:flex;overflow:hidden;
  font-family:var(--f-mono);font-size:clamp(.72rem,1.15vw,1.05rem);
  letter-spacing:.3em;text-transform:uppercase;color:var(--ember-lo)}
.brewswap__ch{display:inline-block;will-change:transform,opacity}
@media (prefers-reduced-motion:reduce){
  .brewswap{display:none}
}

/* ---------- 7. TOP BAR --------------------------------------------------- */
/* The reference bar has no background at all — no scrim, no blur, no border,
   no stuck state. Just the mark in the middle and one small pill on the right. */
.nav{position:fixed;top:0;left:0;right:0;z-index:135;height:var(--nav-h);display:flex;align-items:center;
  color:var(--ivory);background:none;border:0;
  transition:height var(--d-mid) var(--e-out-quint),color .5s var(--e-out-cubic)}
/* three tracks so the roundel is centred on the page, not between its siblings */
.nav__inner{position:relative;z-index:2;width:100%;max-width:var(--maxw);margin-inline:auto;
  padding-inline:var(--gutter);display:grid;grid-template-columns:1fr auto 1fr;
  align-items:center;gap:clamp(12px,2vw,28px)}
.nav__spacer{display:block}
.nav.is-stuck{height:calc(var(--nav-h) * .88)}

/* ---------- 7a. CENTRED MARK (filled ⇄ line cross-fade) ------------------ */
/* No hover animation — the reference mark is completely still under the
   pointer. The only movement is the scroll/section-driven swap below.      */
/* The roundel is allowed to stand taller than the bar it sits in — the bar is
   transparent, so there is nothing for it to be cramped inside. */
.nav__mark{justify-self:center;position:relative;display:block;
  width:clamp(56px,4.6vw,78px);aspect-ratio:1;
  /* it is now as tall as the bar, so nudge it down a little: flush against the
     top edge of the screen reads as a crop, not as a logo */
  margin-top:clamp(5px,.6vw,10px);
  transition:width var(--d-mid) var(--e-out-quint),margin-top var(--d-mid) var(--e-out-quint)}
.nav__mark-fill,.nav__mark-line{position:absolute;inset:0;display:block;
  width:100%;height:100%;
  transition:opacity .62s var(--e-out-cubic),transform .8s var(--e-out-expo)}
.nav__mark-fill{transform:scale(1)}
.nav__mark-line{opacity:0;transform:scale(.94);color:currentColor}
.nav__mark-line svg{width:100%;height:100%;display:block}
.nav__mark.is-line .nav__mark-fill{opacity:0;transform:scale(.94)}
.nav__mark.is-line .nav__mark-line{opacity:1;transform:scale(1)}
.nav.is-stuck .nav__mark{width:clamp(48px,3.9vw,66px)}

/* ---------- 7b. MENU BAND (reference navbar pill) ----------------------- */
/* Smaller than before: the reference pill is a compact dark capsule, roughly
   the height of one line of mono type plus a hair of padding.              */
.band{
  justify-self:end;
  display:flex;align-items:center;gap:clamp(2px,.3vw,6px);
  padding:.24rem .3rem;border-radius:999px;
  background:rgba(14,11,9,.58);
  backdrop-filter:blur(20px) saturate(160%);-webkit-backdrop-filter:blur(20px) saturate(160%);
  border:1px solid rgba(244,238,228,.1);
  box-shadow:0 10px 28px rgba(0,0,0,.3);
  opacity:0;transform:translateY(-12px);
  transition:opacity .8s var(--e-out-cubic),transform .9s var(--e-out-expo),
             background-color .5s var(--e-out-cubic),border-color .5s var(--e-out-cubic),
             box-shadow .5s var(--e-out-cubic);
}
body.is-ready .band{opacity:1;transform:none}
.band:hover{background:rgba(14,11,9,.74);border-color:rgba(244,238,228,.2)}
.band__rule{width:1px;height:14px;background:rgba(244,238,228,.16);flex:none;
  margin-inline:clamp(1px,.2vw,4px)}

.band__links{position:relative;display:flex;align-items:center;gap:1px}
.band__pill{position:absolute;top:0;left:0;height:100%;width:0;border-radius:999px;
  background:rgba(244,238,228,.1);opacity:0;pointer-events:none;
  transition:transform .55s var(--e-out-expo),width .55s var(--e-out-expo),
             opacity .35s var(--e-out-cubic),background-color .4s var(--e-out-cubic)}
.band__pill.is-on{opacity:1}
.band__pill.is-live{background:rgba(226,85,30,.2)}
.band__link{position:relative;z-index:1;white-space:nowrap;padding:.5rem clamp(.5rem,.7vw,.82rem);
  border-radius:999px;font-family:var(--f-mono);font-size:clamp(.55rem,.62vw,.66rem);
  text-transform:uppercase;letter-spacing:.11em;line-height:1;color:rgba(244,238,228,.68);
  transition:color .32s var(--e-out-cubic)}
.band__link span{display:block;transition:transform .5s var(--e-out-expo)}
.band__link:hover,.band__link.is-live{color:var(--ivory)}
.band__link:hover span{transform:translateY(-1px)}
.band__link.is-live{color:#fff}

/* the ambient toggle, icon only: four bars while it plays, a play triangle
   while it does not. Same footprint as the burger, no label.             */
.band__aud{flex:none;position:relative;display:grid;place-items:center;
  width:clamp(28px,2.1vw,34px);height:clamp(28px,2.1vw,34px);border-radius:50%;
  color:var(--ivory);background:rgba(244,238,228,.06);border:0;cursor:pointer;
  transition:background-color .4s var(--e-out-cubic),color .4s var(--e-out-cubic)}
.band__aud:hover{background:rgba(244,238,228,.16)}
.band__aud.is-on{background:rgba(226,85,30,.18);color:var(--ember)}
.band__aud-play{position:absolute;width:10px;height:12px;margin-left:1px;
  transition:opacity .3s var(--e-out-cubic),transform .5s var(--e-out-expo)}
.band__aud.is-on .band__aud-play{opacity:0;transform:scale(.6)}
.band__aud-bars{position:absolute;display:flex;align-items:center;gap:1.5px;height:12px;
  opacity:0;transform:scale(.6);
  transition:opacity .3s var(--e-out-cubic),transform .5s var(--e-out-expo)}
.band__aud.is-on .band__aud-bars{opacity:1;transform:none}
.band__aud-bars i{display:block;width:1.6px;height:3px;border-radius:2px;background:currentColor}
.band__aud.is-on .band__aud-bars i{animation:audBar .9s ease-in-out infinite}
.band__aud.is-on .band__aud-bars i:nth-child(1){animation-delay:-.15s}
.band__aud.is-on .band__aud-bars i:nth-child(2){animation-delay:-.45s}
.band__aud.is-on .band__aud-bars i:nth-child(3){animation-delay:-.75s}
.band__aud.is-on .band__aud-bars i:nth-child(4){animation-delay:-.3s}
.nav.is-light .band__aud{background:rgba(11,8,6,.06);color:var(--ink)}
.nav.is-light .band__aud.is-on{background:rgba(226,85,30,.16);color:var(--ember)}
@media (prefers-reduced-motion:reduce){ .band__aud{display:none} }
@media (max-width:600px){ .band__aud{display:none} }

.band__burger{flex:none;display:grid;place-items:center;width:clamp(28px,2.1vw,34px);
  height:clamp(28px,2.1vw,34px);border-radius:50%;color:var(--ivory);
  background:rgba(244,238,228,.06);
  transition:background-color .4s var(--e-out-cubic),color .4s var(--e-out-cubic)}
.band__burger:hover{background:rgba(244,238,228,.16)}
.band.is-open .band__burger{background:var(--ember);color:#fff;
  box-shadow:0 0 0 0 rgba(226,85,30,.55);animation:burgerPop .7s var(--e-out-expo)}
@keyframes burgerPop{
  0%{transform:scale(.86) rotate(-90deg);box-shadow:0 0 0 0 rgba(226,85,30,.6)}
  60%{transform:scale(1.06) rotate(4deg)}
  100%{transform:none;box-shadow:0 0 0 14px rgba(226,85,30,0)}}
@media (prefers-reduced-motion:reduce){.band.is-open .band__burger{animation:none}}
.band__bars{display:flex;flex-direction:column;gap:3.5px;width:13px}
.band__bars i{display:block;height:1.4px;border-radius:2px;background:currentColor;
  transition:transform .5s var(--e-out-expo)}
.band.is-open .band__bars i:first-child{transform:translateY(2.45px) rotate(45deg)}
.band.is-open .band__bars i:last-child{transform:translateY(-2.45px) rotate(-45deg)}

/* over an ivory section the whole bar flips to ink so it never disappears */
.nav.is-light{color:var(--ink)}
.nav.is-light .band{background:rgba(255,255,255,.62);border-color:rgba(11,8,6,.1);
  box-shadow:0 10px 26px rgba(11,8,6,.12)}
.nav.is-light .band__link{color:rgba(11,8,6,.66)}
.nav.is-light .band__link:hover,.nav.is-light .band__link.is-live{color:var(--ink)}
.nav.is-light .band__pill{background:rgba(11,8,6,.08)}
.nav.is-light .band__pill.is-live{background:rgba(226,85,30,.18)}
.nav.is-light .band__burger{background:rgba(11,8,6,.06);color:var(--ink)}
.nav.is-light .band__rule{background:rgba(11,8,6,.14)}
.nav.is-light .lang{background:rgba(11,8,6,.06);border-color:rgba(11,8,6,.14)}
.nav.is-light .lang button{color:var(--muted-2)}
.nav.is-light .lang button[aria-pressed="true"]{color:#fff}

/* ---------- 7c. LANGUAGE SWITCHER --------------------------------------- */
.lang{position:relative;display:flex;align-items:center;padding:2px;border-radius:999px;
  background:rgba(244,238,228,.05);border:1px solid transparent;
  font-family:var(--f-mono);font-size:var(--t-label)}
.band .lang{flex:none}
.lang__pill{position:absolute;top:2px;left:0;height:calc(100% - 4px);width:0;border-radius:999px;
  background:var(--ember);box-shadow:0 4px 14px rgba(226,85,30,.4);pointer-events:none;opacity:0;
  transition:transform .55s var(--e-out-expo),width .55s var(--e-out-expo),opacity .3s}
.lang__pill.is-on{opacity:1}
.lang button{position:relative;z-index:1;padding:.34rem .45rem;letter-spacing:.12em;
  color:var(--muted);border-radius:999px;transition:color .35s var(--e-out-cubic)}
.lang button[aria-pressed="true"]{color:#fff}
.lang button:not([aria-pressed="true"]):hover{color:var(--ivory)}
.lang--big{font-size:.78rem}
.lang--big button{padding:.6rem .85rem}

/* ---------- 8. ROUND GET-IN-TOUCH ORB (reference .button-round) ---------- */
/* Reference geometry: a filled disc with a concentric hairline ring behind it.
   Reference motion (a-67 / a-68): hovering collapses the ring to scale 0 and
   inverts the disc over 400 ms out / 300 ms back; a-104 makes the whole thing
   magnetic within ±8 px. On top of that it now reads the section it is over:
   it inverts on ivory, tucks away where the page has its own furniture in the
   corner, and steps aside completely on the application block.            */
.orb{
  position:fixed;z-index:130;right:clamp(16px,2vw,34px);bottom:clamp(16px,2vw,34px);
  width:clamp(84px,6.4vw,112px);aspect-ratio:1;
  display:flex;align-items:center;justify-content:center;
  opacity:0;pointer-events:none;
  /* the size and the height off the floor are both state — tucking used to
     change them with no transition at all, which is the hard jump at the top
     of the beans section. They ease now, on the same curve as everything else
     the orb does. */
  transition:opacity .55s var(--e-out-cubic),
             width .72s var(--e-out-expo),
             bottom .72s var(--e-out-expo)}
body.is-ready .orb{opacity:1;pointer-events:auto}
body.menu-open .orb{opacity:0;pointer-events:none}
/* the magnetic tween owns .orb's transform, so scale lives one level down */
.orb__inner{position:relative;width:100%;height:100%;
  display:flex;align-items:center;justify-content:center;
  transform:scale(.82);transition:transform .8s var(--e-out-expo)}
body.is-ready .orb__inner{transform:none}
body.menu-open .orb__inner{transform:scale(.8)}

.orb__disc{
  position:relative;z-index:5;width:74%;height:74%;border-radius:999rem;
  display:flex;align-items:center;justify-content:center;
  background:var(--ember);color:var(--ink);
  box-shadow:0 14px 36px rgba(226,85,30,.34);
  transition:background-color .45s var(--e-out-cubic),color .45s var(--e-out-cubic),
             box-shadow .45s var(--e-out-cubic)}
.orb__ring{
  position:absolute;z-index:4;width:84%;height:84%;border-radius:999rem;
  border:1px solid var(--ember);background:transparent;
  transform:scale(1);transform-origin:50% 50%;
  transition:transform .4s var(--e-out-cubic),border-color .45s var(--e-out-cubic)}
.orb__text{display:flex;flex-direction:column;align-items:center;gap:.02em;
  margin-top:2px;text-align:center;text-transform:uppercase;
  font-family:var(--f-display);font-weight:700;font-stretch:100%;
  font-size:clamp(.6rem,.78vw,.82rem);line-height:1.04;letter-spacing:.01em;
  transform:scale(1);
  transition:opacity .3s var(--e-out-cubic),transform .55s var(--e-out-expo)}

.orb:hover .orb__disc,.orb:focus-visible .orb__disc{
  background:var(--espresso);color:var(--ivory);
  box-shadow:0 18px 48px rgba(11,8,6,.55)}
.orb:hover .orb__ring,.orb:focus-visible .orb__ring{transform:scale(0)}
.orb:not(:hover) .orb__ring,.orb:not(:hover) .orb__disc{transition-duration:.3s}

/* ---- the scroll-progress ring ----------------------------------------- */
.orb__prog{position:absolute;inset:0;z-index:3;width:100%;height:100%;
  transform:rotate(-90deg);overflow:visible;pointer-events:none;
  opacity:0;transition:opacity .5s var(--e-out-cubic)}
body.is-ready .orb__prog{opacity:1}
.orb__prog circle{fill:none;stroke-width:1.4;stroke-linecap:round}
.orb__prog-track{stroke:rgba(244,238,228,.16)}
.orb__prog-arc{stroke:var(--ember);stroke-dasharray:295.3;stroke-dashoffset:295.3;
  transition:stroke-dashoffset .12s linear,stroke .45s var(--e-out-cubic)}
.orb[data-tone="light"] .orb__prog-track{stroke:rgba(11,8,6,.16)}
.orb.is-tuck .orb__prog{opacity:.85}

/* ---- it reads the section it is standing on --------------------------- */
/* over ivory and bone the ember disc glares; ink reads and still stands out */
.orb[data-tone="light"] .orb__disc{background:var(--ink);color:var(--ivory);
  box-shadow:0 14px 36px rgba(11,8,6,.28)}
.orb[data-tone="light"] .orb__ring{border-color:rgba(11,8,6,.4)}
.orb[data-tone="light"]:hover .orb__disc{background:var(--ember);color:#fff;
  box-shadow:0 18px 48px rgba(226,85,30,.45)}

/* the page already has its own furniture in that corner: step aside */
.orb.is-tuck{width:clamp(52px,4vw,66px);bottom:clamp(58px,6.4vh,88px)}
.orb.is-tuck .orb__disc{background:var(--ember);color:#fff}
.orb.is-tuck[data-tone="light"] .orb__disc{background:var(--ink);color:var(--ivory)}

/* The arrow is drawn on every state of the orb, not only the tucked one. It
   used to exist only under .is-tuck, so it could not fade in — it appeared
   fully formed the instant the class landed, on top of a label that was still
   there. Now the two cross-fade: the label leaves first and the arrow follows
   it in 120 ms later, which is what turns a swap into a change. */
.orb::after{content:'';position:absolute;z-index:6;width:34%;height:34%;
  background:currentColor;pointer-events:none;
  opacity:0;transform:scale(.5);
  transition:opacity .32s var(--e-out-cubic),transform .55s var(--e-out-expo);
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 12L12 4M12 4H5.5M12 4v6.5' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 12L12 4M12 4H5.5M12 4v6.5' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat}
.orb.is-tuck::after{opacity:1;transform:scale(1);transition-delay:.12s}
.orb.is-tuck .orb__text{opacity:0;transform:scale(.78)}
.orb.is-tuck{color:#fff}
.orb.is-tuck[data-tone="light"]{color:var(--ivory)}
.orb.is-tuck:hover{width:clamp(84px,6.4vw,112px);bottom:clamp(48px,5.4vh,74px)}
.orb.is-tuck:hover .orb__text{opacity:1;transform:none;transition-delay:.12s}
.orb.is-tuck:hover::after{opacity:0;transform:scale(.5);transition-delay:0s}

/* the application block has its own two buttons — the orb would only shout */
body.is-ready .orb[data-tone="off"]{opacity:0;pointer-events:none;transform:translateY(14px)}

/* it turns a little every time the section under it changes */
/* it turns a little every time the section under it changes. Gentler than it
   was: the box is now easing at the same moment, and two dips read as a lurch */
.orb.is-turn .orb__inner{animation:orbTurn .82s var(--e-out-expo)}
@keyframes orbTurn{
  0%{transform:rotate(0) scale(1)}
  45%{transform:rotate(-9deg) scale(.972)}
  100%{transform:rotate(0) scale(1)}
}
@media (prefers-reduced-motion:reduce){
  .orb.is-turn .orb__inner{animation:none}
}

/* full overlay (reference a-98 / a-99) */
/* The panel opens as a circle growing out of the burger itself rather than a
   sheet sliding up from nowhere: the button you pressed is visibly the origin
   of the thing that appeared. --mx/--my are written by initNav() from the
   button's own box, so it stays correct at every width. */
.menu{position:fixed;z-index:125;inset:0;height:100svh;overflow:hidden;
  background:var(--ink-2);
  --mx:92%; --my:4%;
  clip-path:circle(0% at var(--mx) var(--my));
  transition:clip-path 1s var(--e-out-quint)}
.menu[inert]{pointer-events:none}
.menu.is-open{clip-path:circle(142% at var(--mx) var(--my));
  transition-duration:1.15s}
/* the ember sheet: same origin, a beat ahead, gone by the time you read */
.menu__wash{position:absolute;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(circle at var(--mx) var(--my),
    var(--ember) 0%,rgba(226,85,30,.55) 45%,rgba(226,85,30,0) 78%);
  clip-path:circle(0% at var(--mx) var(--my));opacity:0;
  transition:clip-path .9s var(--e-out-expo),opacity .5s .35s var(--e-out-cubic)}
.menu.is-open .menu__wash{clip-path:circle(150% at var(--mx) var(--my));opacity:0;
  animation:menuWash 1.1s var(--e-out-expo)}
@keyframes menuWash{0%{opacity:0}18%{opacity:.85}100%{opacity:0}}
@media (prefers-reduced-motion:reduce){
  .menu{transition-duration:.25s}
  .menu.is-open .menu__wash{animation:none}
}
.menu__ghost{position:absolute;z-index:0;top:clamp(52px,9vh,120px);right:var(--gutter);
  pointer-events:none;user-select:none;font-family:var(--f-display);font-weight:800;font-stretch:118%;
  font-size:clamp(5rem,17vw,17rem);line-height:.8;letter-spacing:-.04em;color:rgba(244,238,228,.045)}
.menu__cta{margin-top:.4rem}
.menu__inner{position:absolute;left:0;right:0;bottom:0;height:100svh;
  display:grid;grid-template-columns:minmax(0,1.75fr) minmax(300px,1fr);gap:var(--gutter);
  align-items:end;align-content:end;
  padding:var(--nav-h) var(--gutter) clamp(56px,7.5vh,104px)}
.menu__links{position:relative;z-index:1;display:flex;flex-direction:column;gap:clamp(2px,.6vh,10px)}
.menu__links a{display:flex;align-items:baseline;gap:clamp(12px,1.6vw,28px);
  padding-block:.06em;position:relative}
.menu__idx{font-family:var(--f-mono);font-size:clamp(.6rem,.82vw,.86rem);color:var(--muted);
  transform:translate3d(0,120%,0);transition:transform .8s var(--e-out-quint),color .3s}
/* eight rows now, so the type is a step smaller than the five-row version */
.menu__word{font-family:var(--f-display);font-weight:800;font-stretch:112%;text-transform:uppercase;
  /* seven rows have to fit one screen: the vh term is what keeps the last entry
     above the fold on a short laptop, the vw term is what lets a wide monitor
     use the room it has. Both were a step too conservative — the menu is the
     page's biggest typographic moment and was reading like a sidebar. */
  font-size:max(1.05rem,min(5.4rem,5.6vw,7.6vh));line-height:.98;letter-spacing:-.035em;white-space:nowrap;
  transform:translate3d(0,120%,0);transition:transform .9s var(--e-out-quint),color .35s var(--e-out-cubic)}
.menu.is-open .menu__idx,.menu.is-open .menu__word,
.menu.is-open .menu__links .soon{transform:translate3d(0,0,0)}
.menu.is-open .menu__links a:nth-child(2) *{transition-delay:.05s}
.menu.is-open .menu__links a:nth-child(3) *{transition-delay:.10s}
.menu.is-open .menu__links a:nth-child(4) *{transition-delay:.15s}
.menu.is-open .menu__links a:nth-child(5) *{transition-delay:.20s}
.menu.is-open .menu__links a:nth-child(6) *{transition-delay:.25s}
.menu.is-open .menu__links a:nth-child(7) *{transition-delay:.30s}
.menu.is-open .menu__links a:nth-child(8) *{transition-delay:.35s}
.menu.is-open .menu__links a:nth-child(9) *{transition-delay:.40s}
.menu__links:hover a:not(:hover) .menu__word{color:rgba(244,238,228,.3)}
.menu__links:hover a:not(:hover) .menu__idx{color:rgba(244,238,228,.16)}
.menu__links a:hover .menu__word{color:var(--ember)}
.menu__links a:hover .menu__idx{color:var(--ember)}
.menu__side{position:relative;z-index:1;display:flex;flex-direction:column;gap:clamp(18px,3vh,34px);
  opacity:0;transform:translateY(28px);
  transition:opacity .6s .34s var(--e-out-cubic),transform .9s .34s var(--e-out-quint)}
.menu.is-open .menu__side{opacity:1;transform:none}
.menu__block{display:flex;flex-direction:column;gap:.7rem}
/* mail and telephone are the same thing to a reader — two ways of reaching a
   person — so they are set the same way: display face, ivory, one size. The
   number is still a .tbd placeholder, and the amber marker is what says so. */
.menu__mail,.menu__tel{display:block;font-family:var(--f-display);font-weight:600;font-stretch:100%;
  font-size:clamp(1rem,1.5vw,1.5rem);line-height:1.2;letter-spacing:-.01em;
  color:var(--ivory);transition:color .3s}
.menu__mail:hover,.menu__tel:hover{color:var(--ember)}
.menu__tel{margin-top:.45rem}
.menu__tel .tbd{font-family:inherit;font-size:.86em;letter-spacing:-.01em;
  padding:.06em .5em;vertical-align:.02em}
.menu__social{display:flex;flex-wrap:wrap;gap:1.1rem;font-size:var(--t-small);color:var(--muted)}
.menu__social a{transition:color .3s}
.menu__social a:hover{color:var(--ivory)}
/* the little arrow that says "this one has children" */
.menu__has{align-self:center;flex:none;width:clamp(14px,1.1vw,18px);height:1px;
  background:currentColor;opacity:.3;position:relative;
  transform-origin:left;transform:scaleX(.5);
  transition:transform .55s var(--e-out-expo),opacity .35s var(--e-out-cubic)}
.menu__has::after{content:'';position:absolute;right:0;top:50%;width:5px;height:5px;
  border-top:1px solid currentColor;border-right:1px solid currentColor;
  transform:translate(1px,-50%) rotate(45deg)}
.menu__links a:hover .menu__has,.menu__links a.is-live .menu__has{transform:scaleX(1);opacity:.8}

/* ---------- 8c. MENU SUB-PANEL ----------------------------------------- */
/* One stack, one child visible. Swapping is a crossfade rather than a
   re-layout, so the column never jumps while the pointer travels the list. */
.menu__side{position:relative}
.subs{display:flex;flex-direction:column;gap:clamp(14px,2.4vh,28px)}
.subs[hidden]{display:none}
.subs__k{margin-bottom:-.4rem}
.subs__list{display:grid;gap:.1rem}
.subs__list a{display:flex;align-items:center;gap:.7rem;padding:.5rem 0;position:relative;
  font-family:var(--f-display);font-weight:600;font-stretch:100%;
  font-size:clamp(.95rem,1.35vw,1.32rem);letter-spacing:-.012em;color:rgba(244,238,228,.72);
  transition:color .32s var(--e-out-cubic),transform .5s var(--e-out-expo)}
.subs__list a::before{content:'';flex:none;width:0;height:1px;background:var(--ember);
  transition:width .45s var(--e-out-expo)}
.subs__list a:hover{color:var(--ivory);transform:translateX(4px)}
.subs__list a:hover::before{width:14px}
.subs__list .soon{font-size:.56rem;margin-left:auto}
.subs__note{color:var(--muted-2);line-height:1.5;max-width:34ch}
/* the panel content arrives row by row when it is swapped in */
.subs.is-on > *{animation:subsIn .55s var(--e-out-expo) backwards}
.subs.is-on > *:nth-child(2){animation-delay:.05s}
.subs.is-on > *:nth-child(3){animation-delay:.1s}
.subs.is-on > *:nth-child(4){animation-delay:.15s}
@keyframes subsIn{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}

.menu__sub{display:flex;flex-wrap:wrap;gap:.35rem 1.1rem;font-size:var(--t-small);color:var(--muted)}
.menu__sub a{position:relative;transition:color .3s}
.menu__sub a::after{content:'';position:absolute;left:0;right:0;bottom:-3px;height:1px;
  background:currentColor;transform:scaleX(0);transform-origin:right;
  transition:transform .5s var(--e-out-expo)}
.menu__sub a:hover{color:var(--ivory)}
.menu__sub a:hover::after{transform:scaleX(1);transform-origin:left}

.menu__portal{display:flex;flex-direction:column;gap:.3rem;padding:.9rem 1.1rem;border-radius:14px;
  border:1px solid rgba(226,85,30,.28);background:rgba(226,85,30,.07);
  transition:background-color .45s var(--e-out-cubic),border-color .45s var(--e-out-cubic),
             transform .7s var(--e-out-expo)}
.menu__portal:hover{background:rgba(226,85,30,.16);border-color:rgba(226,85,30,.5);
  transform:translateY(-2px)}
.menu__portal-host{display:inline-flex;align-items:center;gap:.5rem;
  font-family:var(--f-mono);font-size:var(--t-small);color:var(--ivory);letter-spacing:.04em}
.menu__portal-host svg{width:13px;height:13px;transition:transform .55s var(--e-out-expo)}
.menu__portal:hover .menu__portal-host svg{transform:translate(3px,-3px)}

.menu__meta{margin-top:auto;color:var(--muted-2)}

/* ---------- 8b. "SOON" BADGE ------------------------------------------- */
/* Used on every entry point that is not live yet. The link still resolves —
   the target page explains what is coming and when — so the badge is a
   promise, not a dead end.                                                */
.soon{display:inline-flex;align-items:center;gap:.35em;flex:none;
  padding:.28em .6em;border-radius:999px;
  font-family:var(--f-mono);font-size:.62em;text-transform:uppercase;letter-spacing:.14em;
  line-height:1;color:var(--ember-lo);
  background:rgba(226,85,30,.12);border:1px solid rgba(226,85,30,.32)}
.soon::before{content:'';width:.42em;height:.42em;border-radius:50%;background:currentColor;
  animation:soonPulse 2.4s ease-in-out infinite}
@keyframes soonPulse{0%,100%{opacity:.35;transform:scale(.85)}50%{opacity:1;transform:scale(1.15)}}
.menu__links .soon{font-size:clamp(.5rem,.72vw,.66rem);align-self:center;
  transform:translate3d(0,120%,0);
  transition:transform .9s var(--e-out-quint)}
.footer__col .soon,.footer .soon{font-size:.58rem;margin-left:.5rem}
.footer__col a.is-soon{display:inline-flex;align-items:center}
@media (prefers-reduced-motion:reduce){.soon::before{animation:none;opacity:.8}}

/* the cookie panel opens from a real button, so it needs the link's look */
.footer__cookiebtn{font:inherit;color:inherit;letter-spacing:inherit;
  text-transform:inherit;text-align:left;padding:0;background:none;border:0;cursor:pointer}

/* ---------- 9. BUTTONS --------------------------------------------------- */
.btn{position:relative;display:inline-flex;align-items:center;gap:.85rem;
  padding:1rem 1.65rem;border-radius:100px;overflow:hidden;isolation:isolate;
  font-family:var(--f-mono);font-size:var(--t-label);text-transform:uppercase;
  letter-spacing:.14em;line-height:1;white-space:nowrap;border:1px solid transparent;will-change:transform}
.btn__fill{position:absolute;inset:0;z-index:-1;border-radius:inherit;
  transform:translate3d(0,101%,0);transition:transform .62s var(--e-out-expo)}
.btn:hover .btn__fill,.btn:focus-visible .btn__fill{transform:translate3d(0,0,0)}

/* ---- the brew ----------------------------------------------------------
   The fill rises like liquid and now behaves like it. Three things make it
   read as real coffee rather than a coloured rectangle sliding up:

     1. the surface is two scalloped rows at different tile widths, scrolling
        at different speeds — no single repeating wave you can lock onto
     2. the level itself bobs, so the meniscus is never a straight line
     3. a foam band sits on the crest and bubbles rise through the body

   Every one of those is driven by a custom property, and initBrew() rewrites
   all of them on each hover. Two buttons never brew alike, and the same button
   never brews the same way twice.                                          */
.btn{--fillc:var(--ivory);--bubblec:rgba(11,8,6,.26);--foamc:rgba(255,255,255,.5);
  --w1s:26px; --w2s:17px; --w1x:0px; --w2x:0px;
  --wdur:1.15s; --w2dur:.78s; --bobdur:2.4s; --bobamt:2.5px;
  --bdur:2s; --b1:9px; --b2:31px; --b3:57px; --b4:78px;
  --bs1:37px; --bs2:53px; --bs3:69px; --bs4:44px;
  /* per-lane bubble radius and sideways drift. The drift is what makes each
     hover read as a different *pour*: bubbles rise on four slanted paths
     instead of four vertical rails, and the slant is re-rolled every time. */
  --br1:2.1px; --br2:1.5px; --br3:2.7px; --br4:1.2px;
  --bx1:0px; --bx2:0px; --bx3:0px; --bx4:0px}

/* 1 + 2 — the surface */
.btn__fill::before{
  content:'';position:absolute;left:-12%;right:-12%;top:-8px;height:15px;
  /* two scalloped rows at different tile widths, the second sitting 3 px
     lower: their union is a wobbly surface rather than one clean repeat */
  background-image:
    radial-gradient(circle at 50% 100%,var(--fillc) 7px,rgba(0,0,0,0) 7.7px),
    radial-gradient(circle at 50% 100%,var(--fillc) 5px,rgba(0,0,0,0) 5.7px);
  background-size:var(--w1s) 15px,var(--w2s) 12px;
  background-position:var(--w1x) bottom,var(--w2x) bottom;
  background-repeat:repeat-x,repeat-x;
  opacity:0;transition:opacity .25s var(--e-out-cubic)}
.btn:hover .btn__fill::before,.btn:focus-visible .btn__fill::before{
  opacity:1;
  animation:brewCrest var(--wdur) linear infinite,
            brewCrest2 var(--w2dur) linear infinite,
            brewBob var(--bobdur) ease-in-out infinite}
@keyframes brewCrest{to{background-position-x:var(--w1s),var(--w2x)}}
@keyframes brewCrest2{to{background-position-x:var(--w1x),calc(-1 * var(--w2s))}}
@keyframes brewBob{0%,100%{transform:translateY(0)}50%{transform:translateY(var(--bobamt))}}

/* 3a — foam riding the crest */
.btn__fill::after{
  content:'';position:absolute;left:-12%;right:-12%;top:-13px;height:13px;
  /* three tile widths that do not share a factor, so the froth never lines up
     into a visible repeat */
  background-image:
    radial-gradient(circle,var(--foamc) 2.2px,rgba(0,0,0,0) 2.7px),
    radial-gradient(circle,rgba(255,255,255,.3) 1.5px,rgba(0,0,0,0) 1.9px),
    radial-gradient(circle,rgba(255,255,255,.2) 3.1px,rgba(0,0,0,0) 3.6px);
  background-size:9px 13px,6px 13px,15px 13px;
  background-position:var(--w2x) 7px,var(--w1x) 4px,calc(var(--w1x) * -1) 9px;
  background-repeat:repeat-x;
  filter:blur(.85px);
  opacity:0;transition:opacity .3s .12s var(--e-out-cubic)}
.btn:hover .btn__fill::after,.btn:focus-visible .btn__fill::after{
  opacity:.7;animation:brewFoam calc(var(--wdur) * 1.6) linear infinite,
                       brewBob var(--bobdur) ease-in-out infinite}
@keyframes brewFoam{
  to{background-position-x:calc(var(--w2x) + 9px),calc(var(--w1x) - 6px),
                           calc(var(--w1x) * -1 + 15px)}}

/* 3b — bubbles rising through the body, four tile heights so they travel at
   four different speeds out of a single element */
.btn::after{
  content:'';position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;
  opacity:0;transition:opacity .35s var(--e-out-cubic) .18s;
  background-image:
    radial-gradient(circle,var(--bubblec) var(--br1),rgba(0,0,0,0) calc(var(--br1) + .5px)),
    radial-gradient(circle,var(--bubblec) var(--br2),rgba(0,0,0,0) calc(var(--br2) + .5px)),
    radial-gradient(circle,var(--bubblec) var(--br3),rgba(0,0,0,0) calc(var(--br3) + .5px)),
    radial-gradient(circle,var(--bubblec) var(--br4),rgba(0,0,0,0) calc(var(--br4) + .5px));
  background-size:var(--bs1) 58px,var(--bs2) 82px,var(--bs3) 112px,var(--bs4) 70px;
  background-position:var(--b1) 100%,var(--b2) 100%,var(--b3) 100%,var(--b4) 100%;
  background-repeat:repeat-x}
.btn:hover::after,.btn:focus-visible::after{opacity:1;animation:brewRise var(--bdur) linear infinite}
@keyframes brewRise{
  to{background-position:
       calc(var(--b1) + var(--bx1)) -58px,
       calc(var(--b2) + var(--bx2)) -82px,
       calc(var(--b3) + var(--bx3)) -112px,
       calc(var(--b4) + var(--bx4)) -70px}
}
/* a press pushes the level up a beat and speeds the bubbles, so a click reads
   as a poured shot rather than as the same hover held down */
.btn.is-tapped .btn__fill{transition-duration:.32s}
.btn.is-tapped::after{animation-duration:calc(var(--bdur) * .55)}

/* ---- the detail pass ----------------------------------------------------
   Four additions, each of them a thing a physical control does:

     1. a specular highlight that tracks the pointer across the face, so the
        surface catches the light instead of being uniformly lit
     2. the arrow leaves the button and comes back in from the other corner
        rather than sliding out and teleporting back on mouse-out
     3. a press squashes and rebounds — on the `scale` property, NOT on
        `transform`, because GSAP owns the transform matrix on the magnetic
        buttons and an animation would drop their offset for its duration
     4. a shadow that lifts on hover and flattens under the press

   The magnetic tilt lives in main.js, for the same GSAP reason.          */
.btn{--mx:50%;--my:50%;
  box-shadow:0 0 0 rgba(0,0,0,0);
  transition:color .5s var(--e-out-cubic),border-color .5s var(--e-out-cubic),
             box-shadow .55s var(--e-out-expo),scale .4s var(--e-out-expo)}
.btn::before{content:'';position:absolute;inset:0;z-index:0;border-radius:inherit;
  pointer-events:none;opacity:0;transition:opacity .45s var(--e-out-cubic);
  background:radial-gradient(9rem 7rem at var(--mx) var(--my),
    rgba(255,255,255,.24),rgba(255,255,255,0) 68%)}
.btn:hover::before,.btn:focus-visible::before{opacity:1}
/* the fill is the one child that must stay behind the sheen */
.btn > :not(.btn__fill){position:relative;z-index:1}
.btn:hover,.btn:focus-visible{box-shadow:0 14px 34px rgba(0,0,0,.3)}

.btn:hover .btn__arrow,.btn:focus-visible .btn__arrow{
  transform:none;animation:btnArrow .66s var(--e-out-expo)}
@keyframes btnArrow{
  0%{transform:translate3d(0,0,0);opacity:1}
  40%{transform:translate3d(.62em,-.62em,0);opacity:0}
  41%{transform:translate3d(-.62em,.62em,0);opacity:0}
  100%{transform:translate3d(0,0,0);opacity:1}}

.btn:active{scale:.985}
.btn.is-tapped{animation:btnPress .52s var(--e-out-expo)}
.btn.is-tapped:hover{box-shadow:0 6px 16px rgba(0,0,0,.34)}
@keyframes btnPress{0%{scale:.972}52%{scale:1.014}100%{scale:1}}

@media (prefers-reduced-motion:reduce){
  .btn::after,.btn__fill::before,.btn__fill::after{display:none}
  .btn:active{transform:none;scale:1}
  .btn::before{display:none}
  .btn.is-tapped{animation:none}
  .btn:hover .btn__arrow,.btn:focus-visible .btn__arrow{animation:none;transform:none}
  .btn:hover,.btn:focus-visible{box-shadow:none}
}
/* The roll mask was exactly 1em tall, which is shorter than the line box of
   the mono face it holds. Anything above the x-height got shaved: the umlaut
   on ÖFFNEN lost its dots, and "PORTAL ÖFFNEN" read as a smudge. The mask is
   now the real line height, and the roll distance follows it. */
.btn__roll{position:relative;display:block;overflow:hidden;
  height:1.32em;line-height:1.32}
.btn__roll span{display:block;line-height:1.32;transition:transform .6s var(--e-out-expo)}
.btn__roll span + span{position:absolute;inset:0;transform:translate3d(0,101%,0)}
.btn:hover .btn__roll span{transform:translate3d(0,-101%,0)}
.btn:hover .btn__roll span + span{transform:translate3d(0,0,0)}
.btn__arrow{width:1.05em;height:1.05em;flex:none;transition:transform .55s var(--e-out-expo)}
.btn:hover .btn__arrow{transform:translate3d(.28em,-.28em,0)}
.btn--primary{background:var(--ember);color:#fff;--fillc:var(--ivory);--bubblec:rgba(226,85,30,.5)}
.btn--primary .btn__fill{background:var(--ivory)}
.btn--primary:hover{color:var(--ink)}
.btn--ghost{border-color:rgba(244,238,228,.28);color:var(--ivory);--fillc:var(--ivory);--bubblec:rgba(109,81,63,.4)}
.btn--ghost .btn__fill{background:var(--ivory)}
.btn--ghost:hover{color:var(--ink);border-color:var(--ivory)}
.btn--ink{border-color:rgba(11,8,6,.24);color:var(--ink);--fillc:var(--ink);--bubblec:rgba(244,238,228,.32)}
.btn--ink .btn__fill{background:var(--ink)}
.btn--ink:hover{color:var(--ivory);border-color:var(--ink)}
.btn--sm{padding:.7rem 1.1rem}
.btn--lg{padding:1.22rem 2rem;font-size:calc(var(--t-label) * 1.06)}
.btn[disabled]{opacity:.45;pointer-events:none}
.btn-row{display:flex;flex-wrap:wrap;gap:clamp(10px,1vw,16px)}

/* ---------- 10. HERO ----------------------------------------------------- */
.hero{position:relative;height:100svh;min-height:600px;overflow:hidden;isolation:isolate}
.hero__media{position:absolute;inset:0;z-index:0;overflow:hidden}
.hero__video{width:100%;height:100%;object-fit:cover;object-position:50% 46%;
  will-change:transform,filter;transform:scale(1.3);filter:brightness(0)}
.hero__scrim{position:absolute;inset:0;z-index:1;pointer-events:none}
.hero__scrim::before{content:'';position:absolute;inset:0;
  background:linear-gradient(to bottom,rgba(11,8,6,.72) 0%,rgba(11,8,6,.3) 20%,rgba(11,8,6,0) 46%),
             linear-gradient(to top,rgba(11,8,6,.84) 0%,rgba(11,8,6,.36) 28%,rgba(11,8,6,0) 62%)}
/* a soft column of shade behind the copy so the type never fights the crowd */
.hero__scrim::after{content:'';position:absolute;inset:0;
  background:linear-gradient(100deg,rgba(11,8,6,.78) 0%,rgba(11,8,6,.5) 26%,rgba(11,8,6,0) 56%)}

.hero__inner{position:relative;z-index:2;height:100%;display:flex;flex-direction:column;
  padding-block:calc(var(--nav-h) + 1rem) clamp(84px,10vh,132px)}
.hero__eyebrow{display:flex;align-items:center;gap:.8rem;padding-top:clamp(12px,3vw,44px)}
.hero__eyebrow .label{color:rgba(244,238,228,.72)}
.hero__eyebrow .dot{width:5px;height:5px;border-radius:50%;background:var(--ember);flex:none;
  box-shadow:0 0 0 0 rgba(226,85,30,.6);animation:dotpulse 2.6s var(--e-out-cubic) infinite}
@keyframes dotpulse{0%{box-shadow:0 0 0 0 rgba(226,85,30,.55)}70%,100%{box-shadow:0 0 0 10px rgba(226,85,30,0)}}

/* the copy holds the left column; the right stays clear for the cup */
.hero__body{flex:1;display:flex;align-items:flex-end;padding-bottom:clamp(24px,3vw,48px)}
.hero__col{width:min(100%,58ch);max-width:56%}
.hero__title{margin-bottom:clamp(18px,2.2vw,32px)}
/* The mask has to clip vertically (that is the whole point of the rise) but a
   heavy display face carries side bearings past its advance width, and clipping
   those cost the A of EUROPA its right diagonal. The box is widened on the
   right without moving the text. */
.hero__title .hline{display:block;overflow:hidden;
  padding-bottom:.06em;margin-bottom:-.06em;
  padding-right:.08em;margin-right:-.08em}
.hero__d{font-size:clamp(2.5rem,7.4vw,8.6rem);white-space:nowrap;
  text-shadow:0 2px 44px rgba(11,8,6,.5),0 0 18px rgba(11,8,6,.35)}
/* brewing: each word fills from the bottom like a cup under the group head,
   with a crema-coloured meniscus riding the top of the level */
.hero__title .hword{display:inline-block;--brew:0%;color:transparent;
  background-image:linear-gradient(to top,
    var(--ivory) 0%, var(--ivory) calc(var(--brew) - 2%),
    var(--ember-lo) calc(var(--brew) - 2%), var(--ember-lo) var(--brew),
    rgba(244,238,228,.14) var(--brew), rgba(244,238,228,.14) 100%);
  -webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;
  will-change:transform,opacity}
@supports not ((-webkit-background-clip:text) or (background-clip:text)){
  .hero__title .hword{color:var(--ivory);-webkit-text-fill-color:currentColor;background-image:none}
}

.hero__sub{max-width:38ch;color:rgba(244,238,228,.9);font-size:var(--t-lead);line-height:1.42;
  text-shadow:0 1px 24px rgba(11,8,6,.6)}
.hero__btns{margin-top:clamp(20px,2.4vw,34px)}

/* One cue, centred on its own, with a rail whose dot travels down it. The old
   row carried a hairline and two more labels that pulled the eye away from the
   headline for information the page repeats further down anyway.          */
.hero__foot{display:flex;justify-content:center;padding-top:clamp(10px,1.4vw,18px)}
/* The cue is a drip, not an arrow: a bead forms at the top of the hairline,
   falls, and lands in a ring that pulses out as it hits — the same gesture the
   whole page is built on. The word underneath rides that beat rather than
   sitting still, and the letters stagger apart on hover.                   */
.hero__scroll{position:relative;display:inline-flex;flex-direction:column;align-items:center;
  gap:.62rem;padding:.4rem 1.1rem .3rem;background:none;border:0;cursor:pointer;
  color:rgba(244,238,228,.66);transition:color .5s var(--e-out-cubic)}
.hero__scroll:hover{color:var(--ivory)}
.hero__scroll:focus-visible{outline:2px solid var(--ember);outline-offset:6px;border-radius:12px}

/* A pour, not an arrow. A hairline stands in for the stream; an ember segment
   runs down it with a bright head, and where it lands a flat ripple opens
   sideways — a surface being hit, which is what a drop actually does. The
   earlier version landed in a circle, and a circle sitting at the bottom of a
   vertical line just reads as a lowercase o.                               */
.hero__scroll-rail{position:relative;display:block;width:1px;height:clamp(36px,4.8vh,56px);
  background:linear-gradient(180deg,
    rgba(244,238,228,0) 0%,rgba(244,238,228,.26) 30%,rgba(244,238,228,.26) 70%,rgba(244,238,228,0) 100%)}

/* the stream: a short segment with the light concentrated at its leading edge */
.hero__scroll-rail i{position:absolute;left:50%;top:0;translate:-50% 0;
  width:1.5px;height:26%;border-radius:2px;
  background:linear-gradient(180deg,rgba(226,85,30,0),rgba(226,85,30,.55) 45%,#FF9A5E);
  box-shadow:0 0 9px 1px rgba(226,85,30,.5);
  transform-origin:50% 100%;
  animation:heroPour 2.6s cubic-bezier(.5,0,.35,1) infinite}
@keyframes heroPour{
  0%      {transform:translate(-50%,-100%) scaleY(.35);opacity:0}
  14%     {transform:translate(-50%,-40%)  scaleY(1);  opacity:1}
  58%     {transform:translate(-50%,290%)  scaleY(1);  opacity:1}
  70%     {transform:translate(-50%,385%)  scaleY(.35);opacity:0}  /* it lands */
  100%    {transform:translate(-50%,385%)  scaleY(.35);opacity:0}}

/* the surface: two flat ripples opening outwards as the stream arrives */
.hero__scroll-rail::before,.hero__scroll-rail::after{
  content:'';position:absolute;left:50%;bottom:-2px;
  width:9px;height:4px;margin-left:-4.5px;border-radius:50%;
  border:1px solid rgba(240,138,84,.9);opacity:0}
.hero__scroll-rail::before{animation:heroRipple 2.6s cubic-bezier(.15,.75,.3,1) infinite}
.hero__scroll-rail::after{animation:heroRipple 2.6s cubic-bezier(.15,.75,.3,1) infinite;
  animation-delay:.13s;border-color:rgba(244,238,228,.42)}
@keyframes heroRipple{
  0%,56%{transform:scale(.5,.5);opacity:0}
  64%   {transform:scale(1.15,1);opacity:.9}
  100%  {transform:scale(3.6,1.35);opacity:0}}

.hero__scroll-txt{display:flex;letter-spacing:.22em;white-space:nowrap;
  transition:letter-spacing .7s var(--e-out-expo)}
.hero__scroll:hover .hero__scroll-txt{letter-spacing:.32em}
/* one span per letter, split in JS; the wave runs left to right just after the
   drop lands, so the word answers the pour instead of ignoring it */
.hero__scroll-txt b{display:inline-block;font-weight:inherit;
  animation:heroWave 2.6s var(--e-in-out-quart) infinite;
  animation-delay:calc(var(--i) * .034s)}
.hero__scroll-txt b.is-space{width:.42em}
@keyframes heroWave{
  0%,54%,100%{transform:translateY(0);opacity:.76}
  66%{transform:translateY(-2.5px);opacity:1}
  82%{transform:translateY(0);opacity:.92}}
@media (prefers-reduced-motion:reduce){
  .hero__scroll-rail i,.hero__scroll-rail::before,.hero__scroll-rail::after,
  .hero__scroll-txt b{animation:none}
  .hero__scroll-rail i{opacity:.85;transform:translate(-50%,120%)}
}

/* the plume, re-laid around the type */
.hero__steam{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:50% 46%;pointer-events:none;
  mix-blend-mode:screen;opacity:0;transition:opacity 1.4s var(--e-out-cubic)}
/* behind the copy: full strength, this is the steam you read */
.hero__steam--back{z-index:1}
.hero__steam--back.is-on{opacity:.92}
/* in front of the copy: a thin pass, and thinner still across the headline
   column, so a wisp crosses the letters instead of erasing them */
/* The headline column runs to about 53 % of the viewport at the narrowest
   desktop width, and the last letter of EUROPA is exactly where the plume
   rises. The front pass is therefore held to a whisper across the whole left
   60 % and only reaches full strength past 82 %, where there is nothing to
   read — a wisp still crosses the type, it just cannot swallow a letter. */
.hero__steam--front{z-index:3;
  -webkit-mask-image:linear-gradient(90deg,rgba(0,0,0,.10) 0%,rgba(0,0,0,.10) 60%,rgba(0,0,0,.42) 72%,#000 84%);
  mask-image:linear-gradient(90deg,rgba(0,0,0,.10) 0%,rgba(0,0,0,.10) 60%,rgba(0,0,0,.42) 72%,#000 84%)}
.hero__steam--front.is-on{opacity:.58}

/* ---------- 11. CHAPTER + FALLING LEAVES (reference a-83 — 1:1) --------- */
.chapter{overflow:clip}
/* The leaves fall past the bottom of the section, and `overflow:clip` on the
   chapter cut them in half against the next section's edge. Fading the whole
   wrapper out over its last fifth means a leaf dissolves into the paper before
   it reaches the boundary instead of being sliced off by it. */
.leaf_wrapper{
  -webkit-mask-image:linear-gradient(180deg,#000 0%,#000 74%,rgba(0,0,0,.45) 88%,transparent 97%);
  mask-image:linear-gradient(180deg,#000 0%,#000 74%,rgba(0,0,0,.45) 88%,transparent 97%)}
/* verbatim from the reference stylesheet */
.leaf_wrapper picture{display:block}
.leaf_wrapper picture img{width:100%;height:auto;display:block}
.leaf_wrapper{z-index:2;justify-content:center;align-items:flex-start;height:100vh;
  display:flex;position:sticky;top:0;overflow:hidden;pointer-events:none}
.leaf-1{filter:saturate(80%);width:10rem;margin-right:80vw;position:absolute;inset:0% auto auto}
.leaf-2{filter:saturate(80%);width:10rem;margin-right:50vw;position:absolute;inset:0% auto auto;transform:scale(.7)}
.leaf-3{filter:saturate(80%);width:12rem;margin-left:30vw;position:absolute;inset:0% auto auto}
.leaf-4{filter:saturate(80%);width:8rem;margin-left:70vw;position:absolute;inset:0% auto auto}
@media screen and (max-width:991px){
  .leaf-2{width:8rem} .leaf-3{width:10rem} .leaf-4{width:6rem}
}
.chapter__grid{position:relative;z-index:3;margin-top:-100vh;
  display:grid;grid-template-columns:repeat(12,1fr);gap:var(--gutter);
  row-gap:clamp(56px,9vw,150px);padding-block:clamp(40px,7vw,120px)}
.chapter__head{grid-column:1/span 3;display:flex;flex-direction:column;gap:.6rem}
.chapter__lead{grid-column:4/span 9}
.chapter__body{grid-column:4/span 5}
.chapter__facts{grid-column:1/span 12;display:grid;grid-template-columns:repeat(3,1fr);
  gap:var(--gutter);border-top:1px solid var(--hairline-dark);padding-top:clamp(24px,3vw,44px)}
.fact{display:flex;flex-direction:column;gap:.7rem}
.fact .label{color:#3D352E}
.fact__v{font-family:var(--f-display);font-weight:800;font-stretch:112%;
  font-size:clamp(2.4rem,6vw,5.4rem);line-height:.9;letter-spacing:-.035em;color:var(--ink)}
.chapter__quote{grid-column:2/span 9;text-align:left}
.chapter__quote .display{color:var(--ink)}
.chapter__quote .mask:last-child .display{color:var(--ember)}

/* ---------- 12. BEAN FIELD (reference a-80 — 1:1) ----------------------- */
.beanworld{position:relative;isolation:isolate;
  background:radial-gradient(120% 80% at 50% 40%,#1C120B 0%,#0B0806 68%),var(--ink)}
.legacy__track{height:420vh;position:relative}
.legacy__sticky{position:sticky;top:0;height:100svh;display:grid;place-items:center;overflow:hidden}
/* flex-centred box + per-bean margins: exactly how the reference positions them */
.beans{position:absolute;inset:0;display:flex;justify-content:center;align-items:center;
  overflow:hidden;pointer-events:none}
.beans picture{display:block;--sat:100%;filter:saturate(var(--sat));will-change:transform}
.beans picture img{width:100%;height:auto;display:block}
.bean-1{z-index:3;width:11vw;margin-right:34vw;position:absolute}
.bean-2{z-index:3;width:11vw;margin-bottom:29rem;margin-right:60vw;position:absolute}
.bean-3{z-index:3;width:5vw;margin-top:25rem;margin-right:40vw;position:absolute}
.bean-4{z-index:3;width:16vw;margin-top:25rem;margin-right:80vw;position:absolute}
.bean-5{z-index:3;width:8vw;margin-bottom:15rem;margin-right:90vw;position:absolute}
.bean-6{z-index:3;width:14vw;margin-bottom:20rem;margin-left:30vw;position:absolute}
.bean-7{z-index:3;width:15vw;margin-bottom:-15rem;margin-left:60vw;position:absolute}
.bean-8{z-index:3;width:9vw;margin-bottom:10rem;margin-left:70vw;position:absolute}
.bean-9{z-index:3;width:7vw;margin-bottom:-6rem;margin-left:90vw;position:absolute}
.beanworld__vignette{position:absolute;inset:0;z-index:1;pointer-events:none;
  background:radial-gradient(56% 46% at 50% 50%,rgba(11,8,6,.66) 0%,rgba(11,8,6,.14) 62%,rgba(11,8,6,0) 100%)}

/* ---------- 13. LEGACY TIMELINE ----------------------------------------- */
.legacy__stage{position:relative;z-index:2;width:100%;height:clamp(220px,30vh,340px);text-align:center}
.legacy__item{position:absolute;inset:0;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:.55rem;opacity:0}
.legacy__item > *{max-width:100%}
.legacy__item .year{font-family:var(--f-mono);font-size:clamp(.7rem,1vw,.86rem);letter-spacing:.34em;color:var(--ember)}
/* NOT .city — that class belongs to the cities carousel further down, and its
   fixed flex width silently clipped this headline's box while the glyphs kept
   painting past it, which pushed the whole word off centre on wide screens. */
.legacy__city{display:block;max-width:100%;
  font-family:var(--f-display);font-weight:800;font-stretch:118%;text-transform:uppercase;
  font-size:clamp(2.3rem,9.4vw,9.5rem);line-height:.84;letter-spacing:-.035em;color:var(--ivory);
  white-space:nowrap;text-align:center}
.legacy__city--ember{color:var(--ember)}
.legacy__item .note{font-size:var(--t-small);color:var(--muted)}
.legacy__rail{position:absolute;z-index:5;left:var(--gutter);right:var(--gutter);
  bottom:clamp(30px,5vw,64px);display:flex;align-items:center;gap:.9rem}
.legacy__rail .bar{flex:1;height:1px;background:rgba(244,238,228,.16);position:relative}
.legacy__rail .bar i{position:absolute;inset:0;background:var(--ember);transform:scaleX(0);transform-origin:0 50%}

/* ---------- 13b. ATMOSPHERE BAND ---------------------------------------- */
.atmos{position:relative;background:var(--ink);padding-block:clamp(60px,8vw,140px);overflow:clip}
.atmos__frame{position:relative;width:100%}
.atmos__clip{
  position:relative;overflow:hidden;
  clip-path:inset(var(--clip,14%) var(--clipx,8%) round 2px);
  will-change:clip-path;
}
.atmos__img{width:100%;height:auto;display:block;transform:scale(var(--z,1.12));
  transform-origin:50% 50%;will-change:transform}
.atmos__scrim{position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to top,rgba(11,8,6,.86) 0%,rgba(11,8,6,.24) 42%,rgba(11,8,6,.1) 100%)}
.atmos__over{
  position:absolute;left:0;right:0;bottom:clamp(24px,3.4vw,56px);z-index:2;
  padding-inline:calc(var(--gutter) + clamp(0px,4vw,64px));
}
.atmos__q{
  margin-top:.9rem;color:var(--ivory);max-width:24ch;
  font-family:var(--f-display);font-weight:800;font-stretch:112%;text-transform:uppercase;
  font-size:clamp(1.5rem,3.4vw,3.2rem);line-height:.96;letter-spacing:-.025em;
  text-shadow:0 2px 30px rgba(11,8,6,.6);
}

/* ---------- 14. 2027 SEQUENCE ------------------------------------------- */
.yearseq{position:relative;background:var(--ink)}
.yearseq__track{height:300vh}
.yearseq__sticky{--glow:0;position:sticky;top:0;height:100svh;display:grid;place-items:center;overflow:hidden;
  background:radial-gradient(90% 70% at 50% 62%,rgba(226,85,30,calc(.05 + .22 * var(--glow))) 0%,rgba(11,8,6,0) 70%)}
.yearseq__digits{display:flex;justify-content:center;gap:clamp(2px,.6vw,12px);
  font-family:var(--f-display);font-weight:800;font-stretch:118%;
  font-size:clamp(4rem,19vw,19rem);line-height:.8;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
/* The slot used to be a hard .66em wide, which is narrower than a tabular
   digit at 118 % width — the last glyph was clipped and the group sat left of
   centre. It now takes its width from a hidden glyph, so it is exactly right at
   every size and in every weight.                                          */
.digit{position:relative;display:block;overflow:hidden;height:.86em}
.digit__size{display:block;visibility:hidden;height:.86em;line-height:.86em;
  padding-inline:.04em;pointer-events:none}
.digit > span{position:absolute;inset:0;display:grid;place-items:center;color:var(--ivory);
  will-change:transform,opacity}
.yearseq__caption{margin-top:clamp(14px,2vw,28px);text-align:center;
  font-family:var(--f-display);font-weight:700;font-stretch:112%;text-transform:uppercase;
  font-size:clamp(1.2rem,3.4vw,3.2rem);letter-spacing:.24em;color:var(--ember);opacity:0}

/* ---------- 15. EUROPE — 3D DOT GLOBE ----------------------------------- */
.europe{position:relative;background:var(--ink);color:var(--ivory)}
.europe__track{height:340vh;position:relative}
.europe__sticky{position:sticky;top:0;height:100svh;overflow:hidden;isolation:isolate}
/* the globe lives in the right half so it never sits under the headline */
.globe{position:absolute;inset:0;z-index:1;transition:left .6s var(--e-out-quint)}
.globe__canvas{width:100%;height:100%;display:block}
/* Two jobs: sink the limb into the page, and dissolve the canvas's own left
   edge. Once the camera closes in on Europe the dot field runs right off the
   canvas, and without this the crop prints as a hard vertical seam beside the
   headline. */
.globe::after{content:'';position:absolute;inset:0;z-index:2;pointer-events:none;
  background:
    linear-gradient(90deg,rgba(11,8,6,1) 0%,rgba(11,8,6,.72) 6%,rgba(11,8,6,0) 20%),
    radial-gradient(120% 90% at 50% 50%,rgba(11,8,6,0) 40%,rgba(11,8,6,.55) 100%)}
.globe__labels{position:absolute;inset:0;z-index:3;pointer-events:none}

/* one chip per city, moved every frame by the projection */
.gl{position:absolute;top:0;left:0;width:0;height:0;opacity:0;
  transition:opacity .5s var(--e-out-cubic)}
.gl.is-on{opacity:1}
.gl__box{position:absolute;display:flex;align-items:baseline;gap:.42rem;white-space:nowrap;
  padding:.3rem .55rem;border-radius:999px;
  background:rgba(11,8,6,.62);border:1px solid rgba(244,238,228,.16);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  font-family:var(--f-mono);font-size:clamp(.56rem,.66vw,.7rem);
  text-transform:uppercase;letter-spacing:.1em;line-height:1}
.gl__name{font-weight:400;color:var(--ivory)}
.gl__note{font-style:normal;color:var(--muted)}
.gl--r .gl__box{left:16px;top:-.85em}
.gl--l .gl__box{right:16px;top:-.85em}
.gl--t .gl__box{left:50%;transform:translateX(-50%);bottom:15px}
.gl--b .gl__box{left:50%;transform:translateX(-50%);top:15px}
.gl--hero .gl__box{border-color:rgba(226,85,30,.55);background:rgba(226,85,30,.2);
  box-shadow:0 6px 24px rgba(226,85,30,.28)}
.gl--hero .gl__name{color:#fff;font-weight:400}
.gl--hero .gl__note{color:var(--ember-lo)}

.globe__fallback{position:absolute;inset:0;display:grid;place-items:center;padding:var(--gutter)}
.globe__fallback[hidden]{display:none!important}
.globe__fallback svg{width:100%;max-width:900px;max-height:70vh;height:auto;overflow:visible}
.globe__fallback .eu-tag{fill:var(--muted)}
.globe__fallback g[stroke]{stroke:rgba(244,238,228,.09)!important}
.globe__fallback .eu-node{fill:var(--ivory)}
.globe__fallback .eu-node--live{fill:var(--ember)}
.globe__fallback .eu-link{stroke:var(--ember);stroke-width:.5;fill:none;opacity:.8}
.globe__fallback .eu-pulse{fill:none;stroke:var(--ember);stroke-width:.45}
.globe__fallback .eu-tag--live{fill:var(--ivory)}

.europe__overlay{position:relative;z-index:4;height:100%;display:flex;flex-direction:column;
  justify-content:space-between;padding-block:calc(var(--nav-h) + clamp(20px,4vh,54px)) clamp(74px,10vh,120px);
  pointer-events:none}
.europe__overlay a,.europe__overlay button{pointer-events:auto}
.europe__head{max-width:min(44vw,700px)}
.europe__h{margin-top:1.2rem}
.europe__lead{margin-top:1.5rem;color:rgba(244,238,228,.72);max-width:32ch}
.europe__legend{display:flex;flex-wrap:wrap;gap:clamp(14px,2vw,32px)}
.europe__legend div{display:flex;align-items:center;gap:.55rem}
.europe__legend i{width:6px;height:6px;border-radius:50%;background:rgba(244,238,228,.4);display:block}
.europe__legend i.on{background:var(--ember);box-shadow:0 0 0 4px rgba(226,85,30,.2)}
@media (min-width:1100px){
  .globe{left:30%}
  .globe::after{background:
    linear-gradient(90deg,rgba(11,8,6,1) 0%,rgba(11,8,6,.78) 7%,rgba(11,8,6,0) 26%),
    radial-gradient(116% 94% at 56% 50%,rgba(11,8,6,0) 42%,rgba(11,8,6,.58) 100%)}
}
.eu-link{stroke:var(--ember);stroke-width:.55;fill:none;opacity:.7;stroke-dasharray:var(--len);stroke-dashoffset:var(--len)}
.eu-node{fill:var(--ivory);opacity:0}
.eu-node--live{fill:var(--ember)}
.eu-pulse{fill:none;stroke:var(--ember);stroke-width:.8;opacity:0}
.eu-tag{font-family:var(--f-mono);font-size:3.1px;letter-spacing:.18em;text-transform:uppercase;fill:var(--muted);opacity:0}
.eu-tag--live{fill:var(--ember)}

/* ---------- 16. CITY TEASER --------------------------------------------- */
.cities{background:var(--ivory);color:var(--ink);padding-bottom:var(--section-y)}
.cities__track{height:280vh;position:relative}
.cities__sticky{position:sticky;top:0;height:100svh;display:flex;flex-direction:column;
  justify-content:center;gap:clamp(28px,4vw,64px);overflow:hidden}
.cities__head{padding-inline:var(--gutter);max-width:44ch}
.cities__row{display:flex;gap:clamp(24px,4vw,80px);padding-inline:var(--gutter);will-change:transform}
.city__plate{display:block;position:relative;overflow:hidden;border-radius:4px;
  margin-bottom:clamp(14px,1.6vw,24px);aspect-ratio:1000/620}
.city__plate img{width:100%;height:100%;object-fit:cover;display:block;
  transform:scale(1.12);transition:transform 1.4s var(--e-out-expo),filter .6s var(--e-out-cubic)}
.city:hover .city__plate img{transform:scale(1)}
.city__plate::after{content:'';position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,rgba(11,8,6,0) 40%,rgba(11,8,6,.35) 100%)}
.city__plate--tba img{filter:grayscale(.55) brightness(.82) contrast(1.05)}
.city:hover .city__plate--tba img{filter:grayscale(.2) brightness(.95) contrast(1.02)}
.city{flex:none;width:clamp(280px,40vw,640px);border-top:1px solid rgba(11,8,6,.18);
  padding-top:1.2rem;padding-bottom:1.4rem;min-height:clamp(260px,40vh,440px);
  display:flex;flex-direction:column;justify-content:space-between}
.city__name{font-family:var(--f-display);font-weight:800;font-stretch:118%;text-transform:uppercase;
  font-size:clamp(2rem,5vw,4.8rem);line-height:.86;letter-spacing:-.035em;white-space:nowrap;margin-block:auto}
.city__name--ember{color:var(--ember)}
.city--tba .city__name{color:rgba(11,8,6,.26)}
.city__meta{display:flex;justify-content:space-between;gap:1rem;border-top:1px solid rgba(11,8,6,.1);padding-top:.9rem}

/* ---------- 17. IMMERSIVE ------------------------------------------------ */
.immersive{position:relative;background:var(--ink)}
.immersive__track{height:300vh;position:relative}
.immersive__sticky{position:sticky;top:0;height:100svh;display:grid;place-items:center;overflow:hidden}
.immersive__media{position:relative;width:66vw;height:74svh;border-radius:34em;overflow:hidden;
  isolation:isolate;will-change:width,height,border-radius}
.immersive__video{position:absolute;inset:0;z-index:1;width:100%;height:100%;object-fit:cover}
/* the copy is a child of the frame now, so the plume can be laid over it */
.immersive__overlay{position:absolute;inset:0;z-index:2;display:grid;place-items:center;
  text-align:center;padding-inline:var(--gutter);pointer-events:none}
/* Both lines are centred on the frame itself, not on each other: the rotating
   word is far wider than the headline in German, and centring it on the
   headline's box would drift it off the cup.                              */
/* lifted off dead centre: the cup's widest point sits a little below the
   middle of the frame, and the copy reads better crossing the rim than the
   belly, where the printed logo competes with it                          */
.immersive__stack{position:absolute;inset:0;display:flex;flex-direction:column;
  align-items:center;justify-content:center;padding-inline:var(--gutter);
  translate:0 -2.5%}
.immersive__headline{opacity:0;color:var(--ivory);text-align:center;
  text-shadow:0 2px 40px rgba(11,8,6,.55)}
.immersive__words{position:relative;width:100%;font-family:var(--f-display);font-weight:800;
  font-stretch:118%;font-size:clamp(2.2rem,7.4vw,7.4rem);line-height:1;height:1.06em;margin-top:.14em}
.immersive__words span{position:absolute;top:0;left:50%;translate:-50% 0;white-space:nowrap;
  opacity:0;text-transform:uppercase;
  font-size:1em;line-height:1;letter-spacing:-.03em;color:var(--ember);
  text-shadow:0 2px 40px rgba(11,8,6,.5)}
.immersive__cup{position:absolute;inset:0;z-index:3;display:block;pointer-events:none}
.immersive__cup img{width:100%;height:100%;object-fit:cover;object-position:50% 46%;display:block}
/* the plume is a rectangular video plate; the mask keeps its edges from ever
   showing as a box over the frame */
.immersive__steam{position:absolute;inset:0;z-index:4;width:100%;height:100%;object-fit:cover;
  object-position:50% 46%;pointer-events:none;mix-blend-mode:screen;
  -webkit-mask-image:radial-gradient(ellipse 58% 86% at 50% 48%,#000 46%,transparent 100%);
  mask-image:radial-gradient(ellipse 58% 86% at 50% 48%,#000 46%,transparent 100%);
  opacity:0;transition:opacity 1.2s var(--e-out-cubic)}
.immersive__steam.is-on{opacity:.9}

/* ---------- 17b. ANIMATED ICONS ----------------------------------------- */
.xp__i,.craft__i{display:block;width:clamp(34px,3vw,48px);color:var(--ember)}
.xp__i svg,.craft__i svg{width:100%;height:auto;display:block;overflow:visible}
.xp__i{margin-bottom:1rem}
.xp__cell{justify-content:flex-start;gap:0}
.xp__cell .label{margin-bottom:0}
.xp__cell > div:last-child{margin-top:auto;padding-top:clamp(44px,7vw,120px)}

/* looping parts — cheap CSS, no JS per frame */
.i-steam path{opacity:0;animation:iSteam 3.2s var(--e-out-cubic) infinite}
.i-steam path:nth-child(2){animation-delay:.45s}
.i-steam path:nth-child(3){animation-delay:.9s}
@keyframes iSteam{
  0%{opacity:0;transform:translateY(4px) scaleY(.7)}
  30%{opacity:.9}
  100%{opacity:0;transform:translateY(-9px) scaleY(1.15)}
}
.i-drip{animation:iDrip 2.4s cubic-bezier(.55,0,.75,.4) infinite}
@keyframes iDrip{0%,55%{opacity:0;transform:translateY(0)}
  60%{opacity:1}100%{opacity:0;transform:translateY(9px)}}
.i-eq path{transform-origin:50% 100%;animation:iEq 1.15s ease-in-out infinite alternate}
.i-eq path:nth-child(2){animation-delay:.18s}
.i-eq path:nth-child(3){animation-delay:.36s}
@keyframes iEq{from{transform:scaleY(.42)}to{transform:scaleY(1)}}
.i-wave path{opacity:0;animation:iWave 2.4s ease-out infinite}
.i-wave path:nth-child(2){animation-delay:.5s}
@keyframes iWave{0%{opacity:0;transform:scale(.55)}40%{opacity:.85}100%{opacity:0;transform:scale(1.15)}}
.i-spin{animation:iSpin 9s linear infinite}
@keyframes iSpin{to{transform:rotate(360deg)}}
.i-pulse{opacity:0;transform-origin:center;animation:iPulse 2.8s var(--e-out-cubic) infinite}
@keyframes iPulse{0%{opacity:.7;transform:scale(.5)}100%{opacity:0;transform:scale(1.7)}}
.i-shine{stroke-dasharray:8 52;animation:iShine 3.4s var(--e-out-cubic) infinite}
@keyframes iShine{0%{stroke-dashoffset:60;opacity:0}25%{opacity:.9}60%,100%{stroke-dashoffset:-10;opacity:0}}
.i-pour{stroke-dasharray:3 6;animation:iPour 1.1s linear infinite}
@keyframes iPour{to{stroke-dashoffset:-9}}

/* ---------- 17c. THE CRAFT — the jazeancoffee bean ---------------------- */
.craft{background:var(--bone);color:var(--ink);position:relative;overflow:clip}
.craft__track{height:620vh;position:relative}
.craft__sticky{position:sticky;top:0;height:100svh;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:clamp(14px,2vh,28px);overflow:hidden;
  padding-block:calc(var(--nav-h) + clamp(10px,1.6vh,26px)) clamp(24px,4vh,48px)}

/* the connector line that runs the section into the next, drawn on scroll */
.craft__connector{position:absolute;z-index:1;pointer-events:none;width:clamp(70px,7vw,119px)}
.craft__connector svg{width:100%;height:100%;overflow:visible}
.craft__connector--in{left:6%;top:0;height:70vh}
.craft__connector path{stroke-dasharray:1;stroke-dashoffset:1;
  /* the dash values are measured and set in JS from getTotalLength */}

/* beans drifting up past the stage */
.craft__beans{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden}
.craft__bean{position:absolute;bottom:-16vh;width:clamp(20px,2vw,34px);aspect-ratio:1;
  background-repeat:no-repeat;background-position:50% 50%;background-size:contain;
  opacity:0;filter:saturate(85%);
  animation:beanDrift 17s linear infinite}
.craft__bean:nth-child(1){left:8%;animation-duration:19s;animation-delay:-2s;
  background-image:url(../../public/img/ref/bean-1.webp)}
.craft__bean:nth-child(2){left:21%;animation-duration:15s;animation-delay:-8s;width:clamp(13px,1.3vw,22px);
  background-image:url(../../public/img/ref/bean-4.webp)}
.craft__bean:nth-child(3){left:78%;animation-duration:21s;animation-delay:-5s;
  background-image:url(../../public/img/ref/bean-6.webp)}
.craft__bean:nth-child(4){left:88%;animation-duration:16s;animation-delay:-12s;width:clamp(15px,1.5vw,25px);
  background-image:url(../../public/img/ref/bean-2.webp)}
.craft__bean:nth-child(5){left:35%;animation-duration:24s;animation-delay:-16s;width:clamp(11px,1.1vw,18px);
  background-image:url(../../public/img/ref/bean-8.webp)}
.craft__bean:nth-child(6){left:64%;animation-duration:18s;animation-delay:-10s;width:clamp(12px,1.2vw,20px);
  background-image:url(../../public/img/ref/bean-3.webp)}
@keyframes beanDrift{
  0%{transform:translateY(0) rotate(0deg);opacity:0}
  9%{opacity:.5}
  90%{opacity:.5}
  100%{transform:translateY(-128vh) rotate(220deg);opacity:0}
}

.craft__head{position:relative;z-index:3;text-align:center;max-width:44ch}
.craft__h{margin-top:.7rem;font-size:clamp(1.15rem,2.4vw,2.1rem)}

/* ---- the bean ---------------------------------------------------------- */
.bean{position:relative;z-index:2;flex:0 1 auto;
  height:min(62vh,580px);aspect-ratio:432/590;display:grid;place-items:center}
.bean__lines{position:absolute;left:50%;top:50%;width:119%;height:113%;
  transform:translate(-50%,-50%);overflow:visible}
.bean__half{fill:none;stroke:var(--ember);stroke-width:2.2;stroke-linecap:round;
  stroke-dasharray:var(--len,900);stroke-dashoffset:var(--len,900)}

.bean__shape{position:relative;width:100%;height:100%;overflow:hidden;background:var(--ink-2);
  -webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 432 590'%3E%3Cpath d='M432 295C432 487.92 358.61 590 216 590C73.39 590 0 487.92 0 295C0 102.08 73.39 0 216 0C358.61 0 432 102.08 432 295Z' fill='%23fff'/%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 432 590'%3E%3Cpath d='M432 295C432 487.92 358.61 590 216 590C73.39 590 0 487.92 0 295C0 102.08 73.39 0 216 0C358.61 0 432 102.08 432 295Z' fill='%23fff'/%3E%3C/svg%3E");
  -webkit-mask-size:100% 100%;mask-size:100% 100%;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}
.bean__clip{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:0;transform:scale(1.12);
  transition:opacity .9s var(--e-out-cubic),transform 1.5s var(--e-out-expo)}
.bean__clip.is-on{opacity:1;transform:scale(1)}
.bean__veil{position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(76% 64% at 50% 46%,rgba(11,8,6,.34) 0%,rgba(11,8,6,.8) 100%)}

/* the copy sits inside the bean, as it does on the reference */
.bean__inner{position:absolute;inset:0;display:grid;place-items:center;
  padding:14% 16%;text-align:center;pointer-events:none}
.bean__panel{grid-area:1/1;display:flex;flex-direction:column;align-items:center;gap:.55rem;
  opacity:0;pointer-events:none;transition:opacity .5s var(--e-out-cubic)}
.bean__panel.is-on{opacity:1}
.bean__n{font-family:var(--f-mono);font-size:var(--t-label);letter-spacing:.24em;color:var(--ember-lo)}
.bean__t{font-family:var(--f-display);font-weight:800;font-stretch:112%;text-transform:uppercase;
  font-size:clamp(1.4rem,2.9vw,2.7rem);text-shadow:0 2px 30px rgba(11,8,6,.6);line-height:1;letter-spacing:-.02em;color:var(--ivory)}
.bean__t .w{display:inline-block}
.bean__b{font-size:var(--t-small);line-height:1.45;color:rgba(244,238,228,.86);max-width:22ch;
  text-shadow:0 1px 18px rgba(11,8,6,.7)}
.bean__ico{display:block;width:clamp(26px,2.4vw,36px);color:var(--ember-lo);margin-top:.35rem}
.bean__ico svg{width:100%;height:auto;display:block;overflow:visible}

.bean__badge{position:absolute;right:-6%;bottom:8%;z-index:3;
  padding:.45rem .75rem;border-radius:999px;background:var(--ink);color:var(--ivory);
  font-family:var(--f-mono);font-size:var(--t-label);letter-spacing:.16em}
.bean__badge i{font-style:normal;color:var(--ember-lo)}

/* ---- the rail ---------------------------------------------------------- */
.craft__rail{position:relative;z-index:3;display:block;padding-top:clamp(12px,2vh,26px)}
.craft__rail-bg,.craft__rail-on{position:absolute;left:var(--gutter);right:var(--gutter);
  top:clamp(12px,2vh,26px);height:1px}
.craft__rail-bg{background:rgba(11,8,6,.16)}
.craft__rail-on{background:var(--ember);transform-origin:0 50%;transform:scaleX(0);
  transition:transform .6s var(--e-out-expo)}
.craft__dots{display:grid;grid-template-columns:repeat(6,1fr)}
.craft__dot{display:flex;flex-direction:column;align-items:flex-start;gap:.3rem;
  padding-top:clamp(10px,1.4vh,18px);color:var(--muted-2);text-align:left;
  font-family:var(--f-mono);font-size:var(--t-label);letter-spacing:.18em;
  transition:color .4s var(--e-out-cubic)}
.craft__dot b{font-family:var(--f-display);font-weight:700;font-stretch:106%;text-transform:uppercase;
  font-size:clamp(.7rem,.95vw,.95rem);letter-spacing:-.008em;line-height:1;white-space:nowrap}
.craft__dot i{width:7px;height:7px;border-radius:50%;background:rgba(11,8,6,.22);
  margin-top:-clamp(10px,1.4vh,18px);position:absolute;top:calc(clamp(12px,2vh,26px) - 3px);
  transition:background-color .4s,transform .5s var(--e-out-expo)}
.craft__dot.is-on{color:var(--ink)}
.craft__dot.is-on i{background:var(--ember);transform:scale(1.5)}

@media (max-width:900px){
  .craft__track{height:520vh}
  .bean{height:min(50vh,430px)}
  .craft__h{font-size:clamp(1.05rem,4.2vw,1.6rem)}
  .bean__badge{right:-2%;bottom:4%}
  .craft__connector{display:none}
  .craft__dot b{display:none}
}

/* ---------- 18. EXPERIENCE GRID ----------------------------------------- */
.xp{background:var(--ivory);color:var(--ink)}
.xp__grid{display:grid;grid-template-columns:repeat(12,1fr);gap:1px;margin-top:clamp(44px,6vw,90px);background:rgba(11,8,6,.14)}
.xp__cell{background:var(--ivory);padding:clamp(22px,2.4vw,42px);display:flex;flex-direction:column;
  justify-content:space-between;gap:clamp(26px,3.4vw,58px);position:relative;overflow:hidden;isolation:isolate;
  transition:background-color .5s var(--e-out-cubic)}
/* the two anchor cells carry a plate, graded into the ivory section */
.xp__bg{position:absolute;inset:0;z-index:-1;display:block}
.xp__bg img{width:100%;height:100%;object-fit:cover;display:block;
  transform:scale(1.06);transition:transform 1.4s var(--e-out-expo),opacity .6s var(--e-out-cubic);
  opacity:.34}
.xp__cell--img:hover .xp__bg img{transform:scale(1);opacity:.55}
.xp__cell--img::before{content:'';position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(105deg,rgba(244,238,228,.92) 6%,rgba(244,238,228,.6) 46%,rgba(244,238,228,.15) 100%)}
.xp__cell--img:hover{background:var(--ivory)}
.xp__cell:hover{background:var(--bone)}
.xp__cell h3{font-family:var(--f-display);font-weight:700;font-stretch:110%;text-transform:uppercase;
  font-size:clamp(1.5rem,3.4vw,3.1rem);line-height:.94;letter-spacing:-.025em}
.xp__cell p{color:var(--muted-2);font-size:var(--t-small);max-width:34ch;margin-top:.5rem}
.xp__cell .label{margin-bottom:auto}
.xp__cell--a{grid-column:span 7;min-height:clamp(230px,22vw,310px)}
.xp__cell--b{grid-column:span 5}
.xp__cell--c,.xp__cell--d,.xp__cell--e{grid-column:span 4}
.xp__cell--f{grid-column:span 12;min-height:clamp(190px,17vw,255px)}
.xp__cell .glow{position:absolute;width:340px;height:340px;border-radius:50%;pointer-events:none;
  background:radial-gradient(circle,var(--ember-glow) 0%,rgba(226,85,30,0) 68%);
  opacity:0;transform:translate(-50%,-50%);transition:opacity .45s var(--e-out-cubic)}
.xp__cell:hover .glow{opacity:1}

/* ---------- 19. MARQUEE -------------------------------------------------- */
.partners{padding-block:clamp(48px,5.4vw,92px)}
.partners__head{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:1rem}
.marquee{position:relative;overflow:hidden;padding-block:clamp(26px,3vw,48px);border-block:1px solid var(--hairline);
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 9%,#000 91%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 9%,#000 91%,transparent)}
.marquee__row{display:flex;width:max-content;will-change:transform}
.marquee__item{display:flex;align-items:center;justify-content:center;padding-inline:clamp(26px,3.4vw,64px);
  flex:none;height:clamp(36px,3.4vw,52px);font-family:var(--f-display);font-weight:700;font-stretch:92%;
  text-transform:uppercase;letter-spacing:.1em;font-size:clamp(.9rem,1.35vw,1.25rem);
  color:rgba(244,238,228,.34);transition:color .4s var(--e-out-cubic);white-space:nowrap}
.marquee:hover .marquee__item{color:rgba(244,238,228,.5)}
.marquee__item:hover{color:var(--ivory)}

/* ---------- 20. B2B ------------------------------------------------------ */
/* ---------- 22b. PARTNERSHIP (compact) ------------------------------------
   The whole offer has to be readable at a glance: headline and the sentence
   that matters side by side, the formats and the CTA under them, and the six
   reasons as one band rather than a page of cards.                        */
.b2b{background:var(--espresso);color:var(--ivory);position:relative;overflow:hidden;
  padding-block:clamp(44px,6.5vh,86px)}
.b2b__glow{position:absolute;inset:auto -10% -40% -10%;height:70%;pointer-events:none;
  background:radial-gradient(60% 100% at 50% 100%,rgba(226,85,30,.2),transparent 70%)}
.b2b__head{position:relative;display:grid;grid-template-columns:repeat(12,1fr);
  gap:clamp(18px,2.4vw,44px);align-items:end}
.b2b__head .h{grid-column:1/span 6}
.b2b__head .a{grid-column:7/span 6;display:flex;flex-direction:column;
  gap:clamp(12px,1.6vh,20px);padding-bottom:.2rem}
.b2b__title{margin-top:clamp(10px,1.4vh,18px);
  font-family:var(--f-display);font-weight:800;font-stretch:112%;text-transform:uppercase;
  font-size:clamp(1.9rem,4.4vw,3.9rem);line-height:.98;letter-spacing:-.035em}
.b2b__lede{max-width:46ch;font-size:clamp(.92rem,1.05vw,1.06rem);line-height:1.55;
  color:rgba(244,238,228,.76)}
.ptypes{display:flex;flex-wrap:wrap;gap:.4rem;position:relative}
.ptype{border:1px solid rgba(244,238,228,.2);border-radius:100px;padding:.5rem .9rem;
  font-family:var(--f-mono);font-size:clamp(.58rem,.66vw,.68rem);text-transform:uppercase;
  letter-spacing:.11em;color:rgba(244,238,228,.72);
  transition:border-color .35s,color .35s,transform .5s var(--e-out-expo)}
.ptype:hover{border-color:var(--ember);color:var(--ember);transform:translateY(-2px)}
.b2b__cta{display:flex;align-items:center;flex-wrap:wrap;gap:.9rem 1.2rem}
.b2b__reply{color:rgba(244,238,228,.5);letter-spacing:.1em}

/* six across on a wide screen: one band, no second row to scroll to */
.why{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:1px;
  margin-top:clamp(26px,3.6vh,52px);position:relative;
  background:rgba(244,238,228,.14);border:1px solid rgba(244,238,228,.14);
  border-radius:6px;overflow:hidden}
.why__item{position:relative;background:var(--espresso);
  padding:clamp(14px,1.5vw,22px) clamp(13px,1.3vw,19px);
  display:flex;flex-direction:column;gap:.4rem;isolation:isolate;
  transition:background-color .5s var(--e-out-cubic)}
/* an ember wash climbs the card on hover instead of a flat colour swap */
.why__item::before{content:'';position:absolute;inset:0;z-index:-1;
  background:linear-gradient(180deg,rgba(226,85,30,.16),rgba(226,85,30,0));
  transform:scaleY(0);transform-origin:0 100%;
  transition:transform .6s var(--e-out-expo)}
.why__item:hover::before{transform:scaleY(1)}
.why__top{display:flex;align-items:center;justify-content:space-between;gap:.6rem}
.why__icon{display:block;width:clamp(22px,1.8vw,28px);color:var(--ember);
  transition:transform .6s var(--e-out-expo)}
.why__item:hover .why__icon{transform:translateY(-3px) scale(1.06)}
.why__num{font-family:var(--f-mono);font-size:.6rem;color:rgba(244,238,228,.36);letter-spacing:.2em}
.why__item h3{font-family:var(--f-display);font-weight:700;font-stretch:112%;text-transform:uppercase;
  font-size:clamp(.86rem,1.05vw,1.06rem);letter-spacing:-.012em;line-height:1.06;margin-top:.15rem}
.why__item p{color:rgba(244,238,228,.6);font-size:clamp(.72rem,.8vw,.8rem);
  margin-top:.15rem;line-height:1.45;
  /* three lines is the tallest any of the six needs in German */
  display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}

@media (max-width:1200px){
  .why{grid-template-columns:repeat(3,minmax(0,1fr))}
  .b2b__head .h{grid-column:1/span 12}
  .b2b__head .a{grid-column:1/span 12}
}
@media (max-width:640px){ .why{grid-template-columns:repeat(2,minmax(0,1fr))} }

/* ---------- 21. CTA ------------------------------------------------------ */
.cta{background:var(--ember);color:#fff;position:relative;overflow:hidden;isolation:isolate}
/* two slow ember-and-roast blooms drifting behind the type, so the block is
   never a flat rectangle of orange */
.cta__aurora{position:absolute;inset:-20%;z-index:0;pointer-events:none;opacity:.55;
  background:
    radial-gradient(38% 46% at 22% 30%,rgba(255,178,120,.55),rgba(255,178,120,0) 70%),
    radial-gradient(42% 50% at 78% 68%,rgba(109,81,63,.6),rgba(109,81,63,0) 70%);
  animation:ctaDrift 26s ease-in-out infinite alternate}
@keyframes ctaDrift{
  0%{transform:translate3d(0,0,0) scale(1)}
  50%{transform:translate3d(3%,-2%,0) scale(1.08)}
  100%{transform:translate3d(-2%,3%,0) scale(1.03)}
}
.cta__beans{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden}
.cta__beans i{position:absolute;bottom:-12%;width:clamp(26px,3vw,52px);aspect-ratio:1;
  background:url(../../public/img/ref/bean-5.webp) no-repeat 50%/contain;
  opacity:.12;animation:ctaBean 24s linear infinite}
.cta__beans i:nth-child(1){left:6%;animation-duration:27s;animation-delay:-4s}
.cta__beans i:nth-child(2){left:31%;animation-duration:21s;animation-delay:-14s;width:clamp(18px,2vw,34px)}
.cta__beans i:nth-child(3){left:56%;animation-duration:31s;animation-delay:-9s}
.cta__beans i:nth-child(4){left:74%;animation-duration:19s;animation-delay:-19s;width:clamp(20px,2.2vw,38px)}
.cta__beans i:nth-child(5){left:92%;animation-duration:25s;animation-delay:-2s;width:clamp(16px,1.8vw,28px)}
@keyframes ctaBean{
  0%{transform:translateY(0) rotate(0)}
  100%{transform:translateY(-135%) rotate(300deg)}
}

.cta__inner{position:relative;z-index:1;display:grid;
  grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr);
  gap:clamp(32px,5vw,90px);align-items:start}
.cta__head{min-width:0}
.cta__live{display:inline-flex;align-items:center;gap:.6rem;color:rgba(255,255,255,.9)}
.cta__dot{width:7px;height:7px;border-radius:50%;background:#fff;flex:none;
  box-shadow:0 0 0 0 rgba(255,255,255,.7);animation:ctaPulse 2.4s var(--e-out-cubic) infinite}
@keyframes ctaPulse{0%{box-shadow:0 0 0 0 rgba(255,255,255,.6)}70%,100%{box-shadow:0 0 0 12px rgba(255,255,255,0)}}
.cta__h{margin-top:1.2rem}
.cta__lead{margin-top:1.5rem;color:rgba(255,255,255,.88)}
.cta__btns{margin-top:clamp(24px,3vw,40px)}
.cta .lead{color:rgba(255,255,255,.86)}
.cta .label{color:rgba(255,255,255,.74)}
.cta__reply{margin-top:1.2rem}
.cta .btn--ink{border-color:rgba(255,255,255,.5);color:#fff;--fillc:#fff;--bubblec:rgba(226,85,30,.55)}
.cta .btn--ink .btn__fill{background:#fff}
.cta .btn--ink:hover{color:var(--ember);border-color:#fff}
.cta__second{background:rgba(255,255,255,.08)}

/* what happens next */
.cta__steps{display:flex;flex-direction:column;gap:0;margin-top:clamp(8px,1.4vw,22px)}
.cta__step{position:relative;padding:clamp(16px,1.8vw,26px) 0;
  border-top:1px solid rgba(255,255,255,.24);
  display:grid;grid-template-columns:auto 1fr;gap:.4rem clamp(14px,1.6vw,24px);
  opacity:0;transform:translateY(20px);
  transition:opacity .7s var(--e-out-cubic),transform .9s var(--e-out-expo)}
.cta__step:last-child{border-bottom:1px solid rgba(255,255,255,.24)}
.cta__step.is-in{opacity:1;transform:none}
.cta__step:nth-child(2){transition-delay:.1s}
.cta__step:nth-child(3){transition-delay:.2s}
.cta__sn{grid-row:1/span 2;font-family:var(--f-mono);font-size:var(--t-label);
  letter-spacing:.22em;color:rgba(255,255,255,.6);padding-top:.28em}
.cta__step h3{font-family:var(--f-display);font-weight:700;font-stretch:110%;
  text-transform:uppercase;font-size:clamp(1rem,1.4vw,1.32rem);letter-spacing:-.01em;line-height:1}
.cta__step p{font-size:var(--t-small);line-height:1.5;color:rgba(255,255,255,.8);max-width:38ch}

/* the categories run along the bottom edge of the block */
.cta__ticker{position:relative;z-index:1;overflow:hidden;margin-top:clamp(40px,5vw,76px);
  padding-top:clamp(18px,2vw,28px);border-top:1px solid rgba(255,255,255,.24)}
.cta__ticker-row{display:flex;width:max-content;
  font-family:var(--f-display);font-weight:700;font-stretch:112%;text-transform:uppercase;
  font-size:clamp(.95rem,1.7vw,1.7rem);letter-spacing:-.01em;color:rgba(255,255,255,.32)}
.cta__ticker-row span{padding-inline:clamp(14px,1.8vw,32px);white-space:nowrap}
.cta__ticker-row span.on{color:#fff}

@media (max-width:1000px){
  .cta__inner{grid-template-columns:1fr;gap:clamp(28px,4vw,44px)}
  .cta__step p{max-width:none}
}

/* ---------- 22. FORMS ---------------------------------------------------- */
.news{background:var(--ink)}
.news__inner{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--gutter) clamp(40px,6vw,110px);align-items:start}
.news__intro{grid-column:1/span 5}
.news__head{margin-top:1.2rem}
.news__intro .lead{margin-top:1.4rem}
.news__points{margin-top:clamp(24px,3vw,40px);display:flex;flex-direction:column;gap:.85rem}
.news__points li{position:relative;padding-left:1.5rem;font-size:var(--t-small);color:var(--muted)}
.news__points li::before{content:'';position:absolute;left:0;top:.62em;width:8px;height:1px;background:var(--ember)}

.form{grid-column:7/span 6;display:flex;flex-direction:column;gap:clamp(18px,2vw,28px);position:relative}
.form__row{display:grid;grid-template-columns:1fr 1fr;gap:clamp(16px,2vw,28px)}
.seg__row{display:flex;gap:.5rem;margin-top:.9rem;flex-wrap:wrap}
.seg__opt{position:relative;cursor:pointer}
.seg__opt input{position:absolute;opacity:0;width:0;height:0}
.seg__opt span{display:block;padding:.78rem 1.15rem;border-radius:100px;
  border:1px solid rgba(244,238,228,.2);font-family:var(--f-mono);font-size:var(--t-label);
  text-transform:uppercase;letter-spacing:.13em;color:var(--muted);
  transition:.4s var(--e-out-cubic)}
.seg__opt:hover span{border-color:rgba(244,238,228,.44);color:var(--ivory)}
.seg__opt input:checked + span{background:var(--ember);border-color:var(--ember);color:#fff}
.seg__opt input:focus-visible + span{outline:2px solid var(--ember);outline-offset:3px}

.field{position:relative;display:flex;flex-direction:column;padding-top:1.35rem}
.field input,.field textarea{width:100%;background:none;border:0;padding:.5rem 0 .75rem;
  font-family:var(--f-display);font-stretch:100%;font-size:clamp(1rem,1.25vw,1.24rem);
  border-bottom:1px solid var(--hairline);transition:border-color .35s var(--e-out-cubic)}
.field input::placeholder,.field textarea::placeholder{color:transparent}
.field label{position:absolute;left:0;top:1.85rem;pointer-events:none;color:var(--muted);
  font-family:var(--f-mono);font-size:var(--t-label);text-transform:uppercase;letter-spacing:.14em;
  transition:transform .42s var(--e-out-quint),color .42s var(--e-out-cubic)}
/* the textarea selectors were missing, so a long answer typed itself underneath
   its own caption — the label only ever lifted for <input> */
.field input:focus + label,.field input:not(:placeholder-shown) + label,
.field textarea:focus + label,.field textarea:not(:placeholder-shown) + label{transform:translateY(-1.6rem)}
.field input:focus + label,.field textarea:focus + label{color:var(--ember)}
.field__line{position:absolute;left:0;right:0;bottom:0;height:1px;background:var(--ember);
  transform:scaleX(0);transform-origin:0 50%;transition:transform .5s var(--e-out-expo)}
.field input:focus ~ .field__line,.field textarea:focus ~ .field__line{transform:scaleX(1)}
.field.has-error input,.field.has-error textarea{border-bottom-color:var(--ember)}
.field__err{min-height:1.1em;margin-top:.5rem;font-family:var(--f-mono);font-size:var(--t-label);
  letter-spacing:.08em;color:var(--ember-lo);opacity:0;transform:translateY(-4px);
  transition:opacity .3s,transform .3s var(--e-out-cubic)}
.field__err.is-on{opacity:1;transform:none}

.check{display:flex;gap:.85rem;align-items:flex-start;cursor:pointer;max-width:52ch}
.check input{position:absolute;opacity:0;width:0;height:0}
.check__box{flex:none;width:19px;height:19px;margin-top:.14rem;border-radius:4px;
  border:1px solid rgba(244,238,228,.28);display:grid;place-items:center;color:#fff;
  transition:.34s var(--e-out-cubic)}
.check__box svg{width:11px;opacity:0;transform:scale(.6);transition:.34s var(--e-out-expo)}
.check:hover .check__box{border-color:rgba(244,238,228,.55)}
.check input:checked + .check__box{background:var(--ember);border-color:var(--ember)}
.check input:checked + .check__box svg{opacity:1;transform:none}
.check input:focus-visible + .check__box{outline:2px solid var(--ember);outline-offset:3px}
.check__text{font-size:var(--t-small);color:var(--muted);line-height:1.5}
.form__submit{display:flex;align-items:center;gap:clamp(16px,2vw,28px);flex-wrap:wrap;margin-top:.4rem}
.form__note{color:var(--muted-2)}
.form__done{position:absolute;inset:0;background:var(--ink);display:flex;flex-direction:column;
  align-items:flex-start;justify-content:center;gap:1rem;z-index:3}
.form__tick{color:var(--ember);width:52px}
.form__donehead{color:var(--ivory)}

/* ---------- 23. FOOTER --------------------------------------------------- */
.footer{background:var(--ink);padding-bottom:clamp(28px,3vw,44px);overflow:hidden;
  position:relative;isolation:isolate}
/* a slow ember bloom behind the sign-off, so the footer has depth rather than
   being the place the page runs out */
.footer__aurora{position:absolute;left:-10%;right:-10%;top:-10%;height:70%;z-index:0;pointer-events:none;
  background:
    radial-gradient(40% 60% at 22% 40%,rgba(226,85,30,.22),rgba(226,85,30,0) 70%),
    radial-gradient(44% 64% at 76% 24%,rgba(109,81,63,.3),rgba(109,81,63,0) 72%);
  opacity:.9;animation:footDrift 30s ease-in-out infinite alternate}
@keyframes footDrift{
  0%{transform:translate3d(0,0,0) scale(1)}
  100%{transform:translate3d(-3%,2%,0) scale(1.1)}
}
.footer > *{position:relative;z-index:1}
.footer__marquee{overflow:hidden;border-block:1px solid var(--hairline);padding-block:clamp(14px,1.6vw,24px)}
.footer__marquee-row{display:flex;width:max-content;will-change:transform;
  font-family:var(--f-display);font-weight:800;font-stretch:118%;text-transform:uppercase;
  font-size:clamp(1.5rem,3.4vw,3.4rem);line-height:1;letter-spacing:-.02em;color:rgba(244,238,228,.13)}
.footer__marquee-row span{padding-inline:clamp(18px,2.4vw,44px);white-space:nowrap}
.footer__marquee-row span.on{color:var(--ember);opacity:.5}
.footer__top{display:grid;grid-template-columns:minmax(0,1.25fr) minmax(0,.75fr);
  align-items:end;gap:clamp(28px,4vw,64px);padding-top:clamp(48px,6vw,100px)}
.footer__mega{font-family:var(--f-display);font-weight:800;font-stretch:116%;text-transform:uppercase;
  font-size:clamp(2.2rem,7.6vw,9rem);line-height:.86;letter-spacing:-.035em;color:var(--ivory);margin-top:1.1rem}
.footer__line{display:block}
.footer__line .w{display:inline-block;will-change:transform}
/* the contact block sits clear of the floating orb */
.footer__contact{display:flex;flex-direction:column;gap:clamp(18px,2.4vw,32px);align-items:flex-start;
  padding-right:clamp(0px,9vw,150px)}
.footer__ctas{display:flex;flex-wrap:wrap;gap:clamp(10px,1vw,14px)}
.footer__mail{display:flex;flex-direction:column;gap:.5rem;padding-bottom:.5rem;position:relative;
  align-items:flex-start;text-align:left;width:100%}
.footer__mail-addr{display:flex;align-items:center;gap:.7rem;
  font-family:var(--f-display);font-weight:600;font-stretch:100%;
  font-size:clamp(1.1rem,2vw,2rem);letter-spacing:-.015em;transition:color .35s var(--e-out-cubic)}
.footer__mail::after{content:'';position:absolute;left:0;bottom:0;height:1px;width:100%;
  background:var(--ember);transform:scaleX(0);transform-origin:0 50%;transition:transform .5s var(--e-out-expo)}
.footer__mail:hover::after{transform:scaleX(1)}
.footer__mail:hover .footer__mail-addr{color:var(--ember)}
.footer__mail-arrow{width:.62em;flex:none;opacity:.55;
  transition:transform .5s var(--e-out-expo),opacity .3s}
.footer__mail:hover .footer__mail-arrow{transform:translate(4px,-4px);opacity:1}
/* ---------- 23b. PARTNER PORTAL ----------------------------------------- */
/* One card, two tracks: the promise on the left, the way in on the right.
   Everything animates from the card's own hover state so there is no JS
   dependency — GSAP only adds the entry reveal.                            */
.portal{position:relative;display:grid;grid-template-columns:1.55fr .9fr;
  gap:clamp(24px,3vw,56px);align-items:center;overflow:hidden;
  margin-block:clamp(48px,6vw,96px);padding:clamp(26px,3.2vw,52px);
  border-radius:clamp(20px,2vw,32px);
  background:linear-gradient(135deg,rgba(36,23,16,.86),rgba(20,18,16,.72));
  border:1px solid rgba(244,238,228,.1);
  box-shadow:0 30px 90px rgba(0,0,0,.4);
  transition:border-color .6s var(--e-out-cubic),transform .8s var(--e-out-expo),
             box-shadow .6s var(--e-out-cubic)}
.portal:hover{border-color:rgba(226,85,30,.42);transform:translateY(-3px);
  box-shadow:0 40px 110px rgba(0,0,0,.5)}
/* two lights: the fixed bloom behind the cup, and a second one that tracks the
   pointer across the card (initPortal writes --px/--py), so the panel feels
   lit from wherever you happen to be reading */
.portal__glow{position:absolute;inset:auto -20% -60% auto;width:min(52%,520px);aspect-ratio:1;
  border-radius:50%;pointer-events:none;
  background:radial-gradient(circle,var(--ember-glow),transparent 68%);
  opacity:.5;transition:opacity .7s var(--e-out-cubic),transform 1.1s var(--e-out-expo)}
.portal:hover .portal__glow{opacity:.9;transform:scale(1.14)}
.portal::before{content:'';position:absolute;inset:0;z-index:0;pointer-events:none;
  border-radius:inherit;opacity:0;transition:opacity .55s var(--e-out-cubic);
  background:radial-gradient(420px circle at var(--px,50%) var(--py,50%),
             rgba(226,85,30,.13),transparent 62%)}
.portal:hover::before{opacity:1}

.portal__title{font-size:clamp(1.5rem,2.5vw,2.5rem);line-height:1.08;letter-spacing:-.02em;
  margin-block:.5em .45em;max-width:20ch;color:var(--ivory)}
.portal__lede{max-width:56ch;color:var(--bone);opacity:.82;
  font-size:clamp(.9rem,1vw,1.02rem);line-height:1.6}

.portal__list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(8px,1vw,14px) clamp(14px,1.8vw,28px);margin-top:clamp(20px,2.4vw,34px)}
/* each capability is a small tile of its own now: it lights up as the ember
   sweep passes it, and it lifts under the pointer, so the four of them read as
   four things you can do rather than as a bulleted list */
.portal__item{position:relative;display:flex;align-items:center;gap:12px;overflow:hidden;
  padding:.62rem .8rem;border-radius:14px;
  border:1px solid rgba(244,238,228,.07);background:rgba(244,238,228,.022);
  font-size:clamp(.8rem,.9vw,.92rem);color:var(--bone);line-height:1.35;
  transition:border-color .5s var(--e-out-cubic),background-color .5s var(--e-out-cubic),
             transform .7s var(--e-out-expo)}
.portal__item:hover{border-color:rgba(226,85,30,.34);background:rgba(226,85,30,.07);
  transform:translateX(3px)}
/* the sweep: one ember bar crosses all four tiles in turn while the card is
   hovered, which is what ties them together instead of four separate blinks */
.portal__item::before{content:'';position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(100deg,rgba(226,85,30,0) 38%,rgba(226,85,30,.16) 50%,rgba(226,85,30,0) 62%);
  transform:translateX(-110%);opacity:0}
.portal:hover .portal__item::before{opacity:1;animation:portalSweep 1.5s var(--e-out-expo) forwards}
.portal:hover .portal__item:nth-child(2)::before{animation-delay:.09s}
.portal:hover .portal__item:nth-child(3)::before{animation-delay:.18s}
.portal:hover .portal__item:nth-child(4)::before{animation-delay:.27s}
@keyframes portalSweep{to{transform:translateX(110%)}}

.portal__ico{position:relative;flex:none;display:grid;place-items:center;
  width:38px;height:38px;border-radius:12px;
  color:var(--ember-lo);background:rgba(226,85,30,.1);border:1px solid rgba(226,85,30,.2);
  transition:background-color .5s var(--e-out-cubic),transform .7s var(--e-out-expo),
             color .5s var(--e-out-cubic),box-shadow .6s var(--e-out-cubic)}
.portal__ico svg{width:20px;height:20px;overflow:visible}
/* the stroke draws itself the first time the card is hovered, the same
   getTotalLength trick the section icons use — done here in pure CSS with a
   dash length generous enough for any of the four paths */
.portal__ico svg path{stroke-dasharray:96;stroke-dashoffset:0;
  transition:stroke-dashoffset .9s var(--e-out-expo)}
.portal:hover .portal__ico{background:rgba(226,85,30,.22);color:var(--ivory);
  box-shadow:0 8px 22px rgba(226,85,30,.24)}
.portal:hover .portal__ico svg path{stroke-dashoffset:96;
  animation:portalDraw .95s var(--e-out-expo) forwards}
@keyframes portalDraw{from{stroke-dashoffset:96}to{stroke-dashoffset:0}}
.portal__item:nth-child(1) .portal__ico,
.portal:hover .portal__item:nth-child(1) .portal__ico svg path{transition-delay:0s;animation-delay:0s}
.portal__item:nth-child(2) .portal__ico,
.portal:hover .portal__item:nth-child(2) .portal__ico svg path{transition-delay:.07s;animation-delay:.07s}
.portal__item:nth-child(3) .portal__ico,
.portal:hover .portal__item:nth-child(3) .portal__ico svg path{transition-delay:.14s;animation-delay:.14s}
.portal__item:nth-child(4) .portal__ico,
.portal:hover .portal__item:nth-child(4) .portal__ico svg path{transition-delay:.21s;animation-delay:.21s}
.portal:hover .portal__item:nth-child(odd) .portal__ico{transform:translateY(-3px) rotate(-4deg)}
.portal:hover .portal__item:nth-child(even) .portal__ico{transform:translateY(-3px) rotate(4deg)}
.portal__item:hover .portal__ico{transform:translateY(-4px) scale(1.06) rotate(0) !important;
  background:var(--ember);color:#fff;border-color:var(--ember)}
@media (prefers-reduced-motion:reduce){
  .portal__item::before,.portal:hover .portal__ico svg path{animation:none}
  .portal__ico svg path{stroke-dashoffset:0}
}

/* right-hand track: a cup drawn as one line, filling on hover -------------
   The old cup was three CSS boxes with border-radius, which read as a
   rectangle with rounded corners rather than as a cup. This is one SVG path
   for the body, one for the handle, and a rect clipped to the body that rises
   as the brew.                                                            */
.portal__go{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;
  gap:clamp(14px,1.6vw,22px);text-align:center}
.portal__cupwrap{position:relative;display:block}
.portal__cup{display:block;width:clamp(104px,8.4vw,148px);height:auto;overflow:visible;
  filter:drop-shadow(0 18px 26px rgba(0,0,0,.34))}

/* the whole cup leans a touch into the hover, as if picked up */
.portal__shade{fill:#000;opacity:.34;filter:blur(2px)}
.portal__tilt{transform-box:view-box;transform-origin:70px 101px;
  transition:transform 1.1s var(--e-out-expo)}
.portal:hover .portal__tilt{transform:translateY(-3px) rotate(-2.4deg)}

/* line work */
.portal__body,.portal__handle,.portal__rim,.portal__saucer{
  fill:none;stroke:rgba(244,238,228,.4);stroke-width:2.2;
  stroke-linecap:round;stroke-linejoin:round;
  transition:stroke .7s var(--e-out-cubic),opacity .7s var(--e-out-cubic)}
.portal__saucer{stroke-width:1.6;opacity:.5}
.portal__handle{stroke-width:2.2}
.portal:hover .portal__body,.portal:hover .portal__rim,.portal:hover .portal__handle{
  stroke:var(--ivory)}
.portal:hover .portal__saucer{stroke:rgba(244,238,228,.7);opacity:.85}
.portal__sheen{fill:url(#portalGlassGrad)}

/* the brew: a wave sheet clipped to the cup, riding up from empty to full.
   The lift is a transform, so it stays on the compositor; the sway is a
   second, independent transform on the wave inside it.                    */
.portal__brew{transform-box:view-box;transform-origin:0 0;
  transform:translateY(106px);
  transition:transform 1.15s var(--e-out-expo)}
.portal:hover .portal__brew{transform:translateY(26px)}
.portal__wave{fill:url(#portalBrewGrad);
  transform-box:view-box;transform-origin:0 0;
  animation:portalSway 5.2s ease-in-out infinite}
.portal__crema{fill:#D89A6A;opacity:.42}
@keyframes portalSway{
  0%,100%{transform:translate(0,0)}
  50%{transform:translate(-72px,1.4px)}}

.portal__steam{position:absolute;left:50%;top:25%;translate:-50% -100%;
  width:40px;height:clamp(34px,3vw,48px);pointer-events:none;opacity:0;
  transition:opacity .8s var(--e-out-cubic) .35s}
.portal:hover .portal__steam{opacity:.5}
.portal__steam i{position:absolute;bottom:0;width:7px;height:100%;
  border-radius:999px;filter:blur(3.5px);
  background:linear-gradient(0deg,rgba(244,238,228,.66),rgba(244,238,228,.2) 55%,transparent);
  animation:portalSteam 4.6s ease-in-out infinite}
.portal__steam i:nth-child(1){left:6px}
.portal__steam i:nth-child(2){left:17px;animation-delay:-1.6s;height:86%}
.portal__steam i:nth-child(3){left:28px;animation-delay:-3.1s;height:70%}
@keyframes portalSteam{
  0%{transform:translate(0,14%) scale(.6,.6);opacity:0}
  22%{opacity:.9}
  55%{transform:translate(-5px,-28%) scale(1.25,1);opacity:.7}
  100%{transform:translate(6px,-72%) scale(1.7,1.25);opacity:0}}

.portal__btn{position:relative;display:inline-flex;align-items:center;gap:10px;overflow:hidden;
  padding:.95rem 1.5rem;border-radius:999px;background:var(--ember);color:#fff;
  font-family:var(--f-mono);font-size:var(--t-label);text-transform:uppercase;letter-spacing:.12em;
  box-shadow:0 14px 34px rgba(226,85,30,.34);
  transition:box-shadow .55s var(--e-out-cubic),transform .7s var(--e-out-expo)}
.portal:hover .portal__btn{transform:translateY(-2px);box-shadow:0 20px 44px rgba(226,85,30,.5)}
/* same fix as .btn__roll: 1em is shorter than the mono face's line box, and
   the umlaut on ÖFFNEN was being shaved off the top */
.portal__btn-roll{display:grid;overflow:hidden;height:1.32em;line-height:1.32}
.portal__btn-roll span{grid-area:1/1;white-space:nowrap;line-height:1.32;
  transition:transform .55s var(--e-out-expo)}
.portal__btn-roll span:last-child{transform:translateY(101%)}
.portal:hover .portal__btn-roll span:first-child{transform:translateY(-101%)}
.portal:hover .portal__btn-roll span:last-child{transform:translateY(0)}
.portal__btn svg{width:14px;height:14px;flex:none;
  transition:transform .6s var(--e-out-expo)}
.portal:hover .portal__btn svg{transform:translate(3px,-3px)}
.portal__host{color:var(--muted);letter-spacing:.1em}

@media (max-width:900px){
  .portal{grid-template-columns:1fr;text-align:left}
  .portal__list{grid-template-columns:1fr}
  .portal__go{align-items:flex-start;text-align:left}
  .portal__steam{display:none}
}
@media (prefers-reduced-motion:reduce){
  .portal__steam i,.portal__wave{animation:none}
  .portal__tilt,.portal__brew{transition-duration:.01ms}
}

.footer__cols{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--gutter);
  margin-top:clamp(44px,5vw,80px);padding-top:clamp(28px,3vw,44px);border-top:1px solid var(--hairline)}
.footer__col{grid-column:span 2}
.footer__col--brand{grid-column:span 4;display:flex;flex-direction:column;gap:1rem}
.footer__col--brand img{width:76px;height:auto;opacity:.9}
.footer__brandmeta{line-height:1.9}
.footer__route{color:var(--muted-2)}
.footer__col h4{margin-bottom:1.1rem;color:var(--ivory)}
.footer__col li{margin-bottom:.6rem}
.footer__col ul a{color:var(--muted);font-size:var(--t-small);position:relative;
  transition:color .3s var(--e-out-cubic)}
.footer__col ul a::after{content:'';position:absolute;left:0;bottom:-2px;height:1px;width:100%;
  background:currentColor;transform:scaleX(0);transform-origin:100% 50%;transition:transform .45s var(--e-out-expo)}
.footer__col ul a:hover{color:var(--ivory)}
.footer__col ul a:hover::after{transform:scaleX(1);transform-origin:0 50%}
.footer__col{opacity:0;transform:translateY(18px);
  transition:opacity .7s var(--e-out-cubic),transform .9s var(--e-out-expo)}
.footer__col.is-in{opacity:1;transform:none}
.footer__col:nth-child(2){transition-delay:.06s}
.footer__col:nth-child(3){transition-delay:.12s}
.footer__col:nth-child(4){transition-delay:.18s}
.footer__col:nth-child(5){transition-delay:.24s}

.footer__social{display:flex;gap:.6rem}
.footer__soc{display:grid;place-items:center;width:40px;height:40px;border-radius:50%;
  border:1px solid var(--hairline);color:var(--muted);
  transition:color .35s var(--e-out-cubic),border-color .35s var(--e-out-cubic),
             background-color .35s var(--e-out-cubic),transform .5s var(--e-out-expo)}
.footer__soc svg{width:18px;height:18px}
.footer__soc:hover{color:#fff;background:var(--ember);border-color:var(--ember);transform:translateY(-3px)}
/* One slim row. It used to be 160 px tall because the Back-to-top button
   shared its class name with the footer's top grid and inherited that grid's
   layout; it is `.footer__up` now and the whole strip is a single line.    */
.footer__bottom{position:relative;display:flex;flex-wrap:wrap;align-items:center;
  justify-content:space-between;gap:.9rem 1.4rem;
  margin-top:clamp(26px,3.2vw,48px);padding-top:clamp(14px,1.4vw,20px);
  border-top:1px solid var(--hairline);
  padding-right:clamp(0px,9vw,150px)}
/* the organiser credit: white mark, small, and a link with a wink */
/* The gag used to grow from max-width 0 inside the row, which shoved every
   other item sideways and clipped itself. It is a tooltip now: absolutely
   positioned above the line, so nothing moves and the whole sentence fits. */
.footer__org{position:relative;display:inline-flex;align-items:center;gap:.7rem;
  transition:opacity .35s var(--e-out-cubic)}
.footer__org img{width:clamp(58px,4.4vw,70px);height:auto;opacity:.8;
  transition:opacity .35s var(--e-out-cubic)}
.footer__org:hover img{opacity:1}
.footer__gag{position:absolute;left:0;bottom:calc(100% + .55rem);z-index:2;
  white-space:nowrap;pointer-events:none;
  padding:.45rem .75rem;border-radius:999px;
  color:var(--bone);background:rgba(20,18,16,.94);
  border:1px solid rgba(244,238,228,.14);
  box-shadow:0 12px 30px rgba(0,0,0,.5);
  opacity:0;transform:translateY(4px);
  transition:opacity .35s var(--e-out-cubic),transform .5s var(--e-out-expo)}
.footer__org:hover .footer__gag,.footer__org:focus-visible .footer__gag{opacity:1;transform:none}
.footer__copy{color:var(--muted-2)}
/* the legal links live on the bottom line as one row — stacked in their own
   column they cost a whole column of height for four short words */
.footer__legal{display:flex;flex-wrap:wrap;align-items:center;gap:.35rem 1.3rem;
  font-family:var(--f-mono);font-size:var(--t-label);text-transform:uppercase;
  letter-spacing:.12em;color:var(--muted-2)}
.footer__legal a,.footer__legal button{position:relative;color:inherit;
  transition:color .3s var(--e-out-cubic)}
.footer__legal a::after,.footer__legal button::after{content:'';position:absolute;
  left:0;right:0;bottom:-3px;height:1px;background:currentColor;
  transform:scaleX(0);transform-origin:right;transition:transform .45s var(--e-out-expo)}
.footer__legal a:hover,.footer__legal button:hover{color:var(--ivory)}
.footer__legal a:hover::after,.footer__legal button:hover::after{transform:scaleX(1);transform-origin:left}

.footer__up{position:relative;display:inline-flex;align-items:center;gap:.7rem;
  white-space:nowrap;color:var(--muted);cursor:pointer;background:none;border:0;padding:0;
  transition:color .3s var(--e-out-cubic)}
.footer__up:hover{color:var(--ember)}
.footer__up-ring{width:34px;height:34px;flex:none;transform:rotate(-90deg);overflow:visible}
.footer__up-ring circle{fill:none;stroke-width:1.4}
.footer__up-ring circle:first-child{stroke:var(--hairline)}
.footer__up-ring circle:last-child{stroke:var(--ember);
  stroke-dasharray:128.8;stroke-dashoffset:128.8;stroke-linecap:round;
  transition:stroke-dashoffset .18s linear}
.footer__up-arrow{position:absolute;left:11px;width:11px;pointer-events:none;
  transition:transform .5s var(--e-out-expo)}
.footer__up:hover .footer__up-arrow{transform:translateY(-3px)}

@media (max-width:700px){
  .footer__bottom{gap:.7rem;padding-right:0}
  .footer__copy{order:3;width:100%}
}

/* ---------- 24. CURSOR + GRAIN ------------------------------------------ */
/* The old cursor grew into a 52 px filled disc on every link, which sat on top
   of the very word you were reading. It is now a dot plus an open ring, and the
   label is parked outside the ring instead of inside it. */
.cursor{position:fixed;top:0;left:0;z-index:300;pointer-events:none;
  width:7px;height:7px;border-radius:50%;background:var(--ember);
  transform:translate3d(-50%,-50%,0);opacity:0;
  transition:opacity .3s,width .35s var(--e-out-expo),height .35s var(--e-out-expo)}
.cursor.is-link{width:5px;height:5px}
.cursor__ring{position:fixed;top:0;left:0;z-index:299;pointer-events:none;
  width:42px;height:42px;margin:-21px 0 0 -21px;border-radius:50%;
  border:1px solid rgba(226,85,30,.85);opacity:0;transform:scale(.4);
  transition:opacity .3s var(--e-out-cubic),transform .5s var(--e-out-expo),
             border-color .3s var(--e-out-cubic)}
.cursor__ring.is-link{opacity:1;transform:scale(1)}
.cursor__tag{position:fixed;top:0;left:0;z-index:299;pointer-events:none;
  transform:translate3d(18px,16px,0);
  padding:.34rem .55rem;border-radius:999px;white-space:nowrap;
  background:var(--ember);color:#fff;
  font-family:var(--f-mono);font-size:9px;letter-spacing:.14em;text-transform:uppercase;
  opacity:0;transition:opacity .25s var(--e-out-cubic)}
.cursor__tag.is-on{opacity:1}
@media (hover:none),(pointer:coarse){
  .cursor,.cursor__ring,.cursor__tag{display:none!important}
}
.grain{position:fixed;inset:-120%;z-index:110;pointer-events:none;opacity:.05;
  background-image:var(--grain-url);background-size:220px 220px;animation:grain 7s steps(6) infinite;mix-blend-mode:overlay}
@keyframes grain{0%{transform:translate(0,0)}20%{transform:translate(-4%,3%)}40%{transform:translate(3%,-4%)}
  60%{transform:translate(-3%,-3%)}80%{transform:translate(4%,4%)}100%{transform:translate(0,0)}}

/* ---------- 25. RESPONSIVE ---------------------------------------------- */
/* the band is much smaller now, so the section links survive further down */
@media (max-width:1080px){
  /* the sections collapse into the overlay; languages and burger stay */
  .band__links,.band__rule{display:none}
  .band{gap:4px}
}
@media (max-width:600px){
  .band .lang{display:none}
}
@media (max-width:1024px){
  .footer__top{grid-template-columns:1fr;gap:clamp(24px,4vw,40px)}
  .footer__contact{padding-right:0}
  .footer__mail{max-width:100%}
  .footer__bottom{padding-right:0;padding-bottom:clamp(76px,12vw,110px)}
}
@media (max-width:1200px){
  .why{grid-template-columns:repeat(2,1fr)}

  .chapter__head{grid-column:1/span 12}
  .chapter__lead{grid-column:1/span 12}
  .chapter__body{grid-column:1/span 8}
  .chapter__quote{grid-column:1/span 12}
  .b2b__head .h,.b2b__head .a{grid-column:1/span 12}
  .b2b__head .a{padding-bottom:0;margin-top:1.6rem}
  .why__item{grid-column:span 6}
  .cta__inner .h,.cta__inner .a{grid-column:1/span 12}
  .cta__inner .a{margin-top:2rem}
  .news__inner{grid-template-columns:1fr;gap:var(--gutter)}
  .news__intro,.form{grid-column:auto}
  .form{margin-top:2.4rem}
  .footer__col{grid-column:span 3}
  .footer__col--brand{grid-column:span 12}
  .xp__cell--a,.xp__cell--b{grid-column:span 12}
  .xp__cell--c,.xp__cell--d,.xp__cell--e{grid-column:span 6}
  .craft__row{grid-template-columns:repeat(3,1fr)}
  /* stacked, the panel is taller than the viewport — let it scroll from the
     top instead of anchoring to the bottom and cutting off the first rows */
  .menu__inner{grid-template-columns:1fr;align-items:start;align-content:start;
    overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}
  .menu__side{flex-direction:row;flex-wrap:wrap;gap:clamp(20px,4vw,48px);align-items:flex-end;margin-top:clamp(24px,4vh,48px)}
  /* stacked, every panel is simply shown in sequence — nothing to hover */
  .subs{width:100%}
  .subs__list a{font-size:clamp(.9rem,3.6vw,1.05rem)}
  .menu__meta{width:100%;margin-top:0}
}
@media (max-width:860px){
  /* with the right-hand controls gone the band would float in the middle */
  .band{margin-left:auto}
  .craft__sticky{padding-bottom:clamp(104px,15vh,150px)}
  .craft__badge{right:2%;bottom:-2%}
  .europe__track{height:250vh}
  .atmos__q{max-width:none}
  .atmos__over{padding-inline:var(--gutter);bottom:clamp(18px,3vw,32px)}
  .europe__head{max-width:none}
  .europe__lead{max-width:30ch}
  .globe::after{background:linear-gradient(180deg,rgba(11,8,6,.86) 0%,rgba(11,8,6,.3) 42%,rgba(11,8,6,.6) 100%)}
  .hero__col{max-width:100%}
  .hero__body{align-items:flex-end}
  .chapter__facts{grid-template-columns:1fr;gap:2rem}
  .fact{flex-direction:row;align-items:baseline;justify-content:space-between;
    border-bottom:1px solid var(--hairline-dark);padding-bottom:1rem}
  .chapter__body{grid-column:1/span 12}
  .immersive__media{width:86vw;height:60svh;border-radius:22em}
  .why{grid-template-columns:1fr}
  .xp__cell--c,.xp__cell--d,.xp__cell--e{grid-column:span 12}
  .craft__row{grid-template-columns:repeat(2,1fr)}
  .form__row{grid-template-columns:1fr}
  .footer__col{grid-column:span 6}
  .footer__col--brand{grid-column:span 12}
  .city{width:78vw;min-height:clamp(200px,30vh,280px)}
  .cities__head .editorial{font-size:clamp(1.15rem,5vw,1.6rem)}
  .btn{padding:1.05rem 1.6rem;min-height:48px}
  .lang button{min-height:44px;min-width:44px;display:grid;place-items:center}
  .menu__inner{padding-bottom:clamp(72px,10vh,120px)}
  .legacy__track,.yearseq__track,.immersive__track,.cities__track{height:260vh}
  .gl__box{padding:.24rem .45rem}
}
@media (max-width:600px){
  .orb{width:clamp(72px,19vw,92px);right:12px;bottom:12px}
  .orb.is-tuck{width:clamp(46px,12vw,58px)}

  .nav .lang{display:none}
  .footer__col{grid-column:span 6}
}
@media (min-width:1900px){
  :root{--maxw:1840px;--gutter:clamp(56px,3.6vw,110px);
    --t-display-xl:clamp(2.7rem,9.6vw,14.5rem);--t-display-l:clamp(2.6rem,7.4vw,10.5rem);
    --t-display-m:clamp(1.9rem,4.6vw,5.6rem);--t-lead:clamp(1.05rem,1.5vw,1.8rem);
    --t-body:clamp(1rem,1.02vw,1.28rem);--t-label:clamp(.625rem,.72vw,.86rem);
    --section-y:clamp(100px,12vw,280px)}
  .legacy__city{font-size:clamp(2.3rem,9.4vw,13rem)}
  .yearseq__digits{font-size:clamp(4rem,19vw,26rem)}
  .footer__mega{font-size:clamp(2.6rem,11.4vw,17rem)}
  .city__name{font-size:clamp(2rem,5vw,6.4rem)}
  .city{width:clamp(280px,34vw,760px)}
  .gl__box{font-size:clamp(.6rem,.66vw,.8rem)}
}

/* ---------- 26. ACCESSIBILITY ------------------------------------------- */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
  .grain{display:none}
  .hero__video{transform:none!important;filter:none!important}
  .beans,.leaf_wrapper{display:none}
  .atmos__clip{clip-path:none}
  .atmos__img{transform:none}
  .i-steam path,.i-drip,.i-eq path,.i-wave path,.i-spin,.i-pulse,.i-shine,.i-pour{animation:none!important;opacity:1}
  .europe__track{height:auto}
  .europe__sticky{position:static;height:auto;min-height:100svh}
  .chapter__grid{margin-top:0}
  .legacy__track,.yearseq__track,.immersive__track,.cities__track{height:auto}
  .legacy__sticky,.yearseq__sticky,.immersive__sticky,.cities__sticky{position:static;height:auto;padding-block:var(--section-y)}
  .legacy__stage{height:auto}
  .legacy__item{position:static;opacity:1!important;transform:none!important;margin-bottom:3rem}
  .legacy__rail{position:static;margin-top:2rem}
  .immersive__media{width:100%;height:60svh;border-radius:0}
  .immersive__headline,.yearseq__caption{opacity:1!important}
  .immersive__words{height:auto;font-size:clamp(1.6rem,5vw,3rem)}
  .immersive__words span{position:static;opacity:1!important;display:inline-block;padding-inline:.3em}
  .mask > span,[data-reveal] .mask > span{transform:none!important;opacity:1!important}
  .scrubtext .line-mask{display:none}
  .cursor{display:none}
}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.skip{position:absolute;left:var(--gutter);top:-100px;z-index:400;background:var(--ember);color:#fff;
  padding:.8rem 1.2rem;border-radius:4px;font-family:var(--f-mono);font-size:var(--t-label);
  text-transform:uppercase;letter-spacing:.14em;transition:top .3s var(--e-out-expo)}
.skip:focus{top:12px}

/* ---------- 26. CONSENT ---------------------------------------------------
   A card in the bottom-left, not a full-screen wall: it never blocks reading.
   Accept and Reject are the same button, same size, same weight — declining is
   not the harder path. Every optional toggle renders unchecked, and each
   category can be unfolded into a table naming provider, purpose, storage
   duration and any transfer outside the EU.                               */
.cc{position:fixed;left:clamp(12px,2vw,28px);bottom:clamp(12px,2vh,28px);z-index:250;
  width:min(460px,calc(100vw - clamp(24px,4vw,56px)));
  opacity:0;transform:translateY(18px) scale(.98);pointer-events:none;
  transition:opacity .6s var(--e-out-cubic),transform .8s var(--e-out-expo)}
.cc.is-on{opacity:1;transform:none;pointer-events:auto}
.cc__card{max-height:calc(100vh - clamp(24px,4vh,56px));overflow:auto;overscroll-behavior:contain;
  padding:clamp(18px,2.2vw,26px);border-radius:20px;color:var(--ivory);
  background:rgba(20,18,16,.96);
  backdrop-filter:blur(26px) saturate(160%);-webkit-backdrop-filter:blur(26px) saturate(160%);
  border:1px solid rgba(244,238,228,.14);
  box-shadow:0 30px 80px rgba(0,0,0,.6);
  scrollbar-width:thin;scrollbar-color:rgba(244,238,228,.22) transparent}
.cc__card::-webkit-scrollbar{width:6px}
.cc__card::-webkit-scrollbar-thumb{background:rgba(244,238,228,.22);border-radius:6px}
.cc__title{margin-top:.55em;font-family:var(--f-display);font-weight:720;font-stretch:104%;
  font-size:clamp(1.05rem,1.4vw,1.3rem);line-height:1.16;letter-spacing:-.02em}
.cc__body{margin-top:.6em;font-size:clamp(.82rem,.92vw,.9rem);line-height:1.6;
  color:var(--bone);opacity:.84}

.cc__opts{display:grid;gap:8px;margin-top:1.1rem}
.cc__cat{border-radius:13px;overflow:hidden;
  border:1px solid rgba(244,238,228,.1);background:rgba(244,238,228,.03);
  transition:border-color .35s var(--e-out-cubic)}
.cc__cat.is-open{border-color:rgba(226,85,30,.36)}
.cc__row{display:flex;align-items:flex-start;gap:12px;padding:.8rem .9rem}
.cc__rowtxt{flex:1;min-width:0;display:grid;gap:.3em}
.cc__rowt{font-size:.88rem;font-weight:640}
.cc__rowb{font-size:.75rem;line-height:1.5;color:var(--bone);opacity:.72}
.cc__det{justify-self:start;display:inline-flex;align-items:center;gap:.4rem;margin-top:.15em;
  padding:0;background:none;border:0;cursor:pointer;
  font-family:var(--f-mono);font-size:.6rem;text-transform:uppercase;letter-spacing:.13em;
  color:var(--ember-lo);transition:color .3s}
.cc__det:hover{color:var(--ivory)}
.cc__det svg{width:9px;height:9px;transition:transform .4s var(--e-out-expo)}
.cc__cat.is-open .cc__det svg{transform:rotate(180deg)}
.cc__always{flex:none;color:var(--muted);align-self:center}

.cc__sw{flex:none;align-self:center;display:block;cursor:pointer}
.cc__sw input{position:absolute;opacity:0;width:0;height:0}
.cc__track{position:relative;display:block;width:40px;height:22px;border-radius:999px;
  background:rgba(244,238,228,.14);border:1px solid rgba(244,238,228,.16);
  transition:background-color .4s var(--e-out-cubic),border-color .4s var(--e-out-cubic)}
.cc__track i{position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;
  background:var(--ivory);transition:transform .45s var(--e-out-expo)}
.cc__sw input:checked + .cc__track{background:var(--ember);border-color:var(--ember)}
.cc__sw input:checked + .cc__track i{transform:translateX(18px);background:#fff}
.cc__sw input:focus-visible + .cc__track{outline:2px solid var(--ember-lo);outline-offset:3px}

/* the per-service table: provider, purpose, duration, transfer */
.cc__table{overflow-x:auto;border-top:1px solid rgba(244,238,228,.1);
  animation:ccUnfold .4s var(--e-out-expo)}
@keyframes ccUnfold{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
.cc__table table{width:100%;border-collapse:collapse;font-size:.7rem;line-height:1.45;
  min-width:520px}
.cc__table th,.cc__table td{text-align:left;vertical-align:top;padding:.55rem .7rem;
  border-bottom:1px solid rgba(244,238,228,.07)}
.cc__table thead th{font-family:var(--f-mono);font-size:.56rem;text-transform:uppercase;
  letter-spacing:.13em;color:var(--muted);white-space:nowrap}
.cc__table tbody th{font-weight:640;color:var(--ivory);white-space:nowrap}
.cc__table td{color:var(--bone);opacity:.8}
.cc__table tbody tr:last-child th,.cc__table tbody tr:last-child td{border-bottom:0}

/* accept and reject are the same control at the same weight */
.cc__acts{display:flex;flex-wrap:wrap;gap:8px;margin-top:1.1rem}
.cc__btn{flex:1 1 8rem;padding:.78rem 1rem;border-radius:999px;cursor:pointer;
  font-family:var(--f-mono);font-size:var(--t-label);text-transform:uppercase;letter-spacing:.11em;
  border:1px solid rgba(244,238,228,.2);background:rgba(244,238,228,.07);color:var(--ivory);
  transition:background-color .4s var(--e-out-cubic),border-color .4s var(--e-out-cubic),
             transform .6s var(--e-out-expo)}
.cc__btn:hover{background:rgba(244,238,228,.15);border-color:rgba(244,238,228,.34);
  transform:translateY(-1px)}
.cc__btn:focus-visible{outline:2px solid var(--ember-lo);outline-offset:3px}

.cc__foot{display:flex;flex-wrap:wrap;align-items:center;gap:.4rem 1.1rem;margin-top:.9rem}
.cc__link{padding:0;background:none;border:0;cursor:pointer;
  font-family:var(--f-mono);font-size:var(--t-label);text-transform:uppercase;letter-spacing:.12em;
  color:var(--muted);transition:color .3s}
.cc__link:hover{color:var(--ember-lo)}
.cc__note{margin-top:.7rem;font-size:.72rem;line-height:1.5;color:var(--muted-2)}
.cc__stamp{margin-top:.4rem;color:var(--muted-2);letter-spacing:.1em}

@media (max-width:620px){
  .cc{left:10px;right:10px;bottom:10px;width:auto}
  .cc__btn{flex:1 1 100%}
}
@media (prefers-reduced-motion:reduce){
  .cc{transition:opacity .2s}
  .cc.is-on{transform:none}
  .cc__table{animation:none}
}

/* ---- it gets out of the way -------------------------------------------
   Anything marked [data-orb-avoid] that would sit under the orb pushes it up
   and out; the check runs on scroll and on resize, not on a fixed guess.  */
.orb.is-dodge{transform:translateY(calc(-1 * var(--orb-dodge,0px)))}
.orb__inner{will-change:transform}

/* ---- hand-over --------------------------------------------------------
   On a section that carries its own primary CTA the orb stops competing with
   it: the disc drops to a quiet outline and the label goes, so there is one
   obvious next action on screen instead of two.                          */
.orb.is-quiet .orb__disc{background:transparent;color:var(--ember);
  border:1px solid rgba(226,85,30,.55);box-shadow:none}
.orb.is-quiet[data-tone="light"] .orb__disc{color:var(--ink);border-color:rgba(11,8,6,.4)}
.orb.is-quiet .orb__text{opacity:.7}
.orb.is-quiet:hover .orb__disc{background:var(--ember);color:#fff;
  border-color:var(--ember);box-shadow:0 18px 48px rgba(226,85,30,.45)}

@media (prefers-reduced-motion:reduce){ .orb__prog-arc{transition:none} }


/* ---------- 28. LOGO LOCKUP ---------------------------------------------
   The roundel beside the wordmark, used in the footer and at the head of the
   application. One component, so the two can never drift apart.          */
.lockup{display:inline-flex;align-items:center;gap:clamp(10px,1vw,16px);
  color:var(--ivory);transition:opacity .35s var(--e-out-cubic)}
.lockup:hover{opacity:.85}
.lockup__mark{flex:none;display:block;width:clamp(40px,3.4vw,54px)}
.lockup__mark img{width:100%;height:auto;display:block}
/* The second line is justified to the exact width of the wordmark above it
   rather than letter-spaced by eye: with a fixed tracking value the sub line
   always ended up a few pixels wider than the mark, which is the one thing a
   lockup is not allowed to do. Three items pushed to the edges of the same
   box means the two lines end flush at every size. */
.lockup__type{display:flex;flex-direction:column;gap:clamp(8px,.72vw,13px);min-width:0}
.lockup__word{display:block;flex:none;width:clamp(112px,10vw,152px);height:auto;color:currentColor}
.lockup__sub{display:flex;flex:none;justify-content:space-between;align-items:baseline;
  width:clamp(112px,10vw,152px);
  color:var(--muted);letter-spacing:.06em;white-space:nowrap}
.lockup__sub i{font-style:normal}

/* ---------- 27. AMBIENT AUDIO -------------------------------------------
   Bottom-left, opposite the orb, so the two never meet. Off until asked, and
   the four bars only move while something is actually playing.           */


@keyframes audBar{0%,100%{height:3px}50%{height:12px}}

/* ---------- 33. PRESS FEEDBACK -------------------------------------------
   The ripple is drawn into a fixed layer rather than into the element, so a
   pill's border-radius and a card's overflow cannot clip it, and one rule set
   covers every pressable thing on the site. assets/js/click.js drives it.  */
.taplayer{position:fixed;inset:0;z-index:200;pointer-events:none;overflow:hidden}
.tap{position:absolute;left:0;top:0;width:14px;height:14px;margin:-7px 0 0 -7px;
  border-radius:50%;pointer-events:none;
  border:1.5px solid rgba(244,238,228,.75);
  animation:tapRing var(--tapd,.6s) cubic-bezier(.2,.8,.25,1) forwards}
/* a second, slower ring leaves behind the first — one press, two beats */
.tap::after{content:'';position:absolute;inset:-3px;border-radius:50%;
  border:1px solid rgba(244,238,228,.3);
  animation:tapRing calc(var(--tapd,.6s) * 1.7) cubic-bezier(.2,.8,.25,1) forwards}
.tap--warm{border-color:rgba(255,150,96,.9);
  box-shadow:0 0 18px 2px rgba(226,85,30,.34)}
.tap--warm::after{border-color:rgba(226,85,30,.4)}
@keyframes tapRing{
  0%  {transform:scale(.35);opacity:0}
  14% {opacity:1}
  100%{transform:scale(calc(5.5 * var(--taps,1)));opacity:0}}
@media (prefers-reduced-motion:reduce){ .taplayer{display:none} }

/* the game is new rather than soon: same chip, the other way round */
.soon--new{color:#fff;background:var(--ember);border-color:var(--ember)}
.soon--new::before{background:#fff}

/* ══ THE GAME PROMO CARD ═══════════════════════════════════════════════════
   Injected by promo.js on every page but the game page and the application.
   Bottom-right, stacked directly above the round Get-in-touch button: the two
   are one column of "things you could do next" rather than two things shouting
   from opposite corners. The offset is built from the orb's own clamps — its
   tallest resting position plus its widest diameter plus a gap — so the card
   clears it in every state the orb has, tucked, hovered or full size.    */
.gpromo{position:fixed;z-index:140;
  right:clamp(12px,2vw,28px);
  bottom:calc(clamp(58px,6.4vh,88px) + clamp(84px,6.4vw,112px) + 16px);
  width:min(342px,calc(100vw - 24px));
  padding:clamp(16px,1.5vw,20px) clamp(16px,1.5vw,20px) clamp(14px,1.4vw,18px);
  border-radius:18px;overflow:hidden;isolation:isolate;
  border:1px solid rgba(244,238,228,.14);
  background:rgba(11,8,6,.88);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  box-shadow:0 26px 70px rgba(0,0,0,.5);
  /* it arrives from the edge it lives on */
  opacity:0;transform:translate3d(26px,0,0) scale(.97);pointer-events:none;
  transition:opacity .55s var(--e-out-cubic),transform .85s var(--e-out-expo)}
.gpromo.is-on{opacity:1;transform:none;pointer-events:auto}
.gpromo[hidden]{display:none}
.gpromo__glow{position:absolute;z-index:-1;inset:auto -30% -60% auto;width:80%;aspect-ratio:1;
  border-radius:50%;pointer-events:none;
  background:radial-gradient(circle,var(--ember-glow),transparent 68%);opacity:.7}

.gpromo__x{position:absolute;top:10px;right:10px;z-index:2;display:grid;place-items:center;
  width:26px;height:26px;border-radius:50%;cursor:pointer;
  border:1px solid rgba(244,238,228,.14);background:rgba(244,238,228,.05);color:var(--muted);
  transition:color .35s,background-color .35s,transform .5s var(--e-out-expo)}
.gpromo__x svg{width:11px;height:11px}
.gpromo__x:hover{color:var(--ivory);background:rgba(244,238,228,.14);transform:rotate(90deg)}
.gpromo__x:focus-visible{outline:2px solid var(--ember);outline-offset:3px}

/* ---- the icon that explains the game ------------------------------------
   Three cups and a bean that hops across them, lands in the middle of the
   third and sparks. That is the whole game in four seconds, and it says it
   without a word — which is the only way to explain a game inside a card this
   small and in three languages at once. */
.gpromo__ico{position:relative;display:block;height:44px;margin:-2px 0 .85rem;
  width:100%}
.gpromo__cups{position:absolute;left:0;bottom:0;display:flex;gap:34px}
.gpromo__cups i{position:relative;display:block;width:26px;height:17px;
  border-radius:2px 2px 7px 7px;
  background:linear-gradient(180deg,var(--roast),var(--roast-deep));
  box-shadow:inset 0 3px 0 rgba(226,85,30,.5)}
.gpromo__cups i::after{content:'';position:absolute;left:50%;top:3px;translate:-50% 0;
  width:3px;height:3px;border-radius:50%;background:rgba(244,238,228,.25)}
/* the cup being landed on lights up in turn */
.gpromo__cups i{animation:gpLand 4s var(--e-out-cubic) infinite}
.gpromo__cups i:nth-child(2){animation-delay:1s}
.gpromo__cups i:nth-child(3){animation-delay:2s}
@keyframes gpLand{
  0%,18%,100%{box-shadow:inset 0 3px 0 rgba(226,85,30,.5)}
  6%{box-shadow:inset 0 3px 0 var(--ember),0 0 16px rgba(226,85,30,.55)}}

/* the bean: X is stepped, Y is the arc — two elements, because one cannot
   carry two different curves on the same axis pair */
.gpromo__hop{position:absolute;left:13px;bottom:17px;width:0;height:0;
  animation:gpX 4s cubic-bezier(.5,0,.5,1) infinite}
.gpromo__hop s{position:absolute;left:-5px;bottom:0;display:block;
  width:10px;height:10px;border-radius:60% 60% 55% 55%;
  background:var(--ember);box-shadow:0 0 12px rgba(226,85,30,.6);
  animation:gpY 1s cubic-bezier(.33,0,.66,1) infinite}
.gpromo__hop s::after{content:'';position:absolute;left:50%;top:14%;translate:-50% 0;
  width:1.4px;height:72%;border-radius:2px;background:rgba(11,8,6,.5)}
@keyframes gpX{
  0%,4%   {transform:translateX(0)}
  25%,29% {transform:translateX(60px)}
  50%,54% {transform:translateX(120px)}
  75%,79% {transform:translateX(60px)}
  100%    {transform:translateX(0)}}
@keyframes gpY{
  0%   {transform:translateY(0) scale(1.15,.82)}
  12%  {transform:translateY(-4px) scale(.94,1.08)}
  50%  {transform:translateY(-26px) scale(1,1)}
  88%  {transform:translateY(-4px) scale(.96,1.06)}
  100% {transform:translateY(0) scale(1.15,.82)}}

.gpromo__k{position:relative;z-index:1;padding-right:26px}
.gpromo__h{position:relative;z-index:1;display:block;margin-top:.45em;
  font-family:var(--f-display);font-weight:720;font-stretch:104%;
  font-size:1.16rem;line-height:1.12;color:var(--ivory)}
.gpromo__b{position:relative;z-index:1;margin-top:.5em;
  font-size:.82rem;line-height:1.55;color:var(--bone);opacity:.86}

.gpromo__act{position:relative;z-index:1;display:flex;flex-wrap:wrap;align-items:center;
  gap:.5rem 1rem;margin-top:1rem}
.gpromo__go{display:inline-flex;align-items:center;gap:.5rem;text-decoration:none;
  padding:.55rem .95rem;border-radius:999px;color:var(--espresso);background:var(--ember);
  font-family:var(--f-mono);font-size:var(--t-label);line-height:1;
  letter-spacing:.11em;text-transform:uppercase;
  transition:transform .6s var(--e-out-expo),filter .4s}
.gpromo__go svg{width:12px;height:12px;transition:transform .6s var(--e-out-expo)}
.gpromo__go:hover{transform:translateY(-2px);filter:brightness(1.08)}
.gpromo__go:hover svg{transform:translate3d(2px,-2px,0)}
.gpromo__go:focus-visible{outline:2px solid var(--ivory);outline-offset:3px}
.gpromo__more{color:var(--muted);font-size:.78rem;text-decoration:underline;
  text-underline-offset:3px;text-decoration-color:rgba(244,238,228,.28);
  transition:color .35s,text-decoration-color .35s}
.gpromo__more:hover{color:var(--ivory);text-decoration-color:var(--ivory)}

@media (max-width:620px){
  .gpromo{left:12px;right:12px;width:auto;
    bottom:calc(clamp(58px,6.4vh,88px) + 84px + 14px)}
  .gpromo__b{font-size:.8rem}
}
@media (prefers-reduced-motion:reduce){
  .gpromo{transition-duration:.01ms;transform:none}
  .gpromo__hop,.gpromo__hop s,.gpromo__cups i{animation:none}
  .gpromo__x:hover,.gpromo__go:hover{transform:none}
}

/* the accessibility entry in the overlay menu — a button, not a link, because
   it opens a panel rather than going anywhere */
.menu__a11y{display:inline-flex;align-items:center;gap:.6rem;margin-top:1.1rem;cursor:pointer;
  padding:.6rem .95rem;border-radius:999px;
  border:1px solid rgba(244,238,228,.18);background:rgba(244,238,228,.03);color:var(--bone);
  font-family:var(--f-mono);font-size:var(--t-label);letter-spacing:.11em;line-height:1;
  text-transform:uppercase;
  transition:color .35s,border-color .35s,background-color .35s,transform .5s var(--e-out-expo)}
.menu__a11y svg{width:15px;height:15px;flex:none}
.menu__a11y:hover{color:var(--ivory);border-color:rgba(226,85,30,.45);transform:translateY(-2px)}
.menu__a11y:focus-visible{outline:2px solid var(--ember);outline-offset:3px}

/* ══ THE PAGE TRANSITION ═══════════════════════════════════════════════════
   An ink disc opens from the point that was clicked, takes the window, and on
   the next document closes back down to the same point. Scale and opacity
   only — the cover must not cost the incoming page the frames it needs to
   paint. Geometry (--x, --y, --s) is measured by swap.js.                 */
/* The pre-cover: painted from the very first frame of the arriving document by
   a class the inline head script sets, because a script at the end of <body>
   cannot mount anything before that first frame — and one bare frame of the
   new page in the middle of the transition is exactly the blink it was there
   to prevent. swap.js drops the class once the disc itself is painted.

   Flat ink, and the mark at exactly the size the disc's mark uses: the two
   covers have to be the same colour to the pixel, or the handover between them
   prints as a step in the black. */
html.pt-cover::before{content:'';position:fixed;inset:0;z-index:899;
  background:url('../../public/logo/mark.svg') center / clamp(58px,5vw,84px) no-repeat,
             #0B0806;
  pointer-events:none}

/* ══ THE PAGE TRANSITION ═══════════════════════════════════════════════════
   An ink disc opens from the point that was clicked, takes the window, and on
   the next document closes back down to the same point.

   The disc is built at the size it has to end up and scaled from 0 to 1 rather
   than built small and magnified: a magnified circle keeps its small raster
   and arrives soft and shimmering. Its ember edge is a stop in its own
   background, not a second full-size layer. swap.js sets --x, --y and the
   element's size; the states are Web Animations, because a class-driven
   transition has to be committed by the main thread and the main thread of a
   document that is still booting cannot commit anything for a second or more.
                                                                          */
.pt{position:fixed;inset:0;z-index:900;pointer-events:none;
  overflow:hidden;contain:layout paint;visibility:hidden;--x:50vw;--y:50vh}
.pt.is-on{visibility:visible}

.pt__disc{position:absolute;left:var(--x);top:var(--y);
  width:160px;height:160px;margin:-80px 0 0 -80px;border-radius:50%;
  transform:scale(0);will-change:transform;
  /* Ink, with the ember edge riding the rim of the circle itself. `closest-side`
     puts the gradient's 100 % exactly on the circle's radius, which lets the
     stops be given in PIXELS — a percentage ring on a three-thousand-pixel
     disc renders as a thirty-pixel orange band sweeping across the screen,
     which is neither a hot edge nor clean. */
  background:radial-gradient(circle closest-side,
    #0B0806 0 calc(100% - 11px),
    rgba(226,85,30,.10) calc(100% - 7px),
    rgba(226,85,30,.55) calc(100% - 2px),
    rgba(226,85,30,0) 100%)}

/* the mark, at the centre, only while the window is covered. The centring
   lives inside `transform` and not in the separate `translate` property,
   because the keyframes animate `transform` — the two would compose and put
   the mark a full width off. */
.pt__logo{position:absolute;left:50%;top:50%;
  width:clamp(58px,5vw,84px);aspect-ratio:1;margin:0;
  background:url('../../public/logo/mark.svg') center/contain no-repeat;
  opacity:0;transform:translate(-50%,-50%) scale(.62) rotate(-16deg);
  will-change:transform,opacity}

/* The page underneath sinks a little as the disc takes it. Only on the way
   OUT, and only a transform: on the way in, the arriving document is already
   busy with its own boot, and a full-page filter or layer promotion at that
   moment is exactly the work that drops frames out of the reveal. Scoped to
   <main> rather than to every child of <body>, because GSAP owns the transform
   of the orb, the cursor and the curtain. */
html.pt-leaving main{opacity:.82;transition:opacity .4s var(--e-out-cubic)}
main{transition:opacity .5s var(--e-out-cubic)}

@media (prefers-reduced-motion:reduce){
  .pt{display:none}
  html.pt-leaving main{opacity:1;transition:none}
}
