/* ==========================================================================
   VAELO — brand guideline inherited from vaelo-agency.html
   Palette, type pairing and motion language are locked. Layout is not.
   ========================================================================== */
:root{
  --black:#0a0a0a; --deep:#030303; --off:#f4f2ec; --dim:#8c887e;
  --accent:#d6ff3f; --line:rgba(244,242,236,0.14); --soft:rgba(244,242,236,0.06);
  --display:'Bricolage Grotesque',ui-sans-serif,system-ui,sans-serif;
  --text:'Archivo',ui-sans-serif,system-ui,-apple-system,sans-serif;
  --pad:5vw;
}
*{margin:0;padding:0;box-sizing:border-box}
/* the script eases scrolling on pointer devices and turns this off; it stays
   for touch, keyboard-only and reduced-motion users */
html{scroll-behavior:smooth}
body{background:var(--black);color:var(--off);font-family:var(--text);font-weight:400;line-height:1.5;
  overflow-x:clip;-webkit-font-smoothing:antialiased}
::selection{background:var(--accent);color:var(--black)}
a{color:inherit;text-decoration:none}
:focus-visible{outline:2px solid var(--accent);outline-offset:4px}
img{max-width:100%;display:block}
h1,h2,h3,.disp{font-family:var(--display);font-weight:700;letter-spacing:-.02em;text-transform:uppercase;text-wrap:balance}
.out{color:transparent;-webkit-text-stroke:1.4px var(--off)}
@media(max-width:700px){.out{-webkit-text-stroke-width:1px}}
.lab{font-size:11px;text-transform:uppercase;letter-spacing:.1em;color:var(--dim)}
.lab.ac{color:var(--accent)}
.tab{font-variant-numeric:tabular-nums}

/* ---------- image slots (stand in for real assets) ---------- */
.slot{position:relative;overflow:hidden;background:#111110;isolation:isolate}
.slot::before{content:'';position:absolute;inset:-14% -4%;
  background:
    radial-gradient(ellipse 60% 50% at 30% 30%,rgba(214,255,63,.10),transparent 60%),
    radial-gradient(ellipse 70% 60% at 75% 70%,rgba(150,150,140,.16),transparent 62%),
    repeating-linear-gradient(135deg,rgba(244,242,236,.035) 0 1px,transparent 1px 11px),
    #121211;
  will-change:transform}
.slot::after{content:attr(data-spec);position:absolute;left:14px;bottom:12px;z-index:2;
  font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--dim)}

/* ---------- page transition wipe ---------- */
.wipe{position:fixed;inset:0;z-index:500;background:var(--accent);transform:scaleY(0);transform-origin:bottom;pointer-events:none}
.wipe.in{transform:scaleY(1);transform-origin:bottom;transition:transform .55s cubic-bezier(.72,0,.16,1)}
.wipe.out{transform:scaleY(0);transform-origin:top;transition:transform .55s cubic-bezier(.72,0,.16,1)}

/* ---------- cursor ---------- */
.cursor{position:fixed;top:0;left:0;width:10px;height:10px;border-radius:50%;background:var(--accent);
  pointer-events:none;z-index:450;mix-blend-mode:difference;transform:translate(-50%,-50%);
  transition:width .28s cubic-bezier(.2,.7,.2,1),height .28s cubic-bezier(.2,.7,.2,1)}
.cursor.big{width:76px;height:76px}
@media(hover:none),(pointer:coarse){.cursor{display:none}}

/* ---------- nav ---------- */
nav.top{position:fixed;top:0;left:0;right:0;z-index:200;display:flex;justify-content:space-between;align-items:center;
  padding:22px var(--pad);mix-blend-mode:difference;transition:background .35s ease,padding .35s ease,backdrop-filter .35s ease}
/* once past the hero the bar takes a ground of its own, so the wordmark
   never has to compete with whatever is scrolling underneath it */
body.scrolled nav.top{mix-blend-mode:normal;background:rgba(6,6,5,.82);backdrop-filter:blur(12px);
  padding-top:15px;padding-bottom:15px;border-bottom:1px solid var(--line)}
.word{font-family:var(--display);font-weight:800;font-size:20px;letter-spacing:-.01em}
.nav-links{display:flex;gap:28px;font-size:12px;text-transform:uppercase;letter-spacing:.05em}
.nav-links a{position:relative;padding-bottom:3px}
.nav-links a::after{content:'';position:absolute;left:0;bottom:0;width:100%;height:1px;background:currentColor;
  transform:scaleX(0);transform-origin:right;transition:transform .4s cubic-bezier(.2,.7,.2,1)}
.nav-links a:hover::after{transform:scaleX(1);transform-origin:left}
.burger{display:none;flex-direction:column;gap:5px;background:none;border:0;cursor:pointer;padding:6px;z-index:210}
.burger i{display:block;width:24px;height:1.5px;background:var(--off);transition:transform .3s,opacity .3s}
body.menu .burger i:nth-child(1){transform:translateY(6.5px) rotate(45deg)}
body.menu .burger i:nth-child(2){opacity:0}
body.menu .burger i:nth-child(3){transform:translateY(-6.5px) rotate(-45deg)}
@media(max-width:820px){
  nav.top{mix-blend-mode:normal}
  .burger{display:flex}
  .nav-links{position:fixed;inset:0;background:var(--deep);flex-direction:column;justify-content:center;gap:22px;
    padding:0 var(--pad);font-family:var(--display);font-weight:700;font-size:clamp(30px,10vw,58px);letter-spacing:-.02em;
    clip-path:inset(0 0 100% 0);transition:clip-path .6s cubic-bezier(.72,0,.16,1);z-index:190}
  body.menu .nav-links{clip-path:inset(0 0 0 0)}
}

/* ---------- hero ---------- */
.hero{position:relative;min-height:100svh;display:flex;flex-direction:column;justify-content:flex-end;
  padding:110px var(--pad) 56px;overflow:hidden;background:var(--deep)}
.hero-media{position:absolute;inset:0;z-index:0}
.hero-media video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  filter:saturate(.72) contrast(1.14) brightness(.66)}
/* Generative backdrop: runs whenever no video file is present, so the hero
   is never a flat black box. Drawn small and blurred up — cheap on mobile. */
#heroCanvas{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  filter:blur(38px) saturate(1.15) contrast(1.06) brightness(.82);transform:scale(1.12)}
.hero-scan{position:absolute;inset:0;z-index:1;pointer-events:none;opacity:.5;
  background:linear-gradient(180deg,transparent 0%,rgba(214,255,63,.05) 46%,transparent 60%);
  animation:scan 13s cubic-bezier(.45,0,.55,1) infinite}
@keyframes scan{0%{transform:translateY(-62%)}100%{transform:translateY(62%)}}
.hero-bars{position:absolute;inset:0;z-index:1;pointer-events:none;opacity:.35;
  background:repeating-linear-gradient(180deg,rgba(0,0,0,.22) 0 1px,transparent 1px 3px)}
.hero-tint{position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(150deg,rgba(6,6,4,.74),rgba(6,6,4,.18) 46%,rgba(6,6,4,.86))}
.hero-vig{position:absolute;inset:0;z-index:1;pointer-events:none;
  background:radial-gradient(ellipse 76% 66% at 50% 54%,transparent 38%,var(--deep) 97%)}
.hero-grain{position:absolute;inset:0;z-index:1;pointer-events:none;opacity:.05;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}
.hero-in{position:relative;z-index:2}
.hero-line{font-size:clamp(13px,1.6vw,17px);color:var(--dim);text-transform:uppercase;letter-spacing:.06em;margin-bottom:20px}
.hero h1{font-size:clamp(38px,9vw,138px);line-height:1.1;max-width:15ch}
.mask{display:block;overflow:hidden}
.mask > i{display:block;font-style:normal;will-change:transform}
.hero-foot{display:flex;justify-content:space-between;align-items:flex-end;gap:24px;flex-wrap:wrap;margin-top:46px}
.hero-sub{font-size:15.5px;color:var(--dim);max-width:38ch;line-height:1.55}
.scroll-cue{display:flex;align-items:center;gap:10px;font-size:11px;text-transform:uppercase;letter-spacing:.09em;color:var(--dim)}
.scroll-cue i{width:1px;height:40px;background:linear-gradient(var(--accent),transparent);display:block;animation:drop 1.9s infinite}
@keyframes drop{0%{transform:scaleY(0);transform-origin:top}48%{transform:scaleY(1);transform-origin:top}
  52%{transform:scaleY(1);transform-origin:bottom}100%{transform:scaleY(0);transform-origin:bottom}}

/* ---------- marquee ---------- */
.marquee{border-top:1px solid var(--line);border-bottom:1px solid var(--line);overflow:hidden;padding:15px 0;background:var(--black)}
.track{display:flex;gap:42px;width:max-content}
.track span{font-family:var(--display);font-weight:800;text-transform:uppercase;font-size:clamp(18px,2.5vw,31px);
  letter-spacing:-.01em;color:var(--dim);display:flex;align-items:center;gap:42px;white-space:nowrap}
.track span::after{content:'';width:7px;height:7px;border-radius:50%;background:var(--accent);flex:none}

/* ---------- section shell ---------- */
.sec{padding:clamp(80px,11vw,150px) var(--pad);border-top:1px solid var(--line);position:relative}
.sec-hd{display:flex;justify-content:space-between;align-items:flex-end;gap:20px;flex-wrap:wrap;margin-bottom:48px}
.sec-hd h2{font-size:clamp(28px,5vw,64px);line-height:.94}

/* ---------- work: horizontal rail ----------
   Wide viewports pin the section and drive the strip with scroll. Narrow
   ones get a native horizontal scroller with snap points — swipeable, and
   still unmistakably sideways. The work never stacks into a column. */
.rail-head{display:flex;justify-content:space-between;align-items:flex-end;gap:20px;flex-wrap:wrap;
  padding:clamp(80px,11vw,150px) var(--pad) 0}
.rail-head h2{font-size:clamp(28px,5vw,64px);line-height:.94}
.prog{height:1px;background:var(--line);margin:30px var(--pad) 0;position:relative}
.prog i{position:absolute;left:0;top:-1px;height:3px;background:var(--accent);width:5%;display:block}
.rail-wrap{position:relative}
.rail-stick{position:sticky;top:0;height:100svh;display:flex;align-items:center;overflow:hidden}
.rail{display:flex;gap:clamp(14px,2vw,28px);padding:0 var(--pad);will-change:transform}
.tile{flex:none;display:block;width:min(56vw,700px)}
.tile.tall{width:min(33vw,400px)}
.tile .frame{position:relative;overflow:hidden;aspect-ratio:4/3;border-radius:18px}
.tile.tall .frame{aspect-ratio:3/4}
/* Every card in a row needs to be the same height to read as organized -
   that matters more here than showing a creative uncropped, so this stays
   a fixed box with object-fit:cover (biased toward the top, where a face
   or headline usually sits, rather than dead centre). The per-project case
   page is where the full, uncropped creative gets shown. */
.tile .slot{position:absolute;inset:0}
.tile .slot::before{transition:transform .9s cubic-bezier(.2,.7,.2,1)}
.tile:hover .slot::before{transform:scale(1.07)}
.tile .veil{position:absolute;inset:0;z-index:1;background:var(--black);opacity:.42;transition:opacity .5s}
.tile:hover .veil{opacity:.14}
.tile .go{position:absolute;right:16px;top:16px;z-index:2;width:44px;height:44px;border:1px solid var(--off);
  border-radius:50%;display:flex;align-items:center;justify-content:center;background:rgba(10,10,10,.3);
  transition:background .35s,color .35s,border-color .35s,transform .35s}
.tile:hover .go{background:var(--accent);color:var(--black);border-color:var(--accent);transform:rotate(45deg)}
.tile .meta{display:flex;justify-content:space-between;align-items:flex-end;gap:16px;padding:15px 2px 0}
.tile .meta h3{font-size:clamp(17px,2vw,28px);transition:color .3s;margin-bottom:10px}
.tile:hover .meta h3{color:var(--accent)}
.tile .idx{font-family:var(--display);font-weight:800;font-size:12px;color:var(--dim);font-variant-numeric:tabular-nums}
.tags{display:flex;flex-wrap:wrap;gap:7px}
.pill{font-size:10px;text-transform:uppercase;letter-spacing:.07em;color:var(--dim);
  border:1px solid var(--line);border-radius:999px;padding:4px 11px;white-space:nowrap;
  transition:color .3s,border-color .3s}
.tile:hover .pill,.arch-item:hover .pill{color:var(--off);border-color:rgba(244,242,236,.3)}

/* narrow: swipeable strip, no pinning */
@media(max-width:720px){
  .rail-wrap{height:auto!important}
  .rail-stick{position:static;height:auto;overflow-x:auto;overflow-y:hidden;padding:36px 0 10px;
    scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;scrollbar-width:none}
  .rail-stick::-webkit-scrollbar{display:none}
  .rail{transform:none!important;padding-right:calc(var(--pad) + 40px)}
  .tile{width:78vw;scroll-snap-align:center}
  .tile.tall{width:64vw}
  .tile .frame,.tile.tall .frame{aspect-ratio:4/3}
}
.swipe-hint{display:none;padding:12px var(--pad) 0;font-size:10.5px;text-transform:uppercase;
  letter-spacing:.1em;color:var(--dim)}
@media(max-width:720px){.swipe-hint{display:block}}

/* ---------- services: cards ---------- */
.svc-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line);border:1px solid var(--line)}
@media(max-width:900px){.svc-grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:600px){.svc-grid{grid-template-columns:1fr}}
.svc-card{display:flex;flex-direction:column;background:var(--black);padding:clamp(24px,2.6vw,34px);
  transition:background .3s}
.svc-card:hover{background:#0f0f0e}
.svc-card .no{font-size:11px;color:var(--dim);letter-spacing:.06em;font-variant-numeric:tabular-nums}
.svc-card .name{font-family:var(--display);font-weight:600;text-transform:uppercase;letter-spacing:-.01em;
  font-size:clamp(19px,2.2vw,25px);margin:14px 0 12px;transition:color .3s}
.svc-card:hover .name{color:var(--accent)}
.svc-card p{font-size:14px;color:var(--dim);line-height:1.6;margin-bottom:16px}
.svc-card ul{list-style:none;display:flex;flex-direction:column;gap:8px;font-size:13px;color:var(--dim);
  margin-bottom:24px}
.svc-card li{padding-left:16px;position:relative}
.svc-card li::before{content:'';position:absolute;left:0;top:9px;width:6px;height:1px;background:var(--accent)}
.svc-card .more{margin-top:auto;display:inline-flex;align-items:center;gap:8px;font-size:12.5px;
  text-transform:uppercase;letter-spacing:.07em;color:var(--off);transition:gap .3s,color .3s}
.svc-card:hover .more{gap:12px;color:var(--accent)}
.svc-card .more .arrow{font-style:normal;transition:transform .35s cubic-bezier(.2,.7,.2,1)}
.svc-card:hover .more .arrow{transform:translate(3px,-3px)}

/* ---------- process ---------- */
.steps{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--soft);border:1px solid var(--line)}
@media(max-width:800px){.steps{grid-template-columns:repeat(2,1fr)}}
@media(max-width:480px){.steps{grid-template-columns:1fr}}
.steps > div{background:var(--black);padding:26px 22px;display:flex;flex-direction:column;gap:9px;min-height:195px}
.steps .n{font-family:var(--display);font-weight:800;font-size:13px;color:var(--accent);font-variant-numeric:tabular-nums}
.steps h3{font-size:16px}
.steps p{font-size:13px;color:var(--dim)}

/* ---------- statement ---------- */
.statement h2{font-size:clamp(26px,5vw,66px);line-height:1.08;text-transform:none;max-width:19ch}
.statement .w{color:#3a3934;transition:color .5s ease}
.statement .w.on{color:var(--off)}
.statement .em{color:var(--accent)}

/* ---------- capabilities ---------- */
.grid6{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--soft);border:1px solid var(--line)}
@media(max-width:900px){.grid6{grid-template-columns:repeat(2,1fr)}}
@media(max-width:560px){.grid6{grid-template-columns:1fr}}
.cell{background:var(--black);padding:26px 22px;display:flex;flex-direction:column;gap:10px;min-height:215px;transition:background .35s}
.cell:hover{background:#131312}
.cell h3{font-size:16px}
.cell p{font-size:13px;color:var(--dim)}
.cell ul{list-style:none;display:flex;flex-direction:column;gap:6px;margin-top:auto;font-size:11.5px;color:var(--dim)}
.cell li{padding-left:14px;position:relative}
.cell li::before{content:'';position:absolute;left:0;top:8px;width:5px;height:1px;background:var(--accent)}

/* ---------- counters ---------- */
.strip{display:flex;flex-wrap:wrap;gap:1px;background:var(--soft);border-block:1px solid var(--line)}
.strip div{background:var(--black);padding:24px clamp(20px,3vw,40px);flex:1 1 180px}
.strip .n{font-family:var(--display);font-weight:800;font-size:clamp(26px,3.4vw,40px);font-variant-numeric:tabular-nums}
.strip .n em{font-style:normal;color:var(--accent)}
.strip .l{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--dim);margin-top:6px}

/* ---------- contact ---------- */
.end{text-align:center;border-top:1px solid var(--line);padding:clamp(80px,12vw,160px) var(--pad)}
.end h2{font-size:clamp(38px,9vw,138px);line-height:.88}
.mail{display:inline-flex;align-items:center;gap:12px;margin-top:36px;font-family:var(--display);font-weight:700;
  font-size:clamp(17px,2.6vw,30px);border-bottom:1px solid var(--line);padding-bottom:8px;transition:color .3s,border-color .3s}
.mail:hover{color:var(--accent);border-color:var(--accent)}
.cbits{display:flex;justify-content:center;gap:clamp(20px,5vw,60px);flex-wrap:wrap;margin-top:46px}
.cbits div{display:flex;flex-direction:column;gap:5px}
.cbits b{font-weight:500;font-size:14px}
footer{border-top:1px solid var(--line);padding:26px var(--pad);display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap;
  font-size:10.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--dim)}

/* ---------- converge: scattered work drifts to centre, then washes out ---
   Pinned like the rail, but reads scroll as a single 0-1 progress value
   (set as --p by script) rather than a horizontal position. Each card
   starts wherever --tx/--ty/--rot place it and eases to dead centre as
   --p approaches 1; the wash behind it fades in on the same progress. */
.converge{position:relative;height:220vh;background:var(--black)}
.converge-stick{position:sticky;top:0;height:100svh;overflow:hidden}
.conv-item{position:absolute;top:50%;left:50%;width:min(20vw,210px);aspect-ratio:4/5;
  border-radius:20px;overflow:hidden;box-shadow:0 40px 80px rgba(0,0,0,.55);
  transform:translate(-50%,-50%) translate(calc(var(--tx) * 1vw),calc(var(--ty) * 1vh))
    scale(1) rotate(calc(var(--rot) * 1deg))}
.conv-item img{width:100%;height:100%;object-fit:cover;display:block;filter:grayscale(.3) contrast(1.04)}
.conv-wash{position:absolute;inset:0;z-index:2;pointer-events:none;opacity:0;
  background:linear-gradient(180deg,var(--black) 0%,var(--black) 45%,#0d2740 72%,var(--off) 100%)}
@media(max-width:720px){.conv-item{width:34vw}}
@media(prefers-reduced-motion:reduce){.converge{display:none}}

/* ==========================================================================
   CASE STUDY PAGE
   ========================================================================== */
.case-hero{position:relative;min-height:82svh;display:flex;align-items:flex-end;padding:130px var(--pad) 52px;overflow:hidden;background:var(--deep)}
.case-hero .slot{position:absolute;inset:0;z-index:0}
.case-hero .tint{position:absolute;inset:0;z-index:1;background:linear-gradient(180deg,rgba(4,4,4,.6),rgba(4,4,4,.2) 40%,rgba(4,4,4,.9))}
.case-hero .in{position:relative;z-index:2;width:100%}
.case-hero h1{font-size:clamp(34px,7.4vw,116px);line-height:.88;max-width:16ch}
.crumb{display:flex;gap:10px;align-items:center;font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--dim);margin-bottom:18px}
.crumb a:hover{color:var(--accent)}
.facts{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--soft);border-block:1px solid var(--line)}
@media(max-width:760px){.facts{grid-template-columns:repeat(2,1fr)}}
.facts div{background:var(--black);padding:22px clamp(18px,2.6vw,32px)}
.facts b{display:block;font-size:15px;font-weight:500;margin-top:7px}
.case-body{padding:clamp(70px,10vw,130px) var(--pad);display:grid;grid-template-columns:minmax(180px,26%) 1fr;
  gap:clamp(22px,5vw,70px);align-items:start}
@media(max-width:860px){.case-body{grid-template-columns:1fr;gap:20px}}
.case-body .stick{position:sticky;top:100px}
@media(max-width:860px){.case-body .stick{position:static}}
.case-body h2{font-size:clamp(22px,3vw,36px);line-height:1.05}
.prose{display:flex;flex-direction:column;gap:20px;font-size:16px;color:var(--dim);max-width:64ch}
.prose b{color:var(--off);font-weight:500}
.gal{padding:0 var(--pad) clamp(60px,9vw,120px);display:grid;grid-template-columns:repeat(12,1fr);gap:clamp(12px,2vw,26px)}
.gal .slot{width:100%}
.g-full{grid-column:1/13;aspect-ratio:16/9}
.g-half{grid-column:span 6;aspect-ratio:4/5}
.g-third{grid-column:span 4;aspect-ratio:1}
@media(max-width:760px){.g-full,.g-half,.g-third{grid-column:1/13;aspect-ratio:4/3}}
.kpis{display:flex;flex-wrap:wrap;gap:1px;background:var(--soft);border-block:1px solid var(--line)}
.kpis div{background:var(--black);padding:28px clamp(20px,3vw,40px);flex:1 1 200px}
.kpis .v{font-family:var(--display);font-weight:800;font-size:clamp(28px,4.2vw,52px);color:var(--accent);font-variant-numeric:tabular-nums}
.kpis .l{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--dim);margin-top:8px}
.next{border-top:1px solid var(--line);padding:clamp(60px,9vw,120px) var(--pad);display:block;position:relative;overflow:hidden}
.next .lab{margin-bottom:14px}
.next h2{font-size:clamp(30px,7vw,96px);line-height:.9;transition:color .35s}
.next:hover h2{color:var(--accent)}
.next .arrow{position:absolute;right:var(--pad);bottom:clamp(60px,9vw,120px);font-size:clamp(28px,5vw,64px);
  transition:transform .45s cubic-bezier(.2,.7,.2,1)}
.next:hover .arrow{transform:translate(14px,-14px)}

/* ---------- reveal system ----------
   Gated on html.js: with scripting off nothing is ever hidden. The motion
   itself is native — IntersectionObserver adds .in, CSS does the rest. */
.js [data-rev]{opacity:0;transform:translateY(26px);
  transition:opacity .85s cubic-bezier(.2,.75,.2,1),transform .85s cubic-bezier(.2,.75,.2,1)}
.js [data-rev].in{opacity:1;transform:none}
.js [data-rev][data-stagger] > *{opacity:0;transform:translateY(22px);
  transition:opacity .7s cubic-bezier(.2,.75,.2,1),transform .7s cubic-bezier(.2,.75,.2,1)}
.js [data-rev][data-stagger] > *.in{opacity:1;transform:none}
.js [data-rev="left"]{transform:translateX(-30px)}
.js [data-rev="scale"]{transform:scale(.95);transform-origin:left bottom}
.js [data-rev="rise"]{transform:translateY(46px)}

/* parallax: JS sets --py, CSS moves it */
[data-par]{--py:0%}
[data-par] .slot::before,.slot[data-par]::before{transform:translateY(var(--py))}

/* hero masked lines run on a class, not a library */
.js .mask > i{transform:translateY(108%)}
.js body.lit .mask > i,.js.no-motion .mask > i{transform:none;
  transition:transform 1.05s cubic-bezier(.2,.75,.2,1)}
.js .mask:nth-of-type(2) > i{transition-delay:.09s}
.js .mask:nth-of-type(3) > i{transition-delay:.18s}
.js .hero-line,.js .hero-foot,.js .crumb,.js .case-hero .facts{opacity:0;transition:opacity .9s ease}
.js body.lit .hero-line,.js body.lit .crumb{opacity:1;transition-delay:.35s}
.js body.lit .hero-foot,.js body.lit .case-hero .facts{opacity:1;transition-delay:.9s}
@media(prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important}
  .rev{transform:none}.tile .frame{clip-path:none!important}.mask > i{transform:none!important}
}

/* ==========================================================================
   WORK ARCHIVE (/work/)
   ========================================================================== */
.arch-hd{padding:130px var(--pad) 0}
.arch-hd h1{font-size:clamp(36px,8vw,120px);line-height:.88}
.tabs{display:flex;gap:8px;flex-wrap:wrap;padding:34px var(--pad) 0;border-bottom:1px solid var(--line);
  margin-bottom:clamp(30px,5vw,60px);padding-bottom:22px}
.tab-btn{font:inherit;font-size:11.5px;text-transform:uppercase;letter-spacing:.07em;color:var(--dim);
  background:none;border:1px solid var(--line);border-radius:999px;padding:8px 16px;cursor:pointer;
  transition:color .25s,border-color .25s,background .25s}
.tab-btn:hover{color:var(--off);border-color:var(--off)}
.tab-btn.on{background:var(--accent);border-color:var(--accent);color:var(--black);font-weight:600}
.tab-btn .c{font-variant-numeric:tabular-nums;opacity:.6;margin-left:6px}
.arch{padding:0 var(--pad) clamp(70px,10vw,130px);display:grid;grid-template-columns:repeat(2,1fr);
  gap:clamp(20px,3vw,44px)}
@media(max-width:760px){.arch{grid-template-columns:1fr}}
.arch-item{display:block}
.arch-item .frame{position:relative;overflow:hidden;aspect-ratio:4/3;border-radius:18px}
.arch-item .slot{position:absolute;inset:0}
.arch-item .slot::before{transition:transform .9s cubic-bezier(.2,.7,.2,1)}
.arch-item:hover .slot::before{transform:scale(1.06)}
.arch-item .veil{position:absolute;inset:0;z-index:1;background:var(--black);opacity:.4;transition:opacity .45s}
.arch-item:hover .veil{opacity:.14}
.arch-item .go{position:absolute;right:14px;top:14px;z-index:2;width:40px;height:40px;border:1px solid var(--off);
  border-radius:50%;display:flex;align-items:center;justify-content:center;background:rgba(10,10,10,.3);
  transition:background .3s,color .3s,border-color .3s,transform .3s}
.arch-item:hover .go{background:var(--accent);color:var(--black);border-color:var(--accent);transform:rotate(45deg)}
.arch-item .meta{display:flex;justify-content:space-between;align-items:flex-end;gap:14px;padding:14px 2px 0}
.arch-item h3{font-size:clamp(18px,2.2vw,30px);transition:color .3s;margin-bottom:10px}
.arch-item:hover h3{color:var(--accent)}
.arch-item .sum{font-size:13px;color:var(--dim);margin-top:8px;max-width:46ch}

/* ---------- blog (/blog/) ---------- */
.post-list{padding:0 var(--pad) clamp(70px,10vw,130px);display:grid;
  grid-template-columns:repeat(2,1fr);gap:clamp(20px,3vw,44px)}
@media(max-width:760px){.post-list{grid-template-columns:1fr}}
.post-card{display:block;border:1px solid var(--line);border-radius:18px;
  padding:clamp(24px,2.6vw,34px);transition:border-color .3s,background .3s}
.post-card:hover{border-color:rgba(244,242,236,.3);background:#0f0f0e}
.post-meta{display:flex;justify-content:space-between;font-size:11px;text-transform:uppercase;
  letter-spacing:.07em;color:var(--dim);margin-bottom:14px}
.post-meta .tag{color:var(--accent)}
.post-card h2{font-size:clamp(20px,2.4vw,28px);margin-bottom:12px;transition:color .3s}
.post-card:hover h2{color:var(--accent)}
.post-card p{font-size:14px;color:var(--dim);line-height:1.6;margin-bottom:20px}
.post-card .more{display:inline-flex;align-items:center;gap:8px;font-size:12.5px;
  text-transform:uppercase;letter-spacing:.07em;color:var(--off);transition:gap .3s,color .3s}
.post-card:hover .more{gap:12px;color:var(--accent)}
.post-card .more .arrow{font-style:normal;transition:transform .35s cubic-bezier(.2,.7,.2,1)}
.post-card:hover .more .arrow{transform:translate(3px,-3px)}
.arch-item .yr{font-family:var(--display);font-weight:800;font-size:12px;color:var(--dim);font-variant-numeric:tabular-nums}


/* ---------- reduced motion: everything resolves, nothing moves ---------- */
@media(prefers-reduced-motion:reduce){
  .js [data-rev],.js [data-rev][data-stagger] > *{opacity:1!important;transform:none!important}
  .js .mask > i{transform:none!important}
  .js .hero-line,.js .hero-foot,.js .crumb,.js .case-hero .facts{opacity:1!important}
}

/* ==========================================================================
   ORNAMENT — the layer that makes it feel made, not assembled
   ========================================================================== */

/* scroll progress, hairline across the top of the page */
.sprog{position:fixed;top:0;left:0;height:2px;width:0;background:var(--accent);z-index:250;
  box-shadow:0 0 14px rgba(214,255,63,.5);pointer-events:none}

/* the cursor speaks when it is over something openable */
.cursor{display:flex;align-items:center;justify-content:center}
.cursor .cur-label{font-family:var(--display);font-weight:800;font-size:10.5px;letter-spacing:.06em;
  color:var(--black);opacity:0;transform:scale(.6);transition:opacity .2s,transform .25s;white-space:nowrap}
.cursor.view .cur-label{opacity:1;transform:scale(1)}
.cursor.view{width:82px;height:82px;mix-blend-mode:normal}

/* rail tiles gain depth as they pass the middle of the screen */
.tile{--depth:1;--lift:0px}
.tile .frame{transform:scale(var(--depth)) translateY(var(--lift));
  transition:transform .5s cubic-bezier(.2,.7,.2,1)}

/* eyebrow labels decode themselves on reveal */
.lab.ac{font-variant-ligatures:none}

/* the wordmark, set enormous, filling with accent as the page ends */
.endmark{position:relative;border-top:1px solid var(--line);
  padding:clamp(34px,5vw,64px) var(--pad) clamp(26px,4vw,52px);text-align:center;line-height:1}
.endmark span{font-family:var(--display);font-weight:800;text-transform:uppercase;
  font-size:clamp(64px,20vw,300px);line-height:.92;letter-spacing:-.03em;display:block;
  padding-bottom:.06em;                      /* room for the baseline, never clipped */
  color:transparent;-webkit-text-stroke:1px rgba(244,242,236,.22);
  background:linear-gradient(90deg,var(--accent) var(--fill,0%),rgba(244,242,236,0) var(--fill,0%));
  -webkit-background-clip:text;background-clip:text}

/* buttons lean toward the pointer */
.magnet{transition:transform .35s cubic-bezier(.2,.7,.2,1)}

/* a hairline that draws itself under every section heading */
.sec-hd,.rail-head{position:relative}
.sec-hd::after,.rail-head::after{content:'';position:absolute;left:0;bottom:-18px;height:1px;width:100%;
  background:var(--line);transform:scaleX(0);transform-origin:left;transition:transform 1.1s cubic-bezier(.2,.75,.2,1)}
.sec-hd.in::after,.rail-head.in::after{transform:scaleX(1)}

@media(prefers-reduced-motion:reduce){
  .sec-hd::after,.rail-head::after{transform:scaleX(1)}
  .tile .frame{transform:none!important}
  .cursor{display:none}
}

/* ==========================================================================
   SECOND MOTION PASS — the parts whose markup exists today
   ========================================================================== */

/* gallery images wipe open on case pages */
.js .gal .slot{clip-path:inset(0 0 100% 0);transition:clip-path 1.1s cubic-bezier(.72,0,.16,1)}
.js .gal.in .slot{clip-path:inset(0 0 0 0)}
.js .gal .slot:nth-child(2){transition-delay:.1s}
.js .gal .slot:nth-child(3){transition-delay:.2s}
.js .gal .slot:nth-child(4){transition-delay:.3s}

/* the mail link sweeps rather than simply changing colour */
.mail{position:relative;overflow:hidden}
.mail::after{content:'';position:absolute;left:0;bottom:0;height:1px;width:100%;background:var(--accent);
  transform:scaleX(0);transform-origin:right;transition:transform .5s cubic-bezier(.2,.7,.2,1)}
.mail:hover::after{transform:scaleX(1);transform-origin:left}

@media(prefers-reduced-motion:reduce){
  .js .gal .slot{clip-path:none!important}
}

/* ==========================================================================
   OPENING CURTAIN + RAIL LEAN
   ========================================================================== */

/* The curtain is built by script, so a page without JS never sees one and is
   never left sitting behind a cover that cannot lift. */
.curtain{position:fixed;inset:0;z-index:600;background:var(--deep);overflow:hidden;
  display:flex;flex-direction:column;justify-content:flex-end;padding:var(--pad);
  transition:clip-path 1.05s cubic-bezier(.72,0,.16,1)}
.curtain.up{clip-path:inset(0 0 100% 0)}
.curtain::after{content:'';position:absolute;inset:0;pointer-events:none;opacity:.05;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")}
.curtain .c-bar{height:1px;background:var(--line);margin-bottom:26px;position:relative}
.curtain .c-bar i{position:absolute;left:0;top:-1px;display:block;height:3px;width:0;background:var(--accent);
  transition:width .25s linear}
.curtain .c-row{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;flex-wrap:wrap}
.curtain .c-word{font-family:var(--display);font-weight:800;text-transform:uppercase;
  font-size:clamp(44px,11vw,150px);letter-spacing:-.03em;line-height:.78;overflow:hidden}
.curtain .c-word i{display:block;font-style:normal;transform:translateY(106%);
  animation:c-rise .95s .05s cubic-bezier(.2,.75,.2,1) forwards}
@keyframes c-rise{to{transform:translateY(0)}}
.curtain .c-num{font-family:var(--display);font-weight:800;font-size:clamp(30px,5vw,68px);
  color:var(--accent);font-variant-numeric:tabular-nums;line-height:1}
.curtain .c-sub{font-size:11px;text-transform:uppercase;letter-spacing:.12em;color:var(--dim);
  margin-bottom:14px}

/* The rail leans into the distance it still has to travel — the lag itself
   drives the lean, so it flexes on a flick and stands up as it settles. */
.rail{transform-origin:center center}

@media(prefers-reduced-motion:reduce){.curtain{display:none}}

/* ==========================================================================
   THIRD MOTION PASS
   ========================================================================== */

/* hero headline arrives letter by letter, each on its own delay */
.js .mask > i .wgrp{display:inline-block}
.js .mask > i b{display:inline-block;font-weight:inherit;transform:translateY(106%);
  transition:transform .85s cubic-bezier(.2,.75,.2,1);transition-delay:calc(var(--i) * 26ms)}
.js body.lit .mask > i b{transform:none}
.js .mask > i b.sp{width:.28em}

/* the hero block drifts and dims as it leaves */
.hero-in{will-change:transform,opacity}

.rail{position:relative;z-index:1}

/* tile titles shuffle their letters on approach */
.tile .meta h3{font-variant-ligatures:none}

@media(prefers-reduced-motion:reduce){
  .js .mask > i b{transform:none!important}
  .hero-in{transform:none!important;opacity:1!important}
}

/* ==========================================================================
   REAL MEDIA — takes over the placeholder frames once images are imported
   ========================================================================== */
.shot{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;
  background:#111110;transform:translateY(var(--py,0))}
.tile .shot,.arch-item .shot{transition:transform .9s cubic-bezier(.2,.7,.2,1),filter .6s ease;
  filter:grayscale(.45) contrast(1.04);object-position:center 22%}
.tile:hover .shot,.arch-item:hover .shot{transform:scale(1.06);filter:grayscale(0) contrast(1.08)}
.case-hero .shot{filter:saturate(.85) contrast(1.06) brightness(.7)}
.gal .shot{position:relative;inset:auto;height:auto}
/* Real media keeps the template's column widths but sizes to its own height
   instead of the template's fixed ratio - a figure with overflow:hidden and
   an aspect-ratio still crops an auto-height image to that ratio, so the
   ratio has to go, not just the image's own sizing. */
.gal figure{position:relative;margin:0}
.gal figure.g-full{grid-column:1/13}
.gal figure.g-half{grid-column:span 6}
.gal figure.g-third{grid-column:span 4}
@media(max-width:760px){.gal figure.g-full,.gal figure.g-half,.gal figure.g-third{grid-column:1/13}}
.js .gal figure{clip-path:inset(0 0 100% 0);transition:clip-path 1.1s cubic-bezier(.72,0,.16,1)}
.js .gal.in figure{clip-path:inset(0 0 0 0)}

/* ==========================================================================
   FOURTH MOTION PASS — tactility
   ========================================================================== */

/* tiles tilt toward the pointer, on a real 3D plane */
.rail,.work,.arch{perspective:1400px}
.tile .frame,.arch-item .frame{transform-style:preserve-3d;
  transition:transform .5s cubic-bezier(.2,.7,.2,1)}
.tile.tilt .frame,.arch-item.tilt .frame{transition:transform .12s linear}

/* the rail can be grabbed and thrown */
.rail-stick{cursor:grab}
.rail-stick.dragging{cursor:grabbing}
.rail-stick.dragging .tile .frame{transition:none}

/* scrambling titles keep their box while the glyphs churn */
.tile .meta h3,.arch-item h3{font-variant-numeric:tabular-nums}

@media(prefers-reduced-motion:reduce){
  .tile .frame,.arch-item .frame{transform:none!important}
}
