/* SOLENNE v6.1 ============================================================
   One stylesheet. Every scroll-driven value arrives as a CSS custom property
   written by one rAF pass; nothing in here is animated by JavaScript directly.
   The rule the whole file obeys: per frame, only transform, opacity and colour
   ever change. No width, no top, no margin, no filter.
   ====================================================================== */

@font-face{font-family:Bodoni;src:url(../fonts/bodoni.woff2) format('woff2');font-weight:400 500;font-style:normal;font-display:swap;
  ascent-override:92%;descent-override:26%;line-gap-override:0%}
@font-face{font-family:Inter;src:url(../fonts/inter.woff2) format('woff2');font-weight:400 600;font-style:normal;font-display:swap;
  ascent-override:96%;descent-override:24%;line-gap-override:0%}

:root{
  --bk:#0a0a0a;          /* the page, and the black baked into every frame */
  --bk2:#111111;         /* cards, plates, the footer */
  --wh:#f2f2f0;          /* type, full-strength rules, the menu panels */
  --mute:rgba(242,242,240,.62);   /* 7:1 on --bk */
  --line:rgba(242,242,240,.16);
  --linei:rgba(10,10,10,.16);     /* hairlines on the white menu panels */

  --fd:Bodoni,'Bodoni MT','Didot','Times New Roman',serif;
  --fs:Inter,system-ui,-apple-system,'Segoe UI',sans-serif;

  --e1:cubic-bezier(.16,1,.3,1);
  --e2:cubic-bezier(.76,0,.24,1);
  --e3:cubic-bezier(.34,1.4,.5,1);
  --e4:cubic-bezier(.4,0,0,1);

  --gut:clamp(18px,4.4vw,64px);
  --wrap:1560px;
  --hd:clamp(58px,7vw,84px);

  --sk:0;            /* scroll velocity skew, degrees */
  --rr:56px;         /* pass ring radius, written by JS */
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:auto}
body{
  margin:0;background:var(--bk);color:var(--wh);
  font-family:var(--fs);font-size:clamp(14.5px,1.02vw,16.5px);line-height:1.55;
  font-weight:400;letter-spacing:-.005em;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  overflow-x:clip;
}
img,canvas,svg,picture{display:block;max-width:100%}
img{height:auto}
h1,h2,h3,p,ul,ol,figure,blockquote{margin:0}
ul,ol{list-style:none;padding:0}
a{color:inherit;text-decoration:none}
button,input{font:inherit;color:inherit}
button{background:none;border:0;padding:0;cursor:pointer}
:focus-visible{outline:2px solid var(--wh);outline-offset:3px;border-radius:2px}
::selection{background:var(--wh);color:var(--bk)}

.wrap{width:min(var(--wrap),100% - var(--gut)*2);margin-inline:auto}
.vhp{position:fixed;top:0;left:0;width:1px;height:100vh;height:100svh;pointer-events:none;visibility:hidden}

/* ---------------------------------------------------------------- type */
.big,.sechd__t,.stage__t,.end__t{
  font-family:var(--fd);font-weight:400;letter-spacing:-.01em;line-height:.94;font-optical-sizing:auto;
  text-wrap:balance;
}
.it{font-style:italic}
.eyebrow{
  font-size:clamp(9.5px,.72vw,11.5px);letter-spacing:.26em;text-transform:uppercase;
  color:var(--mute);font-weight:500;display:flex;align-items:center;gap:.85em;
}
.eyebrow i{font-style:normal;color:var(--mute);font-size:1.05em}

/* line masks: the unit every headline reveal is built from */
.ln{display:block;overflow:hidden;padding-block:.02em .1em;margin-block:-.02em -.1em}
.ln>i{display:block;font-style:normal;transform:translate3d(0,110%,0);
  transition:transform 1.15s var(--e1);transition-delay:calc(var(--d,0)*1ms)}
.ln>i.it{font-style:italic}
.vis.is-in .ln>i,.is-in>.ln>i,.is-in .ln>i{transform:translate3d(0,0,0)}

/* word masks */
.w{display:inline-block;overflow:hidden;vertical-align:top;padding-block:.02em .12em;margin-block:-.02em -.12em}
.w>i{display:inline-block;font-style:inherit;transform:translate3d(0,105%,0);
  transition:transform .95s var(--e1);transition-delay:calc(var(--d,0)*1ms)}
.is-in .w>i{transform:translate3d(0,0,0)}

/* generic reveal */
[data-rv]{opacity:0;transform:translate3d(0,26px,0);
  transition:opacity .9s var(--e1),transform 1.05s var(--e1);
  transition-delay:calc(var(--d,0)*1ms)}
[data-rv].is-in{opacity:1;transform:none}

/* rolling label */
.roll{display:inline-block;position:relative;overflow:hidden;vertical-align:top;
  padding-block:.14em;margin-block:-.14em}
.roll>span{display:block;transition:transform .62s var(--e2)}
.roll>span+span{position:absolute;inset:0;transform:translate3d(0,105%,0)}
a:hover .roll>span,button:hover .roll>span{transform:translate3d(0,-105%,0)}
a:hover .roll>span+span,button:hover .roll>span+span{transform:translate3d(0,0,0)}

/* ---------------------------------------------------------------- grain + chrome */
.grain{
  position:fixed;inset:-120px;z-index:90;pointer-events:none;
  background:url(../img/noise.png) repeat;background-size:96px 96px;
  opacity:.05;mix-blend-mode:normal;
  animation:grain 5.2s steps(6,end) infinite;
}
/* A full viewport mix-blend-mode overlay makes the compositor blend the whole page on
   every frame. It was already dropped on touch; now it is dropped everywhere. Over a
   black page a screen blend at 7 percent and plain alpha at 5 are the same picture,
   and the second one is free. */
@media (pointer:coarse){
  .grain{opacity:.038}
}
@keyframes grain{
  0%{transform:translate3d(0,0,0)}     16%{transform:translate3d(-22px,14px,0)}
  33%{transform:translate3d(18px,-20px,0)} 50%{transform:translate3d(-14px,-16px,0)}
  66%{transform:translate3d(24px,10px,0)}  83%{transform:translate3d(-8px,22px,0)}
  100%{transform:translate3d(0,0,0)}
}

/* cursor */
.cur{position:fixed;top:0;left:0;z-index:200;pointer-events:none;
  transform:translate3d(var(--x,-100px),var(--y,-100px),0);will-change:transform;opacity:0;
  transition:opacity .3s}
.cur.on{opacity:1}
.cur__r,.cur__d{position:absolute;left:0;top:0;border-radius:50%;transform:translate(-50%,-50%) scale(var(--s,1))}
.cur__r{width:38px;height:38px;border:1px solid rgba(242,242,240,.5);
  transition:transform .42s var(--e1),background-color .3s,border-color .3s,width .42s var(--e1),height .42s var(--e1)}
.cur__d{width:4px;height:4px;background:var(--wh);transition:transform .3s var(--e1),opacity .3s}
.cur__t{position:absolute;left:0;top:0;transform:translate(-50%,-50%);
  font-size:9.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--bk);
  opacity:0;transition:opacity .28s;white-space:nowrap;font-weight:500}
.cur.big .cur__r{width:76px;height:76px;background:var(--wh);border-color:transparent}
.cur.big .cur__d{transform:translate(-50%,-50%) scale(0)}
.cur.big .cur__t{opacity:1}
.cur.inv .cur__r{border-color:rgba(10,10,10,.45)}
.cur.inv .cur__d{background:var(--bk)}
.cur.inv.big .cur__r{background:var(--bk)}
.cur.inv.big .cur__t{color:var(--wh)}
@media (hover:none),(pointer:coarse){.cur{display:none}}

/* ---------------------------------------------------------------- loader
   The rule here: everything that MOVES is a CSS animation on transform or opacity,
   so the compositor owns it and a busy main thread cannot make it hitch. The old
   build spun an SVG textPath, which re-rasterises on the main thread every frame
   and cannot be promoted to a layer; the legend below is 44 absolutely positioned
   letters inside ONE rotating box instead, which is a single composited transform.
   The only per-frame main-thread write is the readout, and a dropped frame on a
   number is invisible. */
.ld{
  position:fixed;inset:0;z-index:120;background:var(--bk);
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  transition:opacity .42s var(--e4) .3s;
}
.ld__grain{position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(122% 88% at 50% 44%,transparent 34%,rgba(242,242,240,.085) 100%)}
.ld__mid{position:relative;display:flex;flex-direction:column;align-items:center;
  transition:opacity .4s var(--e4),transform .7s var(--e2)}

.ld__seal{
  position:relative;width:clamp(196px,27vw,308px);aspect-ratio:1;display:grid;place-items:center;
  transform:translate3d(var(--fx,0px),var(--fy,0px),0) scale(var(--fsc,1)) rotate(var(--fr,0deg));
  transition:transform 1.05s var(--e2) .06s,opacity .5s var(--e4) .5s;
  animation:sealIn 1.25s var(--e1) backwards;
}
@keyframes sealIn{from{opacity:0;transform:scale(.82) rotate(-16deg)}to{opacity:1}}

.ld__legend{position:absolute;inset:0;animation:spin 26s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.ld__legend i{position:absolute;left:50%;top:50%;width:1em;margin-left:-.5em;
  font-style:normal;font-size:clamp(8.5px,.86vw,11px);letter-spacing:0;
  font-weight:500;color:var(--mute);
  transform:rotate(var(--a)) translateY(calc(clamp(196px,27vw,308px) * -.5 + 3px));
  transform-origin:50% 0}

.ld__arc{position:absolute;inset:0;transform:rotate(-90deg);overflow:visible}
.ld__arc circle{fill:none;stroke-width:1.25}
.ld__track{stroke:rgba(242,242,240,.11)}
.ld__fill{stroke:var(--wh);stroke-linecap:round;
  stroke-dasharray:295.31;stroke-dashoffset:295.31}
.ld__glyph{font-family:var(--fd);font-size:clamp(74px,10.5vw,124px);line-height:1;color:var(--wh);
  animation:glyphIn 1.3s var(--e1) .14s both}
@keyframes glyphIn{from{opacity:0;transform:translateY(18px) scale(.92)}to{opacity:1;transform:none}}
.ld__tick{position:absolute;left:50%;top:50%;width:1px;height:calc(50% - 12px);
  background:linear-gradient(rgba(242,242,240,.55),transparent);transform-origin:50% 0;
  transform:rotate(var(--a)) translateX(-50%);
  animation:tickIn 1s var(--e1) .34s both}
@keyframes tickIn{from{opacity:0;transform:rotate(var(--a)) translateX(-50%) scaleY(.1)}}

.ld__word{display:flex;gap:.14em;margin-top:clamp(26px,3.6vw,46px);
  font-family:var(--fd);font-size:clamp(26px,3.4vw,42px);letter-spacing:.38em;
  text-indent:.38em;color:var(--wh)}
.ld__word span{display:block;overflow:hidden;padding-block:.06em}
.ld__word i{display:block;font-style:normal;transform:translate3d(0,108%,0);
  animation:wordIn 1s var(--e1) both;animation-delay:calc(.34s + var(--i)*56ms)}
@keyframes wordIn{to{transform:translate3d(0,0,0)}}
.ld__sub{margin-top:clamp(12px,1.6vw,20px);font-size:10.5px;letter-spacing:.28em;
  text-transform:uppercase;color:var(--mute);
  animation:subIn 1s var(--e1) .74s backwards}
@keyframes subIn{from{opacity:0;transform:translateY(10px)}}

.ld__foot{position:absolute;left:0;right:0;bottom:0;
  padding:0 var(--gut) clamp(20px,3.2vw,38px);
  display:grid;grid-template-columns:auto minmax(60px,1fr) auto;align-items:center;
  gap:clamp(14px,2.4vw,30px);
  animation:footIn 1s var(--e1) .5s backwards}
@keyframes footIn{from{opacity:0;transform:translateY(18px)}}
.ld__cap{font-size:10px;letter-spacing:.26em;text-transform:uppercase;color:var(--mute);
  width:9.4em;overflow:hidden;height:1.5em}
.ld__cap span{display:block;transition:transform .46s var(--e2),opacity .36s}
.ld__cap.sw span{transform:translateY(-125%);opacity:0}
.ld__rule{height:1px;background:var(--line);overflow:hidden}
.ld__rule i{display:block;height:100%;background:var(--wh);transform:scaleX(var(--p,0));
  transform-origin:0 50%}
.ld__num{display:flex;align-items:baseline;font-size:11px;letter-spacing:.06em;
  color:var(--wh);font-weight:500;font-feature-settings:'tnum'}
.ld__num b{display:block;width:.66em;height:1.25em;overflow:hidden;font-weight:500}
.ld__num b>i{display:block;font-style:normal;
  transform:translate3d(0,calc(var(--n,0)*-1.25em),0);transition:transform .5s var(--e1)}
.ld__num b s{display:block;height:1.25em;line-height:1.25em;text-decoration:none}
.ld__num em{font-style:normal;color:var(--mute);margin-left:.35em;font-size:.86em}

.slats{position:fixed;inset:0;z-index:110;display:flex;pointer-events:none}
.slats i{flex:1 1 0;background:var(--wh);transform:translate3d(0,0,0);
  transition:transform 1.05s var(--e2);transition-delay:calc(var(--s)*58ms)}

/* THE EXIT. The loader does not fade out, it closes down: the ground goes to ink,
   the seal flies into the header's own wordmark, and then six white
   panels lift away in a staircase to reveal a hero that has already begun composing
   itself. A black loader wiping off a black page is invisible, which is exactly what
   the first pass looked like. The seal keeps flying over the lifting panels, so the
   loader's own mark is what hands the page over. Transform, opacity and colour only. */
html.is-out .ld__seal,html.is-out .ld__sub,html.is-out .ld__foot,
html.is-out .ld__word i,html.is-out .ld__glyph,html.is-out .ld__tick{animation:none}
html.is-out .ld{pointer-events:none;animation:ldGround .62s linear forwards}
@keyframes ldGround{
  0%{background-color:#0a0a0a;animation-timing-function:cubic-bezier(.4,0,0,1)}
  62%{background-color:#f2f2f0}
  99%{background-color:#f2f2f0}
  100%{background-color:transparent}
}
html.is-out .ld__grain{opacity:0;transition:opacity .5s var(--e4)}
html.is-out .ld__glyph{color:var(--bk);transition:color .46s var(--e4) .04s}
html.is-out .ld__legend i{color:rgba(10,10,10,.30);transition:color .46s var(--e4)}
html.is-out .ld__tick{opacity:.2}
html.is-out .ld__track{stroke:rgba(10,10,10,.14);transition:stroke .46s var(--e4)}
html.is-out .ld__fill{stroke:var(--bk)}
html.is-out .ld__mid>:not(.ld__seal){opacity:0;transform:translate3d(0,-20px,0);
  transition:opacity .3s var(--e4),transform .44s var(--e4)}
html.is-out .ld__foot{opacity:0;transform:translate3d(0,20px,0);
  transition:opacity .3s,transform .44s var(--e4)}
html.is-out .ld__seal{transition:transform 1.02s var(--e2) .12s,opacity .34s var(--e4) 1.02s}
html.is-out .ld__seal{opacity:0}
html.is-out .slats i{transform:translate3d(0,-101%,0);
  transition:transform 1.06s var(--e2);transition-delay:calc(590ms + var(--s)*58ms)}
html.done .ld,html.done .slats{display:none}

/* pre-boot: nothing animated shows through the loader */
html.pre body{overflow:hidden}
html.pre .hd,html.pre .cue{opacity:0}

/* ---------------------------------------------------------------- header */
.hd{
  position:fixed;top:0;left:0;right:0;z-index:80;height:var(--hd);
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;
  padding-inline:var(--gut);gap:12px;
  transform:translate3d(0,var(--hy,0px),0);
  transition:transform .55s var(--e1),opacity .6s var(--e1) .55s;
  mix-blend-mode:normal;
}
.hd__btn{display:inline-flex;align-items:center;gap:.7em;min-height:44px;
  font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;font-weight:500;color:var(--wh)}
.hd__menu{justify-self:start}
.hd__shop{justify-self:end}
.hd__bars{display:block;width:19px;height:9px;position:relative}
.hd__bars i{position:absolute;left:0;right:0;height:1px;background:currentColor;
  transition:transform .5s var(--e2),opacity .3s}
.hd__bars i:first-child{top:0}
.hd__bars i:last-child{bottom:0}
.hd__menu[aria-expanded=true] .hd__bars i:first-child{transform:translateY(4px) rotate(45deg)}
.hd__menu[aria-expanded=true] .hd__bars i:last-child{transform:translateY(-4px) rotate(-45deg)}
.hd__mark{justify-self:center;font-family:var(--fd);font-size:clamp(19px,2vw,25px);
  letter-spacing:.26em;text-indent:.26em;line-height:1;overflow:hidden;
  display:flex;align-items:center;min-height:44px;padding-block:.1em}
.hd__markin{display:block;transform:translate3d(0,var(--mk,110%),0);transition:transform .9s var(--e1)}
.hd__ast{color:var(--mute);display:inline-block;transition:transform .6s var(--e1)}
.hd__shop:hover .hd__ast{transform:rotate(180deg)}
html.hd-hide .hd{transform:translate3d(0,-110%,0)}
html.menu-open .hd{transform:none;color:var(--bk)}
@media (max-width:640px){
  .hd__shop .roll{display:none}
  .hd__shop::after{content:'Shop';font-size:10.5px;letter-spacing:.2em}
}

/* ---------------------------------------------------------------- menu */
.menu{position:fixed;inset:0;z-index:79;pointer-events:none;visibility:hidden}
.menu__bg{position:absolute;inset:0;background:var(--wh);
  transform:translate3d(0,-100%,0);transition:transform .95s var(--e2)}
.menu__in{position:relative;height:100%;display:flex;flex-direction:column;justify-content:center;
  padding:var(--hd) var(--gut) clamp(24px,5vw,60px)}
.menu__list li{overflow:hidden}
.menu__list a{display:flex;align-items:baseline;gap:.6em;min-height:48px;color:var(--bk);
  font-family:var(--fd);font-size:clamp(38px,8.6vw,112px);line-height:1.06;letter-spacing:-.02em;
  transform:translate3d(0,110%,0);transition:transform .95s var(--e1),color .4s;
  transition-delay:calc(var(--i)*60ms)}
.menu__list a i{font-style:normal;font-family:var(--fs);font-size:11px;letter-spacing:.2em;
  color:rgba(10,10,10,.46);opacity:1}
.menu__list a:hover{color:#000}
.menu__foot{margin-top:auto;padding-top:clamp(24px,4vw,54px);display:flex;flex-wrap:wrap;gap:clamp(18px,4vw,64px);
  color:rgba(10,10,10,.62);font-size:12px;opacity:0;transition:opacity .6s var(--e1) .3s;
  border-top:1px solid var(--linei)}
.menu__foot .eyebrow{color:rgba(10,10,10,.42)}
.menu__peek{position:absolute;right:var(--gut);top:50%;width:clamp(180px,20vw,300px);aspect-ratio:4/5;
  pointer-events:none;opacity:0;overflow:hidden;
  transform:translate3d(var(--px,0px),calc(-50% + var(--py,0px)),0) scale(.92);
  transition:opacity .5s var(--e1),transform .8s var(--e1)}
.menu__peek img{width:100%;height:100%;object-fit:cover}
.menu__peek.on{opacity:1;transform:translate3d(var(--px,0px),calc(-50% + var(--py,0px)),0) scale(1)}
/* A real lock, on the root rather than on body: body{overflow:hidden} does not hold
   iOS, and a position:fixed body would collapse the scroll geometry the engine has
   just cached. overflow:hidden on <html> leaves scrollHeight intact. */
html.menu-open{overflow:hidden}
html.menu-open .menu{pointer-events:auto;visibility:visible;overscroll-behavior:contain}
html.menu-open .menu__bg{transform:translate3d(0,0,0)}
html.menu-open .menu__list a{transform:translate3d(0,0,0);transition-delay:calc(280ms + var(--i)*62ms)}
html.menu-open .menu__foot{opacity:1;transition-delay:.62s}
@media (max-width:820px){.menu__peek{display:none}}

.bag{position:fixed;right:var(--gut);bottom:22px;z-index:96;
  background:var(--wh);color:var(--bk);padding:11px 17px;border-radius:99px;
  font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;
  transform:translate3d(0,calc(100% + 34px),0);transition:transform .7s var(--e3);pointer-events:none}
.bag.on{transform:translate3d(0,0,0)}
.bag span{color:var(--bk)}

/* ---------------------------------------------------------------- motion off */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important}
  .ln>i,.w>i{transform:none!important}
  [data-rv]{opacity:1!important;transform:none!important}
  .grain{display:none}
  .cue{display:none}
}

/* ================================================================ wave two
   Everything below is written by the same single rAF pass as everything else, as
   a custom property or a class. Nothing here reads layout per frame. */

/* the fixed section index, bottom left */
.idx{position:fixed;left:var(--gut);bottom:clamp(16px,2.4vw,28px);z-index:78;
  display:flex;align-items:baseline;gap:10px;pointer-events:none;
  font-size:10px;letter-spacing:.22em;text-transform:uppercase;
  color:#fff;mix-blend-mode:difference;
  opacity:var(--idxo,0);transition:opacity .5s var(--e1)}
.idx b{font-weight:500;font-variant-numeric:tabular-nums;opacity:.62}
.idx__l{display:block;overflow:hidden;height:1.4em}
.idx__l i{display:block;font-style:normal;transform:translate3d(0,var(--iy,0),0);
  transition:transform .5s var(--e2)}
@media (max-width:820px){.idx{display:none}}

/* velocity skew, capped so it never reads as a glitch */
.skew{transform:translate3d(0,0,0) skewY(var(--sk,0deg));transform-origin:50% 50%}

/* a floating chip inside a product card */
.pc__a{position:relative}
.pc__chip{position:absolute;left:0;top:0;z-index:2;pointer-events:none;
  width:74px;height:74px;border-radius:50%;background:var(--wh);color:var(--bk);
  display:grid;place-items:center;font-size:9px;letter-spacing:.2em;text-transform:uppercase;
  transform:translate3d(calc(var(--cx,0px) - 50%),calc(var(--cy,0px) - 50%),0) scale(var(--cs,0));
  transition:transform .5s var(--e1)}
@media (hover:none){.pc__chip{display:none}}

/* the flying dot that lands in the bag */
.fly{position:fixed;left:0;top:0;z-index:97;width:9px;height:9px;border-radius:50%;
  background:var(--wh);pointer-events:none;opacity:0;
  transform:translate3d(var(--fx,0px),var(--fy,0px),0) scale(var(--fs2,1))}
.fly.go{opacity:1;transition:transform .82s cubic-bezier(.4,0,.2,1),opacity .2s .62s}

/* header gets a plate once it is over content */
.hd::before{content:'';position:absolute;inset:0;background:var(--bk);
  opacity:var(--hdp,0);transition:opacity .45s var(--e1);z-index:-1;
  -webkit-mask-image:linear-gradient(180deg,#000 62%,transparent);
  mask-image:linear-gradient(180deg,#000 62%,transparent)}

/* menu letters answer the pointer */
.menu__list .mlw{display:block;white-space:nowrap}
.menu__list a span.ml{display:inline-block;transition:transform .5s var(--e3);will-change:transform}
.menu__list a:hover span.ml{transform:translate3d(0,-.09em,0)}

@media (prefers-reduced-motion:reduce){
  .idx,.fly,.pc__chip{display:none}
  .end__mark i{transform:none!important}
  .skew{transform:none!important}
}

/* ================================================================ wave three */

/* one white thread down the left gutter, filled by the page's own progress */
.thread{position:fixed;left:calc(var(--gut) * .5);top:22vh;bottom:22vh;width:1px;z-index:77;
  background:rgba(242,242,240,.12);pointer-events:none;opacity:var(--tho,0);
  transition:opacity .6s var(--e1)}
.thread i{display:block;width:100%;height:100%;background:var(--wh);
  transform:scaleY(var(--thp,0));transform-origin:50% 0}
@media (max-width:1100px){.thread{display:none}}

/* back to top, once the end is in sight */
.top{position:fixed;right:var(--gut);bottom:calc(22px + 52px);z-index:96;
  width:48px;height:48px;border-radius:50%;border:1px solid var(--line);
  display:grid;place-items:center;color:var(--wh);
  transform:translate3d(var(--mx,0px),calc(var(--my,0px) + 90px),0) scale(.7);
  opacity:0;transition:opacity .5s var(--e1),transform .7s var(--e3);pointer-events:none}
.top[hidden]{display:none}
.top svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.4;
  stroke-linecap:round;stroke-linejoin:round}
.top.on{opacity:1;pointer-events:auto;
  transform:translate3d(var(--mx,0px),var(--my,0px),0) scale(1)}
.top:hover{background:var(--wh);color:var(--bk)}

@media (prefers-reduced-motion:reduce){
  .thread,.top{display:none}
  .grid.dim .pc{opacity:1}
}

/* ================================================================ wave four
   The menu, and the covered transition out of it. */

/* --- the hovered row owns the overlay: everything else steps back */
@media (hover:hover) and (pointer:fine){
  .menu__list:hover a{opacity:.34;transition:opacity .45s var(--e1),transform .95s var(--e1),color .4s}
  .menu__list a:hover{opacity:1}
}

/* --- a hairline draws out of the row and runs to the edge of the overlay */
.menu__list li{position:relative}
.menu__list li::after{
  content:'';position:absolute;left:0;right:0;bottom:.14em;height:1px;
  background:linear-gradient(90deg,rgba(10,10,10,.44),rgba(10,10,10,0));
  transform:scaleX(0);transform-origin:0 50%;
  transition:transform .72s var(--e2);
}
.menu__list li:hover::after{transform:scaleX(1)}

/* --- the index number rolls out and an arrow takes its place */
.menu__list a i{display:block;position:relative;overflow:hidden;width:2.6em;height:1.35em}
.menu__list a i span,.menu__list a i em{display:block;font-style:normal;
  transition:transform .55s var(--e2),opacity .4s}
.menu__list a i em{position:absolute;left:0;top:0;transform:translate3d(0,120%,0);opacity:0}
.menu__list a:hover i span{transform:translate3d(0,-120%,0);opacity:0}
.menu__list a:hover i em{transform:translate3d(0,0,0);opacity:1}

/* --- one hairline marker that SLIDES between rows rather than appearing on each */
.menu__mark{
  position:absolute;left:var(--gut);top:0;width:clamp(26px,4vw,64px);height:1px;
  background:var(--bk);pointer-events:none;
  transform:translate3d(0,var(--mky,0px),0) scaleX(var(--mks,0));transform-origin:0 50%;
  opacity:var(--mko,0);
  transition:transform .62s var(--e1),opacity .4s var(--e1);
}
@media (max-width:820px){.menu__mark{display:none}}

/* --- the peek arrives as a wipe, not a fade, and holds a hair of parallax */
.menu__peek{clip-path:inset(0 0 100% 0);transition:opacity .45s var(--e1),
  transform .8s var(--e1),clip-path .78s var(--e2)}
.menu__peek.on{clip-path:inset(0 0 0 0)}
.menu__peek img{transform:scale(1.12);transition:transform 1.5s var(--e1)}
.menu__peek.on img{transform:scale(1)}

/* --- the covered transition */
.wipe{position:fixed;inset:0;z-index:104;display:flex;pointer-events:none;visibility:hidden}
.wipe i{flex:1 1 0;background:var(--wh);transform:translate3d(0,101%,0)}
.wipe__l{
  position:absolute;inset:0;display:grid;place-items:center;
  font-family:var(--fd);font-weight:400;
  font-size:clamp(30px,6vw,84px);letter-spacing:-.02em;color:var(--bk);
  opacity:0;transform:translate3d(0,18px,0);
}
html.wipe-in .wipe,html.wipe-out .wipe{visibility:visible}
html.wipe-in .wipe i{transform:translate3d(0,0,0);
  transition:transform .60s var(--e2);transition-delay:calc(var(--s)*40ms)}
html.wipe-in .wipe__l{opacity:1;transform:none;
  transition:opacity .42s var(--e1) .34s,transform .62s var(--e1) .34s}
html.wipe-out .wipe i{transform:translate3d(0,-101%,0);
  transition:transform .72s var(--e2);transition-delay:calc((5 - var(--s))*40ms)}
html.wipe-out .wipe__l{opacity:0;transform:translate3d(0,-16px,0);
  transition:opacity .28s var(--e4),transform .4s var(--e4)}

@media (prefers-reduced-motion:reduce){
  .wipe,.menu__mark{display:none}
  .menu__list li::after{transform:none}
  .menu__peek{clip-path:none!important}
}

/* ================================================================ wave five
   More motion, and more to touch. Everything scroll driven here is written as a
   custom property by the one rAF pass; everything pointer driven is a transition
   on transform, opacity or colour. No new clocks, no new observers. */

/* --- M1 the section overture: a rule draws the full width and the section's own
       number rises out from under it. It is what makes six sections read as one
       document rather than six pages stacked. */
.craft,.coll,.end,.pass{position:relative}
.ovr{position:absolute;left:var(--gut);right:var(--gut);top:0;height:0;
  pointer-events:none;z-index:1}
.ovr s{display:block;height:1px;background:var(--line);text-decoration:none;
  transform:scaleX(var(--ovp,0));transform-origin:0 50%}
.ovr b{position:absolute;right:0;top:6px;font-size:10px;letter-spacing:.24em;
  font-weight:500;color:var(--mute);font-variant-numeric:tabular-nums;
  opacity:var(--ovp,0);transform:translate3d(0,calc((1 - var(--ovp,0))*10px),0)}

/* --- M4 a bead travels the thread and swells at a section boundary */
.thread u{position:absolute;left:50%;top:0;width:5px;height:5px;border-radius:50%;
  background:var(--wh);text-decoration:none;
  transform:translate3d(-50%,calc(var(--thp,0)*var(--thh,0px)),0) scale(var(--thb,1));
  opacity:var(--tho,0);transition:opacity .6s var(--e1)}

/* --- m2 the price turns over to its stock line */
.pc__pr{position:relative;display:inline-block;overflow:hidden;height:1.35em;
  vertical-align:bottom}
.pc__pr>span{display:block;transition:transform .5s var(--e2)}
.pc__pr>span+span{position:absolute;left:0;top:0;transform:translate3d(0,110%,0);
  color:var(--mute)}
.pc:hover .pc__pr>span{transform:translate3d(0,-110%,0)}
.pc:hover .pc__pr>span+span{transform:translate3d(0,0,0)}

/* --- m3 an arrow rides in with the button fill */
.btn__ar{position:relative;z-index:1;display:inline-block;width:0;overflow:hidden;
  opacity:0;transform:translate3d(-8px,0,0);
  transition:width .5s var(--e2),opacity .4s var(--e1),transform .5s var(--e2)}
.btn:hover .btn__ar{width:1.15em;opacity:1;transform:none}

/* --- m4 the newsletter rule draws from the centre on focus */
.nl__row{position:relative}
.nl__row::after{content:'';position:absolute;left:0;right:0;bottom:-1px;height:1px;
  background:var(--wh);transform:scaleX(0);transform-origin:50% 50%;
  transition:transform .6s var(--e2)}
.nl__row:focus-within::after{transform:scaleX(1)}

/* --- m5 a toast for the copied line */
.toast{position:fixed;left:50%;bottom:26px;z-index:99;
  background:var(--wh);color:var(--bk);padding:11px 18px;border-radius:99px;
  font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;white-space:nowrap;
  transform:translate3d(-50%,calc(100% + 34px),0);
  transition:transform .62s var(--e3);pointer-events:none}
.toast.on{transform:translate3d(-50%,0,0)}

/* --- m6 the bag count bumps when it changes */
.bag span{display:inline-block;transform:scale(var(--bgs,1));
  transition:transform .45s var(--e3)}

/* --- m8 the scroll cue is a control, and says so */
.cue{cursor:pointer;padding:6px 10px;min-height:44px}
.cue:hover i{animation-duration:1.2s}
.cue:hover span{color:var(--wh)}

@media (prefers-reduced-motion:reduce){
  .ovr s{transform:none}
  .ovr b{opacity:1;transform:none}
  .thread u{display:none}
}

/* --- m9 the menu bars scissor before they become a cross */
.hd__menu:hover .hd__bars i:first-child{transform:translateY(1px) rotate(-7deg)}
.hd__menu:hover .hd__bars i:last-child{transform:translateY(-1px) rotate(7deg)}
.hd__menu[aria-expanded=true]:hover .hd__bars i:first-child{transform:translateY(4px) rotate(45deg)}
.hd__menu[aria-expanded=true]:hover .hd__bars i:last-child{transform:translateY(-4px) rotate(-45deg)}

/* ================================================================ wave six
   Fixes an adversarial review of the finished page turned up. */


/* The cursor ring animated its WIDTH and HEIGHT, which are layout, in a file
   whose first rule is that only transform, opacity and colour move per frame.
   It is one 76px box scaled instead, and it finally has the press state the
   script has been setting a class for all along. */
.cur__r{width:76px;height:76px;--s:.5;
  transition:transform .42s var(--e1),background-color .34s var(--e1),border-color .34s var(--e1)}
.cur.big .cur__r{--s:1}
.cur.down .cur__r{--s:.36}
.cur.big.down .cur__r{--s:.88}
.cur.down .cur__d{transform:translate(-50%,-50%) scale(2.2)}

/* The peek parallax was written on every pointermove onto a transform carrying a
   0.8s transition, so it trailed the pointer by most of a second, permanently.
   The reveal keeps the long ease; the parallax gets its own short one. */
.menu__peek{transform:translate3d(0,-50%,0) scale(.92)}
.menu__peek.on{transform:translate3d(0,-50%,0) scale(1)}
.menu__peekin{display:block;width:100%;height:100%;overflow:hidden;
  transform:translate3d(var(--px,0px),var(--py,0px),0);
  transition:transform .22s linear}

/* A phone menu was five words and a footer: no peek, no hover, no cursor, nothing
   to read. Each row carries its own line now, masked and staggered with the row
   it belongs to, and it costs no images. */
.menu__sub{display:none}
@media (max-width:820px){
  /* column-gap only. The row's 0.6em gap applied to the WRAPPED row as well, so
     each line floated half way to the item below it and read as that item's
     label instead of its own. */
  .menu__list a{flex-wrap:wrap;column-gap:.6em;row-gap:0;line-height:1.02;padding-bottom:.1em}
  .menu__list a i{order:2}
  .menu__sub{flex:0 0 100%;order:3;display:block;text-decoration:none;
    font-family:var(--fs);font-size:10px;letter-spacing:.2em;text-transform:uppercase;
    color:rgba(10,10,10,.46);margin-top:.28em}
  .menu__list li+li{margin-top:.72em}
}

/* ================================================================ v6.1 sections */

/* ---- 01 + 02 the flow. ONE sticky stage spans the hero, the turn spacer and the
   pass; the ring's canvas lives in it and is the one object on the page from the
   first pixel to the last. The wordmark sits BEHIND the ring in the hero. */
.flow{position:relative;z-index:3}
/* z-index 0, BELOW the pass. `position:sticky` always creates a stacking context, so
   a mix-blend-mode set inside the stage can never reach the type in the section behind
   it: the ring's canvas simply painted an opaque black square over the words. Painting
   the stage under the pass fixes it for good and costs nothing. The ring threads
   behind the letters and the letters keep their edges. */
.stage{position:sticky;top:0;height:100svh;z-index:0;overflow:visible;pointer-events:none}
.stage__t{position:absolute;left:0;right:0;top:calc(var(--hd) + clamp(4px,1.6vw,26px));z-index:1;
  text-align:center;font-family:var(--fd);font-weight:400;font-size:clamp(84px,17vw,260px);
  line-height:.85;letter-spacing:.02em;text-indent:.02em;color:var(--wh);
  transform:translate3d(0,var(--mty,0px),0);opacity:var(--mto,1)}
.stage__box{position:absolute;left:50%;top:50%;width:min(92svh,100vw);aspect-ratio:1;z-index:2;
  margin:calc(min(92svh,100vw) * -.5) 0 0 calc(min(92svh,100vw) * -.5);
  transform:translate3d(var(--hx,0px),var(--hy,0px),0) scale(var(--hs,1));transform-origin:50% 50%;
  will-change:transform}
.stage__cv{position:absolute;inset:0;width:100%;height:100%;opacity:0;transition:opacity 1.1s var(--e1)}
html.seq-live .stage__cv{opacity:1}
/* The frames are opaque over the page's own black, so the box blends by LIGHTEN:
   frame black equals page black and vanishes, lit platinum outshines the letters,
   and the letters show only through the dark interior of the band. The wordmark is
   held back to grey so the metal's midtones still win over it. On a phone the blend
   runs only once the ring is small, over the pass, where it is cheap. */
/* The blend that IS wanted: inside the stage, the ring over the wordmark, so the
   letters show through the dark interior of the band. It runs only while the ring is
   big, which is the only time the wordmark is on screen; once the ring is small the
   blend is switched off and the compositor stops blending a full-screen box on every
   frame of the pass. */
@media (min-width:821px){
  /* Measured: the wordmark and the ring's box only ever overlap on a desktop width.
     On a phone or a tablet the mark sits clear above the ring, so the blend there was
     a full-screen composite bought for nothing. */
  .stage__box{mix-blend-mode:lighten}
  html.ring-sm .stage__box{mix-blend-mode:normal}
  .stage__t{color:rgba(242,242,240,.5)}
}
.hero{position:relative;z-index:4;margin-top:-100svh;height:100svh;display:flex;flex-direction:column;justify-content:flex-end;
  padding:0 var(--gut) clamp(28px,5vw,64px);pointer-events:none}
.hero *{pointer-events:auto}
.hero__in{max-width:min(46ch,60%);transform:translate3d(0,var(--hoy,0px),0);opacity:var(--hoo,1)}
.hero__lede{margin-top:clamp(10px,1.4vw,18px);font-family:var(--fd);font-size:clamp(24px,2.6vw,40px);line-height:1.1;color:var(--wh)}
.hero__cta{display:flex;flex-wrap:wrap;align-items:center;gap:clamp(14px,2.4vw,32px);margin-top:clamp(18px,2.2vw,30px)}
/* the turn's scroll: one viewport of turning, six tenths of shrinking, and the pass
   section's top padding puts the first line at the fold as the shrink ends */
.turn{position:relative;z-index:1;height:154svh;pointer-events:none}
.cue{bottom:clamp(28px,5vw,64px)}
@media (max-width:820px){
  .stage__t{font-size:clamp(56px,18vw,120px);top:calc(var(--hd) + 2px)}
  .stage__box{top:52%}
  .hero__in{max-width:none}
  .hero__lede{font-size:clamp(22px,6.4vw,30px)}
}

/* ---- 02 the ring through the text. The lines scroll; the ring is the stage's.
   The bottom padding is the run the ring needs after it is caught: it leaves with
   the mark line, so the stage must stay stuck until that line is well up the page. */
.pass{position:relative;z-index:1;padding:6svh 0 74svh}
.pass__body{position:relative;z-index:1}
.pass__lines{--fit:1;position:relative;margin-inline:auto;width:min(1560px,100% - var(--gut)*2);
  font-family:var(--fd);text-align:center;font-size:calc(clamp(44px,9.5vw,150px)*var(--fit));
  line-height:1;letter-spacing:-.01em;color:var(--wh);font-optical-sizing:auto}
.pl{display:block;white-space:nowrap}
/* Promoted from the start, with a transform rather than will-change. Five lines of
   137 px Bodoni are expensive to rasterise, and leaving them unpromoted until the
   first paintPass write moved that raster into the reader's gesture: it measured as
   a single 46.7 ms frame in the middle of the pass. */
.pl>span{display:inline-block;transform:translate3d(0,0,0)}
/* the wordmark line: tracked caps, a size up from the lines above it (the ring is
   sized to ITS O, so this is also what sizes the ring), and a real O the ring replaces */
.pl--mark{font-size:1.25em;letter-spacing:.05em;margin-top:.1em}
.pl--mark>span:nth-child(2){opacity:var(--go,1)}
@media (max-width:820px){
  .pass__lines{font-size:calc(clamp(46px,12vw,150px)*var(--fit))}
  .pl--mark{font-size:1.45em}
}

/* ---- 03 the collection */
.coll{padding:clamp(60px,8.4vw,110px) 0 clamp(66px,9vw,122px);background:var(--bk);overflow-x:clip}
.sechd{display:grid;gap:clamp(12px,1.8vw,22px);margin-bottom:clamp(34px,5vw,68px)}
.sechd__t{font-size:clamp(38px,6vw,96px);max-width:16ch}
.grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(14px,2vw,30px)}
@media (max-width:900px){.grid{grid-template-columns:repeat(2,1fr)}}
@media (max-width:560px){.grid{grid-template-columns:1fr}}
/* The arrival and the drift share one transform, so the arrival animates the
   PROPERTIES (registered below, which is what makes them animatable) and `transform`
   itself carries no transition. Without that, every per-frame drift write would be
   smeared through a 1.15 second ease and the row would swim. */
@property --pcx{syntax:'<length>';inherits:false;initial-value:0px}
@property --pcr{syntax:'<angle>';inherits:false;initial-value:0deg}
.pc{position:relative;min-width:0;
  transform:translate3d(var(--pcx,0px),var(--pcy,0px),0) rotate(var(--pcr,0deg));
  transition:--pcx 1.15s var(--e1),--pcr 1.15s var(--e1),opacity .55s var(--e1);
  transition-delay:calc(var(--i)*80ms)}
.pc:nth-child(odd){--pcx:-38px;--pcr:-1.6deg}
.pc:nth-child(even){--pcx:38px;--pcr:1.6deg}
.pc.is-in{--pcx:0px;--pcr:0deg}
.pc__a{display:block;position:relative}
.pc__fig{position:relative;display:block;overflow:hidden;aspect-ratio:4/5;background:var(--bk2);
  clip-path:inset(0 0 100% 0);transition:clip-path 1s var(--e1)}
.pc.is-in .pc__fig{clip-path:inset(0 0 0 0)}
.pc__fig picture,.pc__still{display:block;width:100%;height:100%}
.pc__still{object-fit:cover;transform:scale(1.02) rotate(var(--tr,0deg));transition:transform 1s var(--e1)}
.pc__a:hover .pc__still{transform:scale(1.06) rotate(var(--tr,0deg))}
.pc__cv{position:absolute;inset:0;width:100%;height:100%;opacity:0;transition:opacity .5s var(--e1)}
.pc.cv-live .pc__cv{opacity:1}
.pc__i{position:absolute;left:clamp(12px,1.4vw,20px);top:clamp(12px,1.4vw,20px);z-index:2;
  font-family:var(--fs);font-size:10px;letter-spacing:.24em;color:var(--mute);font-variant-numeric:tabular-nums}
.pc__row{display:flex;justify-content:space-between;gap:10px;align-items:baseline;margin-top:clamp(14px,1.6vw,20px);font-size:clamp(13px,1.06vw,16px)}
.pc__n{font-family:var(--fd);font-size:clamp(28px,2.6vw,40px);line-height:1;letter-spacing:-.01em}
.pc__pr{font-variant-numeric:tabular-nums;color:var(--mute);font-size:13px}
.pc__m{display:block;margin-top:.5em;font-size:11.5px;color:var(--mute);letter-spacing:.02em}
.pc__m i{font-style:normal;opacity:.5;margin:0 .35em}
.pc__rule{display:block;height:1px;background:var(--line);margin-top:clamp(10px,1.2vw,15px);position:relative;overflow:hidden}
.pc__rule::after{content:'';position:absolute;inset:0;background:var(--wh);transform:scaleX(var(--u,0));transform-origin:0 50%;transition:transform .7s var(--e2)}
.pc__a:hover .pc__rule{--u:1}
.add{display:inline-flex;align-items:center;gap:.6em;margin-top:clamp(10px,1.2vw,15px);min-height:44px;padding:.3em .1em;
  font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--mute);
  transform:translate3d(var(--mx,0px),var(--my,0px),0);transition:transform .45s var(--e1),color .4s}
.add:hover,.add.done{color:var(--wh)}
.add svg{width:15px;height:15px;fill:none;stroke:var(--wh);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;
  stroke-dasharray:22;stroke-dashoffset:22;transition:stroke-dashoffset .5s var(--e1)}
.add.done svg{stroke-dashoffset:0}
.grid.dim .pc{opacity:.42;transition:opacity .55s var(--e1)}
.grid.dim .pc.hot{opacity:1}

/* ---- 04 the craft: the one white screen. Ink on paper, the macro set in as a
   black plate. Every hairline and muted tone here is the inverse of the page's. */
.craft{padding:clamp(68px,9vw,122px) 0 clamp(58px,8vw,104px);background:var(--wh);color:var(--bk)}
.craft .eyebrow,.craft .eyebrow i,.craft__p,.craft .stats span,.craft .ovr b{color:rgba(10,10,10,.74)}
.craft .ovr s,.craft .stats li::before{background:var(--linei)}
.craft .stats b{color:var(--bk)}
.craft ::selection{background:var(--bk);color:var(--wh)}
.craft__grid{display:grid;gap:clamp(28px,4vw,64px);align-items:end}
@media (min-width:900px){.craft__grid{grid-template-columns:5fr 7fr}}
.craft__hd{display:grid;gap:clamp(12px,1.8vw,22px)}
.craft__t{font-size:clamp(40px,5.4vw,88px);max-width:9ch}
.craft__p{max-width:38ch;font-size:clamp(14.5px,1.06vw,16.5px)}
.craft__fig{position:relative;overflow:hidden;aspect-ratio:16/9;background:var(--bk);
  clip-path:inset(0 0 100% 0);transition:clip-path 1.15s var(--e1)}
.craft__fig.is-in{clip-path:inset(0 0 0 0)}
.craft__fig img{width:100%;height:100%;object-fit:cover;transform:scale(1.08) translate3d(0,var(--py,0px),0);transition:transform 1.4s var(--e1)}
.stats{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(14px,2.4vw,30px);margin-top:clamp(36px,5vw,72px)}
.stats li{position:relative;padding-top:14px}
.stats li::before{content:'';position:absolute;left:0;right:0;top:0;height:1px;background:var(--line);
  transform:scaleX(0);transform-origin:0 50%;transition:transform .95s var(--e2);transition-delay:calc(var(--si,0)*140ms)}
.stats li.is-in::before{transform:scaleX(1)}
.stats b{display:block;font-family:var(--fd);font-size:clamp(34px,4.6vw,64px);line-height:1;font-weight:400;color:var(--wh)}
.stats span{display:block;margin-top:8px;font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--mute)}
/* the header turns to ink while the paper is under it */
.hd{transition:transform .55s var(--e1),opacity .6s var(--e1) .55s,color .4s var(--e1)}
.hd::before{transition:opacity .45s var(--e1),background-color .4s var(--e1)}
.hd__btn,.hd__mark,.hd__ast{transition:color .4s var(--e1)}
html.on-light:not(.menu-open) .hd{color:var(--bk)}
html.on-light:not(.menu-open) .hd__btn,html.on-light:not(.menu-open) .hd__mark{color:var(--bk)}
html.on-light:not(.menu-open) .hd__ast{color:rgba(10,10,10,.62)}
html.on-light:not(.menu-open) .hd::before{background:var(--wh)}

/* ---- 05 contact and footer, a shade off the page so it reads as the end */
.end{position:relative;background:var(--bk2);color:var(--wh);padding:clamp(68px,9.4vw,124px) 0 0;overflow:hidden}
.end .eyebrow{color:var(--mute)}
.end__top{display:grid;gap:clamp(34px,5vw,70px);padding-bottom:clamp(48px,7vw,96px);border-bottom:1px solid var(--line)}
@media (min-width:900px){.end__top{grid-template-columns:1.2fr .8fr;align-items:end}}
.end__t{font-size:clamp(38px,7.2vw,108px);margin:clamp(14px,2vw,26px) 0 clamp(14px,1.8vw,24px)}
.end__p{color:var(--mute);max-width:38ch;font-size:14.5px}
.nl__l{display:block;font-size:10px;letter-spacing:.22em;text-transform:uppercase;color:var(--mute);margin-bottom:12px}
.nl__row{display:flex;align-items:center;gap:14px;border-bottom:1px solid var(--line);padding-bottom:10px;position:relative}
.nl__row::after{content:'';position:absolute;left:0;right:0;bottom:-1px;height:1px;background:var(--wh);transform:scaleX(0);transform-origin:50% 50%;transition:transform .6s var(--e2)}
.nl__row:focus-within::after{transform:scaleX(1)}
.nl__i{flex:1;min-width:0;background:none;border:0;padding:10px 0;color:var(--wh);font-size:16px;min-height:44px}
.nl__i::placeholder{color:var(--mute)}
.nl__b{flex:none;min-height:44px;padding:0 4px;font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:var(--wh);
  transform:translate3d(var(--mx,0px),var(--my,0px),0);transition:transform .45s var(--e1)}
.nl__msg{min-height:1.4em;margin-top:10px;font-size:11.5px;color:var(--wh);opacity:0;transform:translateY(6px);transition:opacity .4s,transform .4s}
.nl__msg.on{opacity:1;transform:none}
.end__cols{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(24px,4vw,50px);padding:clamp(40px,6vw,80px) 0 clamp(30px,5vw,60px);color:var(--mute);font-size:13px}
@media (min-width:760px){.end__cols{grid-template-columns:repeat(4,1fr)}}
.end__k{font-size:10px;letter-spacing:.22em;text-transform:uppercase;color:var(--wh);margin-bottom:10px}
.end__mark{display:flex;justify-content:center;gap:.01em;overflow:hidden;font-family:var(--fd);text-align:center;line-height:.8;
  color:rgba(242,242,240,.09);font-size:min(24.5vw,380px);letter-spacing:.02em;user-select:none;
  transform:translate3d(var(--emx,0px),0,0) scale(var(--ems,1));transform-origin:50% 100%;padding-top:.06em;margin-bottom:-.1em}
.end__mark span{display:block;overflow:hidden;padding-block:.02em .12em;margin-block:-.02em -.12em}
.end__mark i{display:block;font-style:normal;transform:translate3d(0,108%,0);transition:transform 1.1s var(--e1);transition-delay:calc(var(--i)*70ms)}
.end__mark.is-in i{transform:translate3d(0,0,0)}
.end__legal{display:flex;flex-wrap:wrap;justify-content:space-between;gap:12px;padding:clamp(18px,2.4vw,30px) 0;border-top:1px solid var(--line);
  font-size:11px;color:var(--mute);font-variant-numeric:tabular-nums}

/* ---- the hairline rule for Bodoni on black: nothing in the display face under 22px */
.pc__pr,.pc__m,.pc__i,.eyebrow,.add,.btn,.lnk,.nl__l,.end__k,.end__legal,.stats span,.idx,.cur__t,.toast,.bag{font-family:var(--fs)}

@media (prefers-reduced-motion:reduce){
  .pc{transform:none!important}
  .lamp{display:none}
  .craft__ann line,.craft__ann circle{stroke-dashoffset:0!important}
  .craft__ann text{opacity:1!important}
  .turn{height:auto;min-height:100svh}
  .stage{position:relative}
  .stage__box{transform:none!important}
  .pc__cv{display:none}
  .pc{transform:none!important}
  .craft__fig{clip-path:none!important}
}

/* ---- controls */
.btn{position:relative;display:inline-flex;align-items:center;gap:.8em;overflow:hidden;
  padding:1.02em 1.9em;min-height:44px;border:1px solid var(--wh);border-radius:999px;
  font-size:11px;letter-spacing:.2em;text-transform:uppercase;font-weight:500;
  transform:translate3d(var(--mx,0px),var(--my,0px),0);transition:transform .45s var(--e1),color .45s}
.btn__fill{position:absolute;inset:0;background:var(--wh);border-radius:999px;
  transform:translate3d(0,101%,0);transition:transform .62s var(--e2)}
.btn:hover{color:var(--bk)}
.btn:hover .btn__fill{transform:translate3d(0,0,0)}
.btn .roll{position:relative;z-index:1}
.btn__ar{position:relative;z-index:1;display:inline-block;width:0;overflow:hidden;
  opacity:0;transform:translate3d(-8px,0,0);
  transition:width .5s var(--e2),opacity .4s var(--e1),transform .5s var(--e2)}
.btn:hover .btn__ar{width:1.15em;opacity:1;transform:none}
.lnk{position:relative;display:inline-flex;align-items:center;min-height:44px;
  font-size:11px;letter-spacing:.2em;text-transform:uppercase;font-weight:500;
  padding-bottom:.35em}
.lnk::after{content:'';position:absolute;left:0;right:0;bottom:calc(50% - .8em);height:1px;background:currentColor;
  transform:scaleX(var(--u,0));transform-origin:0 50%;transition:transform .55s var(--e2)}
.lnk:hover{--u:1}
.lnk--sm{font-size:10.5px;letter-spacing:.1em;text-transform:none;min-height:44px}
.cue{position:absolute;left:50%;bottom:clamp(28px,5vw,64px);transform:translateX(-50%);
  display:flex;flex-direction:column;align-items:center;gap:8px;cursor:pointer;padding:6px 10px;min-height:44px;
  font-size:9.5px;letter-spacing:.28em;text-transform:uppercase;color:var(--mute);
  opacity:var(--cueo,1);transition:opacity .5s var(--e1)}
.cue i{display:block;width:1px;height:34px;background:linear-gradient(var(--mute),transparent);
  animation:cue 2.1s var(--e2) infinite}
@keyframes cue{0%{transform:scaleY(0);transform-origin:50% 0}
  45%{transform:scaleY(1);transform-origin:50% 0}
  46%{transform:scaleY(1);transform-origin:50% 100%}
  100%{transform:scaleY(0);transform-origin:50% 100%}}
.cue:hover i{animation-duration:1.2s}
.cue:hover span{color:var(--wh)}
@media (max-width:820px){.cue{display:none}}
@media (prefers-reduced-motion:reduce){.cue{display:none}}

/* ================================================================ v6.2 detail
   Everything below obeys the same rule as everything above it: per frame, only
   transform, opacity and colour ever change, and every scroll-driven value is a
   custom property written by the one rAF pass. */

/* ---- D1 the light in the room.
   A flat #0a0a0a over five screens is what reads as inert. This is one 1100 px
   radial, composited, that follows the pointer with the cursor's own damping, so
   the black becomes a surface with a light on it rather than an absence. It is a
   fixed-size layer moved by transform, never a repainted full-screen gradient,
   and a coarse pointer gets a still version anchored above the fold instead. */
/* z-index 89, under the grain and the chrome but OVER the sections: every black
   section paints its own background, so a lamp behind them would be behind a wall.
   Fine pointers only. It is a translucent layer moved by transform, never a blend
   mode and never a repaint, so it costs the compositor one alpha pass and nothing
   else; a phone gets no lamp at all rather than paying for one it cannot aim. */
.lamp{display:none;position:fixed;left:0;top:0;width:1100px;height:1100px;margin:-550px 0 0 -550px;
  z-index:89;pointer-events:none;opacity:0;
  background:radial-gradient(circle closest-side,rgba(242,242,240,.070),rgba(242,242,240,.028) 42%,transparent 72%);
  transform:translate3d(var(--lx,50vw),var(--ly,40vh),0);
  transition:opacity .8s var(--e1)}
html.done .lamp{opacity:1}
html.on-light .lamp{opacity:0}
@media (hover:hover) and (pointer:fine){ .lamp{display:block} }
@media (prefers-reduced-motion:reduce){.lamp{transform:none}}

/* ---- D2 the stones colour their own cards.
   The only colour on the page comes from the three stones, so it is the stones
   that lend it: the card's number, its rule and the glow behind its plate all take
   --gem. On the black page that is a whisper, which is the point. */
.pc{--gem:#f2f2f0}
.pc:nth-child(2){--gem:#4fd08a}
.pc:nth-child(3){--gem:#6aa8ff}
.pc__i{transition:color .5s var(--e1),transform .6s var(--e1)}
.pc:hover .pc__i{color:var(--gem);transform:translate3d(0,-2px,0)}
.pc__rule::after{background:var(--gem)}
.pc__fig::after{content:'';position:absolute;inset:0;z-index:1;pointer-events:none;
  background:radial-gradient(60% 45% at 50% 34%,color-mix(in srgb,var(--gem) 26%,transparent),transparent 70%);
  opacity:0;transition:opacity .7s var(--e1)}
.pc:hover .pc__fig::after{opacity:1}
.pc__n{transition:color .45s var(--e1)}
.pc:hover .pc__n{color:var(--gem)}

/* ---- D3 the collection drifts. Each card rides the scroll at its own rate, a few
   pixels apart, so the row breathes instead of sitting as three static rectangles.
   One transform per card per frame, from the same pass as everything else; the
   transform itself is declared with the arrival above so they cannot fight. */
.pc{will-change:transform}

/* ---- D4 the craft plate is annotated.
   A real measurement, drawn on the macro the way it would be drawn on a bench
   drawing: three leaders that draw themselves in as the plate arrives. */
.craft__fig{position:relative}
.craft__ann{position:absolute;inset:0;z-index:2;pointer-events:none;overflow:visible}
.craft__ann line,.craft__ann circle{stroke:rgba(242,242,240,.6);stroke-width:2;fill:none;
  stroke-dasharray:var(--len,120);stroke-dashoffset:var(--len,120);
  transition:stroke-dashoffset 1.1s var(--e2);transition-delay:calc(var(--d,0)*1ms)}
.craft__fig.is-in .craft__ann line,.craft__fig.is-in .craft__ann circle{stroke-dashoffset:0}
/* the viewBox is 1600 wide inside a figure about 730 px wide, so a 9 px glyph
   landed on screen at four pixels: sized in user units, not CSS pixels */
.craft__ann text{fill:rgba(242,242,240,.78);font-family:var(--fs);font-size:24px;letter-spacing:2.6px;
  text-transform:uppercase;opacity:0;transition:opacity .6s var(--e1);transition-delay:calc((var(--d,0) + 700)*1ms)}
.craft__fig.is-in .craft__ann text{opacity:1}
@media (max-width:900px){.craft__ann{display:none}}

/* ---- D5 the footer wordmark answers the pointer.
   Each letter lifts as the pointer passes under it, by how close it is, so the
   mark reads as a row of objects rather than a picture of a word. */
.end__mark span{transition:transform .5s var(--e1)}
.end__mark span{transform:translate3d(0,calc(var(--lift,0) * -1px),0)}

/* ---- D6 everything you can press, presses.
   A control that does not move under the finger is the single most common tell
   that a page was never finished. */
.btn,.lnk,.add,.nl__b,.top,.cue,.hd__btn{transition:transform .45s var(--e1),color .45s var(--e1)}
.btn:active,.nl__b:active,.top:active{transform:translate3d(var(--mx,0px),var(--my,0px),0) scale(.965)}
.lnk:active,.add:active,.hd__btn:active,.cue:active{transform:translate3d(0,1px,0)}
.pc__a:active .pc__fig{transform:scale(.992)}
.pc__fig{transition:transform .4s var(--e1)}
/* the focus ring is the same shape as the thing it is on, not a browser rectangle */
:focus-visible{outline:2px solid var(--wh);outline-offset:3px;border-radius:3px}
.btn:focus-visible{border-radius:999px;outline-offset:4px}
.pc__a:focus-visible{outline-offset:6px}
html.on-light :focus-visible{outline-color:var(--bk)}

/* ---- D7 the section overture carries its own eyebrow rule further */
.ovr b{transition:opacity .5s var(--e1)}

/* ---- D8 the hero cue fades the moment the reader takes the hint */
.cue i{transition:opacity .4s var(--e1)}

/* ================================================================ v6.2 phone
   The three stones are the point of the collection, and stacked one per screen a
   reader never sees two of them at once, which is exactly the comparison the whole
   screen exists to make. On a phone the row becomes a snap rail: three cards, the
   next one peeking, swiped rather than scrolled past. */
@media (max-width:560px){
  .grid{display:flex;grid-template-columns:none;gap:14px;
    overflow-x:auto;overflow-y:visible;scroll-snap-type:x mandatory;
    scroll-padding-inline:var(--gut);padding-inline:var(--gut);
    margin-inline:calc(var(--gut) * -1);
    -webkit-overflow-scrolling:touch;scrollbar-width:none}
  .grid::-webkit-scrollbar{display:none}
  .coll .wrap{width:100%;padding-inline:var(--gut)}
  .coll .sechd{padding-inline:0}
  .pc{flex:0 0 78vw;scroll-snap-align:center;--pcx:0px!important;--pcr:0deg!important}
  .pc__fig{aspect-ratio:1/1}
  /* the rail says it is a rail: a hairline that fills as you swipe */
  .coll__rail{display:block;height:1px;background:var(--line);margin:clamp(20px,4vw,28px) var(--gut) 0;position:relative;overflow:hidden}
  .coll__rail i{position:absolute;left:0;top:0;bottom:0;width:33.4%;background:var(--wh);
    transform:translate3d(var(--rx,0%),0,0);transition:transform .35s var(--e1)}
}
.coll__rail{display:none}

/* small type has a floor on a phone: 10.5px uppercase at 0.2em tracking is a
   specification, not a label anybody reads */
@media (max-width:820px){
  .eyebrow{font-size:11px}
  .add,.end__k,.nl__l,.stats span,.pc__i{font-size:11.5px}
  .lnk,.btn{font-size:11.5px}
  .end__legal,.end__cols{font-size:12.5px}
  .stats span{letter-spacing:.1em}
  /* the macro is the whole point of the craft screen: give it room */
  .craft__fig{aspect-ratio:4/3}
  .craft__t{max-width:none}
}
@media (max-width:400px){
  .stats{grid-template-columns:1fr 1fr;gap:18px 14px}
  .stats li:last-child{grid-column:1 / -1}
}

/* ---- D10 the cursor carries the stone it is over */
.cur{--curc:var(--wh)}
.cur__d{background:var(--curc)}
.cur.big .cur__r{background:var(--curc)}
.cur__r{border-color:color-mix(in srgb,var(--curc) 55%,transparent)}
.cur.big .cur__t{color:var(--bk)}
