:root{
  --bg:#ffffff;
  --ink:#000000;
  --grey:#8a8a8a;
  --grey-d:#4d4d4d;
  --grey-m:#c9c9c9;
  --grey-l:#efefef;
  --radius:12px;
  --shadow:0 2px 0 var(--grey-m);
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0;min-height:100%}
body{
  background:var(--bg);color:var(--ink);
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",system-ui,sans-serif;
  display:flex;justify-content:center;
  -webkit-font-smoothing:antialiased;
  user-select:none;-webkit-user-select:none;-webkit-touch-callout:none; /* no text selection */
  touch-action:manipulation;                                            /* no double-tap zoom */
}
#app{width:100%;max-width:480px;min-height:100dvh;display:flex;flex-direction:column;padding:20px 18px;gap:16px;position:relative}
#view{flex:1;display:flex;flex-direction:column;position:relative}
/* game screens stretch to the bottom of the phone screen. The prompt text
   centers in the gap above the game box; the status line sits right under the
   box; the button row (Try again / Submit / Next level) centers vertically in
   the remaining space below. */
.card.full{flex:1;display:flex;flex-direction:column}
/* when space is tight (tall game boxes) the prompt gap gives way first, so the
   button row always stays on screen, centered between the box and the bottom */
.card.full .prompt{flex:1;display:flex;align-items:center;justify-content:center;margin-top:0;min-height:0}
.card.full .stage{flex:none} /* exactly the game box's own height — never collapses, never grows */
.card.full .status{min-height:0}
.card.full .row{flex:1;align-items:center;margin-top:0;min-height:52px}


/* page header (back + title) for sub-pages — sits above the sticky seg's halo */
.pagehead{display:flex;align-items:center;gap:10px;margin-bottom:14px;position:relative;z-index:6;background:var(--bg)}
.pagehead .back{
  background:none;border:1.5px solid var(--ink);border-radius:8px;color:var(--ink);
  width:32px;height:32px;font-size:16px;line-height:1;cursor:pointer;flex:none;
}
.pagehead .title{font-size:13px;font-weight:800;letter-spacing:.12em;text-transform:uppercase}

/* landing + home — logo + buttons centered in the full vertical space */
.landing{display:flex;flex-direction:column;justify-content:center;flex:1;gap:8px;position:relative;z-index:1}
.landing .menu{margin-top:30px}

/* ink chain — one dot per consecutive daily-game day, snaking down the home
   screen behind the buttons and around the logo */
.chain{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden}
/* dot size (small/medium/big) comes inline from the wallet; every dot lands
   with a little splat, staggered by an inline delay */
.chain i{position:absolute;border-radius:50%;background:var(--ink);display:block;animation:chain-pop .45s ease-out both}
@keyframes chain-pop{
  0%{opacity:0;transform:scale(2.6)}
  70%{opacity:1;transform:scale(.9)}
  100%{opacity:1;transform:scale(1)}
}

/* INKO — animated wordmark: pen-written I·N·K, the O falls in as an ink drop */
.logo{width:272px;max-width:78vw;margin:0 auto}
.logo svg{width:100%;height:auto;display:block}
.logo .lt{stroke:#000;stroke-width:7;stroke-linecap:round;stroke-linejoin:round}
/* replays are static: strokes fully drawn, O solid in place */
.logo.done *{animation:none!important}
.logo.done .lt{stroke-dashoffset:0!important}
@keyframes ink-draw{to{stroke-dashoffset:0}}
.logo .ink-i{stroke-dasharray:25;stroke-dashoffset:25;animation:ink-draw .28s ease-in-out .2s both}
.logo .ink-n{stroke-dasharray:84;stroke-dashoffset:84;animation:ink-draw .55s ease-in-out .55s both}
.logo .ink-k1{stroke-dasharray:25;stroke-dashoffset:25;animation:ink-draw .25s ease-in-out 1.18s both}
.logo .ink-k2{stroke-dasharray:51;stroke-dashoffset:51;animation:ink-draw .4s ease-in-out 1.48s both}
/* the O: a drop of ink falls from the viewer's POV onto the screen —
   big, faint and out of focus while close, shrinking and sharpening as it
   falls away, landing solid with a tiny radial splat */
.logo .ink-o{transform-box:fill-box;transform-origin:50% 50%;animation:ink-o .8s cubic-bezier(.45,0,.8,.6) 2.1s both}
@keyframes ink-o{
  0%{opacity:0;transform:scale(2);filter:blur(5px)}
  18%{opacity:.3}
  68%{opacity:.9;transform:scale(1);filter:blur(.5px);animation-timing-function:ease-out} /* impact */
  80%{transform:scale(1.12)}                                     /* radial splat pulse */
  100%{opacity:1;transform:scale(1);filter:blur(0)}
}
.bigbtn{
  display:block;width:100%;text-align:center;cursor:pointer;color:var(--ink);
  background:var(--bg);border:1.5px solid var(--ink);border-radius:var(--radius);
  padding:18px 16px;box-shadow:var(--shadow);font-family:inherit;
  font-size:14px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;
  transition:transform .06s ease,background .16s ease,color .16s ease;
}
.bigbtn:hover,.bigbtn:active{background:var(--ink);color:var(--bg)}
.bigbtn:active{transform:translateY(2px);box-shadow:none}
.bigbtn .bsub{font-size:10.5px;font-weight:600;letter-spacing:.08em;color:var(--grey);margin-top:5px}
.bigbtn:hover .bsub,.bigbtn:active .bsub{color:var(--grey-m)}

/* user chip (home, top right) — floats over the page so the menu centers on the
   full screen height, not below the header */
.userbar{position:absolute;top:14px;right:16px;z-index:10}
.userchip{
  display:flex;align-items:center;gap:9px;background:none;border:none;cursor:pointer;
  font-family:inherit;color:var(--ink);padding:4px;
}
.userchip .uname{font-size:12.5px;font-weight:700;letter-spacing:.06em;max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.userchip .uava{width:34px;height:34px;display:block}
.userchip .uava svg{width:100%;height:100%}

/* modals */
.ovl{position:fixed;inset:0;background:rgba(0,0,0,.45);display:flex;align-items:center;justify-content:center;z-index:60;padding:18px}
.modal{position:relative;background:var(--bg);border:1.5px solid var(--ink);border-radius:14px;box-shadow:var(--shadow);padding:20px;width:100%;max-width:360px}
.mclose{
  position:absolute;top:10px;right:10px;width:30px;height:30px;
  background:none;border:1.5px solid var(--grey-m);border-radius:8px;color:var(--ink);
  font-size:13px;line-height:1;cursor:pointer;font-family:inherit;
}
.mtitle{font-size:14px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;text-align:center;margin-bottom:14px;padding:0 34px}
.mtitle.tall{min-height:56px;display:flex;align-items:center;justify-content:center;margin-bottom:8px}
.field{margin:10px 0}
.field label{display:block;font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--grey);margin-bottom:6px}
.field input{
  width:100%;padding:12px 13px;border:1.5px solid var(--grey-m);border-radius:10px;
  font-family:inherit;font-size:15px;color:var(--ink);background:var(--bg);outline:none;
}
.field input:focus{border-color:var(--ink)}
.field input.ghosty{color:var(--grey)}
.merr{min-height:18px;text-align:center;font-size:12px;font-weight:700;color:var(--ink);margin-top:4px}
.modal .row{margin-top:8px;flex-direction:column;align-items:stretch}
.modal .row .btn{width:100%}

/* random game picker (slot-machine reveal) */
.pick{flex:1;display:flex;flex-direction:column;justify-content:center;gap:26px}
.pick-big-wrap{display:flex;align-items:center;justify-content:center}
.pcard-big{
  position:relative;width:min(86vw,340px);display:flex;align-items:center;gap:16px;
  padding:20px 22px;border-radius:16px;background:var(--bg);border:1.5px solid var(--grey-l);
  transition:width .42s cubic-bezier(.3,.9,.35,1),padding .42s ease,gap .42s ease,border-color .3s ease;
}
/* spinning state: a true square around the 76px image (76 + 2·14 pad + 2·1.5 border) */
.pcard-big.slot-mode{width:107px;padding:14px;gap:0;border-color:var(--ink)}
.pcard-big .pname{
  flex:1;font-size:17px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
  overflow:hidden;white-space:nowrap;opacity:1;transition:opacity .3s ease .2s;
}
.pcard-big.slot-mode .pname{flex:0 0 0;width:0;min-width:0;opacity:0;transition:none}
.pcard-big .gpv{
  flex:none;width:76px;height:76px;border:1px solid var(--grey-l);border-radius:14px;
  overflow:hidden;display:flex;align-items:center;justify-content:center;padding:7px;
}
.pcard-big .gpv svg{width:100%;height:100%;display:block}
.pcard-big .cring{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible}
.pcard-big .cring path{stroke-dasharray:100;animation:cring 2s linear forwards}
@keyframes cring{from{stroke-dashoffset:0}to{stroke-dashoffset:-100}}

/* leaderboards */
.board{display:flex;flex-direction:column;gap:7px;padding-bottom:16px}
.bhint{text-align:center;color:var(--grey);font-size:12.5px;padding:26px 0;letter-spacing:.04em}
.brow{
  display:flex;align-items:center;gap:10px;background:var(--bg);
  border:1.5px solid var(--grey-l);border-radius:10px;padding:11px 14px;font-size:13.5px;
  overflow:hidden; /* huge milestone dots get cut by the tile, by design */
}
/* milestone dot — daily streak, opposite color of the tile via currentColor;
   negative vertical margins keep even insane diameters from stretching the row */
.brow .mdot{
  flex:none;width:var(--d,4px);height:var(--d,4px);border-radius:50%;background:currentColor;
  align-self:center;margin-top:calc(var(--d,4px) / -2);margin-bottom:calc(var(--d,4px) / -2);
}
.brow .rk{width:44px;font-weight:800;color:var(--grey-d);font-variant-numeric:tabular-nums}
.brow .nm{flex:1;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.brow .sc{font-weight:800;font-variant-numeric:tabular-nums}
.brow.me{ /* the player: inverted + glued to the bottom until scrolled into place */
  background:var(--ink);color:var(--bg);border-color:var(--ink);
  position:sticky;bottom:10px;z-index:4;
}
.brow.me .rk{color:var(--grey-m)}
.gbtn .lbpos{text-transform:none;letter-spacing:.03em}

/* INKO map — every player is an ink ball sized by the dots they've fed it.
   No box: the field owns the whole screen; only the floating header sits above */
.glogo{display:block;height:17px;width:auto;margin:0 auto} /* wordmark, matches the text height of the other menu buttons */
.dmap{
  position:fixed;inset:0;background:var(--bg);
  overflow:hidden;touch-action:none; /* pinch belongs to the map */
}
.inkohd{ /* back arrow + FEED, floating over the balls.
    #view is the containing block and already sits at the app padding, so 0/0
    puts the back arrow exactly where the leaderboards page renders its own */
  position:absolute;top:0;left:0;right:0;z-index:10;
  display:flex;align-items:center;pointer-events:none;
}
.inkohd .back{
  pointer-events:auto;background:var(--bg);border:1.5px solid var(--ink);border-radius:8px;
  color:var(--ink);width:32px;height:32px;font-size:16px;line-height:1;cursor:pointer;flex:none;
}
.inkohd .btn{ /* centered on the same line as the back arrow; white border over the ink */
  pointer-events:auto;border-color:var(--bg);padding:7px 20px;
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
}
.inkohd .btn:active{transform:translate(-50%,calc(-50% + 2px))}
.dmap svg{width:100%;height:100%;display:block;cursor:grab}
.dmap svg:active{cursor:grabbing}
/* balls move (repacks) and grow (feeding) smoothly */
.dmap g.ball{transition:transform .6s cubic-bezier(.3,.9,.35,1)}
.dmap circle{fill:var(--ink);transition:r .35s ease}
.dmap text{
  fill:var(--bg);font-family:inherit;font-weight:800;letter-spacing:.02em;
  text-anchor:middle;dominant-baseline:central;pointer-events:none;
  transition:font-size .35s ease;
}
/* feeding splat: an expanding ring off the ball's edge (reuses mm-pulse) */
.dmap .dpulse{
  fill:none;stroke:var(--ink);stroke-width:3;transform-box:fill-box;
  transform-origin:center;animation:mm-pulse .45s ease-out forwards;
}
.dmap .bhint{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}
/* the "you are here" arrow — white with black borders, glued to the edge */
.dmarr{position:absolute;width:30px;height:30px;cursor:pointer;z-index:3}
.dmarr svg{width:100%;height:100%;display:block}

/* difficulty selector — sticks to the top while the game list scrolls */
.seg{
  display:flex;border:1.5px solid var(--ink);border-radius:10px;overflow:hidden;
  box-shadow:0 -20px 0 12px var(--bg),var(--shadow);margin-bottom:14px;background:var(--bg);
  position:sticky;top:12px;z-index:5;
}
.seg button{
  flex:1;padding:11px 0;background:none;border:none;border-left:1.5px solid var(--grey-l);
  font-family:inherit;font-size:11px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;
  color:var(--grey);cursor:pointer;
}
.seg button:first-child{border-left:none}
.seg button.on{background:var(--ink);color:var(--bg)}

/* cards & menu */
.card{background:var(--bg);border:1.5px solid var(--ink);border-radius:var(--radius);padding:18px;box-shadow:var(--shadow)}
.menu{display:flex;flex-direction:column;gap:12px}
.gbtn{
  display:flex;align-items:center;gap:14px;width:100%;text-align:left;cursor:pointer;color:var(--ink);
  background:var(--bg);border:1.5px solid var(--ink);border-radius:var(--radius);
  padding:14px 16px;box-shadow:var(--shadow);transition:transform .06s ease;
  font-family:inherit;
}
.gbtn{transition:transform .06s ease,background .16s ease,color .16s ease}
.gbtn:active{transform:translateY(2px);box-shadow:none}
/* hover / press: invert */
.gbtn:hover,.gbtn:active{background:var(--ink);color:var(--bg)}
.gbtn:hover .d,.gbtn:active .d{color:var(--grey-m)}
.gbtn:hover .best,.gbtn:active .best{color:var(--grey)}
.gbtn:hover .gpv,.gbtn:active .gpv{border-color:var(--grey-d)}
.gbtn .gtxt{flex:1;min-width:0}
.gbtn .t{font-size:15px;font-weight:800;letter-spacing:.06em;text-transform:uppercase}
.gbtn .d{font-size:12.5px;color:var(--grey-d);margin-top:5px;line-height:1.45}
.gbtn .best{font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--grey);margin-top:8px}
.gbtn .star{
  flex:none;font-size:21px;line-height:1;color:var(--grey-m);padding:8px 2px;cursor:pointer;
  user-select:none;transition:color .12s ease,transform .06s ease;
}
.gbtn .star:active{transform:scale(1.25)}
.gbtn .star.on{color:var(--ink)}
.gbtn:hover .star{color:var(--grey)}
.gbtn:hover .star.on,.gbtn:active .star.on{color:var(--bg)}
.gbtn .gpv{
  flex:none;width:70px;height:70px;border:1px solid var(--grey-l);border-radius:14px;
  overflow:hidden;display:flex;align-items:center;justify-content:center;background:var(--bg);padding:7px;
}
.gbtn .gpv svg{width:100%;height:100%;display:block}

/* game shell */
.hud{display:flex;align-items:center;gap:10px}
.hud .back,.rules .back{
  background:none;border:1.5px solid var(--ink);border-radius:8px;color:var(--ink);
  width:32px;height:32px;font-size:16px;line-height:1;cursor:pointer;flex:none;
}
.rules{position:relative}
.rules .back{position:absolute;top:14px;left:14px}
.hud .title{font-size:13px;font-weight:800;letter-spacing:.12em;text-transform:uppercase}
.hud .right{margin-left:auto;display:flex;align-items:center;gap:12px}
.hud .lvl{font-size:12px;font-weight:700;letter-spacing:.08em;color:var(--grey-d)}
.hud .lives{display:flex;gap:5px}
.hud .lives i{width:9px;height:9px;border-radius:50%;background:var(--ink);display:block}
.hud .lives i.lost{background:var(--bg);border:1.5px solid var(--grey-m)}

/* countdown bar */
.bar{height:3px;background:var(--grey-l);border-radius:2px;margin:14px 0 0;overflow:hidden}
.bar i{display:block;height:100%;width:100%;background:var(--ink);transition:width linear}

.prompt{min-height:22px;text-align:center;font-size:14px;font-weight:600;margin-top:14px}
.prompt .sw{display:inline-block;width:12px;height:12px;border-radius:3px;vertical-align:-1px;margin-right:6px;border:1.5px solid var(--ink)}
.prompt .sw.hi{background:var(--ink)}
.prompt .sw.sh{background:var(--grey);border-color:var(--grey)}
.prompt .sw.reg{background:var(--bg)}
.stage{display:flex;justify-content:center;align-items:center;margin:16px 0;min-height:120px;position:relative}

/* trailing tiles: YES banner + confetti */
.yes-ov{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;pointer-events:none;z-index:3}
.yes-ov .burst{position:absolute;left:50%;top:50%}
.yes-ov .burst i{position:absolute;left:0;top:0;display:block;background:var(--ink)}
.yes-ov .yes{
  position:relative;background:var(--ink);color:var(--bg);border-radius:12px;
  padding:13px 30px;font-size:20px;font-weight:800;letter-spacing:.2em;
}
.status{min-height:20px;text-align:center;font-size:13px;font-weight:700;letter-spacing:.04em}
.status.good{color:var(--ink)}
.status.bad{color:var(--grey-d)}
.status.hint{color:var(--grey);font-weight:500}
.row{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;margin-top:14px;min-height:44px}

/* buttons */
.btn{
  background:var(--ink);color:var(--bg);border:1.5px solid var(--ink);border-radius:10px;
  padding:12px 26px;font-size:13px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;
  cursor:pointer;font-family:inherit;box-shadow:var(--shadow);transition:transform .06s ease;
}
.btn:active{transform:translateY(2px);box-shadow:none}
.btn.ghost{background:var(--bg);color:var(--ink)}
.btn:disabled{opacity:.35;cursor:default}

/* tile grid (recall game) */
.grid{display:grid;gap:6px;width:100%;max-width:340px;touch-action:manipulation}
.cell{
  aspect-ratio:1/1;background:var(--bg);border:1.5px solid var(--grey-m);border-radius:8px;
  display:flex;align-items:center;justify-content:center;
  font-size:18px;font-weight:800;cursor:pointer;user-select:none;
}
.cell.hi{background:var(--ink);border-color:var(--ink)}
.cell.sh{background:var(--grey);border-color:var(--grey)}
.cell.seq{background:var(--ink);border-color:var(--ink)}
/* answer phase: grid tints slightly blue, picked tiles take the asked category's color */
.grid.answer .cell{background:#e9eefb;border-color:#ccd7ef}
.grid.answer .cell.pick-hi{background:var(--ink);border-color:var(--ink)}
.grid.answer .cell.pick-sh{background:var(--grey);border-color:var(--grey)}
.grid.answer .cell.pick-reg{background:#fff;border-color:var(--ink)}
.cell .g{pointer-events:none}
.cell.hi .g{color:var(--bg)}
.cell.sh .g{color:var(--ink)}

/* ray game svg */
svg.ray{display:block;touch-action:manipulation}
svg.ray .dot{cursor:pointer}
svg.ray .pulse{
  transform-box:fill-box;transform-origin:center;pointer-events:none;
  animation:mm-pulse .4s ease-out forwards;
}
@keyframes mm-pulse{
  from{transform:scale(.35);opacity:.9}
  to{transform:scale(2.1);opacity:0}
}

/* cubes game */
.fly{
  position:relative;overflow:hidden;width:100%;height:260px;
  border:1.5px solid var(--grey-m);border-radius:var(--radius);
}
.fly svg{position:absolute;left:0;top:0;will-change:transform}
.stepper{display:flex;align-items:center;gap:18px;justify-content:center}
.stepper button{
  width:52px;height:52px;border-radius:50%;border:1.5px solid var(--ink);background:var(--bg);
  color:var(--ink);font-size:24px;font-weight:700;cursor:pointer;box-shadow:var(--shadow);
  font-family:inherit;transition:transform .06s ease;
}
.stepper button:active{transform:translateY(2px);box-shadow:none}
.stepper .val{font-size:34px;font-weight:800;min-width:64px;text-align:center;font-variant-numeric:tabular-nums}

/* accuracy game */
.band{
  position:relative;width:100%;height:76px;border:1.5px solid var(--ink);border-radius:10px;
  overflow:hidden;background:var(--bg);touch-action:manipulation;
}
.band .tbox{position:absolute;top:0;bottom:0;background:#dcdcdc}
.band .tbox.hit{background:var(--ink)}
.band .tbox .g{
  position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font-size:20px;font-weight:800;color:var(--ink);pointer-events:none;
}
.band .tbox.hit .g{color:var(--bg)}
.band .tline{position:absolute;top:0;bottom:0;width:3px;background:var(--ink);will-change:transform}
.tut rect.sweep{animation:tut-sweep 1.15s linear infinite alternate}
.tut rect.tt{animation:tut-trail 2.4s linear infinite}
@keyframes tut-trail{
  0%{fill:#fff}3%{fill:#000}26%{fill:#000}42%{fill:#fff}100%{fill:#fff}
}
@keyframes tut-sweep{from{transform:translateX(0)}to{transform:translateX(65px)}}

/* pinball */
.pin{
  position:relative;width:100%;height:min(320px,46dvh);background:var(--bg);
  border:2px solid var(--ink);border-bottom:none;border-radius:12px 12px 0 0;overflow:hidden;
}
.pin .pscore{
  position:absolute;top:12px;left:0;right:0;text-align:center;
  font-size:34px;font-weight:800;color:#e2e2e2;pointer-events:none;font-variant-numeric:tabular-nums;
}
.pin .ball{position:absolute;left:0;top:0;width:14px;height:14px;border-radius:50%;background:var(--ink);will-change:transform}
.pin .paddle{position:absolute;bottom:0;left:0;height:5px;background:var(--ink);border-radius:3px;will-change:transform}
.pin-pulse{
  position:absolute;width:22px;height:22px;margin:-11px 0 0 -11px;border:2px solid var(--ink);
  border-radius:50%;pointer-events:none;animation:mm-pulse .4s ease-out forwards;
}
.tut circle.pinb{animation:tut-pin 2.6s linear infinite}
@keyframes tut-pin{
  0%{transform:translate(14px,62px)}30%{transform:translate(40px,11px)}
  55%{transform:translate(71px,42px)}80%{transform:translate(48px,71px)}100%{transform:translate(14px,62px)}
}

/* skyscraping */
.sky{
  position:relative;width:100%;height:min(400px,52dvh);background:var(--bg);
  border:2px solid var(--ink);border-radius:12px;overflow:hidden;
}
.sky canvas{position:absolute;left:0;top:0}
.sky .pscore{
  position:absolute;top:12px;left:14px;right:auto;text-align:left;
  font-size:34px;font-weight:800;color:#e2e2e2;pointer-events:none;font-variant-numeric:tabular-nums;
}
/* piano */
.piano{
  position:relative;width:100%;height:min(460px,52dvh);background:var(--bg);
  border:2px solid var(--ink);border-radius:12px;overflow:hidden;
  touch-action:none; /* no gesture recognition — simultaneous taps must all register */
}
.piano .pscore{
  position:absolute;top:12px;left:0;right:0;text-align:center;
  font-size:34px;font-weight:800;color:#e2e2e2;pointer-events:none;font-variant-numeric:tabular-nums;
}
.piano .seps i{position:absolute;top:0;bottom:0;width:1px;background:var(--grey-l);pointer-events:none}
.piano .ptile{position:absolute;top:0;left:0;background:var(--ink);border-radius:6px;will-change:transform}
.piano .ptile.hit{background:#dcdcdc}
.piano .px{
  position:absolute;bottom:6px;transform:translateX(-50%);font-size:20px;font-weight:800;
  font-style:normal;color:var(--ink);pointer-events:none;animation:piano-x .6s ease-out forwards;
}
@keyframes piano-x{from{opacity:1}to{opacity:0}}
.tut rect.pfall{animation:tut-pfall 2.2s linear infinite}
@keyframes tut-pfall{from{transform:translateY(0)}to{transform:translateY(110px)}}

/* blocks — isometric platform stacking */
.blocks{
  position:relative;width:100%;height:min(400px,52dvh);background:var(--bg);
  border:2px solid var(--ink);border-radius:12px;overflow:hidden;
}
.blocks canvas{position:absolute;left:0;top:0}
.blocks .pscore{
  position:absolute;top:12px;left:14px;text-align:left;
  font-size:34px;font-weight:800;color:#e2e2e2;pointer-events:none;font-variant-numeric:tabular-nums;
}
.tut g.bslide{animation:tut-bslide 1.5s ease-in-out infinite alternate}
@keyframes tut-bslide{from{transform:translate(-20px,-10px)}to{transform:translate(8px,4px)}}

/* end-of-run result overlay (engine, all games) */
.final-ov{
  position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;
  pointer-events:none;z-index:3;
}
.final-ov .n{
  background:var(--ink);color:var(--bg);border-radius:14px;padding:12px 34px 14px;
  display:flex;flex-direction:column;align-items:center;gap:2px;
}
.final-ov .fl{font-size:10px;font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:var(--bg)}
.final-ov .fn{font-size:34px;font-weight:800;font-variant-numeric:tabular-nums;line-height:1.1}
.tut g.swing{animation:tut-swing 1.5s ease-in-out infinite alternate;transform-origin:41px 5px}
@keyframes tut-swing{from{transform:rotate(-38deg)}to{transform:rotate(38deg)}}

/* first-time rules tooltip */
.rules{text-align:center;padding:26px 20px}
.rules .big{font-size:17px;font-weight:800;letter-spacing:.14em;text-transform:uppercase}
.rules .label{font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--grey);margin-top:8px}
.rules .sub{font-size:13.5px;color:var(--grey-d);margin:14px 0 0;line-height:1.65;text-align:left}
.rules .sub b{color:var(--ink)}
.rules .sub.dim{color:var(--grey);font-size:11px;letter-spacing:.1em;text-transform:uppercase;text-align:center;margin-top:16px}
.rules .row{margin-top:20px}

/* visual tutorial: three-panel flow */
.tut{display:flex;align-items:flex-start;justify-content:center;gap:6px;margin:18px 0 0}
.tut .p{display:flex;flex-direction:column;align-items:center;gap:7px;flex:1;min-width:0}
.tut .p svg{width:100%;height:auto;max-width:96px;display:block}
.tut .cap{font-size:9.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--grey);line-height:1.4}
.tut .arr{color:var(--grey-m);font-size:15px;flex:none;align-self:center;padding-bottom:18px}
.tut .win{overflow:hidden;border:1px solid var(--grey-l);border-radius:8px;width:100%;display:flex;justify-content:center}
.tut .win svg{animation:tut-slide 1.5s ease-in-out infinite alternate}
@keyframes tut-slide{from{transform:translateX(-16px)}to{transform:translateX(16px)}}
.tut path.demo{animation:tut-ray 2.4s linear infinite}
@keyframes tut-ray{0%{stroke-dashoffset:104}65%{stroke-dashoffset:0}100%{stroke-dashoffset:0}}
.tut .mstep{
  display:flex;align-items:center;gap:8px;justify-content:center;
  border:1px solid var(--grey-l);border-radius:8px;padding:20px 4px;width:100%;
}
.tut .mstep span{
  width:24px;height:24px;border-radius:50%;border:1.5px solid var(--ink);
  display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;
}
.tut .mstep b{font-size:18px}

/* ray: entry arrow knocks against the grid edge until the light launches */
@keyframes arr-down{from{transform:translateY(0)}to{transform:translateY(7px)}}
@keyframes arr-up{from{transform:translateY(0)}to{transform:translateY(-7px)}}
@keyframes arr-right{from{transform:translateX(0)}to{transform:translateX(7px)}}
@keyframes arr-left{from{transform:translateX(0)}to{transform:translateX(-7px)}}
.arr-down{animation:arr-down .65s ease-in-out infinite alternate}
.arr-up{animation:arr-up .65s ease-in-out infinite alternate}
.arr-right{animation:arr-right .65s ease-in-out infinite alternate}
.arr-left{animation:arr-left .65s ease-in-out infinite alternate}

@media (min-width:600px){
  #app{padding-top:36px}
  .grid{max-width:360px}
}
