:root{--head-zoom:1;--accent:#2B44FF;--on:#F2F1EC;--ink:#0E0E0E;--paper:#ECEBE6;
--fs-hero:clamp(38px,4.8vw,76px);--fs-section:clamp(38px,5vw,72px);--fs-contact:clamp(44px,7.4vw,116px);--fs-title:clamp(30px,3vw,44px);--fs-metric:clamp(44px,3.9vw,56px);--fs-body:18px;
--intro-roll:2.2s;--intro-turn-start:0s;--intro-turn:2.8s;--intro-door-start:0s;--intro-door:2.8s;--intro-cue:2.8s} /* keep in sync with INTRO_TIMING in main.js */
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;text-size-adjust:100%}
/* white arrow, hotspot on its tip; 32px is the largest size Chrome keeps showing at the window edges */
html{-webkit-user-select:none;user-select:none}
input{-webkit-user-select:text;user-select:text}
html{cursor:url(../assets/cursor.png) 10 9,auto;cursor:-webkit-image-set(url(../assets/cursor.png) 1x,url(../assets/cursor@2x.png) 2x) 10 9,auto;cursor:image-set(url(../assets/cursor.png) 1x,url(../assets/cursor@2x.png) 2x) 10 9,auto}
a,button,label{cursor:url(../assets/cursor-hand.png) 17 8,pointer;cursor:-webkit-image-set(url(../assets/cursor-hand.png) 1x,url(../assets/cursor-hand@2x.png) 2x) 17 8,pointer;cursor:image-set(url(../assets/cursor-hand.png) 1x,url(../assets/cursor-hand@2x.png) 2x) 17 8,pointer}
/* the finger pushes forward on a click: two frames, shrinking toward its tip */
.press-1 a,.press-1 button,.press-1 label{cursor:url(../assets/cursor-hand-press-1.png) 17 8,pointer;cursor:-webkit-image-set(url(../assets/cursor-hand-press-1.png) 1x,url(../assets/cursor-hand-press-1@2x.png) 2x) 17 8,pointer;cursor:image-set(url(../assets/cursor-hand-press-1.png) 1x,url(../assets/cursor-hand-press-1@2x.png) 2x) 17 8,pointer}
.press-2 a,.press-2 button,.press-2 label{cursor:url(../assets/cursor-hand-press-2.png) 17 8,pointer;cursor:-webkit-image-set(url(../assets/cursor-hand-press-2.png) 1x,url(../assets/cursor-hand-press-2@2x.png) 2x) 17 8,pointer;cursor:image-set(url(../assets/cursor-hand-press-2.png) 1x,url(../assets/cursor-hand-press-2@2x.png) 2x) 17 8,pointer}
/* the rest of the set, same drawing rules: put these classes and attributes on whatever needs them */
input,textarea{cursor:url(../assets/cursor-text.png) 22 22,text;cursor:-webkit-image-set(url(../assets/cursor-text.png) 1x,url(../assets/cursor-text@2x.png) 2x) 22 22,text;cursor:image-set(url(../assets/cursor-text.png) 1x,url(../assets/cursor-text@2x.png) 2x) 22 22,text}
:disabled,[aria-disabled="true"]{cursor:url(../assets/cursor-not-allowed.png) 22 22,not-allowed;cursor:-webkit-image-set(url(../assets/cursor-not-allowed.png) 1x,url(../assets/cursor-not-allowed@2x.png) 2x) 22 22,not-allowed;cursor:image-set(url(../assets/cursor-not-allowed.png) 1x,url(../assets/cursor-not-allowed@2x.png) 2x) 22 22,not-allowed}
[aria-busy="true"]{cursor:url(../assets/cursor-wait.png) 22 22,wait;cursor:-webkit-image-set(url(../assets/cursor-wait.png) 1x,url(../assets/cursor-wait@2x.png) 2x) 22 22,wait;cursor:image-set(url(../assets/cursor-wait.png) 1x,url(../assets/cursor-wait@2x.png) 2x) 22 22,wait}
.cursor-zoom{cursor:url(../assets/cursor-zoom.png) 20 20,zoom-in;cursor:-webkit-image-set(url(../assets/cursor-zoom.png) 1x,url(../assets/cursor-zoom@2x.png) 2x) 20 20,zoom-in;cursor:image-set(url(../assets/cursor-zoom.png) 1x,url(../assets/cursor-zoom@2x.png) 2x) 20 20,zoom-in}
.cursor-grab{cursor:url(../assets/cursor-grab.png) 24 26,grab;cursor:-webkit-image-set(url(../assets/cursor-grab.png) 1x,url(../assets/cursor-grab@2x.png) 2x) 24 26,grab;cursor:image-set(url(../assets/cursor-grab.png) 1x,url(../assets/cursor-grab@2x.png) 2x) 24 26,grab}
.cursor-grab:active{cursor:url(../assets/cursor-grabbing.png) 24 26,grabbing;cursor:-webkit-image-set(url(../assets/cursor-grabbing.png) 1x,url(../assets/cursor-grabbing@2x.png) 2x) 24 26,grabbing;cursor:image-set(url(../assets/cursor-grabbing.png) 1x,url(../assets/cursor-grabbing@2x.png) 2x) 24 26,grabbing}
/* over the head the arrow gives way to an open palm that main.js moves, tips and swings, from its heel */
/* over what can be slapped the cursor is an open palm; on a click it turns 45°, in two frames like the finger */
.over-head,.over-head *{cursor:url(../assets/cursor-palm.png) 32 38,pointer;cursor:-webkit-image-set(url(../assets/cursor-palm.png) 1x,url(../assets/cursor-palm@2x.png) 2x) 32 38,pointer;cursor:image-set(url(../assets/cursor-palm.png) 1x,url(../assets/cursor-palm@2x.png) 2x) 32 38,pointer}
.palm-press-1.over-head,.palm-press-1.over-head *{cursor:url(../assets/cursor-palm-hit-1.png) 32 38,pointer;cursor:-webkit-image-set(url(../assets/cursor-palm-hit-1.png) 1x,url(../assets/cursor-palm-hit-1@2x.png) 2x) 32 38,pointer;cursor:image-set(url(../assets/cursor-palm-hit-1.png) 1x,url(../assets/cursor-palm-hit-1@2x.png) 2x) 32 38,pointer}
.palm-press-2.over-head,.palm-press-2.over-head *{cursor:url(../assets/cursor-palm-hit-2.png) 32 38,pointer;cursor:-webkit-image-set(url(../assets/cursor-palm-hit-2.png) 1x,url(../assets/cursor-palm-hit-2@2x.png) 2x) 32 38,pointer;cursor:image-set(url(../assets/cursor-palm-hit-2.png) 1x,url(../assets/cursor-palm-hit-2@2x.png) 2x) 32 38,pointer}
body{margin:0;font-kerning:normal;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}
h1,h2,h3{text-wrap:balance}
p{text-wrap:pretty}
::selection{background:var(--ink);color:var(--paper)}
a{color:var(--ink)}
.page{width:100%;min-height:100vh;background-color:var(--paper);color:var(--ink);font-family:'Outfit','Geist Mono',system-ui,sans-serif;font-size:var(--fs-body);line-height:1.5;overflow-x:clip}
.tex{background-image:url(../assets/texture.png);background-size:240px 240px;background-repeat:repeat}
.meta{font-size:15px;line-height:1.4}
[data-time]{font-variant-numeric:tabular-nums}
.dim{opacity:.6}
.accent{color:var(--accent)}
.g12{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));column-gap:24px;padding-inline:40px}
.span-all{grid-column:1/-1}

/* ---------- PASSWORD GATE ---------- */
/* Floats over the still empty hero, leaves together with the head's roll-in (same curve) */
.gate{display:none;position:fixed;inset:0;z-index:100;align-items:center;justify-content:center;padding:16px;color:var(--on);font-family:'Outfit','Geist Mono',system-ui,sans-serif}
.gated .gate{display:flex}
html{background-color:var(--paper)}
html.gated,html.intro-lock{background-color:#2640DE;background-color:color-mix(in srgb,var(--accent) 86%,#0E0E0E);overflow:hidden}
.gated:not(.gate-leave) .page>:not(.hero){visibility:hidden}
/* the password screen always fills the window: a shorter hero's paper block rises into place with the intro */
/* the same blue as the hero under its ground shadow, so no seam shows where the hero ends */
.gated .page{background-color:#2640DE;background-color:color-mix(in srgb,var(--accent) 86%,#0E0E0E)}
.gated .work{transform:translateY(100vh)}
.gate-leave .work{transform:none;transition:transform 1.1s cubic-bezier(.16,.84,.3,1)}
.gate-form{display:flex;flex-direction:column;gap:12px;width:min(320px,100%)}
.gate-leave .gate{pointer-events:none}
.gate-row{display:flex;align-items:center;border-bottom:3px solid var(--on)}
.gate-row input{flex:1;min-width:0;height:64px;padding:0;background:none;border:0;outline:0;color:inherit;font:600 40px/1 'Outfit',system-ui,sans-serif;letter-spacing:.2em}
.gate-row button{flex:none;display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;padding:0;background:none;border:0;color:inherit;opacity:.88;transition:transform .3s cubic-bezier(.2,.8,.2,1),opacity .2s}
.icon-go{display:none}
/* after the password the field says what's going on, each line filling with colour as it gets done */
.gate-row{position:relative}
.gate-status{display:none;position:absolute;left:0;bottom:14px;font:600 26px/1.15 'Outfit',system-ui,sans-serif;letter-spacing:-.01em;white-space:nowrap;color:transparent;background:linear-gradient(90deg,var(--on) calc(var(--fill,0)*100%),#F2F1EC4d 0);-webkit-background-clip:text;background-clip:text}
.gate-busy .gate-status{display:block}
.gate-busy .gate-row input,.gate-busy .gate-row button,.gate-busy .gate-form label{visibility:hidden}
.gate-row button svg{width:24px;height:24px;display:block}
.gate-error{margin:0}
.gate-wrong .gate-row{animation:gateShake .4s cubic-bezier(.3,.7,.4,1)}
@keyframes gateShake{20%{transform:translateX(-8px)}45%{transform:translateX(6px)}70%{transform:translateX(-3px)}100%{transform:none}}

/* ---------- HERO ---------- */
/* Choreography: 0–2.2s head rolls in from the right in profile, looking right, and pushes the
   password field out, while receding from close up to its place (0–2.8s). The text rides along
   hidden behind it, edge-on, and swings out like a door hinged at the head's centre as it turns;
   main.js turns the head by this door's own angle, so the two read as one space rotating. */
.hero{position:relative;height:min(calc(100vh + 2px),max(700px,78vw));height:min(calc(100dvh + 2px),max(700px,78vw));min-height:700px;overflow:hidden;overflow:clip;background-color:var(--accent);color:var(--on)}
.world{position:absolute;inset:0}
.hero-grid{position:relative;height:100%;grid-template-rows:1fr;padding-top:24px;padding-bottom:24px}
.hero-title{grid-column:7/13;grid-row:1;align-self:stretch;position:relative;z-index:2}
.hero-copy{height:100%;display:flex;flex-direction:column;justify-content:center;transition:transform .7s cubic-bezier(.2,.8,.2,1)}
.hero-ride{perspective:460px;perspective-origin:var(--hinge,0px) 50%;animation:roll var(--intro-roll) cubic-bezier(.4,0,.08,1) both}
.hero-door{display:flex;flex-direction:column;gap:48px;transform-origin:var(--hinge,0px) 50%;animation:door var(--intro-door) var(--intro-door-start) cubic-bezier(.65,0,.25,1) both}
@keyframes door{0%{transform:translateZ(-620px) rotateY(90deg)}100%{transform:translateZ(0) rotateY(0)}}
.hero-h1{margin:0 0 0 -.04em;font-size:var(--fs-hero);line-height:1.06;font-weight:600;letter-spacing:-.015em}
.hero-h1 span{display:block;text-wrap:balance}
.hero-facts{display:flex;flex-direction:column;margin:0;font-size:var(--fs-body);line-height:1.35}
.hero-name{font-weight:600}
.hero-role{font-weight:400}
.hero-head{grid-column:2/6;grid-row:1;position:relative;z-index:4;transform:translateY(var(--y,0px))}
.layer{position:absolute;inset:0;transition:transform .7s cubic-bezier(.2,.8,.2,1);will-change:transform}
.head-layer{perspective:1100px}
/* oversized so its edges stay outside the hero while it shifts */
.hero-bg{inset:-48px;background-color:var(--accent)}
.stage{perspective:1400px;perspective-origin:50% 40%}
.head3d{position:absolute;inset:0;width:100%;height:100%;display:block;pointer-events:none;animation:headRecede 2.8s cubic-bezier(.35,0,.1,1) both}
@keyframes headRecede{0%{transform:scale(1.7)}100%{transform:none}}
.roll{zoom:var(--head-zoom);width:1100px;height:1100px;position:absolute;left:50%;top:max(50%,calc(100% - 520px));margin:-550px 0 0 -550px;pointer-events:none;transform-style:preserve-3d;animation:roll var(--intro-roll) cubic-bezier(.4,0,.08,1) both}
.intro-wait .light,.intro-wait .hero-ride,.intro-wait .head3d,.intro-wait .roll,.intro-wait .drop,.intro-wait .horizon,.intro-wait .hero-door,.intro-wait .hero-h1,.intro-wait .hero-facts{animation-play-state:paused}
.horizon{position:absolute;left:-80px;right:-80px;top:68%;height:0;animation:horizon var(--intro-turn) var(--intro-turn-start) cubic-bezier(.65,0,.25,1) both}
.ground{position:absolute;left:0;right:0;top:0;height:2400px;background:linear-gradient(#0E0E0E00,#0E0E0E1c 240px,#0E0E0E24)}
.light{position:absolute;inset:-20%;pointer-events:none;background:radial-gradient(ellipse var(--light-rx,45%) var(--light-ry,40%) at var(--light-x,32%) var(--light-y,34%),#FFFFFF40,#FFFFFF00 70%),radial-gradient(ellipse 80% 50% at 50% 115%,#0E0E0E2e,#0E0E0E00 70%);animation:lightIn var(--intro-roll) cubic-bezier(.4,0,.2,1) both}
.measure-head .roll,.measure-head .head3d{animation:none}
@keyframes lightIn{0%{opacity:0}100%{opacity:1}}
.drop{transform-origin:50% 100%;animation:drop var(--intro-turn) var(--intro-turn-start) cubic-bezier(.65,0,.25,1) both}
@keyframes roll{0%{transform:translateX(1400px)}100%{transform:translateX(0)}}
@keyframes riseText{0%{transform:translateY(100vh)}100%{transform:none}}
/* further than the text, and the canvas is zoomed down: it stays below the text all the way up */
@keyframes riseHead{0%{transform:translateY(170vh)}100%{transform:none}}
@keyframes horizon{0%{transform:translateY(-1000px)}100%{transform:none}}
@keyframes drop{0%{transform:translateY(-1000px) rotateX(-80deg) scaleY(.2)}100%{transform:none}}
@supports (animation-timeline: view()){
.ps-slow,.ps-fast{animation-timing-function:linear;animation-fill-mode:both;animation-timeline:view();animation-range:exit 0% exit 100%}
.ps-slow{animation-name:psSlow}.ps-fast{animation-name:psFast}
}
@keyframes psSlow{to{transform:translateY(320px)}}
@keyframes psFast{to{transform:translateY(-140px)}}
/* head pinned on scroll until it hits the paper block: impact = squash + shake */
.bump{animation:shake .45s cubic-bezier(.3,.7,.4,1)}
@keyframes shake{0%{transform:none}18%{transform:translate(0,calc(7px*var(--hit,1)))}36%{transform:translate(calc(-4px*var(--hit,1)),calc(-3px*var(--hit,1)))}54%{transform:translate(calc(3px*var(--hit,1)),calc(2px*var(--hit,1)))}72%{transform:translate(calc(-1px*var(--hit,1)),calc(-1px*var(--hit,1)))}100%{transform:none}}
.head-hit{transform-origin:50% calc(50% + 210px);animation:squash .55s cubic-bezier(.3,.7,.4,1)}
@keyframes squash{0%{transform:translateY(var(--y))}22%{transform:translateY(calc(var(--y) + 4px*var(--squash,1))) scale(calc(1 + .06*var(--squash,1)),calc(1 - .1*var(--squash,1)))}55%{transform:translateY(calc(var(--y) - 16px*var(--squash,1))) scale(calc(1 - .02*var(--squash,1)),calc(1 + .03*var(--squash,1)))}100%{transform:translateY(var(--y))}}
.clay{display:inline-block;border-radius:50%;background:radial-gradient(circle at 34% 28%,#FFFFFF 0%,#F2F0EB 16%,#D4D0C6 52%,#9A9588 86%,#77726A 100%);box-shadow:0 .08em .12em #0E0E0E40}
@keyframes fade{from{opacity:0}to{opacity:1}}


/* ---------- LANGUAGE SWITCH ---------- */
.lang{display:flex;align-items:center;gap:2px}
.hero-tools{position:absolute;top:24px;right:40px;z-index:5;display:flex;align-items:center;gap:4px;--lang-dim:.88}
.lang-btn{font:inherit;letter-spacing:inherit;text-transform:inherit;color:inherit;background:none;border:0;min-width:44px;min-height:44px;padding:0 6px;opacity:var(--lang-dim,.65);transition:opacity .2s}
.lang-btn.on{opacity:1;text-decoration:underline;text-underline-offset:5px;text-decoration-thickness:2px}

/* ---------- SOUND SWITCH ---------- */
.sound-btn{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;padding:0;color:inherit;background:none;border:0;opacity:var(--lang-dim,.65);transition:opacity .2s}
.sound-btn svg{width:20px;height:20px;display:block}
.sound-btn .slash{display:none}
.sound-btn.off .slash{display:block}
.sound-btn.off .waves{display:none}

/* ---------- SCROLL CUE ---------- */
/* left edge on the headline's grid column */
.scroll-cue{position:absolute;left:calc(40px + (100% - 80px + 24px) / 2);bottom:32px;z-index:5;display:block;width:56px;height:56px;color:var(--accent);transition:opacity .3s}
.scroll-cue svg{display:block;box-sizing:border-box;width:56px;height:56px;padding:14px;border-radius:50%;background:var(--on);animation:fade .6s var(--intro-cue) both,cueBounce 1.5s cubic-bezier(.45,0,.55,1) infinite}
.intro-wait .scroll-cue svg{animation-play-state:paused}
.cue-hide{opacity:0;pointer-events:none}
@keyframes cueBounce{0%,100%{transform:translateY(-6px)}50%{transform:translateY(6px)}}

/* ---------- WORK ---------- */
/* its own paper: the page behind it stays blue until the password screen has gone */
.work{padding-top:160px;background-color:var(--paper)}
.work-head{align-items:end;align-items:last baseline;padding-bottom:64px}
.work-label{grid-column:1/4}
.work-title{grid-column:4/11;margin:0;font-size:var(--fs-section);line-height:1.04;font-weight:600;letter-spacing:-.015em}
.work-count{grid-column:11/13;text-align:right}
.work-list{padding-inline:40px;display:flex;flex-direction:column}

/* ---------- COMING SOON ---------- */
/* tall enough for the head to land on any screen, without a screenful of empty paper */
.soon{min-height:70vh;min-height:70svh;padding-bottom:160px}
.soon-grid{row-gap:24px;align-items:first baseline}
.soon-label{grid-column:1/4}
.soon-title{grid-column:4/13;margin:0;font-size:var(--fs-section);line-height:1.04;font-weight:600;letter-spacing:-.015em}
.soon-line{grid-column:4/11;margin:0;font-size:var(--fs-body);line-height:1.5}
.soon-caret{display:inline-block;width:.55em;height:1.05em;margin-left:.2em;vertical-align:-.15em;background:currentColor;animation:caret 1.1s steps(1) infinite}
@keyframes caret{50%{opacity:0}}

/* ---------- PROJECT CARDS ---------- */
.card{position:relative;display:grid;grid-template-columns:repeat(12,minmax(0,1fr));column-gap:24px;padding:0 0 120px;color:var(--ink);text-decoration:none;min-height:760px}
.card-meta{grid-column:1/5;display:flex;flex-direction:column;gap:28px;padding-bottom:40px}
.card-index{display:flex;justify-content:space-between;align-items:baseline}
.card-intro{display:flex;flex-direction:column;gap:12px}
.card-summary{margin:0;font-size:var(--fs-body);line-height:1.5;max-width:34em}
.client{color:#2340FF;font-weight:500}
.card-cover{grid-column:5/13;position:relative;overflow:hidden;aspect-ratio:16/10;background-color:#E2E1DB;align-self:start}
.cover-paper{background-color:#DAD7CF}
.cover-dark{background-color:var(--ink)}
.cover-blue{background-color:#2340FF}
.cover-art{position:absolute;inset:0;transition:transform .9s cubic-bezier(.2,.8,.2,1)}
.cover-open{position:absolute;left:0;right:0;bottom:0;display:flex;justify-content:space-between;align-items:center;padding:18px 24px;font-weight:500;background:var(--ink);color:var(--paper);transform:translateY(101%);transition:transform .5s cubic-bezier(.7,0,.2,1)}
.cover-open-accent{background:var(--accent);color:var(--on)}
.shot{position:absolute;background:#F7F6F2;box-shadow:inset 0 1px 0 #FFFFFF99,0 50px 90px -40px #0E0E0E99,0 18px 30px -18px #0E0E0E66;transition:transform .9s cubic-bezier(.2,.8,.2,1)}
.shot-dark{background:#1C1C1B;color:var(--paper)}
.shot-desk{left:11%;right:11%;top:13%;bottom:-6%;border-radius:12px 12px 0 0;transform-origin:50% 100%;transform:perspective(1600px) rotateX(16deg)}
.shot-phone{left:50%;width:28%;margin-left:-14%;top:12%;bottom:-12%;border-radius:40px 40px 0 0;transform:rotate(-7deg) translateY(16px)}
.shot-label{position:absolute;left:20px;top:16px;font-size:14px;opacity:.55}
.shot-phone .shot-label{left:28px;top:28px}
.glow{position:absolute;inset:0;background:radial-gradient(ellipse 60% 70% at 50% 100%,var(--accent),transparent 70%);opacity:.5;transition:opacity .6s}
.idx{font-size:120px;line-height:.8;font-weight:300;letter-spacing:-.02em;transition:color .3s,transform .5s cubic-bezier(.2,.8,.2,1);transform-origin:left bottom}
.ptitle{font-size:var(--fs-title);line-height:1.1;font-weight:600;letter-spacing:-.01em;margin:0}
.spec{display:grid;grid-template-columns:96px 1fr;row-gap:8px;margin:0}
.spec dt{opacity:.6}
.spec dd{margin:0}
.tags{display:flex;flex-wrap:wrap;gap:8px}
.tag{display:inline-block;background:#0E0E0E12;border-radius:999px;padding:5px 14px;font-size:14px}
.metric{display:flex;align-items:baseline;gap:12px;transition:transform .5s}
.metric-value{font-size:var(--fs-metric);line-height:1.1;font-weight:600;letter-spacing:-.01em}

/* ---------- CONTACT ---------- */
.contact{margin-top:160px;background:var(--ink);color:var(--paper);padding-block:120px}
.contact-grid{row-gap:64px;align-items:first baseline}
.contact-label{grid-column:1/4}
.contact-main{grid-column:4/13;display:flex;flex-direction:column;gap:48px}
.contact-title{margin:0;font-size:var(--fs-contact);line-height:1.02;font-weight:600;letter-spacing:-.02em}
.contact-list{display:flex;flex-direction:column;font-size:clamp(18px,1.5vw,22px)}
.contact-row{display:grid;grid-template-columns:120px 1fr auto;align-items:center;min-height:72px;border-top:1px solid #ECEBE62b;color:var(--paper);text-decoration:none;transition:padding .4s,background .3s}
.contact-row:last-child{border-bottom:1px solid #ECEBE62b}
.contact-row .arr{transition:transform .4s}
.mail{align-self:flex-start;font-size:clamp(26px,3.6vw,52px);line-height:1.2;font-weight:400;letter-spacing:-.005em;color:var(--paper);text-decoration:none;background-image:linear-gradient(var(--accent),var(--accent));background-size:0% 6px;background-repeat:no-repeat;background-position:0 100%;transition:background-size .6s cubic-bezier(.7,0,.2,1)}

/* ---------- FOOTER ---------- */
.footer{padding-top:56px;position:relative}
.marquee{overflow:hidden;white-space:nowrap}
.track{display:inline-flex;width:max-content;animation:mq 36s linear infinite}
.track span{font-size:180px;line-height:1.1;font-weight:600;letter-spacing:-.015em;padding-right:56px}
/* the variable font's glyphs have overlapping contours: paint the fill over the inner half of the stroke to hide them */
.outline{color:var(--paper);-webkit-text-stroke:2px var(--ink);paint-order:stroke fill}
@keyframes mq{to{transform:translateX(-50%)}}
.footer-grid{padding-top:48px;padding-bottom:40px;align-items:center;row-gap:32px}
.footer-stamp{grid-column:1/4;position:relative;width:160px;height:160px}
.footer-stamp .clay{position:absolute;left:62px;top:62px;width:36px;height:36px}
.footer-info{grid-column:4/10;display:flex;flex-direction:column;gap:16px}
.footer-top{grid-column:10/13;display:flex;justify-content:flex-end}
.stamp{animation:spin2 18s linear infinite}
@keyframes spin2{to{transform:rotate(360deg)}}
.dots{display:flex;gap:6px;height:24px;align-items:flex-end}
.dots span{display:inline-block;width:10px;height:10px;background:var(--ink);animation:hop 1.4s ease-in-out infinite}
.dots span:nth-child(2){animation-delay:.15s}.dots span:nth-child(3){animation-delay:.3s}.dots span:nth-child(4){animation-delay:.45s}
@keyframes hop{0%,60%,100%{transform:none}30%{transform:translateY(-14px);background:var(--accent)}}
.top-link{display:inline-flex;align-items:center;justify-content:center;width:120px;height:120px;border-radius:50%;background:var(--ink);color:var(--paper);font-weight:500;text-decoration:none;transition:transform .5s cubic-bezier(.2,.8,.2,1),background .3s}

/* ---------- HOVER AND TOUCH ---------- */
@media (hover:hover){
a:hover{color:#2340FF}
.gate-row button:hover{opacity:1;transform:translateX(-4px)}
.lang-btn:hover{opacity:1}
.sound-btn:hover{opacity:1}
.scroll-cue:hover{color:var(--accent)}
.card:hover{color:var(--ink)}
.card:hover .cover-art{transform:scale(1.02)}
.card:hover .cover-open{transform:none}
.card:hover .shot-desk{transform:perspective(1600px) rotateX(0deg) translateY(-14px)}
.card:hover .shot-phone{transform:rotate(0deg) translateY(-12px)}
.card:hover .glow{opacity:.85}
.card:hover .idx{color:var(--accent);transform:translateX(12px)}
.card:hover .metric{transform:translateX(12px)}
.contact-row:hover{padding-inline:20px;background:var(--accent);color:var(--on)}
.contact-row:hover .arr{transform:rotate(-45deg)}
.mail:hover{color:var(--paper);background-size:100% 6px}
.top-link:hover{transform:translateY(-10px) rotate(-12deg);background:var(--accent);color:var(--ink)}
}
a,button,label,.hero{-webkit-tap-highlight-color:transparent}
a,button,label{touch-action:manipulation}
/* no hover to rely on: what it reveals stays visible, and a press answers instead */
@media (hover:none){
.cover-open{transform:none}
.mail{padding-block:7px}
.card:active .cover-art{transform:scale(1.02)}
.card:active .idx{color:var(--accent)}
.contact-row:active{background:var(--accent);color:var(--on)}
.mail:active{background-size:100% 6px}
.top-link:active{background:var(--accent);color:var(--ink)}
.lang-btn:active,.sound-btn:active{opacity:1}
}

/* a thumb needs a clear, big button, and the phone's keyboard has its own Go */
@media (hover:none),(max-width:860px){
.gate-row button{width:52px;height:52px;margin-bottom:6px;background:var(--on);border-radius:50%;color:var(--accent);opacity:1}
.gate-row button:active{transform:scale(.92)}
.icon-enter{display:none}
.icon-go{display:block}
}

/* ---------- RESPONSIVE ---------- */
@media (min-width:861px) and (max-width:1100px){
:root{--head-zoom:.85}
}
@media (max-width:860px){
:root{--intro-roll:1.6s;--intro-turn-start:.9s;--intro-turn:.7s;--intro-cue:1.6s;--fs-hero:clamp(32px,10.2vw,60px);--head-zoom:.9;--head-travel:calc(237px*var(--head-zoom))}
.g12{grid-template-columns:repeat(4,minmax(0,1fr));column-gap:16px;padding-inline:16px}
.g12>*,.card-meta,.card-cover{grid-column:1/-1}
/* the browser pins the text and head itself until the chin meets the paper: a script always lags a phone's scrolling */
.hero{height:auto;min-height:0;isolation:isolate}
/* the room it travels lies under the paper, so all of the torso stays inside the pinned block: iOS clips what sticks out of it */
.hero::after{content:"";display:block;height:var(--head-travel)}
.work{position:relative;z-index:1;margin-top:calc(-1*var(--head-travel))}
/* title first: the torso runs off the hero's bottom edge, so it can't sit above the text */
.hero-grid{position:sticky;top:0;height:auto;grid-template-rows:auto auto;padding-bottom:0}
.ps-slow{animation:none}
/* the light behind the head lives in the pinned block, so the two never part; only the shade at the bottom stays on the background */
.hero-grid::before{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;background:radial-gradient(ellipse calc(760px*var(--head-zoom)) calc(504px*var(--head-zoom)) at calc(50% - 17px*var(--head-zoom)) calc(100% - 643px*var(--head-zoom)),#FFFFFF40,#FFFFFF00 70%);animation:lightIn var(--intro-roll) cubic-bezier(.4,0,.2,1) both}
.intro-wait .hero-grid::before{animation-play-state:paused}
.light{background:radial-gradient(ellipse 80% 50% at 50% 115%,#0E0E0E2e,#0E0E0E00 70%)}
.hero-title{grid-row:1;padding-top:56px;animation:none}
/* text above the head: the whole column rises from below and pushes the field out at the top */
.hero-ride{perspective:1000px;perspective-origin:50% 0%;animation:none}
.hero-door{gap:32px;animation:none}
.hero-h1,.hero-facts{animation:riseText var(--intro-roll) cubic-bezier(.16,.84,.3,1) backwards}
.roll{animation:riseHead var(--intro-roll) .06s cubic-bezier(.16,.84,.3,1) both}
.gate-leave .gate-form{transform:translateY(-100vh);transition:transform 1s cubic-bezier(.16,.84,.3,1)}
.hero-head{height:calc(715px*var(--head-zoom));grid-row:2}
.roll{top:auto;bottom:-110px;margin:0 0 0 -550px}
.head3d{animation:none}
.hero-tools{top:12px;right:8px}
/* in sight even when the hero is taller than the screen */
.scroll-cue{left:16px;bottom:max(calc(var(--head-travel) + 20px),calc(100% - 100dvh + 20px))}
.work{padding-top:96px}
.soon{padding-bottom:96px}
.work-head{row-gap:24px;padding-bottom:48px}
.work-list{padding-inline:16px}
.card{grid-template-columns:repeat(4,minmax(0,1fr));column-gap:16px;min-height:0;padding-bottom:80px}
.card-cover{order:-1;margin-bottom:24px}
.idx{font-size:72px}
.hide-sm{display:none}
.track span{font-size:96px}
.contact{margin-top:96px;padding-block:80px}
.contact-row{grid-template-columns:80px 1fr auto}
.footer-stamp{grid-column:1/3;width:120px;height:120px}
.stamp{width:100%;height:100%}
.footer-stamp .clay{left:46px;top:46px;width:28px;height:28px}
.footer-top{grid-column:3/-1;grid-row:1}
.footer-info{grid-row:2}
.top-link{width:96px;height:96px}
}
@media (max-width:640px){
:root{--head-zoom:.82}
}
@media (max-width:480px){
:root{--head-zoom:.62}
}
/* a tablet's width: the card's details take two columns under the cover */
@media (min-width:600px) and (max-width:860px){
.g12{padding-inline:32px}
.work-list{padding-inline:32px}
.hero-title{padding-top:72px}
.hero-tools{top:16px;right:20px}
.scroll-cue{left:32px}
.card-meta{display:grid;grid-template-columns:1fr 1fr;column-gap:24px;align-items:start}
.card-index{grid-column:1/-1}
.card-intro{grid-column:1;grid-row:2}
.metric{grid-column:1;grid-row:3}
.spec{grid-column:2;grid-row:2}
.tags{grid-column:2;grid-row:3}
}
/* a phone on its side: too short to stack, so back to two columns with a small head */
@media (orientation:landscape) and (max-height:560px){
:root{--head-zoom:.5;--fs-hero:clamp(28px,4.6vw,44px)}
.hero{height:calc(100vh + 2px);height:calc(100dvh + 2px);min-height:340px}
.hero::after{display:none}
.hero-grid::before{display:none}
.light{background:radial-gradient(ellipse var(--light-rx,45%) var(--light-ry,40%) at var(--light-x,32%) var(--light-y,34%),#FFFFFF40,#FFFFFF00 70%),radial-gradient(ellipse 80% 50% at 50% 115%,#0E0E0E2e,#0E0E0E00 70%)}
.work{margin-top:0}
.hero-grid{position:relative;height:100%;grid-template-columns:repeat(12,minmax(0,1fr));grid-template-rows:1fr;padding-bottom:24px}
.hero-head{grid-column:1/6;grid-row:1;height:auto}
.hero-title{grid-column:6/13;grid-row:1;padding-top:0;transform:translateY(var(--y,0px))}
.hero-door{gap:16px}
.roll{top:max(50%,calc(100% - 520px));bottom:auto;margin:-550px 0 0 -550px;animation:roll var(--intro-roll) cubic-bezier(.16,.84,.3,1) both}
.hero-h1,.hero-facts{transform-origin:50% 100%;animation:drop var(--intro-turn) var(--intro-turn-start) cubic-bezier(.65,0,.25,1) backwards}
.scroll-cue{left:auto;right:16px;bottom:16px}
}
@media (prefers-reduced-motion:reduce){*{animation-duration:.01ms!important;animation-delay:0s!important;animation-iteration-count:1!important;transition:none!important}}
