
#stage{position:absolute;left:0;top:0;width:1080px;height:2160px;transform-origin:0 0;overflow:hidden;background:transparent;z-index:1}   /* UNIFORM SCALE: fit() CONTAINS the artboard (nothing cropped) and centers it against the VISUAL viewport incl. offset (kills toolbar drift). #stage is transparent so the single cover background (#bgfs) shows through screens that don't paint their own bg (intro) — no double-bg, no seam. The game keeps its own #bg for tower alignment. */
/* full-bleed background: a single COVER-scaled copy of the current screen's background fills the whole viewport edge-to-edge (no letterbox band). Splash/loader/lobby screens make their own bg transparent so this shows through full-width; the fixed-artboard game keeps its own #bg for tower-ground alignment (this fills only its thin letterbox band). */
#bgfs{position:fixed;inset:0;z-index:0;overflow:hidden;pointer-events:none;background:#0c1720}
#bgfsImg{width:100%;height:100%;object-fit:cover;object-position:center}
#egnhost img{display:block;pointer-events:none;-webkit-user-drag:none}.abs{position:absolute}
#bg{left:0;top:0;width:1080px;height:2160px}
/* tower */
#towerG{pointer-events:none;left:245px;top:85px;width:483px;height:1738px;z-index:25;transform:translate(calc(var(--ox,0px) + var(--dsx,0px)),var(--oy,0px)) scale(calc(1.22 * var(--os,1)));transform-origin:top left;transition:transform .7s cubic-bezier(.6,0,.3,1)}   /* base scale 1.22 composes with the lab override vars; .side/.shake below still win during result/miss */
#tw{clip-path:inset(134px 0 0 0)}   /* cut the little finial spike off the top (roof stays) */
#stage.mx #towerG{--dsx:var(--door-tx,0px)}   /* lost at the ENTRANCE on a narrow screen: the tower stops short of its lose spot so the doorway and the samurai in it are whole (owner 2026-10-14: the samurai never slides at the door) — game.js doorTx; only the variable here, never the transform (.side / the engine's inline slide keep winning while they run) */
#towerG.side{transform:translate(-428px,22px) scale(1.22)}   /* owner (Losing Screen Lab): tower at -183 → sad Naybo peeks visibly */
#towerG.shake{animation:shake .5s}
#towerG img{position:absolute}
.int{opacity:0;transition:opacity .5s}.int.on{opacity:1}
#stage.fast .int{transition-duration:.25s}#stage.fast #wn{transition-duration:.1s,.7s}      /* fast mode: window open/close at half duration */
#stage.fast #ng{transition:none}                                                        /* fast mode: ground Naybo vanishes instantly on the first key — no slide */
#wn{position:absolute;overflow:hidden;left:80px;width:150px;height:129px;top:1196px;opacity:0;transition:opacity .2s,translate .7s cubic-bezier(.6,0,.3,1)}   /* left/top now set per floor from GEO.chars */
#wn.on{opacity:1}#sp{position:absolute;left:0;top:0;width:147px;height:212px;transform-origin:50% 88%;will-change:transform,filter}
#sp img{left:0;top:0;width:147px;transform-origin:50% 50%}#spS,#spB{opacity:0}
#wn.win{width:148px;height:114px;overflow:visible}#wn.win #sp{left:0;width:148px;transform:scale(1.22);transform-origin:0 0}#wn.win #sp img{width:148px}   /* owner: top-win char ×1.22 at (127,223) from render() */
#wn.door{overflow:visible}#wn.door #sp{top:0;transform:scale(.64);transform-origin:0 0}   /* floor 1 = the open door: whole figure at 64%, positioned directly by GEO.chars[0] */
#wn.R #sp{left:0;transform:scaleX(-1)}#wn.L #sp{left:0}            /* R = right-side window → mirrored so he faces INTO the tower (owner rule) */
#wn{--ox:0px;--oy:0px;--os:1}   /* own values: the tower's lose nudge (--ox/--oy/--os on #towerG) must not leak into the samurai */
#stage.mx #wn.sad{translate:calc(var(--sdx,0px) + var(--ox) / var(--wts,1.22)) calc(var(--oy) / var(--wts,1.22));scale:var(--os);transform-origin:50% 100%}   /* LOSE board: he slides right as the tower slides left, whole on screen (config GEO.sadDx) + the lose editor's per-samurai nudge 'lose-char' (stage px ÷ the tower's real scale --wts; scale keeps the balcony cut); back with the tower on PLAY AGAIN (#wn transition, no snap) */
#stage.mx #wn.door.sad{translate:0 0}   /* the ENTRANCE (owner 2026-10-08: "na ulazu… samo postane sad… pomeri se desno samo na spratovima"; 2026-10-14 "NE slidne se desno"): no slide, no editor nudge — he stays in the doorway; on a narrow screen the tower stops short instead (#stage.mx #towerG --dsx) */
#wn.sad #sp{left:0;transform:none}#wn.door.sad #sp{left:0;transform:scale(.64);transform-origin:0 0}   /* game over: peek from the window facing RIGHT (no flip = right, like odd floors) toward the result */
#ng{left:703px;top:1420px;width:346px;z-index:26;transition:transform .55s ease-in,opacity .45s .1s;transform:translate(var(--ox,0px),var(--oy,0px)) scale(var(--os,1));transform-origin:50% 100%}   /* base composes lab override vars; .in/.sad below win during climb/gameover */
#ng img{width:346px;transform-origin:50% 100%}   /* owner layout: ground Naybo 134%; no idle bob (owner 2026-09-28: the shadow looked wrong under it) */#ngS{position:absolute;left:0;top:0;opacity:0}
/* the character's ground shadow is its own black layer now (the baked blue one was removed from the sprites, tools/split_naybo_shadow.py):
   stays on the ground (no bob), strength = --nsh from the background lab ("Character shadow"). */
#ngImg{position:relative}#ng #ngSh{position:absolute;left:0;top:0;animation:none;opacity:var(--nsh,.45);pointer-events:none}
#ng.sad img{transform:scaleX(-1);animation:none}   /* game over: face right toward the result, no idle bob */
#ng.in{transform:translate(-290px,20px) scale(.4);opacity:0}
/* stones */
#stones{left:19px;top:1910px;width:1039px;height:235px;z-index:28}
#stones{transform:translate(var(--ox,0px),var(--oy,0px)) scale(var(--os,1));transform-origin:50% 100%}   /* ONE setting for every game (app/shell/stonerow.js, labs/stones_lab.html — was the per-screen editor element "All 6 stones") */   /* owner stack: stones frontmost, key 27, tower 25, bg 0 */
.stone{position:absolute;top:0;height:235px;cursor:pointer}
.stone img{position:absolute;left:0;top:0;height:235px;transform-origin:50% 100%;transition:transform .12s}
.stone:active img{transform:scale(.95)}
#stones.lock>.stone{pointer-events:none;cursor:default}   /* a tap would not count yet (rising / broken / waiting on the server) — game.js stoneLock() */
.stone .an{position:absolute;left:50%;margin-left:-188px;top:-49px;width:376px;height:290px;background:url() -2256px 0/2632px 290px no-repeat;display:none;pointer-events:none}
.stone.gone{z-index:2}.stone.gone img{display:none}
.stone.gone .an{display:block;animation:crash .12s step-end}   /* owner-tuned (Tap Timing Lab 2026-09-24): crash 120ms, frames 1,5,6,7, hard cuts */
.stone.grow img{animation:grow .06s ease-out backwards}   /* owner-tuned (Tap Timing Lab 2026-09-24): grow pop 60ms */
/* STONES RESET — rise up from below the screen (staggered in JS), ease-in-out */
.stone.rise{animation:stoneRise .34s ease-in-out backwards}
@keyframes stoneRise{0%{transform:translateY(700px);opacity:0}14%{opacity:1}100%{transform:translateY(0);opacity:1}}
@keyframes crash{0%{background-position:0 0}25%{background-position:-1504px 0}50%{background-position:-1880px 0}75%{background-position:-2256px 0}100%{background-position:-2256px 0}}   /* frames 1→5→6→7 (376px each); base style holds the frame-7 rubble after the animation ends */
@keyframes grow{0%{transform:scale(1.03)}55%{transform:scale(.98)}100%{transform:scale(1)}}   /* owner-tuned (Frame Lab): stone APPEARS INSTANTLY at 103% (no fade, no scale-up), dips to 98%, settles at 100% in 130ms */
#hand{z-index:14;width:150px;left:420px;top:1790px;animation:tap 1s ease-in-out infinite;display:none}
#fly{z-index:27;width:96px;display:none;filter:drop-shadow(0 0 14px #ffdf6b)}
.fx{position:absolute;z-index:46;font-size:44px;font-weight:800;color:#ffe36e;text-shadow:0 3px 0 #3d2a4f,0 0 12px rgba(0,0,0,.5);pointer-events:none;animation:rise 1.3s forwards;white-space:nowrap;display:flex;align-items:center;gap:10px}
.fx img{width:44px}
#idleCd{left:0;top:1560px;width:1080px;text-align:center;z-index:55;display:none;font-size:52px;font-weight:800;color:#ffe36e;text-shadow:0 3px 0 #3d2a4f,0 0 18px rgba(0,0,0,.6);animation:pulse 1s infinite}
/* tint + matrix */
#loseBg{z-index:18;display:none}
#stage.mx #loseBg{display:block}                             /* the lose screen shows the field you played on (game.js loseBgFromField) */
#loseShade{left:0;top:0;width:1080px;height:2160px;z-index:18;display:none;pointer-events:none;
  background:linear-gradient(180deg,rgba(12,8,24,.62) 0%,rgba(12,8,24,.30) 38%,rgba(12,8,24,.38) 62%,rgba(12,8,24,.82) 100%)}
#stage.mx #loseShade{display:block}
#stage.mx #tint{background:rgba(84,62,104,.26)}              /* owner: tint dialed down to 26% over it */
#tint{inset:0;z-index:20;background:rgba(84,62,104,.88);opacity:0;pointer-events:none;transition:opacity .6s}
#tint.on{opacity:1;pointer-events:auto}
#mx{inset:0;z-index:30;display:none;text-align:center}
#mx h1{position:absolute;left:0;width:100%;top:296px;font-size:80px;font-weight:800;color:#ffe36e;letter-spacing:-1px}   /* NB: for not this */
#mx h1{top:35px;left:-50px;transform:scale(1.2);transform-origin:top left}   /* owner layout v2 */
#mx h2{position:absolute;left:0;width:100%;top:398px;font-size:38px;font-weight:700}
#mx h2{top:173px;left:69px}   /* owner layout v2 */
.pill{position:absolute;left:489px;top:294px;transform:scale(.92);transform-origin:top left;display:flex;gap:18px}   /* owner: B glowing chip(s) */
.pill .chipK{width:250px;background:linear-gradient(160deg,#4a3560,#2c1f3e);border:3px solid #ffd75e;border-radius:24px;padding:22px 12px;box-shadow:0 0 22px rgba(255,215,94,.4);text-align:center}
.pill .chipK .n{font-size:62px;font-weight:800;color:#ffe36e;line-height:1}
.pill .chipK .n:empty{display:none}   /* pre-claim: no number yet, chip reads just "NEW KEYS"; the count appears once keys start landing */
.pill .chipK .t{font-size:22px;letter-spacing:.14em;color:#cbb8e0;margin-top:6px;display:flex;align-items:center;justify-content:center;gap:8px}
.pill .chipK .t img{height:78px;width:auto;filter:drop-shadow(0 4px 6px rgba(0,0,0,.45))}
/* KEYCHAIN chip (owner 2026-09-27): "NEW ● KEYS" — the keychain in its dark disc, words either side, no box, no glow.
   Same 250px slot as the old box so the saved lab position (mx-chip) still centres it. The count lands in place of NEW. */
.pill .chipK.kc{width:250px;background:none;border:0;box-shadow:none;padding:0;display:flex;align-items:center;justify-content:center;gap:22px;overflow:visible}
.pill .chipK.kc .t{margin:0;font-size:30px;font-weight:900;letter-spacing:.14em;color:#fff;white-space:nowrap;text-shadow:0 2px 8px rgba(0,0,0,.5)}
.pill .chipK.kc img.kc{height:130px;width:130px;filter:drop-shadow(0 6px 10px rgba(0,0,0,.45))}   /* owner 2026-09-27: NO glow on any key */   /* owner: big hero key in the chip (height-based for the tall K2 key) */
#grid{position:absolute;left:254px;top:499px;transform:scale(1.17);transform-origin:top left;width:700px;display:grid;grid-template-columns:repeat(6,114.8px);grid-auto-rows:169.6px}
.cell{position:relative}
.cell img.r{position:absolute;left:0;top:0;width:105px;opacity:.5}.cell.kk img.r{opacity:1}
.cell img.k{position:absolute;left:37px;top:24px;height:120px;width:auto;opacity:0}   /* K2 samurai key is tall (1:2.9) — size by height, upright, centered in the 115×170 cell */
.cell.kk img.k{opacity:.32;filter:brightness(0) invert(1)}   /* owner: ghost keys 32% */
.cell.ok img.k{opacity:1;filter:drop-shadow(0 4px 6px rgba(0,0,0,.45));transform-origin:50% 60%;animation:land 410ms cubic-bezier(.2,.8,.3,1) both}   /* owner 2026-09-27: NO glow on any key; owner 2026-10-10: each hit key LANDS in its stone (board_land_lab (lab retired 2026-10-12) pick) */   /* owner 2026-09-27: NO glow on any key; each hit key POPS in as its cell is revealed */
#grid .cell.ok img.k.taken{opacity:0!important;transition:opacity .12s}   /* CLAIM: key picked up & flown to the tally. #grid prefix beats the win-key override (#grid img.k[data-edit]) so the original vanishes as its flyer lifts off */
.cell.ok img.r{filter:brightness(.7)}
/* MISS marker — realistic red X emblem (SVG built in game.js as MISSX): crossing arms, dark bevel
   outline, red gradient, top gloss, rivet studs. Same .x element → lab "miss-x" edit still works. */
.cell .x{position:absolute;left:-6px;width:118px;height:118px;top:22px;font-size:0;display:none;filter:drop-shadow(0 4px 5px rgba(0,0,0,.4))}
.cell.fail .x{display:block;transform-origin:50% 50%;animation:land 410ms cubic-bezier(.2,.8,.3,1) both}   /* the X lands the same way (owner pick xToo=true) */
.cell .x svg.mx-svg{width:100%;height:100%;display:block;overflow:visible}
.cell .g{position:absolute;left:28px;top:54px;width:50px;height:50px;opacity:.6;transition:.3s}
.cell .g.win{opacity:1;transform:scale(1.7);filter:drop-shadow(0 0 10px #ffe36e)}
.cell .g img,.cell .g .orb{width:50px;height:50px}
#chs{display:none}   /* owner: chance column removed from the result board */

.btn{position:absolute;left:334px;width:413px;top:1780px;height:163px;line-height:1;display:flex;align-items:center;justify-content:center;border-radius:64px;background:#fde235;color:#2f2d2d;box-shadow:0 12px 0 #e4ac11;font-size:44px;font-weight:800;cursor:pointer;text-align:center;letter-spacing:2px}   /* GLOBAL BUTTON style (canon = intro CONTINUE); colors themable from the Intro Lab */
.btn:active{transform:translateY(6px);box-shadow:0 6px 0 #e4ac11}
#mxB{left:379px!important;top:1758px!important;transform:scale(1.04);transform-origin:top left}   /* owner layout (losing screen) */
#stage.mx #vNeed,#stage.mx #lvlbar{visibility:hidden!important}   /* owner v2: board screen shows NO pot / NO mana */
/* result-board content needs an explicit z so a lose-screen background card (z0-3) can sit BEHIND it (z2+ in front) */
#mx h1,#mx h2,#mx .pill,#mx #grid,#mx .btn,#mx .lnk{z-index:40}   /* above the lose-lab background-card ceiling (cards ≤39) so a card can never hide the CLAIM chip */
/* LOOSE BACKDROP (owner 2026-09-27): a black panel BEHIND the result stones, fully editable in the LOSE lab —
   move (--ox/--oy), scale (--os), opacity (--oa), corner radius (border-radius, editor "Corner radius"), layer
   (--oz). Defaults to a soft black rectangle covering the 6×6 grid area; pointer-events:none so it never blocks. */
#loosebg{position:absolute;left:254px;top:499px;width:820px;height:1191px;background:#000;pointer-events:none;
  z-index:var(--oz,39);opacity:var(--oa,.5);border-radius:48px;transform-origin:top left;
  transform:translate(var(--ox,0px),var(--oy,0px)) scale(var(--os,1))}
/* CLAIM chip: invites a tap on a keyed loss; glow-pulses (not scale — the lab may set a transform) */
#mxP.claimchip{border-radius:24px}   /* no pulse/glow on the keychain chip (owner) */   /* gentle glow to draw the eye; not clickable — collection fires on PLAY AGAIN / MAIN MENU */
#mxP.claimchip .t{color:#fff}
@keyframes claimpulse{0%,100%{box-shadow:0 0 10px rgba(255,215,94,.35)}50%{box-shadow:0 0 28px rgba(255,215,94,.9)}}
#stage.mx #ava,#stage.mx .hrow,#stage.mx #vLvl,#stage.mx #mode,#stage.mx #full,#stage.mx #stones,#stage.mx #hand,#stage.mx #ng,#stage.mx #potBag{visibility:hidden}   /* the board screen shows ONLY the owner's lab elements */   /* board screen shows only POT + mana (owner design — title now lives where the HUD was) */
/* win scene */
/* ===== WIN SCENE A1 (owner pick 2026-09-23): our tower top + fireworks + coin rain ===== */
@keyframes coinfall{0%{transform:translateY(-140px) rotate(0);opacity:0}8%{opacity:1}92%{opacity:1}100%{transform:translateY(2320px) rotate(540deg);opacity:0}}
@keyframes fwburst{0%{transform:translate(0,0) scale(1);opacity:0}6%{opacity:1}70%{opacity:.9}100%{transform:translate(var(--dx),var(--dy)) scale(.3);opacity:0}}
/* HUD */
#hud{left:0;top:0;width:100%;height:150px;z-index:50}
#ava{left:30px;top:31px;width:94px;height:94px;border-radius:50%;background:#fff no-repeat 46% 9%/205%;border:4px solid #fff;cursor:pointer}
.hrow{position:absolute;left:144px;display:flex;align-items:center;gap:12px;text-shadow:0 2px 4px rgba(0,0,0,.35)}
/* WAVE-2 tiered keys: bronze / silver / gold counters in the HUD (one key art, CSS-tinted) */
.krow{display:flex;align-items:center;gap:8px}
.kIco{height:44px;width:auto;filter:drop-shadow(0 4px 6px rgba(0,0,0,.45))}   /* K2 samurai key, upright, real per-metal art (bronze/silver/gold assets — no tint) */
#vKb{color:#e0a35c}#vKs{color:#dfe6ea}#vKg{color:#ffd94a}

#ctr{left:340px;width:400px;top:26px;text-align:center;text-shadow:0 2px 4px rgba(0,0,0,.35)}
#ctr b{display:block;font-size:56px;font-weight:800;line-height:1.05}#ctr span{font-size:26px;color:#ffe36e;font-weight:600}
#vNeed{display:inline-block;transition:transform .2s,color .2s}#vNeed.tick{transform:scale(1.31);color:#fff}   /* tick pulse on top of the 1.19 base scale */
/* mana = 20 SEGMENTS, one per smack (owner picked #2 in the Mana Bar Lab) */
#lvlbar{width:260px;height:20px;margin:8px auto 0;display:flex;gap:3px}
#lvlbar i{flex:1;border-radius:4px;background:rgba(61,42,79,.55);box-shadow:inset 0 1px 3px rgba(0,0,0,.5)}
#lvlbar i.on{background:linear-gradient(180deg,#c8f05a,#5abf3e);box-shadow:0 0 8px rgba(150,220,70,.55)}
#lvlup{display:none;margin:4px auto 0;width:300px;height:96px;line-height:96px;border-radius:48px;background:#fde235;color:#2f2d2d;box-shadow:0 8px 0 #e4ac11;font-size:40px;font-weight:800;cursor:pointer;text-shadow:none;animation:pulse 1s infinite}
#full{left:960px;top:40px;width:80px;height:80px;cursor:pointer}#full img{width:80px}
#toLobby{left:40px;top:300px;z-index:51;font-size:24px;font-weight:800;color:#ffe36e;background:rgba(20,14,28,.6);border:1px solid rgba(255,227,110,.4);border-radius:20px;padding:8px 18px;cursor:pointer;white-space:nowrap;transform-origin:top left;text-shadow:0 2px 4px rgba(0,0,0,.5)}   /* back to the lobby any time during play; position it in the Play Screen Lab */
#stage.mx #toLobby{visibility:hidden}   /* not on the result board (PLAY AGAIN / MAIN MENU are there) */
/* PORTRAIT LOCK — a phone held sideways gets a friendly "turn it up" screen. Only fires on short, landscape, TOUCH screens so desktop/tablet testing is never blocked. */
#rotate{display:none;position:fixed;inset:0;z-index:9999;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:16px;padding:18px;background:radial-gradient(circle at 50% 34%,#241a38,#0c0a16)}
#rotate img{width:auto;height:min(58vh,340px);max-width:86vw;filter:drop-shadow(0 10px 26px rgba(0,0,0,.55));animation:rwig 2.6s ease-in-out infinite;transform-origin:50% 60%}
@keyframes rwig{0%,100%{transform:rotate(-5deg)}50%{transform:rotate(5deg)}}
@media (orientation:landscape) and (max-height:600px) and (pointer:coarse){#rotate{display:flex}}
/* live "how many are attacking this tower" — humans present + active bots (tower_player_counts) */
/* "attacking now" = 3 independent, background-free elements; each left/top/scale/color is set in the Play Screen Lab (draw your own card behind them) */
.atkEl{position:absolute;z-index:49;pointer-events:none;display:none;transform-origin:top left;color:#ffd9c0;font-size:27px;font-weight:800;text-shadow:0 2px 4px rgba(0,0,0,.5);white-space:nowrap}
#atkIco{left:352px;top:352px}#atkIco img{height:34px;width:auto;filter:drop-shadow(0 1px 2px rgba(0,0,0,.5))}
#atkNum{left:402px;top:352px}#atkNum b{color:#ff9e6b}
#atkLbl{left:446px;top:356px}
#stage.mx .atkEl{visibility:hidden}   /* not on the result board */
/* published background cards (design labs): each card is a direct child of its screen's container with its own z.
   PLAY cards are direct children of #stage → hide them on the result board (LOSE cards live inside #mx and stay). */
#stage.mx > [data-ovrcard]{display:none}
#lvlbar.full i.on{background:#7ee08a;animation:pulse 1s infinite}
.orb{border-radius:50%;background:radial-gradient(circle at 35% 30%,#e9fdff,#36bfe8 45%,#0b5b9a);box-shadow:0 0 12px rgba(95,216,255,.8);display:inline-block}
#modal{inset:0;z-index:91;background:rgba(40,28,52,.7);display:none}
#mbox{position:absolute;left:calc(50% - var(--jw,852px)/2);width:var(--jw,852px);min-height:var(--jh,0px);box-sizing:border-box;top:790px;background:#3d2a4f;border-radius:var(--jr,30px);padding:60px 50px;text-align:center;transform:translate(var(--ox,0px),var(--oy,0px)) scale(var(--os,1));opacity:var(--oa,1)}
#mbox [data-edit]{--ox:0px;--oy:0px;--os:1;--oa:1;transform:translate(var(--ox,0px),var(--oy,0px)) scale(var(--os,1));opacity:var(--oa,1)}   /* message box parts: editor elements (owner 2026-09-28) */
#mbox h3{font-size:calc(var(--ofs,50px) * var(--fit,1));font-weight:800;color:#ffe36e}#mbox p{font-size:var(--ofs,34px);font-weight:400;margin:20px 0 40px;line-height:1.35}
#mbtns>div{font-size:var(--ofs,34px)}
#mbtns{display:flex;flex-direction:column;gap:22px}#mbtns div{height:110px;line-height:110px;border-radius:55px;background:#fde235;color:#2f2d2d;box-shadow:0 8px 0 #e4ac11;font-size:36px;font-weight:800;cursor:pointer;letter-spacing:1px}
#mbtns div.alt{background:#574070;color:#fff}
#mbox.nobg{background:none}   /* editor: sheet background OFF */
#toast{left:114px;right:114px;top:380px;z-index:92;background:#3d2a4f;border-radius:20px;padding:26px;font-size:var(--ofs,34px);text-align:center;opacity:0;transition:.3s;pointer-events:none;font-weight:500;transform:translate(var(--ox,0px),var(--oy,0px)) scale(var(--os,1))}
#flash{inset:0;z-index:55;background:#fff;opacity:0;pointer-events:none}

.scr{position:absolute;inset:0;z-index:80;display:none;background:#4a3560 center/cover no-repeat;text-align:center;overflow:hidden}
.scr .x{position:absolute;right:40px;top:36px;width:90px;height:90px;cursor:pointer;z-index:3}
.scr .x:before,.scr .x:after{content:'';position:absolute;left:12px;top:41px;width:66px;height:8px;border-radius:4px;background:#ffe36e;transform:rotate(45deg)}.scr .x:after{transform:rotate(-45deg)}
.b{position:absolute;display:block;height:163px;line-height:163px;border-radius:24px;background:#ffe36e;color:#3d2a4f;font-size:44px;font-weight:800;cursor:pointer;letter-spacing:1px;text-decoration:none;text-align:center}
.b:active{transform:scale(.97)}.b.p{background:#4a3560;color:#fff;box-shadow:0 0 0 2px rgba(255,255,255,.06) inset}.b.off{opacity:.55}
.lnk{position:absolute;left:0;width:100%;font-size:38px;font-weight:700;cursor:pointer;text-shadow:0 2px 6px rgba(0,0,0,.4)}
.lnk.big{font-size:46px;padding:34px 0}   /* enlarged tap band while it's the only live control (10s sharing window) */
.scr h1{position:absolute;left:0;width:100%;font-size:72px;font-weight:800;color:#ffe36e}
.scr h2{position:absolute;left:0;width:100%;font-size:38px;font-weight:500}
#ld{z-index:95;background-color:#0e2230}#ld:before{content:'';position:absolute;inset:-40px;background:inherit;background-size:cover;filter:blur(18px) brightness(.6)}
#ld img{position:absolute;left:408px;top:420px;width:264px}#spin{position:absolute;left:490px;top:1000px;width:100px;height:100px;border-radius:50%;border:10px dotted #fff;opacity:.85;animation:spin 1.6s linear infinite}
#ld p{position:absolute;left:0;width:100%;top:1225px;font-size:32px;font-weight:400}
#wl>img{position:absolute;left:195px;top:250px;width:690px;animation:bob 3s ease-in-out infinite}
#wl p{position:absolute;left:70px;width:940px;top:690px;font-size:38px;line-height:1.3;text-shadow:0 2px 8px rgba(0,0,0,.45)}#wl p i{font-style:normal;font-weight:400;font-size:32px}
#mn>img{position:absolute;left:380px;top:300px;width:320px}
.panel{position:absolute;left:56px;width:969px;border-radius:24px;background:rgba(61,42,79,.72)}
.tile{position:absolute;top:1363px;width:303px;height:218px;border-radius:20px;background:#ffe36e;color:#3d2a4f;cursor:pointer;padding-top:52px;font-size:40px;font-weight:800;line-height:1.2}
.tile small{display:block;font-size:27px;font-weight:500;margin-top:8px}.tile.sel{box-shadow:0 0 0 8px #fff}.tile:active{transform:scale(.97)}
#rl{background:#4a3560;text-align:left}#rlIn{position:absolute;inset:0;overflow-y:auto;padding:150px 70px 200px;touch-action:pan-y;-webkit-overflow-scrolling:touch}
#rlIn img{width:520px;margin:30px auto 50px}#rlIn h4{font-size:38px;color:#ffe36e;margin:20px 0 26px;font-weight:800}#rlIn p{font-size:33px;line-height:1.5;font-weight:400;margin-bottom:34px}#rlIn p b{font-weight:700}
#pfTop{position:absolute;left:0;top:0;width:100%;height:900px;background:rgba(61,42,79,.6)}
#pfAva{position:absolute;left:154px;top:220px;width:214px;height:214px;border-radius:50%;background:#fff no-repeat 46% 9%/205%;border:6px solid #fff}
#pfName{position:absolute;left:415px;top:238px;text-align:left;font-size:36px;font-weight:500}#pfName b{display:block;font-size:64px;font-weight:800;line-height:1.2}#pfName span{color:#ffe36e}
#pfStats{position:absolute;left:0;width:100%;top:760px;display:flex;justify-content:space-around;font-size:40px;font-weight:600}
#pfSw{position:absolute;left:0;top:900px;width:100%;height:198px;background:rgba(40,28,52,.55);display:flex;justify-content:center;gap:90px;align-items:center;font-size:32px;font-weight:600}
.sw{display:flex;align-items:center;gap:22px;cursor:pointer}.sw i{width:126px;height:51px;border-radius:26px;background:#2a1d38;position:relative;transition:.2s}
.sw i:after{content:'';position:absolute;left:6px;top:6px;width:39px;height:39px;border-radius:50%;background:#8a7a9c;transition:.2s}.sw.on i:after{left:81px;background:#ffe36e}
#bub{position:absolute;left:41px;top:894px;width:1003px;min-height:600px;z-index:48;display:none;background:#fff;color:#1c1424;border-radius:70px;padding:120px 150px 80px;font-size:36px;line-height:1.42;font-weight:400;text-align:left;box-shadow:0 12px 40px rgba(40,28,52,.35)}
#bub:after{content:'';position:absolute;right:120px;bottom:-78px;border:40px solid transparent;border-top:60px solid #fff;border-right-width:10px;transform:skewX(-20deg)}
#bub b{font-weight:800}#bub u{display:block;margin-top:50px;text-align:center;font-weight:800;cursor:pointer;font-size:38px}
#bubX{position:absolute;right:36px;top:36px;width:92px;height:92px;border-radius:50%;background:#3d2a4f;cursor:pointer}
#bubX:before,#bubX:after{content:'';position:absolute;left:24px;top:43px;width:44px;height:6px;border-radius:3px;background:#fff;transform:rotate(45deg)}#bubX:after{transform:rotate(-45deg)}
#mode{font-size:22px;letter-spacing:2px;color:#fff;opacity:.85;display:block;margin-top:4px}
/* sound lab */
#sdTabs{position:absolute;left:0;width:100%;top:330px;display:flex;justify-content:center;gap:26px}
#sdTabs div{width:220px;height:92px;line-height:92px;border-radius:18px;background:#4a3560;cursor:pointer;font-size:36px;font-weight:800;box-shadow:0 0 0 2px rgba(255,255,255,.08) inset}
#sdTabs div.sel{background:#ffe36e;color:#3d2a4f}
#sdList{position:absolute;left:44px;right:44px;top:470px;height:940px;overflow-y:auto;touch-action:pan-y;-webkit-overflow-scrolling:touch;text-align:left;border-bottom:3px solid rgba(255,255,255,.15);padding-bottom:20px}
.chips{flex:1;min-width:0;display:flex;flex-wrap:wrap;gap:12px}
.chip{background:#fff;color:#3d2a4f;border-radius:30px;padding:12px 22px;font-size:25px;font-weight:600;cursor:pointer;white-space:nowrap}
.chip u{text-decoration:none;margin-left:14px;color:#c0392b;font-weight:800}
.chip.dim{background:rgba(255,255,255,.16);color:#fff;opacity:.7;cursor:default}
#sdLib{position:absolute;left:44px;right:44px;top:1440px;bottom:40px;overflow-y:auto;touch-action:pan-y;-webkit-overflow-scrolling:touch;text-align:left}
#sdLib p,#sdList p{font-size:32px;font-weight:400;opacity:.8;margin-top:40px;text-align:center}
@keyframes spin{to{transform:rotate(360deg)}}
@keyframes pulse{50%{opacity:.65}}
/* idle "alive" loop: breathe (chest/shoulders rise via bottom-anchored scaleY) + a tiny shoulder sway */
@keyframes bob{0%,100%{transform:translateY(0) rotate(0) scale(1,1)}25%{transform:translateY(-3px) rotate(.4deg)}50%{transform:translateY(-7px) rotate(0) scale(1.012,1.022)}75%{transform:translateY(-3px) rotate(-.4deg)}}
@keyframes hop{40%{transform:translateY(-16px) scale(1.06)}}
@keyframes rise{to{transform:translateY(-90px);opacity:0}}
@keyframes pop{from{transform:scale(2.2);opacity:0}}
/* lose-board landing — owner pick 2026-10-10 from board_land_lab (lab retired 2026-10-12): {"boardLand":{"drop":28,"start":1.9,"squash":0.87,"over":1.18,"dur":410,"touch":48,"wobble":true,"xToo":true}}
   drop from above at 1.9× → touchdown at 48 % squashed to .87 → overshoot 1.18 at 69.84 % → small wobble .937 at 84.92 % → rest.
   2026-10-10: option 2 (56 px / 600 ms) was tried live and reverted the same hour — owner: "sad su veći nego što su bili, vrati" — his original numbers stay */
/* every frame composes the lose editor's own place/size (--ox/--oy/--os on win-key / miss-x) so the landing never jumps off the edited spot */
@keyframes land{0%{transform:translate(var(--ox,0px),calc(var(--oy,0px) - 28px)) scale(calc(var(--os,1) * 1.9));opacity:0}18%{opacity:1}48%{transform:translate(var(--ox,0px),var(--oy,0px)) scale(calc(var(--os,1) * .87));opacity:1}69.84%{transform:translate(var(--ox,0px),var(--oy,0px)) scale(calc(var(--os,1) * 1.18))}84.92%{transform:translate(var(--ox,0px),var(--oy,0px)) scale(calc(var(--os,1) * .937))}100%{transform:translate(var(--ox,0px),var(--oy,0px)) scale(calc(var(--os,1) * 1))}}
@keyframes tap{50%{transform:translate(8px,22px)}}
/* shake must compose with the tower's own position (--ox/--oy/--os) — bare translateX snapped it back to
   centre (a rightward jump) before the lose-slide. Jitter AROUND the real position instead. */
@keyframes shake{
  0%,100%{transform:translate(var(--ox,0px),var(--oy,0px)) scale(calc(1.22 * var(--os,1)))}
  20%{transform:translate(calc(var(--ox,0px) - 14px),var(--oy,0px)) scale(calc(1.22 * var(--os,1)))}
  40%{transform:translate(calc(var(--ox,0px) + 12px),var(--oy,0px)) scale(calc(1.22 * var(--os,1)))}
  60%{transform:translate(calc(var(--ox,0px) - 8px),var(--oy,0px)) scale(calc(1.22 * var(--os,1)))}
  80%{transform:translate(calc(var(--ox,0px) + 6px),var(--oy,0px)) scale(calc(1.22 * var(--os,1)))}
}

/* ===== owner layout pass (from /?edit COPY CHANGES, 2026-09-20) =====
   !important so these final overrides always beat base rules like `#ctr span{font-size:26px}` (which is more
   specific than a plain `#vNeed` and was silently shrinking the POT). The editor now exports !important too. */
#wl p:nth-child(4)>i:nth-child(3){position:relative!important;left:0!important;top:29px!important;font-size:38px!important}
#ctrInfo{position:relative!important;left:1px!important;top:123px!important}
#vLvl{position:absolute!important;left:225px!important;top:-121px!important;font-size:28px!important;font-weight:800!important;width:400px;text-align:center}   /* tower name top-right, abs (566,28) */
#vNeed{position:absolute!important;left:202px!important;top:-36px!important;width:400px;text-align:left;transform:scale(1.37);transform-origin:top left;font-size:62px!important;font-weight:800!important;min-height:84px;line-height:84px;color:#fff}   /* owner: pot AMOUNT — LEFT-aligned so the left edge is the drag anchor (value length no longer shifts it); position from the money bag */
#potBag{position:absolute;left:284px;top:-36px;height:115px;transform-origin:top left}   /* the MONEY BAG — its own element, positioned separately in the lab */
#mode{position:absolute!important;left:302px!important;top:-89px!important;width:400px;text-align:left;transform:scale(1.26);transform-origin:top left;font-size:26px!important}   /* price/tries line — LEFT-aligned to match the pot amount (left edge = anchor) */
#lvlbar{position:absolute!important;left:-301px!important;top:892px!important;margin:0!important;transform:scale(2.26) rotate(-90deg) translate(-260px,0);transform-origin:top left}   /* owner: VERTICAL mana, left side, ×2.26, fills upward — abs (40,1041) */
#iCoin{position:relative!important;left:13px!important;top:-7px!important}
#vCoins{position:relative!important;left:13px!important;top:-10px!important}
#rowKeys{flex-direction:column!important}   /* WAVE-2 guard: keep the 3 tiered-key rows stacked even if a hand-edited published layout override sets a conflicting display/flex on #rowKeys (labs export can't emit this, but DB-direct edits could) */

/* === new app: hide the engine's legacy HUD — the V3 HUD (tower screen) replaces it === */
#hud,#toLobby,#hand,.atkEl{display:none!important}

/* === new app: make the LOSE result-board fully lab-editable (move/scale/fade), composing base transforms === */
#mxT{transform:translate(var(--ox,0px),var(--oy,0px)) scale(calc(1.2 * var(--os,1)))!important}
#mxS{transform:translate(var(--ox,0px),var(--oy,0px)) scale(var(--os,1))!important}
.pill#mxP{transform:translate(var(--ox,0px),var(--oy,0px)) scale(calc(.92 * var(--os,1)))!important}
#grid{transform:translate(var(--ox,0px),var(--oy,0px)) scale(calc(1.17 * var(--os,1)))!important}
#mxB{transform:translate(var(--ox,0px),var(--oy,0px)) scale(calc(1.04 * var(--os,1)))!important}
/* the PLAY AGAIN text is its own editor element (owner 2026-09-28): move it inside the button, size, colour, wording */
#mxB .btxt{display:inline-block;--ox:0px;--oy:0px;--os:1;--oa:1;transform:translate(var(--ox,0px),var(--oy,0px)) scale(var(--os,1));opacity:var(--oa,1);font-size:var(--ofs,inherit)}
#mxM,#mxV{transform:translate(var(--ox,0px),var(--oy,0px)) scale(var(--os,1))!important}
#mxM{display:flex;justify-content:center;align-items:center;gap:12px;line-height:1}   /* "← LOBBY" (owner's pick 2026-10-06, back_lobby_lab (lab retired 2026-10-12): arrow · LOBBY · #ffe36e · 32 px · arrow .95em · gap 12 · stroke 3.5 · arrow -0.14em) — was MAIN MENU */
#mxM .bl-ico{display:inline-flex;width:.95em;height:.95em;flex:none;transform:translateY(-.14em);filter:drop-shadow(0 2px 6px rgba(0,0,0,.4))}   /* Luckiest Guy's capitals sit .14em above the line's middle — the arrow rises with them */
#mxM .bl-ico svg{width:100%;height:100%;display:block}
/* board cell sub-elements — edit ALL of a kind at once (shared data-edit key): size + transparency + position */
/* keys: the GHOST look applies only while the cell is NOT yet hit (.ok) — the reveal loop adds .ok one cell at a time
   and the cell is re-tagged win-key synchronously (tower.js/lose.js observer). No !important on opacity/transform:
   the specificity already wins, and !important would kill the `pop` keyframes (they animate transform + opacity). */
#grid .cell:not(.ok) img.k[data-edit="ghost-key"]{opacity:var(--oa,.32);transform:translate(var(--ox,0px),var(--oy,0px)) scale(var(--os,1))}
#grid .cell.ok img.k[data-edit="win-key"]{opacity:var(--oa,1);transform:translate(var(--ox,0px),var(--oy,0px)) scale(var(--os,1))}
#grid .cell:not(.kk) img.r[data-edit="rock-empty"]{opacity:var(--oa,.5)!important;transform:translate(var(--ox,0px),var(--oy,0px)) scale(var(--os,1))!important}
#grid .cell.kk img.r[data-edit="rock-key"]{opacity:var(--oa,1)!important;transform:translate(var(--ox,0px),var(--oy,0px)) scale(var(--os,1))!important}
#grid .x[data-edit="miss-x"]{transform:translate(var(--ox,0px),var(--oy,0px)) scale(var(--os,1))}   /* no !important since 2026-10-10: it would block the landing animation, whose frames carry the same vars */
/* waiting for the server's answer to a smack (js/game/net.js rpcSmack): three pulsing dots over the smashed stone after 1 s */
#stones>.stone.pend::after{content:'\2022\2022\2022';position:absolute;left:50%;top:-40px;transform:translateX(-50%);font:700 78px/1 sans-serif;letter-spacing:10px;color:#fff;text-shadow:0 0 3px #000,0 0 8px #000,0 2px 0 #1a1226;animation:pendDots .9s ease-in-out infinite;pointer-events:none}   /* ≈28 px on a phone, dark edge so it reads on the desert sand too (agent review) */
@keyframes pendDots{0%,100%{opacity:.5}50%{opacity:1}}
@media (prefers-reduced-motion:reduce){#stones>.stone.pend::after{animation:none;opacity:1}}
