/* ============================================================
   QUIZVERSE · Motion
   Kept GPU-cheap on purpose: transforms and opacity only, so
   older lab PCs stay smooth with a whole class running at once.
   ============================================================ */

@keyframes gradShift{0%,100%{background-position:0% 50%}50%{background-position:100% 50%}}
@keyframes orbit{
  0%,100%{transform:translate3d(0,0,0) scale(1)}
  33%{transform:translate3d(3vw,2vw,0) scale(1.06)}
  66%{transform:translate3d(-2vw,3vw,0) scale(.96)}
}
@keyframes floaty{0%,100%{transform:translateY(0)}50%{transform:translateY(-10px)}}
@keyframes spin{to{transform:rotate(360deg)}}
@keyframes blink{0%,49%{opacity:1}50%,100%{opacity:0}}
@keyframes pulseDot{0%{box-shadow:0 0 0 0 currentColor}70%{box-shadow:0 0 0 7px transparent}100%{box-shadow:0 0 0 0 transparent}}

@keyframes riseIn{from{opacity:0;transform:translate3d(0,22px,0)}to{opacity:1;transform:none}}
@keyframes riseBlur{from{opacity:0;transform:translate3d(0,28px,0);filter:blur(8px)}to{opacity:1;transform:none;filter:blur(0)}}
@keyframes dropIn{from{opacity:0;transform:translate3d(0,-14px,0)}to{opacity:1;transform:none}}
@keyframes popIn{from{opacity:0;transform:scale(.92)}to{opacity:1;transform:scale(1)}}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}

/* question card: unfolds on a hinge, leaves by folding away */
@keyframes unfold{
  0%{opacity:0;transform:perspective(1400px) rotateX(-58deg) translateY(26px);filter:blur(6px)}
  60%{opacity:1;filter:blur(0)}
  80%{transform:perspective(1400px) rotateX(4deg)}
  100%{opacity:1;transform:perspective(1400px) rotateX(0)}
}
@keyframes foldAway{
  to{opacity:0;transform:perspective(1400px) rotateX(42deg) translateY(-22px);filter:blur(5px)}
}
@keyframes wipeIn{
  from{opacity:0;clip-path:inset(0 100% 0 0);transform:translateX(-10px)}
  to{opacity:1;clip-path:inset(0 0 0 0);transform:none}
}
@keyframes sweep{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes shimmer{from{transform:translateX(-120%) skewX(-18deg)}to{transform:translateX(320%) skewX(-18deg)}}
@keyframes rippleOut{to{transform:scale(2.8);opacity:0}}
@keyframes nudge{
  0%,100%{transform:translateX(0)}20%{transform:translateX(-8px)}40%{transform:translateX(7px)}
  60%{transform:translateX(-4px)}80%{transform:translateX(3px)}
}
@keyframes bloom{0%{transform:scale(.5);opacity:.8}100%{transform:scale(2.3);opacity:0}}
@keyframes panic{0%,100%{transform:scale(1)}50%{transform:scale(1.07)}}
@keyframes chipFlip{
  0%{opacity:0;transform:perspective(600px) rotateX(-90deg)}
  65%{opacity:1;transform:perspective(600px) rotateX(10deg)}
  100%{opacity:1;transform:none}
}
@keyframes barGrow{from{transform:scaleY(0)}to{transform:scaleY(1)}}
@keyframes sealIn{
  0%{transform:scale(.4) rotate(-20deg);opacity:0}
  60%{transform:scale(1.12) rotate(4deg);opacity:1}
  100%{transform:scale(1) rotate(0);opacity:1}
}
@keyframes draw{to{stroke-dashoffset:0}}
@keyframes scan{from{transform:translateY(-100%)}to{transform:translateY(100%)}}

/* ============================================================
   CURSOR — dot + spring ring that docks onto controls
   ============================================================ */
.cursor-dot,.cursor-ring{position:fixed;top:0;left:0;z-index:99999;pointer-events:none;border-radius:50%;will-change:transform}
.cursor-dot{
  width:7px;height:7px;margin:-3.5px 0 0 -3.5px;background:var(--brand);
  transition:width .22s var(--ease-spring),height .22s var(--ease-spring),margin .22s var(--ease-spring),opacity .2s;
}
.cursor-ring{
  width:36px;height:36px;margin:-18px 0 0 -18px;border:1.5px solid rgba(79,70,229,.38);
  display:flex;align-items:center;justify-content:center;
  transition:width .3s var(--ease-spring),height .3s var(--ease-spring),margin .3s var(--ease-spring),
             border-color .25s,background .25s,opacity .25s,border-radius .3s var(--ease-spring),padding .3s var(--ease-spring);
}
.cursor-ring__label{
  font-family:var(--font-mono);font-size:9.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:#fff;opacity:0;transform:scale(.6);white-space:nowrap;
  transition:opacity .2s,transform .26s var(--ease-spring);
}
html.cur-hover .cursor-ring{width:54px;height:54px;margin:-27px 0 0 -27px;border-color:var(--brand);background:rgba(79,70,229,.10)}
html.cur-hover .cursor-dot{opacity:0}
html.cur-label .cursor-ring{width:auto;height:26px;padding:0 12px;border-radius:99px;margin:-13px 0 0 0;background:var(--ink);border-color:var(--ink)}
html.cur-label .cursor-ring__label{opacity:1;transform:scale(1)}
html.cur-label .cursor-dot{opacity:0}
html.cur-down .cursor-dot{width:12px;height:12px;margin:-6px 0 0 -6px}
html.cur-text .cursor-ring{width:2px;height:24px;border-radius:2px;margin:-12px 0 0 -1px;background:var(--brand);border-color:transparent}
html.cur-text .cursor-dot{opacity:0}
html.cur-hidden .cursor-ring,html.cur-hidden .cursor-dot{opacity:0}

/* ============================================================
   VIEW TRANSITION — a gradient shutter with a code glyph
   ============================================================ */
.shutter{position:fixed;inset:0;z-index:9000;pointer-events:none;visibility:hidden;display:flex}
.shutter.on{visibility:visible;pointer-events:all}
.shutter__bar{flex:1;background:var(--ink);transform:scaleY(0);transform-origin:top}
.shutter__bar:nth-child(2n){background:#111a33}
.shutter.in .shutter__bar{animation:barDown .42s var(--ease-swift) forwards}
.shutter.out .shutter__bar{transform:scaleY(1);transform-origin:bottom;animation:barUp .42s var(--ease-swift) forwards}
@keyframes barDown{from{transform:scaleY(0)}to{transform:scaleY(1)}}
@keyframes barUp{from{transform:scaleY(1)}to{transform:scaleY(0)}}
.shutter__glyph{
  position:absolute;inset:0;display:flex;align-items:center;justify-content:center;opacity:0;
  font-family:var(--font-mono);font-weight:700;font-size:2.6rem;color:#fff;letter-spacing:-.04em;
}
.shutter__glyph span{background:var(--grad);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
.shutter.in .shutter__glyph{animation:glyphPop .5s var(--ease-out) .12s forwards}
@keyframes glyphPop{0%{opacity:0;transform:scale(.8)}55%{opacity:1;transform:scale(1)}100%{opacity:0;transform:scale(1.08)}}

/* ============================================================
   REVEALS
   ============================================================ */
[data-reveal]{opacity:0}
[data-reveal].revealed{animation:riseBlur .7s var(--ease-out) forwards}
[data-reveal="pop"].revealed{animation:popIn .55s var(--ease-out) forwards}

.reveal-words .w{display:inline-block;overflow:hidden;vertical-align:top;padding-bottom:.08em}
.reveal-words .w>span{display:inline-block;transform:translateY(110%);animation:wordUp .9s var(--ease-out) forwards}
@keyframes wordUp{to{transform:translateY(0)}}

.stagger>*{opacity:0;animation:riseIn .6s var(--ease-out) forwards}
.stagger>*:nth-child(1){animation-delay:.04s}.stagger>*:nth-child(2){animation-delay:.1s}
.stagger>*:nth-child(3){animation-delay:.16s}.stagger>*:nth-child(4){animation-delay:.22s}
.stagger>*:nth-child(5){animation-delay:.28s}.stagger>*:nth-child(6){animation-delay:.34s}
.stagger>*:nth-child(7){animation-delay:.4s}.stagger>*:nth-child(8){animation-delay:.46s}

/* ============================================================
   RIPPLE / SHEEN / BLOOM
   ============================================================ */
.ripple{position:absolute;border-radius:50%;pointer-events:none;transform:scale(0);
  background:radial-gradient(circle,rgba(255,255,255,.7),rgba(255,255,255,0) 68%);animation:rippleOut .6s var(--ease-out) forwards}
.ripple.dark{background:radial-gradient(circle,rgba(79,70,229,.32),rgba(79,70,229,0) 68%)}
.sheen{position:absolute;inset:0;overflow:hidden;pointer-events:none;border-radius:inherit}
.sheen::after{content:"";position:absolute;top:-60%;bottom:-60%;width:36%;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.55),transparent);transform:translateX(-120%) skewX(-18deg)}
.has-sheen:hover .sheen::after{animation:shimmer 1s var(--ease-out)}
.bloomfx{position:absolute;border-radius:50%;pointer-events:none;animation:bloom .8s var(--ease-out) forwards}

#fxCanvas{position:fixed;inset:0;z-index:8500;pointer-events:none}

/* ============================================================
   TIMER RING
   ============================================================ */
.ring{position:relative;width:96px;height:96px;flex:none}
.ring.panic{animation:panic .9s ease-in-out infinite}
.ring svg{width:100%;height:100%}
.ring__track,.ring__fill{fill:none;stroke-linecap:round}
.ring__track{stroke:var(--bg-2);stroke-width:7}
.ring__fill{stroke:url(#ringGrad);stroke-width:7;transform:rotate(-90deg);transform-origin:50% 50%;transition:stroke .4s}
.ring__fill.warn{stroke:var(--warn-2)}
.ring__fill.dire{stroke:var(--bad-2)}
.ring__fill.grace{stroke:var(--info-2)}
.ring__label{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center}
.ring__num{font-family:var(--font-mono);font-size:1.6rem;font-weight:700;color:var(--ink);line-height:1;letter-spacing:-.04em}
.ring__cap{font-family:var(--font-mono);font-size:.56rem;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3);margin-top:4px;font-weight:600}

/* utilities */
.shake{animation:nudge .5s var(--ease-swift)}
.floaty{animation:floaty 7s var(--ease) infinite}
.spin{animation:spin 1s linear infinite}

/* ============================================================
   REDUCED MOTION — intentionally NOT honoured.
   The teacher asked for the full animated experience on every
   machine; Windows switches reduced-motion on whenever its
   "Animation effects" setting is off, which would otherwise
   leave the site static on many lab PCs.
   ============================================================ */
