/* ═══════════════════════════════════════════════════════════════════════
   alilotfy.com — one page
   Visual language from Website/References/ 01–09.
   Two font weights only: 400 and 500. Blurs and glows are live CSS.
   ═══════════════════════════════════════════════════════════════════════ */

@font-face{
  font-family:'Geist';
  src:url('assets/fonts/Geist-Variable.woff2') format('woff2-variations');
  font-weight:100 900; font-display:swap;
}
@font-face{
  font-family:'Geist Mono';
  src:url('assets/fonts/GeistMono-Variable.woff2') format('woff2-variations');
  font-weight:100 900; font-display:swap;
}

:root{
  --void:#04070F;  --navy:#0A1424;  --navy-lift:#122238;
  --blue-deep:#0B2545; --blue-mid:#1D5FA8;
  --blue-glow:#4DA3E8; --blue-haze:#8FC9F2;
  --paper:#F6F8FB; --white:#fff;
  --ink:#0A1424;  --ink-soft:#5A6675; --mist:#C8D4E2;

  --ease:cubic-bezier(.16,1,.3,1);
  --r-ctl:14px; --r-card:20px; --r-hero:28px;

  /* glass, dark */
  --glass:rgba(255,255,255,.06);
  --glass-bd:rgba(255,255,255,.12);
  --glass-hi:rgba(255,255,255,.10);

  --gutter:clamp(20px,5vw,64px);
  --measure:62ch;

  /* the hero card's inset, and the inset of the controls sitting inside it.
     The nav is aligned to their sum so ALI LOTFY lines up with SCROLL. */
  --hero-pad:14px;
  --hero-edge:clamp(18px,3vw,34px);

  /* Device safe areas. `viewport-fit=cover` is set in the head, so on a
     notched phone the page really does run under the notch and the home
     indicator — everything pinned to a screen edge has to add these. They
     resolve to 0px everywhere else, so the desktop layout is untouched. */
  --sa-t:env(safe-area-inset-top,0px);
  --sa-b:env(safe-area-inset-bottom,0px);
  --sa-l:env(safe-area-inset-left,0px);
  --sa-r:env(safe-area-inset-right,0px);
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0; background:var(--void); color:var(--white);
  font-family:'Geist',system-ui,sans-serif; font-weight:400;
  font-size:17px; line-height:1.65;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
img{max-width:100%; display:block}
svg{fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
h1,h2,h3{font-weight:400;margin:0}
p{margin:0}
::selection{background:var(--blue-glow);color:var(--void)}

.mono{
  font-family:'Geist Mono',ui-monospace,monospace;
  font-size:11px; font-weight:400;
  letter-spacing:.14em; text-transform:uppercase;
  line-height:1.5;
}
.wrap{
  width:min(1280px,100%);margin-inline:auto;
  padding-left:calc(var(--gutter) + var(--sa-l));
  padding-right:calc(var(--gutter) + var(--sa-r));
}

/* ── signature reveal: blur → sharp ──────────────────────────────────── */
.reveal{opacity:0;filter:blur(12px);transform:translateY(24px)}
.reveal.is-in{
  opacity:1;filter:blur(0);transform:none;
  transition:opacity .95s var(--ease),filter .95s var(--ease),transform .95s var(--ease);
}

/* ── texture + atmosphere ────────────────────────────────────────────── */
.grain{
  position:absolute;inset:0;pointer-events:none;z-index:3;opacity:.5;
  background-image:
    linear-gradient(rgba(255,255,255,.022) 1px,transparent 1px),
    linear-gradient(90deg,rgba(255,255,255,.022) 1px,transparent 1px);
  background-size:3px 3px;
  mask-image:radial-gradient(120% 100% at 50% 40%,#000 20%,transparent 100%);
}
/* generated glass-and-light sheet, shot on pure black so `screen` drops
   the background out entirely — no cutout needed. Kept low and soft so it
   reads as depth rather than as a literal object. */
.shards{
  position:absolute;pointer-events:none;
  mix-blend-mode:screen;
  object-fit:cover;
  will-change:transform;
}
.shards--hero{
  z-index:2;inset:-14% -8% auto;width:116%;height:auto;
  opacity:.30;filter:blur(1px) saturate(1.15);
}
.shards--work{
  z-index:1;inset:auto -10% -18%;width:120%;height:auto;
  opacity:.16;filter:blur(3px);transform:scaleY(-1);
}

.streaks{
  position:absolute;inset:0;pointer-events:none;z-index:0;opacity:.55;
  background:
    linear-gradient(103deg,transparent 38%,rgba(143,201,242,.10) 46%,transparent 52%),
    linear-gradient(97deg,transparent 60%,rgba(77,163,232,.08) 68%,transparent 74%);
  filter:blur(28px);
}

/* ═══ UI KIT — refs 09 + 08 ═══════════════════════════════════════════ */

.panel{
  background:var(--glass);
  backdrop-filter:blur(20px) saturate(140%);
  -webkit-backdrop-filter:blur(20px) saturate(140%);
  border:1px solid var(--glass-bd);
  border-radius:var(--r-card);
}

.btn{
  display:inline-flex;align-items:center;gap:12px;
  padding:9px 12px 9px 22px;border-radius:999px;
  font-size:14px;line-height:1;font-weight:500;
  transition:background .3s var(--ease),transform .3s var(--ease);
}
.btn__badge{
  width:30px;height:30px;border-radius:999px;
  display:grid;place-items:center;flex:none;
  transition:transform .35s var(--ease);
}
.btn__badge svg{width:15px;height:15px}
.btn:hover .btn__badge{transform:translateX(2px)}

.btn--ghost{
  background:var(--glass);border:1px solid var(--glass-bd);
  backdrop-filter:blur(20px) saturate(140%);
  -webkit-backdrop-filter:blur(20px) saturate(140%);
}
.btn--ghost .btn__badge{background:var(--white);color:var(--void)}
.btn--ghost:hover{background:var(--glass-hi)}

.btn--solid{background:var(--white);color:var(--void)}
.btn--solid .btn__badge{background:var(--void);color:var(--white)}
.btn--solid:hover{transform:translateY(-1px)}

.iconbtn{
  width:38px;height:38px;flex:none;border-radius:999px;
  display:grid;place-items:center;
  background:var(--glass);border:1px solid var(--glass-bd);
  backdrop-filter:blur(20px) saturate(140%);
  -webkit-backdrop-filter:blur(20px) saturate(140%);
  transition:background .3s var(--ease),transform .3s var(--ease);
}
.iconbtn svg{width:16px;height:16px}
.iconbtn:hover{background:var(--glass-hi)}
.iconbtn:active{transform:scale(.94)}

.dot{
  width:6px;height:6px;border-radius:999px;flex:none;
  background:var(--blue-glow);
  box-shadow:0 0 0 3px rgba(77,163,232,.18);
  animation:pulse 2.4s var(--ease) infinite;
}
@keyframes pulse{
  0%,100%{box-shadow:0 0 0 3px rgba(77,163,232,.18)}
  50%    {box-shadow:0 0 0 6px rgba(77,163,232,.05)}
}

/* ═══ 00 · NAV ════════════════════════════════════════════════════════ */
/* Padded, not inset, so both nav edges land on the same vertical as the
   hero card's own controls — ALI LOTFY over SCROLL, Contact over the arrow. */
.nav{
  position:fixed;top:calc(16px + var(--sa-t));right:0;left:0;z-index:80;
  padding-left:calc(var(--hero-pad) + var(--hero-edge) + var(--sa-l));
  padding-right:calc(var(--hero-pad) + var(--hero-edge) + var(--sa-r));
  display:flex;align-items:center;justify-content:space-between;gap:16px;
}
.nav__mark{
  font-family:'Geist Mono',monospace;font-size:11px;
  letter-spacing:.22em;
  /* the type is 17px tall; the padding takes the hit area to ~41px and the
     matching negative margin keeps it out of the layout */
  padding-block:12px;margin-block:-12px;
  transition:opacity .3s var(--ease),color .4s var(--ease);
}
.nav__mark:hover{opacity:.6}

/* ── over a light section ─────────────────────────────────────────────
   Proof and brands are one continuous paper-coloured block, and the nav is
   fixed over it: white mark on #F6F8FB is invisible and the inactive tabs
   are barely better. `is-light` is set from initNav() by an observer whose
   root is a zero-height band at the nav's own vertical position, so the
   flip happens exactly as the section passes underneath. */
.nav.is-light .nav__mark{color:var(--ink)}
.nav.is-light .seg{
  background:rgba(10,20,36,.05);
  border-color:rgba(10,20,36,.13);
}
.nav.is-light .seg__item{color:var(--ink-soft)}
.nav.is-light .seg__pill{background:var(--ink)}
.nav.is-light .seg__item.is-active{color:var(--white)}
.nav.is-light .nav__cta{
  background:rgba(10,20,36,.05);border-color:rgba(10,20,36,.13);color:var(--ink);
}
.nav.is-light .nav__cta .btn__badge{background:var(--ink);color:var(--white)}

.seg{
  position:relative;display:flex;padding:6px;border-radius:999px;
  background:var(--glass);border:1px solid var(--glass-bd);
  backdrop-filter:blur(20px) saturate(140%);
  -webkit-backdrop-filter:blur(20px) saturate(140%);
  transition:background .4s var(--ease),border-color .4s var(--ease);
}
/* sits exactly on the active item's box; the seg's own padding is the gap,
   so the pill never touches the container edge at either end */
.seg__pill{
  position:absolute;top:6px;bottom:6px;left:0;width:0;
  border-radius:999px;background:var(--white);
  transition:transform .45s var(--ease),width .45s var(--ease);
}
.seg__item{
  position:relative;z-index:1;
  font-family:'Geist Mono',monospace;font-size:10.5px;
  letter-spacing:.14em;text-transform:uppercase;
  padding:8px 16px;border-radius:999px;
  color:var(--mist);transition:color .35s var(--ease);
}
.seg__item.is-active{color:var(--void)}

/* ═══ 01 · HERO — inset card on black, ref 04 ═════════════════════════ */
.beat{position:relative}

.beat--hero{padding:var(--hero-pad);background:#000}
.hero__card{
  position:relative;overflow:hidden;
  border-radius:var(--r-hero);
  min-height:min(100svh,920px);
  display:grid;place-items:center;
  isolation:isolate;
}
.hero__bloom{
  position:absolute;inset:0;z-index:0;
  background:radial-gradient(120% 90% at 50% 100%,
    #4DA3E8 0%,#1D5FA8 32%,#0B2545 62%,#04070F 100%);
}
.atmos{position:absolute;inset:-10%;z-index:1;pointer-events:none;filter:blur(60px)}
.atmos--a{
  background:radial-gradient(40% 30% at 22% 32%,rgba(143,201,242,.30),transparent 70%);
  animation:drift 26s var(--ease) infinite alternate;
}
.atmos--b{
  background:radial-gradient(36% 28% at 78% 62%,rgba(77,163,232,.22),transparent 70%);
  animation:drift 34s var(--ease) infinite alternate-reverse;
}
@keyframes drift{
  from{transform:translate3d(-3%,-2%,0) scale(1)}
  to  {transform:translate3d(4%,3%,0) scale(1.12)}
}

/* ── the hero folder, opening — ref 02 at hero scale ─────────────────── */
/* Centred on the card's vertical axis. Centring uses `translate`, not
   `transform` — `transform` belongs to the float keyframe and the two must
   never share a property (see README, note 4). */
.herofolder{
  --hue:206;
  position:absolute;z-index:4;
  right:clamp(24px,10vw,190px);top:50%;bottom:auto;
  translate:0 -50%;
  width:clamp(230px,25vw,370px);
  aspect-ratio:1/.86;
  display:block;
  animation:float 16s ease-in-out infinite alternate;
}
.herofolder:hover .herofolder__body{
  box-shadow:
    inset 0 1px 0 hsl(var(--hue) 90% 88% / .55),
    inset 0 -40px 70px hsl(var(--hue) 80% 12% / .45),
    0 40px 76px -18px hsl(var(--hue) 85% 40% / .5);
}
.herofolder__body{transition:box-shadow .5s var(--ease)}
@keyframes float{from{transform:translateY(0)}to{transform:translateY(-14px)}}

/* Portrait cards, matching the work-section folder peeks. */
.herofolder__fan{position:absolute;inset:0;display:block}
.fanslot{
  position:absolute;left:50%;bottom:34%;
  width:36%;margin-left:-18%;
  transform-origin:50% 100%;
  opacity:0;
  animation-duration:1.1s;
  animation-timing-function:var(--ease);
  animation-fill-mode:forwards;
}
.fanslot img{
  width:100%;aspect-ratio:3/4;object-fit:cover;
  border-radius:10px;
  border:1px solid rgba(255,255,255,.20);
  box-shadow:0 24px 50px -18px rgba(0,0,0,.85);
  transition:transform .5s var(--ease),box-shadow .5s var(--ease);
}

/* Literal values per card. Custom properties inside @keyframes are not
   reliably interpolated, and the whole animation was being dropped. */
.fanslot:nth-child(1){animation-name:fan1;animation-delay:.35s}
.fanslot:nth-child(2){animation-name:fan2;animation-delay:.45s}
.fanslot:nth-child(3){animation-name:fan3;animation-delay:.55s}
.fanslot:nth-child(4){animation-name:fan4;animation-delay:.65s}

@keyframes fan1{
  from{opacity:0;transform:translate(0,10%) rotate(0deg) scale(.9)}
  to  {opacity:1;transform:translate(-96%,4%)  rotate(-15deg) scale(1)}
}
@keyframes fan2{
  from{opacity:0;transform:translate(0,10%) rotate(0deg) scale(.9)}
  to  {opacity:1;transform:translate(-33%,-9%) rotate(-5deg) scale(1)}
}
@keyframes fan3{
  from{opacity:0;transform:translate(0,10%) rotate(0deg) scale(.9)}
  to  {opacity:1;transform:translate(33%,-9%)  rotate(5deg)  scale(1)}
}
@keyframes fan4{
  from{opacity:0;transform:translate(0,10%) rotate(0deg) scale(.9)}
  to  {opacity:1;transform:translate(96%,4%)   rotate(15deg) scale(1)}
}

/* Hover — the same gesture as the work folders. Applied to the image, not
   the slot, so it never collides with the entrance animation's transform. */
.herofolder:hover .fanslot img{
  box-shadow:0 30px 60px -16px rgba(0,0,0,.9);
}
.herofolder:hover .fanslot:nth-child(1) img{transform:translate(-14%,-16px) rotate(-5deg)}
.herofolder:hover .fanslot:nth-child(2) img{transform:translate(-5%,-24px)}
.herofolder:hover .fanslot:nth-child(3) img{transform:translate(5%,-24px)}
.herofolder:hover .fanslot:nth-child(4) img{transform:translate(14%,-16px) rotate(5deg)}
.herofolder:focus-visible{outline:2px solid var(--blue-glow);outline-offset:10px;border-radius:14px}

/* the folder itself, in front */
.herofolder__body{
  position:absolute;left:0;right:0;bottom:0;height:62%;z-index:3;
  border-radius:0 20px 20px 20px;
  background:linear-gradient(158deg,
    hsl(var(--hue) 72% 62% / .92) 0%,
    hsl(var(--hue) 70% 46% / .94) 42%,
    hsl(var(--hue) 74% 26% / .96) 100%);
  border:1px solid hsl(var(--hue) 80% 78% / .34);
  box-shadow:
    inset 0 1px 0 hsl(var(--hue) 90% 88% / .45),
    inset 0 -40px 70px hsl(var(--hue) 80% 12% / .5),
    0 30px 60px -18px hsl(var(--hue) 80% 8% / .85);
  transform-origin:50% 100%;
  animation:flap 1s var(--ease) .15s both;
}
/* the tab */
.herofolder__body::before{
  content:'';position:absolute;top:-26px;left:-1px;width:46%;height:28px;
  background:linear-gradient(180deg,
    hsl(var(--hue) 74% 64% / .95),hsl(var(--hue) 70% 48% / .95));
  border-radius:12px 6px 0 0;
  clip-path:polygon(0 0,72% 0,100% 100%,0 100%);
  box-shadow:inset 0 1px 0 hsl(var(--hue) 90% 88% / .40);
}
/* gloss sweep, ref 02 */
.herofolder__body::after{
  content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  background:linear-gradient(122deg,
    rgba(255,255,255,.30) 0%,rgba(255,255,255,.06) 26%,
    transparent 46%,rgba(255,255,255,.12) 100%);
  mix-blend-mode:screen;
}
@keyframes flap{
  from{transform:rotateX(-38deg) translateY(6%)}
  to  {transform:none}
}

/* keeps the type legible against the bloom without adding an image */
.hero__card::after{
  content:'';position:absolute;inset:0;z-index:2;pointer-events:none;
  background:
    linear-gradient(96deg,rgba(4,7,15,.72) 0%,rgba(4,7,15,.34) 38%,transparent 62%),
    radial-gradient(120% 80% at 50% 108%,transparent 40%,rgba(4,7,15,.55) 100%);
}

/* The wrapper is full-card-width at the same z-index as the folder and later
   in the DOM, so it was winning the hit test across the folder's whole middle
   band — only the top 48px and bottom 43px of the folder responded to hover.
   The wrapper takes no pointer events; the children do, so the text is still
   selectable. `justify-items:start` already shrinks them to their content, so
   they never reach the folder. */
.hero__inner{
  position:relative;z-index:4;text-align:left;
  width:min(1280px,100%);margin-inline:auto;
  padding-inline:var(--gutter);
  display:grid;gap:18px;justify-items:start;
  transform:translateY(-4%);
  pointer-events:none;
}
.hero__inner > *{pointer-events:auto}
.hero__eyebrow{color:var(--blue-haze);opacity:.85}
.hero__statement{
  font-size:clamp(42px,6.4vw,104px);
  letter-spacing:-.035em;line-height:.96;
  max-width:11ch;
  text-shadow:0 4px 70px rgba(4,7,15,.6);
}
.hero__sub{font-size:clamp(14px,1.5vw,18px);color:var(--mist)}

.hero__cue{
  position:absolute;z-index:4;
  left:calc(var(--hero-edge) + var(--sa-l));
  bottom:calc(var(--hero-edge) + var(--sa-b));
  display:flex;align-items:center;gap:12px;color:var(--mist);
}
.hero__cueline{
  display:block;width:56px;height:1px;
  background:linear-gradient(90deg,var(--blue-haze),transparent);
}
.hero__down{
  position:absolute;z-index:4;
  right:calc(var(--hero-edge) + var(--sa-r));
  bottom:calc(var(--hero-edge) + var(--sa-b));
}

/* ═══ 02 · PERSON ═════════════════════════════════════════════════════ */
.beat--person{
  padding:clamp(110px,18vh,190px) 0;
  background:linear-gradient(180deg,#000 0%,var(--void) 22%,var(--navy) 100%);
  overflow:hidden;
}
.ghostnum{
  position:absolute;z-index:0;pointer-events:none;
  left:-2vw;top:8%;
  font-size:min(46vw,620px);line-height:.8;font-weight:500;
  color:rgba(143,201,242,.035);
  letter-spacing:-.06em;
}
.ghostnum--r{left:auto;right:-3vw;top:auto;bottom:2%}

.meta-stack{position:absolute;color:var(--mist);opacity:.5}
.meta-stack--tl{top:-46px;left:var(--gutter)}

/* The display size lives on the container, not the lines. `ch` resolves
   against the element's own font-size, so with the size on the child the
   measure was computed from 17px body text — a 225px column holding 43px
   type, one word per line. Keep the size and the measure on the same box. */
.person__lines{
  position:relative;z-index:2;
  font-size:clamp(24px,3.4vw,46px);
  max-width:min(24ch,100%);
}
.person__line{
  font-size:1em;
  letter-spacing:-.03em;line-height:1.2;
  text-wrap:balance;
}
.person__line + .person__line{margin-top:.18em}
.person__line:last-child{color:var(--blue-haze)}

/* ═══ 03 · WORK — the folders ═════════════════════════════════════════ */
.beat--work{
  padding:clamp(80px,12vh,140px) 0 clamp(120px,18vh,200px);
  background:linear-gradient(180deg,var(--navy) 0%,var(--blue-deep) 55%,var(--navy) 100%);
  overflow:hidden;
}
.sec{position:relative;z-index:2;margin-bottom:clamp(40px,6vh,72px)}
.sec__eyebrow{color:var(--blue-haze);margin-bottom:18px}
.sec__head{font-size:clamp(32px,4.5vw,60px);letter-spacing:-.025em;line-height:1.05}
.sec__sub{margin-top:14px;color:var(--mist);max-width:var(--measure)}
.sec--light .sec__eyebrow{color:var(--blue-mid)}
.sec--light .sec__head{color:var(--ink)}
.sec--light .sec__sub{color:var(--ink-soft)}

/* The peek thumbnails overflow ~33px above each folder's box, so this
   margin has to clear that as well as the hover lift. */
.work__hint{
  position:relative;z-index:2;
  display:inline-flex;align-items:center;gap:9px;
  color:var(--mist);margin-bottom:clamp(74px,9vh,104px);
}

/* shelf of closed folders — row gap carries the peek overflow on top of the
   spacing, so it has to be much larger than the column gap */
.shelf{
  position:relative;z-index:2;
  display:grid;gap:clamp(60px,7vw,88px) clamp(24px,3vw,40px);
  grid-template-columns:repeat(3,1fr);
}

.folder{
  position:relative;text-align:left;
  padding-top:52px;                    /* room for the peeking thumbnails */
  transition:transform .45s var(--ease);
}
/* The pocket seam was drawn as its own box and never lined up with the
   folder's rounded corners, so it read as a stray line across the card.
   The tab alone carries the folder shape; no seam needed. */
.folder__lip{display:none}
.folder:hover{transform:translateY(-8px)}
.folder:focus-visible{outline:2px solid var(--blue-glow);outline-offset:8px;border-radius:var(--r-card)}
/* a press has to be visible, or a click that opens nothing feels broken */
.folder:active{transform:translateY(-2px) scale(.985)}
.folder:active .folder__body{
  box-shadow:
    inset 0 1px 0 hsl(var(--hue) 90% 88% / .6),
    inset 0 -30px 60px hsl(var(--hue) 80% 12% / .4),
    0 0 0 2px var(--blue-glow),
    0 18px 40px -18px hsl(var(--hue) 85% 40% / .6);
}

/* thumbnails peeking above the flap */
.folder__peek{
  position:absolute;left:0;right:0;top:0;height:132px;
  display:flex;justify-content:center;align-items:flex-end;
  pointer-events:none;
}
.folder__peek img{
  width:34%;aspect-ratio:3/4;object-fit:cover;
  border-radius:10px 10px 0 0;
  border:1px solid rgba(255,255,255,.16);border-bottom:0;
  box-shadow:0 -10px 30px rgba(0,0,0,.4);
  transition:transform .5s var(--ease);
  background:var(--navy-lift);
}
.folder__peek img:nth-child(1){transform:rotate(-7deg) translate(16%,10px)}
.folder__peek img:nth-child(2){transform:translateY(-4px);z-index:2}
.folder__peek img:nth-child(3){transform:rotate(7deg)  translate(-16%,10px)}
.folder:hover .folder__peek img:nth-child(1){transform:rotate(-13deg) translate(6%,-6px)}
.folder:hover .folder__peek img:nth-child(2){transform:translateY(-18px)}
.folder:hover .folder__peek img:nth-child(3){transform:rotate(13deg)  translate(-6%,-6px)}

/* folders that hold only links and figures peek as icon chips */
.folder__peek--chips{gap:14px;justify-content:center;padding-bottom:8px}
.peekchip{
  width:60px;height:74px;border-radius:12px 12px 0 0;
  display:grid;place-items:center;color:var(--blue-haze);
  background:linear-gradient(180deg,rgba(255,255,255,.14),rgba(255,255,255,.04));
  border:1px solid rgba(255,255,255,.18);border-bottom:0;
  box-shadow:0 -10px 30px rgba(0,0,0,.4);
  transition:transform .5s var(--ease);
}
.peekchip svg{width:22px;height:22px}
.peekchip:nth-child(1){transform:rotate(-8deg) translateY(8px)}
.peekchip:nth-child(3){transform:rotate(8deg)  translateY(8px)}
.folder:hover .peekchip:nth-child(1){transform:rotate(-14deg) translateY(-8px)}
.folder:hover .peekchip:nth-child(2){transform:translateY(-16px)}
.folder:hover .peekchip:nth-child(3){transform:rotate(14deg)  translateY(-8px)}

/* the folder itself — a real folder silhouette: a raised tab on the left,
   the top edge stepping down to the pocket. Built as two stacked layers so
   the tab can carry its own gloss. */
.folder__body{
  position:relative;z-index:3;
  margin-top:26px;                       /* room for the tab above */
  border-radius:0 18px 18px 18px;
  padding:20px 20px 22px;
  min-height:190px;
  display:flex;flex-direction:column;justify-content:flex-end;gap:10px;
  background:
    linear-gradient(158deg,
      hsl(var(--hue) 72% 62% / .90) 0%,
      hsl(var(--hue) 70% 46% / .92) 42%,
      hsl(var(--hue) 74% 26% / .95) 100%);
  border:1px solid hsl(var(--hue) 80% 78% / .34);
  box-shadow:
    inset 0 1px 0 hsl(var(--hue) 90% 88% / .45),
    inset 0 -30px 60px hsl(var(--hue) 80% 12% / .5),
    0 24px 50px -18px hsl(var(--hue) 80% 8% / .8);
  overflow:hidden;
  transition:box-shadow .45s var(--ease);
}
/* the tab — angled on its right edge, the way a folder tab actually is */
.folder__body::before{
  content:'';position:absolute;top:-25px;left:-1px;width:46%;height:28px;
  background:linear-gradient(180deg,
    hsl(var(--hue) 74% 64% / .95),hsl(var(--hue) 70% 48% / .95));
  border-radius:12px 6px 0 0;
  clip-path:polygon(0 0,72% 0,100% 100%,0 100%);
  box-shadow:inset 0 1px 0 hsl(var(--hue) 90% 88% / .40);
}
/* gloss sweep */
.folder__body::after{
  content:'';position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(122deg,
    rgba(255,255,255,.30) 0%,rgba(255,255,255,.06) 26%,
    transparent 46%,rgba(255,255,255,.10) 100%);
  mix-blend-mode:screen;
}
.folder:hover .folder__body{
  box-shadow:
    inset 0 1px 0 hsl(var(--hue) 90% 88% / .55),
    inset 0 -30px 60px hsl(var(--hue) 80% 12% / .45),
    0 34px 64px -18px hsl(var(--hue) 85% 40% / .55);
}

.folder__num{
  position:absolute;top:16px;right:18px;
  font-family:'Geist Mono',monospace;font-size:11px;letter-spacing:.14em;
  color:rgba(255,255,255,.62);z-index:2;
}
.folder__label{position:relative;z-index:2;color:rgba(255,255,255,.72)}
.folder__name{
  position:relative;z-index:2;
  font-size:clamp(19px,1.6vw,23px);letter-spacing:-.02em;line-height:1.2;
}
.folder__meta{
  position:relative;z-index:2;
  font-size:13px;color:rgba(255,255,255,.72);line-height:1.45;
}

.folder__foot{
  position:relative;z-index:2;
  display:flex;align-items:center;justify-content:space-between;
  gap:12px;margin-top:6px;
}
.folder__count{color:rgba(255,255,255,.62)}
.folder__open{
  width:32px;height:32px;border-radius:999px;flex:none;
  display:grid;place-items:center;
  background:rgba(255,255,255,.16);
  border:1px solid rgba(255,255,255,.28);
  transition:background .3s var(--ease),transform .3s var(--ease);
}
.folder__open svg{width:14px;height:14px}
.folder:hover .folder__open{background:var(--white);color:hsl(var(--hue) 74% 22%);transform:rotate(45deg)}

/* highlight pill, ref 02 */
.folder__pill{
  position:absolute;z-index:4;top:38px;right:-6px;
  padding:7px 13px;border-radius:999px;
  font-family:'Geist Mono',monospace;font-size:10px;letter-spacing:.12em;
  text-transform:uppercase;white-space:nowrap;
  background:rgba(6,14,26,.72);
  border:1px solid hsl(var(--hue) 90% 70% / .45);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  box-shadow:0 0 26px hsl(var(--hue) 90% 55% / .35);
  transition:transform .45s var(--ease);
}
.folder:hover .folder__pill{transform:translateY(-6px) rotate(-2deg)}

/* ═══ 03b · TOOLS — the constellation ═════════════════════════════════
   Names only. No logos, no proficiency bars, no star ratings.
   Depth (--d, 0–1) drives size, opacity and blur, the same idea as the
   ring's depth cue flattened into two dimensions. */
.beat--tools{
  padding:clamp(80px,12vh,140px) 0 clamp(90px,14vh,160px);
  background:linear-gradient(180deg,var(--navy) 0%,var(--void) 50%,var(--navy) 100%);
  overflow:hidden;
}
.constel{
  position:relative;z-index:2;
  height:clamp(300px,42vh,440px);
  margin-top:clamp(24px,4vh,44px);
}
.star{
  position:absolute;
  translate:-50% -50%;
  white-space:nowrap;
  font-size:calc(12px + var(--d) * 12px);
  color:var(--white);
  opacity:calc(.22 + var(--d) * .68);
  filter:blur(calc((1 - var(--d)) * 1.6px));
  letter-spacing:-.01em;
  /* Two drifts of different lengths running together, so no two names ever
     travel in step. `--d` (depth) scales the distance — nearer names move
     further — and the seeded `--delay` offsets each one. The single 14s
     translate this replaced read as static. */
  animation:
    driftx calc(19s + var(--d) * 11s) ease-in-out infinite alternate,
    drifty calc(13s + var(--d) * 9s)  ease-in-out infinite alternate,
    breathe calc(9s + var(--d) * 6s)  ease-in-out infinite alternate;
  animation-delay:
    calc(var(--delay) * -1),
    calc(var(--delay) * -1.7),
    calc(var(--delay) * -1.3);
  transition:opacity .35s var(--ease),filter .35s var(--ease),color .35s var(--ease);
}
/* translate and opacity are animated on separate axes/properties so they can
   run at different periods without fighting over one transform */
/* the -50% is the centring offset from .star and has to be carried through,
   or animating `translate` knocks every name off its anchor point */
@keyframes driftx{
  from{translate:calc(-50% + var(--d) * -9px)  -50%}
  to  {translate:calc(-50% + var(--d) * 12px)  -50%}
}
@keyframes drifty{
  from{transform:translate3d(0,calc(var(--d) * 7px),0)}
  to  {transform:translate3d(0,calc(var(--d) * -10px),0)}
}
@keyframes breathe{
  from{opacity:calc(.18 + var(--d) * .58)}
  to  {opacity:calc(.30 + var(--d) * .70)}
}
/* !important because the `breathe` animation also writes opacity, and an
   animation beats a plain declaration — without this, hovering a group chip
   no longer dims the rest of the field. */
.constel.is-filtered .star{opacity:.10!important;filter:blur(2px)}
.constel.is-filtered .star.is-lit{
  opacity:1!important;filter:none;color:var(--blue-haze);
}

.constel__key{
  position:relative;z-index:2;
  display:flex;flex-wrap:wrap;gap:8px;
  margin-top:clamp(20px,3vh,32px);
}
.key{
  display:inline-flex;align-items:center;gap:8px;
  padding:7px 14px;border-radius:999px;
  font-family:'Geist Mono',monospace;font-size:10px;
  letter-spacing:.14em;text-transform:uppercase;
  color:var(--mist);
  background:var(--glass);border:1px solid var(--glass-bd);
  backdrop-filter:blur(20px) saturate(140%);
  -webkit-backdrop-filter:blur(20px) saturate(140%);
  transition:background .3s var(--ease),color .3s var(--ease);
}
.key__dot{
  width:5px;height:5px;border-radius:999px;flex:none;
  background:var(--blue-glow);opacity:.6;
  transition:opacity .3s var(--ease);
}
.key:hover,.key.is-on{background:var(--glass-hi);color:var(--white)}
.key:hover .key__dot,.key.is-on .key__dot{opacity:1}

/* ═══ SECTION TRANSITIONS — hard cuts ═════════════════════════════════
   There were long gradient dividers here, navy → white and back. However
   many stops they carried, they read as a band across the page rather than
   as a dissolve. Both are now straight edges: the dark stack meets the light
   proof section, and the light brands row meets the dark about section. */

/* ═══ 04 · PROOF — light, refs 06 + 07 ════════════════════════════════ */
.beat--proof{
  background:var(--paper);color:var(--ink);
  padding:clamp(80px,14vh,150px) 0 clamp(60px,10vh,110px);
  overflow:hidden;
}
/* Pulled clear of the section's bottom edge. At `-30%` the 60px blur was cut
   flush by `.beat--proof{overflow:hidden}`, leaving a hard horizontal seam
   exactly where the white brands band starts. */
.lightbloom{
  position:absolute;inset:auto -20% 8%;height:66%;pointer-events:none;
  background:radial-gradient(50% 60% at 30% 55%,rgba(143,201,242,.5),transparent 72%);
  filter:blur(60px);
}
.metrics{
  position:relative;z-index:2;
  display:grid;gap:clamp(28px,4vw,56px) clamp(20px,3vw,40px);
  grid-template-columns:repeat(6,1fr);
  margin-bottom:clamp(60px,9vh,110px);
}
/* asymmetric editorial placement, ref 06 */
.metric:nth-child(1){grid-column:span 3}
.metric:nth-child(2){grid-column:span 2}
.metric:nth-child(3){grid-column:span 1}
.metric:nth-child(4){grid-column:span 2;grid-column-start:2}
.metric:nth-child(5){grid-column:span 2}

.metric__v{
  font-size:clamp(40px,6vw,88px);letter-spacing:-.03em;line-height:1;
  font-variant-numeric:tabular-nums;
}
.metric__l{margin-top:10px;font-size:15px;color:var(--ink);max-width:18ch}
.metric__n{margin-top:6px;color:var(--ink-soft);opacity:.9}

.results{
  position:relative;z-index:2;
  display:grid;grid-template-columns:repeat(3,1fr);
  gap:clamp(20px,3vw,40px);
  padding-top:clamp(28px,4vh,48px);
  border-top:1px solid rgba(10,20,36,.10);
}
.result__v{
  font-size:clamp(32px,4.4vw,64px);letter-spacing:-.03em;line-height:1;
  font-variant-numeric:tabular-nums;
}
.result__l{margin-top:8px;color:var(--ink-soft);font-size:15px}
.results__cap{
  grid-column:1/-1;margin-top:14px;color:var(--ink-soft);opacity:.75;
}

/* ═══ 05 · BRANDS ═════════════════════════════════════════════════════ */
/* No top padding — proof and brands are one continuous light block now that
   no divider sits between them and the section below. */
.beat--brands{background:var(--paper);padding:0 0 clamp(70px,11vh,120px)}
.brands{
  display:grid;grid-template-columns:auto 1fr;
  gap:clamp(20px,4vw,52px);align-items:center;
}
.brands__label{color:var(--ink-soft);white-space:nowrap}
.marquee{
  overflow:hidden;position:relative;
  mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent);
}
.marquee__track{display:flex;gap:clamp(34px,5vw,72px);width:max-content;animation:slide 42s linear infinite}
.marquee:hover .marquee__track{animation-play-state:paused}
@keyframes slide{to{transform:translateX(-50%)}}
/* Logos come at wildly different aspect ratios, so matching them on height
   alone made Elie Saab enormous next to Hilton. Cap the width too and let
   each sit in a fixed box. */
.marquee img{
  height:clamp(18px,2vw,26px);
  max-width:clamp(90px,10vw,150px);
  width:auto;object-fit:contain;object-position:center;
  filter:grayscale(1) brightness(.35);opacity:.62;
  transition:opacity .35s var(--ease),filter .35s var(--ease);
  flex:none;
}
.marquee img:hover{opacity:1;filter:grayscale(1) brightness(.15)}
.marquee__track{align-items:center;padding-block:6px}

/* ═══ 06 · ABOUT ══════════════════════════════════════════════════════ */
.beat--about{
  background:linear-gradient(180deg,var(--navy) 0%,var(--void) 100%);
  padding:clamp(70px,11vh,120px) 0 0;overflow:hidden;
}
.about__glow{
  position:absolute;inset:auto -20% -10%;height:70%;pointer-events:none;
  background:radial-gradient(46% 60% at 68% 80%,rgba(29,95,168,.55),transparent 70%);
  filter:blur(70px);
}
.about{
  position:relative;z-index:2;
  display:grid;grid-template-columns:1fr .82fr;
  gap:clamp(30px,5vw,80px);align-items:end;
}
.about__text{padding-bottom:clamp(60px,9vh,110px);max-width:var(--measure)}
.about__p{margin-top:18px;color:var(--mist)}

/* One typeface across the whole page. The serif here was a deliberate
   change of voice in the original spec, but it read as a bug. */
.pov{
  margin:clamp(28px,4vh,44px) 0 0;padding:22px 0 0;
  border-top:1px solid rgba(255,255,255,.12);
  font-size:clamp(17px,1.5vw,20px);line-height:1.6;color:var(--mist);
}
.pov p + p{margin-top:.7em}
.pov__last{color:var(--white)}

.contact{margin-top:clamp(28px,4vh,44px);padding:22px}
.contact__label{color:var(--blue-haze);margin-bottom:14px}
.contact__row{
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:13px 0;border-top:1px solid rgba(255,255,255,.10);
  font-size:16px;transition:padding-left .35s var(--ease);
}
.contact__row:hover{padding-left:8px}
.contact__go{
  width:30px;height:30px;border-radius:999px;flex:none;display:grid;place-items:center;
  border:1px solid var(--glass-bd);background:var(--glass);
  transition:background .3s var(--ease),color .3s var(--ease);
}
.contact__go svg{width:14px;height:14px}
.contact__row:hover .contact__go{background:var(--white);color:var(--void)}
.contact__cv{margin-top:20px}

/* vertically centred against the text column. No scroll parallax on this —
   any scrub pulls it off the centre it is supposed to hold. */
.about__portrait{position:relative;margin:0;align-self:center}

/* The image already carries its own rim light, so no CSS glow —
   it just sits on the dark and fades into it at the bottom edge. */
.portrait__main{
  position:relative;z-index:2;width:100%;height:auto;
  mask-image:linear-gradient(180deg,#000 78%,transparent 100%);
  -webkit-mask-image:linear-gradient(180deg,#000 78%,transparent 100%);
}

.foot{
  display:flex;justify-content:space-between;gap:16px;
  padding:22px calc(var(--gutter) + var(--sa-r))
          calc(22px + var(--sa-b)) calc(var(--gutter) + var(--sa-l));
  background:var(--void);
  border-top:1px solid rgba(255,255,255,.08);
  color:var(--mist);opacity:.6;
}

/* ═══ THE RING — 360° folder contents ═════════════════════════════════ */
.ring{
  position:fixed;inset:0;z-index:100;display:grid;grid-template-rows:auto 1fr auto;
  overscroll-behavior:contain;      /* a flick past the end must not reach the page */
}
.ring[hidden]{display:none}
.ring__scrim{
  position:absolute;inset:0;z-index:0;
  touch-action:none;                /* dragging the backdrop scrolls nothing */
  background:rgba(2,5,11,.86);
  backdrop-filter:blur(26px) saturate(120%);
  -webkit-backdrop-filter:blur(26px) saturate(120%);
  opacity:0;transition:opacity .5s var(--ease);
}
.ring.is-open .ring__scrim{opacity:1}

.ring__bar{
  position:relative;z-index:3;
  display:flex;align-items:flex-start;justify-content:space-between;gap:20px;
  padding:calc(18px + var(--sa-t)) calc(var(--gutter) + var(--sa-r))
          18px calc(var(--gutter) + var(--sa-l));
  opacity:0;transform:translateY(-12px);
  transition:opacity .5s .12s var(--ease),transform .5s .12s var(--ease);
}
.ring.is-open .ring__bar{opacity:1;transform:none}
.ring__id{display:flex;gap:16px;align-items:baseline}
.ring__num{color:var(--blue-haze);font-size:12px}
.ring__name{font-size:clamp(20px,2.4vw,30px);letter-spacing:-.02em}
.ring__meta{color:var(--mist);margin-top:6px}
.ring__tools{display:flex;align-items:center;gap:10px}
.ring__count{color:var(--mist);min-width:56px;text-align:center;font-variant-numeric:tabular-nums}
.iconbtn--close{margin-left:6px}

/* `perspective` is set from JS, scaled to the ring's radius, so the front
   card is magnified the same amount whatever the item count. A fixed value
   here made a 16-item folder 2.3x bigger than a 7-item one. */
.ring__stage{
  position:relative;z-index:2;
  perspective:1500px;perspective-origin:50% 50%;
  display:grid;place-items:center;
  touch-action:pan-y;cursor:grab;overflow:hidden;
}
.ring__stage.is-drag{cursor:grabbing}
.ring__spin{
  position:relative;width:0;height:0;
  transform-style:preserve-3d;
  transform:rotateX(-8deg) rotateY(0deg);
}

.rcard{
  position:absolute;
  width:var(--cw);height:var(--ch);
  margin-left:calc(var(--cw) / -2);
  margin-top:calc(var(--ch) / -2);
  border-radius:var(--r-card);
  background:var(--glass);
  border:1px solid var(--glass-bd);
  backdrop-filter:blur(16px) saturate(140%);
  -webkit-backdrop-filter:blur(16px) saturate(140%);
  /* deliberately not overflow:hidden — the glow pill label sits outside
     the card edge, as it does in reference 02 */
  transform-style:preserve-3d;
  will-change:transform,filter,opacity;
  box-shadow:0 30px 60px -24px rgba(0,0,0,.85);
  text-align:left;
  transition:border-color .3s var(--ease);
}
.rcard:hover{border-color:rgba(143,201,242,.5)}
.rcard:focus-visible{outline:2px solid var(--blue-glow);outline-offset:4px}
/* paint() writes transform, filter and opacity inline every frame, so a press
   state can only use properties it never touches */
button.rcard:active{
  border-color:var(--blue-glow);
  box-shadow:0 0 0 2px var(--blue-glow),0 30px 60px -24px rgba(0,0,0,.85);
}
button.rcard:active .rcard__cta{background:var(--blue-glow);color:var(--void)}

/* A card with nothing to open must not look clickable. */
div.rcard{cursor:default}
div.rcard:hover{border-color:var(--glass-bd)}
.rcard__img{
  width:100%;height:100%;object-fit:cover;
  border-radius:inherit;
}
/* starts higher than it used to — poster cards can carry a two-line title
   over a bright screenshot, and the text needs something to sit on */
.rcard__shade{
  position:absolute;inset:0;pointer-events:none;border-radius:inherit;
  background:linear-gradient(180deg,transparent 28%,rgba(4,7,15,.55) 62%,rgba(4,7,15,.92) 100%);
}
.rcard__cap{
  position:absolute;left:14px;right:14px;bottom:12px;z-index:2;
  color:var(--white);
}
.rcard__cap b{display:block;font-weight:500;font-size:13px;letter-spacing:0;text-transform:none;font-family:'Geist',sans-serif;line-height:1.35}
/* one line, always — domains like connect.radiantrealestate.ae wrapped onto a
   second line and rode up over the image */
.rcard__cap i{
  display:block;font-style:normal;color:var(--mist);margin-top:3px;font-size:10px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}

/* per-type treatments */
.rcard--fact{
  display:flex;flex-direction:column;justify-content:center;gap:8px;padding:22px;
  background:linear-gradient(155deg,rgba(29,95,168,.5),rgba(11,37,69,.6));
}
.rcard--fact .f-v{font-size:clamp(30px,3.4vw,46px);letter-spacing:-.03em;line-height:1;font-variant-numeric:tabular-nums}
.rcard--fact .f-l{font-size:14px;color:var(--white);line-height:1.35}
.rcard--fact .f-n{color:var(--blue-haze);opacity:.8}

.rcard--doc{
  display:flex;flex-direction:column;justify-content:space-between;padding:20px;
  background:linear-gradient(160deg,rgba(255,255,255,.10),rgba(255,255,255,.03));
}
.rcard--doc .d-ico{
  width:32px;height:32px;color:var(--blue-haze);
  align-self:flex-end;                 /* clears the CTA pill top-left */
}
.rcard--doc .d-ico svg{width:100%;height:100%}
.rcard--doc .d-nm{display:block;font-size:15px;line-height:1.3}
.rcard--doc .d-x{display:block;color:var(--mist);margin-top:5px}
.rcard--link .l-nm,.rcard--embed .l-nm{display:block}
.rcard--link .l-x,.rcard--embed .l-x{display:block}

.rcard--link{
  display:flex;flex-direction:column;justify-content:space-between;padding:20px;
}
.tile{
  width:44px;height:44px;border-radius:12px;display:grid;place-items:center;
  background:rgba(255,255,255,.10);border:1px solid var(--glass-bd);
  color:var(--blue-haze);transition:background .3s var(--ease),color .3s var(--ease);
}
.tile svg{width:20px;height:20px}
.rcard--link:hover .tile{background:var(--white);color:var(--void)}
.rcard--link .l-nm{font-size:15px;line-height:1.3}
.rcard--link .l-x{color:var(--mist);margin-top:6px;overflow-wrap:anywhere}
.l-live{display:inline-flex;align-items:center;gap:7px;color:var(--blue-haze);margin-top:10px}

.rcard--video .v-play,.rcard--film .v-play{
  position:absolute;inset:0;z-index:2;display:grid;place-items:center;
}
.v-play span{
  width:52px;height:52px;border-radius:999px;display:grid;place-items:center;
  background:rgba(255,255,255,.16);border:1px solid rgba(255,255,255,.4);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  transition:background .3s var(--ease),transform .3s var(--ease);
}
.v-play svg{width:18px;height:18px;fill:currentColor;stroke:none;margin-left:2px}
.rcard:hover .v-play span{background:var(--white);color:var(--void);transform:scale(1.06)}

.rcard--embed{background:linear-gradient(155deg,rgba(77,163,232,.35),rgba(11,37,69,.65))}

/* A doc, link or embed carrying a poster drops the icon-tile layout entirely —
   the image fills the card exactly as a render does. The padding and flex
   above are for the icon fallback only. */
.rcard--doc.has-poster,
.rcard--link.has-poster,
.rcard--embed.has-poster{
  display:block;padding:0;background:var(--glass);
}
/* PDF covers are pages, not photographs: fit the whole page in rather than
   cropping the title off, and sit it on a dark mat. */
.rcard--doc.has-poster .rcard__img{
  object-fit:contain;
  background:linear-gradient(160deg,rgba(6,14,26,.9),rgba(6,14,26,.75));
}

/* graceful placeholder when an asset is not on disk yet */
.rcard.is-missing .rcard__img,
.folder__peek img.is-missing{visibility:hidden}
.rcard.is-missing{
  background:linear-gradient(155deg,rgba(255,255,255,.09),rgba(255,255,255,.03));
}
.rcard.is-missing .rcard__shade{display:none}
.folder__peek img.is-missing{
  visibility:visible;
  background:linear-gradient(160deg,rgba(255,255,255,.16),rgba(255,255,255,.05));
}

/* floating glow pill label, ref 02 */
.rlabel{
  position:absolute;z-index:5;left:50%;top:-16px;translate:-50% 0;
  padding:6px 12px;border-radius:999px;white-space:nowrap;
  font-family:'Geist Mono',monospace;font-size:9.5px;letter-spacing:.12em;text-transform:uppercase;
  background:rgba(6,14,26,.8);
  border:1px solid rgba(143,201,242,.45);
  box-shadow:0 0 22px rgba(77,163,232,.45);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  opacity:0;transition:opacity .3s var(--ease),translate .3s var(--ease);
}
.rcard.is-front .rlabel{opacity:1;translate:-50% -6px}

/* ── grid view — every item at once, no spatial reasoning required ───── */
.viewtog{
  display:inline-flex;align-items:center;gap:8px;
  padding:8px 14px;border-radius:999px;
  font-size:12.5px;font-weight:500;
  background:var(--glass);border:1px solid var(--glass-bd);
  backdrop-filter:blur(20px) saturate(140%);
  -webkit-backdrop-filter:blur(20px) saturate(140%);
  transition:background .3s var(--ease);
}
.viewtog:hover{background:var(--glass-hi)}
.viewtog__ico{display:grid;place-items:center}
.viewtog__ico svg{width:15px;height:15px}

.ring.is-grid .ring__stage{
  perspective:none;display:block;overflow:hidden auto;
  padding:4px var(--gutter) 24px;cursor:default;
}
.ring.is-grid .ring__spin{
  width:100%;height:auto;transform:none!important;transform-style:flat;
  display:grid;gap:16px;
  grid-template-columns:repeat(auto-fill,minmax(clamp(220px,20vw,290px),1fr));
}
.ring.is-grid .rcard{
  position:relative;width:auto;height:200px;margin:0;
  transform:none!important;filter:none!important;opacity:1!important;
}
.ring.is-grid .rlabel{display:none}
.ring.is-grid .rcard__cta{opacity:1;transform:none;bottom:auto;top:10px;left:10px;translate:0 0;
                          font-size:11px;padding:6px 11px}
.ring.is-grid .ring__foot .rail,
.ring.is-grid .ring__now{display:none}
.ring.is-grid .ring__tools .iconbtn:not(.iconbtn--close),
.ring.is-grid .ring__count{display:none}

/* ── the foot: what you're looking at, the rail, and the rule ────────── */
.ring__foot{
  position:relative;z-index:3;
  display:grid;justify-items:center;gap:12px;
  padding:10px calc(var(--gutter) + var(--sa-r))
          calc(20px + var(--sa-b)) calc(var(--gutter) + var(--sa-l));
}
.ring__now{
  color:var(--white);font-size:12px;letter-spacing:.1em;
  min-height:1em;text-align:center;
}
.ring__hint{color:var(--mist);opacity:.5;text-align:center;font-size:10px}

.rail{
  display:flex;gap:6px;flex-wrap:wrap;justify-content:center;
  max-width:min(720px,100%);
}
.rail__dot{
  width:26px;height:26px;border-radius:8px;
  display:grid;place-items:center;
  transition:background .25s var(--ease);
}
.rail__dot span{
  display:block;width:100%;height:3px;border-radius:99px;
  background:rgba(255,255,255,.22);
  transition:background .25s var(--ease),height .25s var(--ease);
}
.rail__dot:hover span{background:rgba(255,255,255,.5)}
.rail__dot:active span{background:var(--blue-glow);height:5px}
.rail__dot.is-on span{background:var(--blue-glow);height:5px}

/* the front card says what clicking it will do */
.rcard__cta{
  position:absolute;z-index:6;left:50%;bottom:-15px;translate:-50% 0;
  display:inline-flex;align-items:center;gap:7px;white-space:nowrap;
  padding:8px 14px;border-radius:999px;
  font-family:'Geist',sans-serif;font-size:12px;font-weight:500;letter-spacing:0;
  background:var(--white);color:var(--void);
  box-shadow:0 8px 26px rgba(0,0,0,.55);
  opacity:0;transform:translateY(6px);pointer-events:none;
  transition:opacity .3s var(--ease),transform .3s var(--ease);
}
.rcard__cta svg{width:13px;height:13px}
/* shows on the front card and under the cursor — with one-click-opens the
   affordance has to be where the pointer actually is */
.rcard.is-front .rcard__cta,
.rcard:hover .rcard__cta{opacity:1;transform:none}
.rcard.is-front{border-color:rgba(143,201,242,.45)}

/* ═══ LIGHTBOX ════════════════════════════════════════════════════════ */
.lb{position:fixed;inset:0;z-index:120;display:grid;place-items:center;background:rgba(2,5,11,.95);
    backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);
    overscroll-behavior:contain;
    padding:calc(56px + var(--sa-t)) calc(20px + var(--sa-r))
            calc(56px + var(--sa-b)) calc(20px + var(--sa-l))}
.lb[hidden]{display:none}
.lb__close{position:absolute;top:calc(18px + var(--sa-t));right:calc(18px + var(--sa-r));z-index:2}
.lb__body{max-width:min(1400px,100%);max-height:100%;display:grid;place-items:center}
.lb__body img,.lb__body video{max-width:100%;max-height:82svh;border-radius:var(--r-card);object-fit:contain}
.lb__body iframe{width:min(1200px,92vw);aspect-ratio:16/9;border:0;border-radius:var(--r-card)}
.lb__cap{position:absolute;left:0;right:0;bottom:18px;text-align:center;color:var(--mist)}

/* ═══ RESPONSIVE ══════════════════════════════════════════════════════ */
@media (max-width:1000px){
  .shelf{grid-template-columns:repeat(2,1fr)}
  .about{grid-template-columns:1fr;align-items:start}
  .about__text{padding-bottom:0;max-width:none}
  .about__portrait{max-width:440px;margin-inline:auto}
  .metrics{grid-template-columns:repeat(4,1fr)}
  .metric:nth-child(n){grid-column:span 2;grid-column-start:auto}
}

@media (max-width:720px){
  body{font-size:16px}
  :root{--hero-pad:8px}
  /* The whole nav becomes ONE glass bar, so ALI LOTFY sits on the same blur
     the tabs do. On its own it was bare type over whatever happened to be
     behind it — unreadable against the hero bloom and invisible over the
     light sections. The segment gives up its own pill; the bar is the pill. */
  .nav{
    top:calc(10px + var(--sa-t));
    left:calc(10px + var(--sa-l));right:calc(10px + var(--sa-r));
    gap:8px;
    padding:5px 6px 5px 15px;
    border-radius:999px;
    background:var(--glass);
    border:1px solid var(--glass-bd);
    backdrop-filter:blur(20px) saturate(140%);
    -webkit-backdrop-filter:blur(20px) saturate(140%);
    transition:background .4s var(--ease),border-color .4s var(--ease);
  }
  .seg{background:none;border-color:transparent;padding:0;
       backdrop-filter:none;-webkit-backdrop-filter:none}
  .seg__pill{top:0;bottom:0}          /* the seg no longer has padding to inset it */
  .nav__cta{display:none}
  /* Vertical padding only — the bar has ~340px of usable width and the four
     tabs already take 236px of it. This takes each tab from a 30px box to a
     40px target without widening it. */
  .seg__item{padding:11px 11px;font-size:9.5px}
  .nav__mark{font-size:10px;padding-block:12px;margin-block:-12px}

  /* over the light sections the bar itself carries the flip */
  .nav.is-light{background:rgba(255,255,255,.72);border-color:rgba(10,20,36,.10)}
  .nav.is-light .seg{background:none;border-color:transparent}

  /* ── HERO: text first, folder after ─────────────────────────────────
     The folder used to sit above the headline and eat the top half of the
     screen, leaving ~200px of dead black under the text. Card becomes a
     centred flex column and the folder moves into flow below the text with
     `order`. Every decorative layer in here is position:absolute, so only
     .hero__inner and .herofolder participate. */
  .hero__card{
    min-height:92svh;
    display:flex;flex-direction:column;justify-content:center;
    /* the folder wants clear air under the sub-line, not to crowd it */
    gap:clamp(52px,8vh,80px);
    padding:calc(92px + var(--sa-t)) 0 calc(76px + var(--sa-b));
  }
  .hero__inner{order:1;position:relative;transform:none;width:100%}
  .herofolder{
    order:2;position:relative;
    /* `translate` has to be cleared, not reused: `transform` belongs to the
       float keyframe and the two must never share a property (README note 4).
       Centring is margin-inline here. */
    right:auto;top:auto;bottom:auto;translate:none;
    margin-inline:auto;
    width:min(64vw,262px);
  }
  /* Tighter fan on a phone, or the cards run off the edge.
     Needs its own keyframes now that the desktop ones carry literal values. */
  .fanslot{width:40%;margin-left:-20%}
  .fanslot:nth-child(1){animation-name:fanm1}
  .fanslot:nth-child(2){animation-name:fanm2}
  .fanslot:nth-child(3){animation-name:fanm3}
  .fanslot:nth-child(4){display:none}
  @keyframes fanm1{
    from{opacity:0;transform:translate(0,10%) rotate(0deg) scale(.9)}
    to  {opacity:1;transform:translate(-62%,0)   rotate(-11deg) scale(1)}
  }
  @keyframes fanm2{
    from{opacity:0;transform:translate(0,10%) rotate(0deg) scale(.9)}
    to  {opacity:1;transform:translate(0,-11%)   rotate(0deg)   scale(1)}
  }
  @keyframes fanm3{
    from{opacity:0;transform:translate(0,10%) rotate(0deg) scale(.9)}
    to  {opacity:1;transform:translate(62%,0)    rotate(11deg)  scale(1)}
  }
  .hero__statement{max-width:none}
  /* The wash follows the type. With the text now in the upper-middle band
     rather than the lower third, the weight moves up with it. */
  .hero__card::after{
    background:
      linear-gradient(180deg,
        rgba(4,7,15,.62) 0%,rgba(4,7,15,.46) 34%,
        rgba(4,7,15,.22) 62%,rgba(4,7,15,.55) 100%);
  }
  .hero__down{display:none}

  /* ── SECTION RHYTHM ─────────────────────────────────────────────────
     The desktop 18vh/12vh padding was tuned against a ~900px viewport. On an
     844px phone it left 230–250px bands of nothing between beats. */
  .beat--person{padding:clamp(64px,9vh,92px) 0 clamp(44px,6vh,64px)}
  .beat--work  {padding:clamp(44px,6vh,64px) 0 clamp(40px,5.5vh,60px)}
  .beat--tools {padding:clamp(44px,6vh,64px) 0 clamp(52px,7vh,76px)}
  .beat--proof {padding-block:clamp(56px,8vh,84px)}
  .beat--about {padding-block:clamp(56px,8vh,84px)}
  .sec{margin-bottom:clamp(26px,4vh,38px)}
  /* has to clear the peek thumbnails (118px here, carried by .folder's own
     52px padding-top) and still read as a gap between the instruction and the
     first folder rather than a caption stuck to it */
  .work__hint{margin-bottom:clamp(60px,8.5vh,84px)}

  /* One column, so this row gap is the whole break between one folder and the
     next one's thumbnails — 44px read as a single run of cards, not eight
     separate folders. */
  .shelf{grid-template-columns:1fr;gap:76px}
  .folder__peek{height:118px}

  .metrics{grid-template-columns:repeat(2,1fr);}
  .metric:nth-child(n){grid-column:span 1}
  .metric:nth-child(1){grid-column:span 2}
  .results{grid-template-columns:1fr;gap:22px}

  .brands{grid-template-columns:1fr;gap:18px}
  .brands__label{text-align:left}

  /* The hard break in the POV is placed for a desktop measure. At 350px the
     line already wraps on its own and the <br> left a stranded short line. */
  .pov br{display:none}

  .meta-stack--tl{display:none}

  /* the constellation would collide with itself on a phone — lay it out */
  .constel{height:auto;display:flex;flex-wrap:wrap;gap:8px 14px;margin-top:26px}
  .star{
    position:static;translate:none;transform:none!important;
    animation:none;font-size:15px;opacity:.85;filter:none;
  }
  .key{padding-block:12px}                    /* 33px box → 44px */

  /* ── THE RING ON A PHONE ────────────────────────────────────────────
     It opens in grid (see openRing). The carousel below is the ring view a
     reader can switch back to. */

  /* Two rules here are load-bearing and both fixed a carousel that could not
     be used at all:

     `touch-action` is PER MODE and must never go back to one global value.
     The stage is a horizontal scroller in ring view, so the `pan-y` inherited
     from the 3D ring told the browser to refuse horizontal touch panning —
     swiping did nothing whatsoever and the rail dots were the only way to move.

     `justify-content:flex-start` on a flex row, NOT a block box holding a
     wider child. The stage also inherits `place-items:center`, and a scroll
     container that centres content wider than itself puts everything before
     the midpoint at an offset nothing can scroll back to — the first eight
     cards of a seventeen-card folder simply did not exist. */
  .ring__stage{
    perspective:none;
    display:flex;align-items:center;justify-content:flex-start;
    overflow:auto hidden;
    scroll-snap-type:x mandatory;
    -webkit-overflow-scrolling:touch;
    touch-action:pan-x pinch-zoom;
    overscroll-behavior:contain;
    padding:10px calc(var(--gutter) + var(--sa-r))
            20px calc(var(--gutter) + var(--sa-l));
  }
  .ring.is-grid .ring__stage{
    touch-action:pan-y pinch-zoom;
    scroll-snap-type:none;
    padding:4px calc(var(--gutter) + var(--sa-r))
            24px calc(var(--gutter) + var(--sa-l));
  }

  .ring__spin{
    width:max-content;height:100%;transform:none!important;
    flex:0 0 auto;                 /* must not be squeezed into the stage */
    display:flex;gap:14px;align-items:center;justify-content:flex-start;
  }
  /* 3:2, matching the source renders exactly — the old 4:3 box cropped the
     sides off every landscape image it held. */
  .rcard{
    position:relative;flex:0 0 auto;
    width:calc(100vw - (var(--gutter) + var(--sa-l)) - (var(--gutter) + var(--sa-r)));
    max-width:420px;height:auto;aspect-ratio:3/2;
    margin:0;transform:none!important;filter:none!important;opacity:1!important;
    scroll-snap-align:center;
    scroll-snap-stop:always;      /* one card per flick, like the desktop wheel lock */
    /* 17 cards each compositing a backdrop blur, behind a full-screen blurred
       scrim, is the heaviest thing on the page and it all lands the moment a
       folder opens. The image covers the card anyway. */
    backdrop-filter:none;-webkit-backdrop-filter:none;
    will-change:auto;
    background:rgba(255,255,255,.07);
    box-shadow:0 14px 30px -18px rgba(0,0,0,.85);
  }
  .ring__scrim{
    /* opacity carries what the smaller blur gives up */
    backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
    background:rgba(2,5,11,.94);
  }

  /* grid view — one full-width column, chosen as the mobile default */
  .ring.is-grid .ring__spin{grid-template-columns:1fr;gap:14px}
  .ring.is-grid .rcard{width:auto;max-width:none;height:auto;aspect-ratio:3/2}
  /* icon-tile and fact cards are type, not image — 3:2 leaves them hollow */
  .ring.is-grid .rcard--fact,
  .ring.is-grid .rcard--doc:not(.has-poster),
  .ring.is-grid .rcard--link:not(.has-poster),
  .ring.is-grid .rcard--embed:not(.has-poster){aspect-ratio:auto;min-height:148px}

  .rlabel{display:none}
  .rcard__cta{opacity:1;transform:none;bottom:auto;top:12px;left:12px;translate:0 0;
              font-size:11px;padding:6px 11px}
  /* the label stays: with grid as the default, the way back to the ring has
     to be readable, and prev/next are hidden so there is room for it */
  .viewtog{padding:8px 12px}
  .ring__tools .iconbtn:not(.iconbtn--close){display:none}
  .ring__count{display:none}
  .ring__bar{gap:12px}
  .ring__meta{display:none}
  /* one scrollable row instead of four wrapped ones — a 17-item folder was
     spending 58px of a 146px foot on rail dots alone */
  .rail{
    flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;
    justify-content:flex-start;
    scrollbar-width:none;-webkit-overflow-scrolling:touch;
    max-width:100%;padding-bottom:2px;
  }
  .rail::-webkit-scrollbar{display:none}
  .rail__dot{width:30px;height:34px;flex:0 0 auto}
  .ring__foot{gap:8px}
  .lb{padding:calc(48px + var(--sa-t)) 12px calc(48px + var(--sa-b))}
}

/* ═══ REDUCED MOTION — every animation resolves to its final state ════ */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important;
  }
  .reveal{opacity:1!important;filter:none!important;transform:none!important}
  .marquee__track{animation:none;transform:none}
  /* Same flat carousel as the phone, and the same two rules it needs: a
     flex row started at flex-start (a centred row wider than its container
     puts the first cards at an offset nothing can scroll back to), and a
     touch-action that permits the axis this thing actually scrolls on. */
  .ring__stage{
    perspective:none;
    display:flex;align-items:center;justify-content:flex-start;
    overflow:auto hidden;
    touch-action:pan-x pinch-zoom;overscroll-behavior:contain;
    padding:10px var(--gutter) 20px;
  }
  .ring.is-grid .ring__stage{touch-action:pan-y pinch-zoom}
  .ring__spin{width:max-content;height:100%;transform:none!important;flex:0 0 auto;
              display:flex;flex-wrap:nowrap;gap:14px;align-items:center;justify-content:flex-start}
  .rcard{position:relative;flex:0 0 auto;width:300px;height:420px;margin:0;
         transform:none!important;filter:none!important;opacity:1!important}
  .rlabel{opacity:1;translate:-50% 0}
  .herofolder,.atmos{animation:none}
  /* the tool names hold their seeded position and opacity, no drift */
  .star{animation:none;translate:-50% -50%;transform:none}
  /* resolve the fan to its finished, spread-out state rather than animating */
  .fanslot{opacity:1;animation:none}
  .fanslot:nth-child(1){transform:translate(-96%,4%)  rotate(-15deg)}
  .fanslot:nth-child(2){transform:translate(-33%,-9%) rotate(-5deg)}
  .fanslot:nth-child(3){transform:translate(33%,-9%)  rotate(5deg)}
  .fanslot:nth-child(4){transform:translate(96%,4%)   rotate(15deg)}
  .fanslot img{transition:none}
  .herofolder__body{animation:none}
}
