:root{
  --bg:#000; --text:#ecebe8; --mute:#8b8a87; --dim:#55544f; --line:rgba(255,255,255,.13);
  --acc:#ff4a1c; --font:"Doto";
  --mono:"JetBrains Mono",ui-monospace,Menlo,monospace;
  --glow:0 0 6px var(--acc),0 0 18px color-mix(in srgb,var(--acc) 55%,transparent);
  --ease:cubic-bezier(.22,.61,.36,1);
  --ready:#3ddc84;
}
*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
html,body{height:100%;background:var(--bg);color:var(--text);overflow:hidden;font-family:var(--mono);
  -webkit-font-smoothing:antialiased;user-select:none;-webkit-user-select:none;touch-action:manipulation}
.grid{position:fixed;inset:0;pointer-events:none;
  background:radial-gradient(900px 420px at 50% -160px,color-mix(in srgb,var(--acc) 16%,transparent),transparent 70%),
             radial-gradient(rgba(255,255,255,.05) .9px,transparent 1.2px) 0 0/13px 13px}
.stage{position:fixed;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;
  padding:calc(env(safe-area-inset-top) + 48px) 30px calc(env(safe-area-inset-bottom) + 48px);
  opacity:0;visibility:hidden;transition:opacity 1.1s var(--ease),visibility 0s 1.1s}
body[data-stage="intro"] #intro,body[data-stage="waiting"] #waiting,body[data-stage="focus"] #focus,body[data-stage="reveal"] #reveal{opacity:1;visibility:visible;transition:opacity 1.3s var(--ease) .25s,visibility 0s}
/* intro exits quickly so Allow/Continue and camera hints don't sit over the waiting pills */
body:not([data-stage="intro"]) #intro{transition:opacity .4s var(--ease),visibility 0s .4s}
body:not([data-stage="intro"]) #intro .begin,body:not([data-stage="intro"]) #intro .hint,body:not([data-stage="intro"]) #intro .cam-act,body:not([data-stage="intro"]) #intro .fine{opacity:0;transition:opacity .25s var(--ease)}


/* dot rings */
.dotring{width:100%;height:100%;overflow:visible}
.dotring .d{fill:rgba(255,255,255,.22)}
.dotring .d.o{animation:dotwave 3.2s linear infinite;animation-delay:calc(var(--i) / var(--n) * -3.2s)}
.dotring .d.m{fill:rgba(255,255,255,.36);transform-origin:100px 100px;animation:breathe 6s var(--ease) infinite}
.dotring .d.i{fill:rgba(255,255,255,.18);transform-origin:100px 100px;animation:breathe 6s var(--ease) infinite reverse}
body[data-anim="orbit"] .dotring.big .d.m{animation:spin 16s linear infinite}
body[data-anim="orbit"] .dotring.big .d.i{animation:spin 24s linear infinite reverse}
body[data-anim="still"] .dotring.big .d{animation:none}
body[data-anim="still"] .dotring.big .d.o{fill:rgba(255,255,255,.16)}

/* intro */
.mark{position:relative;width:58px;height:58px;display:grid;place-items:center;margin-bottom:40px}
.mark svg{position:absolute;inset:0}
.mark i{width:5px;height:5px;border-radius:50%;background:var(--acc);box-shadow:var(--glow)}
.mark.logo svg,.mark.logo i{display:none}
.mark img{max-width:96px;max-height:72px;object-fit:contain}
.mark.logo{width:auto;height:auto}
.title{font-family:var(--font),var(--mono);font-weight:800;font-size:clamp(40px,13vw,58px);letter-spacing:.08em;line-height:1.02;text-transform:uppercase}
.title em{display:block;font-style:normal;color:var(--acc);text-shadow:0 0 18px color-mix(in srgb,var(--acc) 60%,transparent)}
body.serif .title,body.serif .name{font-weight:300;text-transform:none;letter-spacing:0}
body.serif .title{font-size:clamp(44px,14vw,60px)}
.lede{margin-top:30px;font-size:13px;line-height:1.8;color:var(--mute);letter-spacing:.02em}
.begin{margin-top:52px;appearance:none;border:1px solid var(--line);background:rgba(255,255,255,.055);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  color:var(--text);border-radius:999px;padding:17px 40px 17px 34px;display:inline-flex;align-items:center;gap:14px;cursor:pointer;
  font:500 12px/1 var(--mono);letter-spacing:.32em;text-transform:uppercase;transition:transform .4s var(--ease),border-color .4s}
.begin i{width:6px;height:6px;border-radius:50%;background:var(--acc);box-shadow:var(--glow);animation:blink 2.2s steps(1) infinite}
.begin:active{transform:scale(.96);border-color:var(--acc)}
.begin[disabled]{opacity:.55}
.hint{margin-top:20px;font-size:11px;line-height:1.7;color:var(--dim);max-width:270px}
.fine{position:absolute;bottom:calc(env(safe-area-inset-bottom) + 30px);left:0;right:0;font-size:10px;color:var(--dim);letter-spacing:.06em;padding:0 24px}
.hint.cam-warn{color:color-mix(in srgb,var(--acc) 50%,#8b8a87);max-width:300px}
.cam-act{margin-top:16px;display:none;gap:22px;justify-content:center;align-items:center}
.cam-act.on{display:flex}
.cam-act a,.cam-act button{appearance:none;background:none;border:0;color:var(--acc);font:500 11px/1 var(--mono);letter-spacing:.16em;text-transform:uppercase;cursor:pointer;text-decoration:none;padding:8px 0;text-shadow:0 0 10px color-mix(in srgb,var(--acc) 40%,transparent)}
.cam-act button.ok{color:#3ddc84;text-shadow:none}
.wait-cam{margin-top:16px;appearance:none;border:1px solid var(--line);background:rgba(255,255,255,.035);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  color:var(--dim);border-radius:999px;padding:9px 16px;display:none;align-items:center;gap:10px;cursor:pointer;
  font:500 10px/1 var(--mono);letter-spacing:.22em;text-transform:uppercase;max-width:92vw}
.wait-cam.on{display:inline-flex}
.wait-cam i{width:5px;height:5px;flex:none;border-radius:50%;background:var(--acc);box-shadow:var(--glow);animation:blink 2.2s steps(1) infinite}
.wait-cam.hint{cursor:default;letter-spacing:.08em;text-transform:none;font-size:10px;line-height:1.4;color:color-mix(in srgb,var(--acc) 45%,#8b8a87)}
.wait-cam.hint i{animation:none;opacity:.55}
body.controller .wait-cam,body.glitching .wait-cam{display:none!important}


/* waiting */
.wait-ring{position:relative;width:min(46vw,190px);aspect-ratio:1;margin-bottom:46px}
.wait-ring .dotring .d{fill:rgba(255,255,255,.2);animation:waitdot 2.8s ease-in-out infinite;animation-delay:calc(var(--i) / var(--n) * -2.8s)}
.wait-ring .core{animation:pulse 2.6s ease-in-out infinite}
.wait-title{font-family:var(--font),var(--mono);font-weight:800;font-size:clamp(30px,10vw,44px);letter-spacing:.08em;text-transform:uppercase}
body.serif .wait-title{font-weight:300;text-transform:none;letter-spacing:0}
.wait-text{margin-top:18px;font-size:13px;line-height:1.7;color:var(--mute);letter-spacing:.03em}
.joined{margin-top:44px;display:inline-flex;align-items:center;gap:10px;font-size:10px;letter-spacing:.32em;text-transform:uppercase;color:var(--dim);
  border:1px solid var(--line);border-radius:999px;padding:9px 16px;background:rgba(255,255,255,.035);
  transition:color .5s,border-color .5s,box-shadow .5s}
.joined i{width:5px;height:5px;border-radius:50%;background:var(--acc);box-shadow:var(--glow);animation:blink 2.2s steps(1) infinite}
/* confirmed join: same green as the Perform READY pill */
body[data-stage="waiting"] .joined,body.controller .joined{
  color:color-mix(in srgb,var(--ready) 85%,#fff);
  border-color:color-mix(in srgb,var(--ready) 38%,transparent);
  box-shadow:0 0 18px -8px var(--ready)}
body[data-stage="waiting"] .joined i,body.controller .joined i{
  background:var(--ready);box-shadow:0 0 8px var(--ready);animation:readyglow 2.6s ease-in-out infinite}
@keyframes readyglow{0%,100%{opacity:.65;transform:scale(1)}50%{opacity:1;transform:scale(1.35)}}

/* focus: finger target -> pulse */
.step{font-size:10.5px;letter-spacing:.34em;text-transform:uppercase;color:var(--mute);min-height:1.4em;transition:color .6s}
body[data-phase="finger"] .step{color:var(--text)}
.orbit{position:relative;width:min(70vw,290px);aspect-ratio:1;margin:34px 0 14px;border-radius:50%;touch-action:none;-webkit-touch-callout:none}
.orbit .touch{position:absolute;inset:27%;border-radius:50%;border:1px dashed color-mix(in srgb,var(--acc) 55%,transparent);
  box-shadow:0 0 30px color-mix(in srgb,var(--acc) 25%,transparent),inset 0 0 26px color-mix(in srgb,var(--acc) 18%,transparent);
  opacity:0;transform:scale(.9);transition:opacity .8s var(--ease),transform .8s var(--ease),background .5s}
body[data-phase="finger"] .orbit .touch{opacity:1;transform:scale(1);animation:invite 2.4s ease-in-out infinite}
body.held .orbit .touch{animation:none;transform:scale(.92);background:color-mix(in srgb,var(--acc) 14%,transparent);border-style:solid}
.core{position:absolute;left:50%;top:50%;width:8px;height:8px;margin:-4px;border-radius:50%;background:var(--acc);box-shadow:var(--glow)}
.core.beat{animation:beat .42s ease-out}
.bpm{display:flex;align-items:baseline;gap:8px;opacity:.18;transition:opacity 1.2s var(--ease)}
body.held .bpm,body[data-phase="pulse"] .bpm,body.locked .bpm{opacity:1}
.bpm b{font-family:"Doto",var(--mono);font-weight:800;font-size:46px;letter-spacing:.06em;min-width:2.3ch;text-align:right;text-shadow:0 0 16px rgba(255,255,255,.25)}
.bpm small{font-size:10px;letter-spacing:.3em;color:var(--mute)}
.pstat{margin-top:6px;font-size:10px;letter-spacing:.3em;text-transform:uppercase;color:var(--acc);min-height:1.5em;text-shadow:0 0 10px color-mix(in srgb,var(--acc) 50%,transparent)}
.ecg{width:min(84vw,340px);height:56px;margin:10px 0 18px;
  -webkit-mask:linear-gradient(90deg,transparent,#000 18%,#000 82%,transparent);mask:linear-gradient(90deg,transparent,#000 18%,#000 82%,transparent)}
.whisper{font-size:14px;line-height:1.6;letter-spacing:.03em;min-height:3.2em;max-width:300px;color:var(--text);transition:opacity .8s var(--ease),filter .8s var(--ease)}
.whisper.out{opacity:0;filter:blur(5px)}
body[data-phase="finger"] .whisper{opacity:0}

/* reveal */
.kicker{font-size:10.5px;letter-spacing:.34em;text-transform:uppercase;color:var(--mute);opacity:0;transition:opacity 1.2s var(--ease) .2s}
.name{margin-top:26px;font-family:var(--font),var(--mono);font-weight:800;font-size:clamp(42px,15vw,84px);line-height:1;letter-spacing:.1em;
  white-space:nowrap;max-width:100%;text-transform:uppercase;text-shadow:0 0 18px rgba(255,255,255,.35)}
.name .ch{display:inline-block}
body[data-rstyle="blur"] .name .ch{opacity:0;filter:blur(14px);transform:translateY(8px);transition:opacity 1.3s var(--ease),filter 1.5s var(--ease),transform 1.5s var(--ease)}
body[data-rstyle="fade"] .name{opacity:0;transition:opacity 3.2s var(--ease) .4s}
body[data-rstyle="type"] .name .ch{opacity:0}
body[data-rstyle="type"] .name .ch.on{opacity:1}
body[data-rstyle="type"] .name .cur{display:inline-block;width:.5em;height:.08em;background:var(--acc);box-shadow:var(--glow);margin-left:.08em;vertical-align:baseline;animation:blink 1s steps(1) infinite}
.rule{display:block;margin-top:34px;height:2px;width:0;background:radial-gradient(circle,var(--acc) 1px,transparent 1.4px) 0 50%/6px 2px repeat-x;filter:drop-shadow(0 0 3px var(--acc));transition:width 1.8s var(--ease)}
.after{position:absolute;bottom:calc(env(safe-area-inset-bottom) + 44px);left:0;right:0;font-size:10.5px;color:var(--dim);letter-spacing:.08em;opacity:0;transition:opacity 1s}
.after .bar{display:block;width:140px;height:2px;margin:0 auto 12px;background:var(--line);overflow:hidden;border-radius:2px}
.after .bar i{display:block;height:100%;width:0;background:var(--acc);box-shadow:var(--glow)}
body.revealed .kicker,body.revealed .after{opacity:1}
body.revealed[data-rstyle="blur"] .name .ch{opacity:1;filter:none;transform:none}
body.revealed[data-rstyle="fade"] .name{opacity:1}
body.revealed .rule{width:72px;transition-delay:1.2s}

/* flash + hot zones */
.flash{position:fixed;inset:0;background:#fff;opacity:0;pointer-events:none;z-index:9;transition:opacity var(--fade,120ms) ease-out;will-change:opacity}
#cam{position:fixed;width:2px;height:2px;opacity:0;pointer-events:none;left:0;top:0}
.hot{position:fixed;top:0;width:72px;height:72px;z-index:10;touch-action:none;-webkit-touch-callout:none}
.hot-tr{right:0}.hot-tl{left:0}
.ctl-dot{position:fixed;top:calc(env(safe-area-inset-top) + 10px);left:50%;width:4px;height:4px;margin-left:-2px;border-radius:50%;background:var(--acc);opacity:0;z-index:11;pointer-events:none;transition:opacity .3s,transform .3s}
body.controller .ctl-dot{opacity:.55}
body.controller .ctl-dot.tap{opacity:1;transform:scale(2.2);box-shadow:var(--glow)}
.ctl-toast{position:fixed;left:50%;top:calc(env(safe-area-inset-top) + 26px);transform:translate(-50%,-8px);z-index:12;pointer-events:none;opacity:0;
  font:500 10.5px/1 var(--mono);letter-spacing:.28em;text-transform:uppercase;color:var(--text);white-space:nowrap;
  padding:11px 16px;border-radius:999px;border:1px solid color-mix(in srgb,var(--acc) 60%,transparent);background:rgba(10,10,10,.72);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
  box-shadow:0 0 24px -6px var(--acc);transition:opacity .25s,transform .25s}
.ctl-toast.on{opacity:1;transform:translate(-50%,0)}
.ctl-toast.sync{overflow:hidden}
.ctl-toast.sync b{color:var(--acc);font-weight:600;display:inline-block;min-width:1ch}
.ctl-toast .cd{position:absolute;left:0;bottom:0;height:2px;width:100%;background:var(--acc);box-shadow:0 0 8px var(--acc);transform-origin:left;animation:cd linear forwards}
@keyframes cd{from{transform:scaleX(1)}to{transform:scaleX(0)}}
.ctl-toast.bad{border-color:#ff6a4a;color:#ffb3a3;letter-spacing:.12em;text-transform:none;font-size:12px}
.ripple{position:fixed;width:16px;height:16px;margin:-8px 0 0 -8px;border-radius:50%;z-index:12;pointer-events:none;border:1.5px solid var(--acc);box-shadow:0 0 18px var(--acc);animation:ripple .75s var(--ease) forwards}
@keyframes ripple{from{transform:scale(.6);opacity:1}to{transform:scale(7);opacity:0}}

@keyframes blink{0%,70%{opacity:1}71%,100%{opacity:.25}}
@keyframes dotwave{0%{fill:var(--acc)}12%{fill:rgba(255,255,255,.22)}100%{fill:rgba(255,255,255,.22)}}
@keyframes breathe{0%,100%{transform:scale(.86);opacity:.45}50%{transform:scale(1);opacity:1}}
@keyframes spin{to{transform:rotate(360deg)}}
@keyframes pulse{0%,100%{transform:scale(.8)}12%{transform:scale(1.6)}24%{transform:scale(1)}36%{transform:scale(1.35)}50%{transform:scale(.9)}}
@keyframes sweep{from{stroke-dashoffset:100}to{stroke-dashoffset:0}}
@keyframes waitdot{0%,100%{fill:rgba(255,255,255,.14)}50%{fill:color-mix(in srgb,var(--acc) 70%,#fff)}}
@keyframes invite{0%,100%{box-shadow:0 0 18px color-mix(in srgb,var(--acc) 18%,transparent)}50%{box-shadow:0 0 44px color-mix(in srgb,var(--acc) 45%,transparent),inset 0 0 30px color-mix(in srgb,var(--acc) 22%,transparent)}}
@keyframes beat{0%{transform:scale(1)}18%{transform:scale(2)}34%{transform:scale(1.2)}48%{transform:scale(1.7)}100%{transform:scale(1)}}
@media (prefers-reduced-motion:reduce){.dotring .d,.core,.hb-run,.begin i,.orbit .touch,.joined i{animation:none!important}}

/* v3: dot-matrix suspense reveal (canvas) + redirect glitch */
.name.sr{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;margin:0}
.name-box{width:100%;height:110px;margin-top:22px}
.fx{position:fixed;inset:0;width:100%;height:100%;pointer-events:none;z-index:6;opacity:0;transition:opacity .6s}
body.fx-on .fx{opacity:1}
body:not([data-stage="reveal"]):not(.glitching) .fx{opacity:0}
.scan{position:fixed;inset:0;pointer-events:none;z-index:7;opacity:0;
  background:repeating-linear-gradient(0deg,rgba(0,0,0,.55) 0 1px,transparent 1px 3px),repeating-linear-gradient(90deg,rgba(255,74,28,.05) 0 1px,transparent 1px 4px)}
.fx-fade{position:fixed;inset:0;background:#000;opacity:0;pointer-events:none;z-index:10}
/* RGB split + jitter on the DOM text while glitching (positional only: no brightness strobe) */
body.glitching .stage{animation:gljit .26s steps(2,end) infinite}
body.glitching .kicker,body.glitching .title,body.glitching .wait-title,body.glitching .joined{text-shadow:calc(var(--gq,0) * -6px) 0 rgba(255,31,61,.8),calc(var(--gq,0) * 6px) 0 rgba(31,230,255,.7)}
@keyframes gljit{0%{transform:translate(0,0) skewX(0)}50%{transform:translate(calc(var(--gq,0) * 9px),calc(var(--gq,0) * -2px)) skewX(calc(var(--gq,0) * -4deg))}100%{transform:translate(calc(var(--gq,0) * -7px),0) skewX(0)}}
/* controller hold ring */
.hold-ring{position:fixed;width:96px;height:96px;margin:-48px 0 0 -48px;z-index:12;pointer-events:none;opacity:0;transform:scale(.7);transition:opacity .15s,transform .15s}
.hold-ring svg{width:100%;height:100%;transform:rotate(-90deg)}
.hold-ring circle{fill:none;stroke-width:3}
.hold-ring .trk{stroke:rgba(255,255,255,.12)}
.hold-ring .fil{stroke:var(--acc);stroke-linecap:round;stroke-dasharray:213.6;stroke-dashoffset:213.6;filter:drop-shadow(0 0 6px var(--acc))}
.hold-ring.on{opacity:1;transform:scale(1)}
.hold-ring.on .fil{animation:holdfill 1s linear forwards}
.hold-ring.fire{opacity:0;transform:scale(1.5);transition:opacity .45s,transform .45s}
.hold-ring.fire .fil{stroke-dashoffset:0}
@keyframes holdfill{to{stroke-dashoffset:0}}

.pulse-line{font-family:var(--font),var(--mono);font-weight:700;font-size:clamp(15px,4.6vw,20px);letter-spacing:.12em;text-transform:uppercase;color:var(--text);margin:0 0 10px;padding:0 22px;text-shadow:0 0 14px color-mix(in srgb,var(--acc) 35%,transparent)}
.pulse-line:empty{display:none}
/* controller: keep iOS from turning the reveal hold into a callout / selection / scroll */
body.controller{-webkit-touch-callout:none}
body.controller[data-stage="reveal"]{touch-action:none}
.ctl-open{position:fixed;left:50%;bottom:calc(env(safe-area-inset-bottom) + 26px);transform:translateX(-50%);z-index:13;display:none;
  font:500 10.5px/1 var(--mono);letter-spacing:.24em;text-transform:uppercase;color:var(--text);padding:13px 18px;border-radius:999px;
  border:1px solid color-mix(in srgb,var(--acc) 55%,transparent);background:rgba(10,10,10,.8);text-decoration:none}
.go-on{position:fixed;inset:auto 0 calc(env(safe-area-inset-bottom) + 18%) 0;margin:auto;width:max-content;z-index:11;display:none;
  font:600 13px/1 var(--mono);letter-spacing:.22em;text-transform:uppercase;color:#000;padding:18px 26px;border-radius:999px;text-decoration:none;
  background:var(--acc);box-shadow:0 0 34px color-mix(in srgb,var(--acc) 70%,transparent),0 0 0 1px rgba(255,255,255,.25) inset;-webkit-tap-highlight-color:transparent}
body.stuck .go-on{display:block}

.ctl-count{position:fixed;bottom:calc(env(safe-area-inset-bottom) + 22px);left:50%;transform:translateX(-50%);z-index:12;display:none;pointer-events:none;
  font-family:'Doto',var(--mono),monospace;font-weight:800;font-size:15px;letter-spacing:.14em;text-transform:uppercase;color:var(--acc);opacity:.85}
body.controller .ctl-count.on{display:block}
body.controller[data-stage="focus"] .ctl-count{bottom:calc(env(safe-area-inset-bottom) + 28px)}
body.glitching .ctl-count{display:none}

.ctl-src{position:fixed;left:50%;bottom:calc(env(safe-area-inset-bottom) + 50px);transform:translateX(-50%);z-index:12;display:none;pointer-events:none;white-space:nowrap;max-width:94vw;overflow:hidden;text-overflow:ellipsis;
  font:500 9px/1 var(--mono),monospace;letter-spacing:.14em;text-transform:uppercase;color:rgba(241,239,233,.3)}
.ctl-src b{color:rgba(241,239,233,.5);font-weight:500;text-transform:none;letter-spacing:.06em}
.ctl-src i{display:inline-block;width:5px;height:5px;border-radius:50%;background:var(--acc);margin-right:7px;vertical-align:1px;opacity:.6}
.ctl-src i.ping{animation:srcping .9s ease-out}
@keyframes srcping{0%{transform:scale(2.2);opacity:1;box-shadow:0 0 10px var(--acc)}100%{transform:scale(1);opacity:.6}}
.ctl-src.bad{color:#ff6a4a}.ctl-src.bad i{background:#ff6a4a}
body.controller .ctl-src.on{display:block}
body.glitching .ctl-src{display:none}

/* controller: "Show ended" note in amber */
.ctl-toast.ended{color:#ffb02e;border-color:color-mix(in srgb,#ffb02e 45%,transparent)}

/* controller heartbeat: the word to be revealed — muted, low contrast, top band (outside the tap zone) */
.ctl-reveal{position:fixed;left:50%;bottom:calc(env(safe-area-inset-bottom) + 2px);transform:translateX(-50%);z-index:12;display:none;background:none;border:0;padding:4px 10px;
  font-family:'Doto',var(--mono),monospace;font-weight:800;font-size:13px;letter-spacing:.16em;text-transform:uppercase;color:color-mix(in srgb,var(--acc) 42%,#000);white-space:nowrap;-webkit-tap-highlight-color:transparent}
.ctl-reveal b{color:color-mix(in srgb,var(--acc) 60%,#000);font-weight:800}
body.controller .ctl-reveal.on{display:block}
.ctl-reveal.hid{opacity:.12}.ctl-reveal.hid b{visibility:hidden}
