@font-face{font-family:"Lilita One";src:url(../assets/fonts/lilita-one-latin-400-normal.woff2) format("woff2");font-weight:400;font-display:swap}
@font-face{font-family:"Nunito";src:url(../assets/fonts/nunito-latin-800-normal.woff2) format("woff2");font-weight:700 900;font-display:swap}
/* Voxel Siege: the game-ui-basic kit (css/ui-kit.css, loaded first) skinned to the indigo-and-gold reference
   (art-source~/ref/ui-reference.webp). Layout: painted arena (#bg) + transparent 3D canvas, HUD on top, slot bar and
   the crate panel docked at the bottom. The page is laid out at a 440x900 reference (game.js applyViewport); every UI
   row sits in one 440 px column, so the UI is identical from 1:2.1 phones to 3:4 tablets. */
:root{
  --ink:#1c1438; --gold:#ffcf4a; --gold-2:#e39a23; --goldline:#b98a45; --indigo:#2e2563; --indigo-2:#1d1742; --cream:#fff3dc; --hp:#e9353c;
  color-scheme:light;
  /* native insets arrive in device px; the page is scaled by --ui-scale, so divide */
  --safe-top:calc(var(--ub-safe-top,env(safe-area-inset-top,0px)) / var(--ui-scale,1));
  --safe-bottom:calc(var(--ub-safe-bottom,env(safe-area-inset-bottom,0px)) / var(--ui-scale,1));
  --safe-left:calc(var(--ub-safe-left,env(safe-area-inset-left,0px)) / var(--ui-scale,1));
  --safe-right:calc(var(--ub-safe-right,env(safe-area-inset-right,0px)) / var(--ui-scale,1));
  --col:440px;
}
html,body{background:#7cc65a;-webkit-touch-callout:none}
/* the painted arena: a 3:4 picture filling the screen height, centred. A 3:4 tablet shows all of it, taller phones
   crop the sides. */
#bg{position:fixed;top:0;left:50%;height:100%;width:auto;max-width:none;max-height:none;transform:translateX(-50%);pointer-events:none;user-select:none} /* max-width:none: a page-wide img{max-width:100%} would squeeze it; it crops at the sides instead */
#gl{position:fixed;inset:0;width:100%;height:100%;display:block;touch-action:none}
#ui{position:fixed;inset:0;display:flex;flex-direction:column;pointer-events:none;padding-top:calc(var(--safe-top) + 8px)}
.gut{width:100%;max-width:var(--col);margin-inline:auto;box-sizing:border-box;padding-inline:14px}
.title-text{font-size:44px} /* the kit's vw clamp would grow on tablets; the column is fixed */

/* ---------------------------------------------------------------- HUD: buttons, crowned title plate, HP bar */
#hud{display:flex;flex-direction:column;align-items:center}
.hrow{display:flex;align-items:center;justify-content:space-between;width:100%}
.hspace{flex:none;width:52px} /* (unused: the speed button now balances the pause button) */
.hbtn{pointer-events:auto;flex:none;width:52px;height:51px;padding:0;border:0;background:none;cursor:pointer;transition:transform .1s ease-out}
.hbtn img{width:100%;height:100%;display:block}
.hbtn:active{transform:scale(.92)}
/* x3 speed boost: a square button like the pause one (gold frame, rounded face, CSS-drawn): grey while off, warm and
   glowing (an additive white inner outline) while on, with the time left in a little panel under it */
.spdwrap{position:relative;flex:none;width:52px;height:51px}
.hbtn.spd{position:relative;width:52px;height:51px;border-radius:14px;box-sizing:border-box;border:3px solid #f4b42c;
  background:linear-gradient(#ffd56a,#e9952a);box-shadow:inset 0 0 0 2px #fff0b0,0 3px 0 #9a5a12,0 4px 6px rgba(20,10,40,.35);
  filter:grayscale(1) brightness(.95);transition:transform .1s ease-out,filter .2s ease-out}
.hbtn.spd::before{content:"";position:absolute;inset:4px;border-radius:9px;background:linear-gradient(#5b4bd6,#3a2c9e)}
.hbtn.spd span{position:relative;font-family:var(--display);font-size:22px;line-height:1;color:#fff;-webkit-text-stroke:4px var(--ink);paint-order:stroke fill;text-shadow:0 2px 0 var(--ink)}
.hbtn.spd::after{content:"";position:absolute;inset:4px;border-radius:9px;border:2px solid rgba(255,255,255,.55);mix-blend-mode:plus-lighter;opacity:0;transition:opacity .2s ease-out}
.hbtn.spd.on{filter:none}
.hbtn.spd.on::before{background:linear-gradient(#ff8a3d,#e8306a)}
.hbtn.spd.on::after{opacity:1}
.spdtime{position:absolute;left:50%;top:100%;margin-top:3px;translate:-50% 0;padding:1px 7px 2px;border-radius:9px;background:#2a1f55;border:2px solid #f4b42c;
  font-family:var(--display);font-size:12px;line-height:14px;color:#fff;white-space:nowrap;font-variant-numeric:tabular-nums;
  opacity:0;scale:.6;transition:opacity .18s ease-out,scale .22s cubic-bezier(.3,1.5,.5,1);pointer-events:none}
.hbtn.spd.on+.spdtime{opacity:1;scale:1}
.spdbig{width:84px;height:84px;margin:0 auto;border-radius:22px;border:4px solid #f4b42c;background:linear-gradient(#ff8a3d,#e8306a);display:grid;place-items:center;
  box-shadow:inset 0 0 0 3px rgba(255,255,255,.4),0 4px 0 #9a5a12}
.spdbig span{font-family:var(--display);font-size:38px;color:#fff;-webkit-text-stroke:6px var(--ink);paint-order:stroke fill;text-shadow:0 3px 0 var(--ink)}
#plate{position:relative;top:-9px;z-index:1;width:199px;height:63px;flex:none;background:url(../assets/ui/plate.webp) center/100% 100% no-repeat;
  display:flex;align-items:center;justify-content:center;padding:19px 26px 5px;box-sizing:border-box}
#ename{font-family:var(--display);font-size:16.5px;line-height:1;color:#fff;white-space:nowrap;letter-spacing:.01em;
  -webkit-text-stroke:3px var(--ink);paint-order:stroke fill;text-shadow:0 1.5px 0 var(--ink)}
#ename b{font-weight:400;background:linear-gradient(#fff4a8,#ffc928 60%,#f39a1c);-webkit-background-clip:text;background-clip:text;color:transparent;-webkit-text-stroke:0;text-shadow:none;
  filter:drop-shadow(0 0 1.5px var(--ink)) drop-shadow(0 2px 0 var(--ink))}
#ename i{font-style:normal;font-size:10px;background:linear-gradient(#ff6a5c,#c8202c);border:2px solid var(--ink);border-radius:7px;padding:0 5px 1px;margin-right:5px;vertical-align:2px;letter-spacing:.06em;-webkit-text-stroke:3px var(--ink)}
/* HP bar: generated art (art-source~/ui/hp-v1.png): dark track, the glossy red capsule fill (a 9-slice, so it shrinks
   with rounded ends; game.js updateHP sets --hp 0..1), then the gold frame with a transparent hole on top */
#hpbar{position:relative;width:272px;height:36px;margin-top:-14px;--hp:1}
#hpbar::before{content:"";position:absolute;inset:7px 8px;border-radius:12px;background:#3d0f19;box-shadow:inset 0 3px 4px rgba(0,0,0,.55)}
#hpfill{position:absolute;left:7px;top:7px;bottom:7px;width:calc((100% - 14px) * var(--hp));box-sizing:border-box;
  border:2px solid transparent;border-image:url(../assets/ui/hp-fill.webp) 32 fill / 11px;transition:width .2s ease-out}
/* lag: a white bar that trails the HP, catching up once a second (--hplag, set in game.js lagStep) */
#hplag{--d:calc((100% - 14px) * (var(--hplag,1) - var(--hp)));position:absolute;top:7px;bottom:7px;left:calc(7px + (100% - 14px) * var(--hp) - 11px);
  width:max(0px,calc(min(var(--d) * 100,11px) + var(--d)));border-radius:0 11px 11px 0;background:linear-gradient(#ffffff,#ffe9e4);transition:width .4s ease-out,left .2s ease-out}
/* the white lag exists only past the fill: it starts 11px under the fill's rounded end and is 0 wide once caught up,
   so no white can show around the fill's ends */
#hpbar::after{content:"";position:absolute;inset:0;border:2px solid transparent;border-image:url(../assets/ui/hp-frame.webp) 43 / 18px;pointer-events:none}
#hptext{position:absolute;inset:0;z-index:1;display:grid;place-items:center;font-family:var(--display);font-size:17px;line-height:1;color:#fff;
  -webkit-text-stroke:4px var(--ink);paint-order:stroke fill;font-variant-numeric:tabular-nums}

/* ---------------------------------------------------------------- dock: slots + the crate panel, no full-width backdrop
   (the painted arena shows around them). Frames are generated art (art-source~/ui), drawn as 9-slices. */
#view{flex:1;position:relative}
/* gameplay callouts (game.js callout): big gold words over the boss, animated in and out with the Web Animations API */
#callout{position:absolute;left:0;right:0;top:18%;margin:0;text-align:center;font-family:var(--display);font-size:40px;line-height:1;color:#ffd23f;
  -webkit-text-stroke:6px var(--ink);paint-order:stroke fill;text-shadow:0 4px 0 var(--ink);opacity:0;pointer-events:none;will-change:transform,opacity}
#dock{position:relative;pointer-events:none;padding-top:6px;padding-bottom:calc(var(--safe-bottom) + 8px)}
#slots{display:grid;gap:10px;margin:0 0 29px;justify-content:space-evenly} /* columns: game.js SLOT_W each, never stretched, spread evenly over the row */
/* a slot is a round wooden podium at its bottom; the docked warrior stands on its top (game.js SLOT_DROP) */
.slot{position:relative;height:68px;box-sizing:border-box;transition:translate .35s ease-out} /* translate: game.js arcSlots */
/* the podiums live in #pods, a layer under the 3D canvas that game.js syncPods keeps on the slots' screen rects, so the
   3D heroes waiting on a slot stand on top of it */
#pods{position:fixed;inset:0;pointer-events:none}
.pod{position:fixed}
.pod::before{content:"";position:absolute;left:0;right:0;bottom:0;aspect-ratio:152/78;background:url(../assets/ui/podium.png) center/contain no-repeat;
  scale:1.09;transform-origin:50% 47%} /* the empty-slot podium, about its top centre (where the warriors stand) */
#pods.no-podium .pod::before{display:none} /* game.js SHOW_PODIUMS */
/* a filled slot: the round button in its crate's colour (game.js podBtn) pops in over the stone podium, and fades out
   when the slot empties; the stone podium fades under it */
.pod>i{position:absolute;left:0;right:0;bottom:0;aspect-ratio:283/137;background:center/100% 100% no-repeat;scale:.7;opacity:0;transform-origin:50% 47%;
  transition:opacity .18s ease-out,scale .28s cubic-bezier(.3,1.5,.5,1)}
.pod.on>i{opacity:1;scale:1.14} /* 15% bigger than the stone podium, then 95% */
.pod::before{transition:opacity .18s ease-out}
.pod.on::before{opacity:0;transition-delay:.1s}
.sunit.squad>img{display:none} /* the 3D squad on the podium has taken over from the flying 2D hero; the count stays */
.slot::after{content:"";position:absolute;left:-3px;right:-3px;bottom:-3px;aspect-ratio:283/137;border-radius:50%;scale:1.09;transform-origin:50% 47%;border:3px solid #ff4a4a;box-shadow:0 0 12px rgba(255,60,60,.85);opacity:0;pointer-events:none}
.slot::after{display:none} /* the red slot-warning ring is off (the last-free-slot pulse and full-slots glow above) */
.slot.warn::after{animation:slotWarn .9s ease-in-out infinite}
.slot.full::after{opacity:.75;transition:opacity .25s}
@keyframes slotWarn{0%,100%{opacity:.15}50%{opacity:.95}}
.slot.shake{animation:shake .3s}
.slot.added{animation:slotIn .45s var(--spring)}
@keyframes slotIn{from{transform:scale(.3);opacity:0}to{transform:none;opacity:1}}
@keyframes shake{25%{transform:translateX(-4px)}75%{transform:translateX(4px)}}
#panel{border:2px solid transparent;border-image:url(../assets/ui/panel.webp) 52 fill / 26px;padding:9px 9px 3px}
#cols{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;min-height:253px} /* the height of three rows + the "+N" line: the panel never shrinks as columns run low */
.col{display:flex;flex-direction:column;gap:8px;min-width:0}
.col .crate.front{margin-top:-8px}.col .crate.q:nth-of-type(2){margin-top:22px} /* a little gap between the front row and the queue */

/* crate: the pre-rendered card button of its colour (game.js crateEl sets the image) with the icon and count on top */
/* Cards are 9-slices: the corners (46 px in the 280x172 source) keep their shape at any card size. --ppu works like
   Unity's "Pixels Per Unit Multiplier": corners are drawn at 46px / --ppu, so a higher value = smaller rounded corners
   and a thinner rim. */
.crate{--ppu:3.2;position:relative;height:68px;box-sizing:border-box;display:grid;place-items:center;
  border:2px solid transparent;border-image-slice:46 fill;border-image-width:calc(46px / var(--ppu));border-radius:calc(40px / var(--ppu))}
.crate>img{position:absolute;left:50%;top:50%;width:107px;height:107px;max-width:none;max-height:none;margin:-75.5px 0 0 -57.5px;pointer-events:none} /* bigger than the card: centred 4px left, 22px up, so his feet stay low on the card */ /* head to feet (and shadow) stay inside the card, like art-source~/ref/card-target.png */
.crate .num,.sunit .num{position:absolute;right:-2px;bottom:3px;min-width:22px;height:22px;padding:0 4px;box-sizing:border-box;border-radius:11px;
  background:radial-gradient(circle at 40% 30%,#fffaf0,#f3e2bf 70%);border:1.5px solid #6b4a22;box-shadow:0 1px 2px rgba(20,10,40,.45);
  font-family:var(--display);font-size:13px;line-height:19px;text-align:center;color:#3a2716;font-variant-numeric:tabular-nums}
.col .crate.front{pointer-events:auto;cursor:pointer;transition:transform .12s ease-out}
.crate.bmp{border-image:none;background-origin:border-box;background-size:100% 100%} /* the seamless bitmap (game.js crateCard) */
.col .crate.front:active{transform:scale(.94)}
/* after a tap every card of that column moves up one row from exactly where it was: 2nd to front 90px (card 68 + gap 8
   + the front row gap 14), 3rd to 2nd 76px */
.col .crate.rise{animation:riseQ .3s cubic-bezier(.25,1.15,.45,1)}
.col .crate.q.rise:nth-of-type(3){animation-name:riseIn} /* the card coming in from the hidden queue fades in */
.col .crate.front.rise{animation-name:riseFront}
/* the queued soldiers are 90% size (scaled about their feet); one reaching the front row grows back to full size */
.col .crate>img{transform-origin:54% 87%}
.col .crate.q>img{scale:.9}
.col .crate.front.rise>img{animation:soldierUp .3s cubic-bezier(.25,1.15,.45,1)}
@keyframes soldierUp{from{scale:.9}to{scale:1}}
@keyframes riseFront{from{transform:translateY(90px)}to{transform:none}}
@keyframes riseQ{from{transform:translateY(76px)}to{transform:none}}
@keyframes riseIn{from{transform:translateY(76px);opacity:0}to{transform:none;opacity:1}}
.more{align-self:center;min-width:50px;height:18px;box-sizing:border-box;padding:0 9px;margin-top:-7px;
  font-family:var(--display);font-size:19px;line-height:18px;text-align:center;color:var(--cream)}
.more:empty{visibility:hidden}
/* a docked warrior: standing in the slot, his head above it (size: game.js SLOT_UNIT), with the count in the corner */
.sunit{position:absolute;inset:0;z-index:5;pointer-events:none} /* above the crate panel: the warrior flies over it */
.sunit.flying .num{opacity:0}
.sunit>img{position:absolute;width:107px;height:107px;max-width:none} /* game.js SLOT_UNIT; placed by slotUnit: his feet on the podium top */
.sunit .num{right:-5px;bottom:-6px}
.sunit.land>img{animation:land .32s ease-out}
@keyframes land{0%{transform:scale(1.14,.82)}55%{transform:scale(.95,1.06)}100%{transform:none}}
.sunit.pop{animation:pop .22s ease-in forwards}
@keyframes pop{to{transform:scale(0);opacity:0}}
@keyframes bump{50%{transform:scale(1.25)}}
.flyer{position:fixed;z-index:20;pointer-events:none;transform-origin:0 0}

/* ---------------------------------------------------------------- coach (first level) */
#coach{position:fixed;inset:0;z-index:25;pointer-events:none}
#coachText{position:absolute;left:0;right:0;margin:0;text-align:center;font-size:26px;transition:opacity .25s}
#coachHand{position:absolute;width:62px;height:74px;margin:-6px 0 0 -18px;transition:left .35s ease-in-out,top .35s ease-in-out;animation:tap 1.1s ease-in-out infinite}
@keyframes tap{0%,100%{transform:translate(10px,14px) rotate(-8deg)}45%{transform:translate(0,0) scale(.92) rotate(-8deg)}60%{transform:translate(0,0) scale(.92) rotate(-8deg)}}

/* ---------------------------------------------------------------- popups: indigo panel with a gold rim */
.overlay{z-index:30;pointer-events:auto}
.overlay .menu{animation:menuIn .38s var(--spring)}
@keyframes menuIn{from{transform:scale(.7);opacity:0}to{transform:none;opacity:1}}
.overlay.out{opacity:0;transition:opacity .18s ease-in}
.overlay.out .menu{transform:scale(.92);transition:transform .18s ease-in}
.rpanel{background:linear-gradient(#3d3178,#2a2157);border:4px solid #f2b23c;
  box-shadow:0 0 0 3px #5e3510,inset 0 0 0 2px rgba(255,255,255,.12),inset 0 4px 0 rgba(255,255,255,.08),0 8px 0 rgba(10,6,30,.6),0 18px 30px rgba(10,6,30,.45)}
.rpanel .tag{color:#d9d0f5}
.rpanel .b3d{width:100%}
#result .coinpill{position:fixed;top:calc(var(--safe-top) + 14px);right:max(18px,calc(50% - 202px));z-index:2;min-width:84px;justify-content:flex-end}
#coinPill.bump{animation:bump .25s var(--spring)}
.stars{display:flex;justify-content:center;align-items:flex-end;gap:4px;margin-top:-6px;height:84px}
.stars img{width:66px;height:66px}
.stars img:nth-child(2){width:80px;height:80px;margin-bottom:12px}
.reward{display:flex;align-items:center;justify-content:center;gap:6px}
.reward img{width:46px;height:46px}
.reward .stroke{font-size:40px;line-height:1;font-variant-numeric:tabular-nums}
.nearmiss{width:100%;position:relative}
.nm-bar{height:30px;border-radius:15px;background:#1f1846;border:3px solid #f2b23c;overflow:hidden;box-shadow:inset 0 3px 0 rgba(0,0,0,.3)}
.nm-bar i{display:block;height:100%;width:100%;transform-origin:0 50%;background:linear-gradient(#ff8a78,#e2363f);transition:transform .7s cubic-bezier(.2,.8,.3,1)}
#nmText{position:absolute;inset:0;display:grid;place-items:center;font-size:18px;-webkit-text-stroke:4px var(--ink);text-shadow:none}
#rsub{font-size:16px;max-width:300px}
@media (prefers-reduced-motion:reduce){#coachHand,.slot.warn::after{animation:none}}

/* ---------------------------------------------------------------- popup skin: generated art (art-source~/popup) */
/* titles with the lettering built in; the h2 stays for screen readers */
#result .ribbon,#pause .ribbon{width:min(390px,100%);padding:0;background:center/contain no-repeat;margin-bottom:-34px}
#result .ribbon{aspect-ratio:800/419;background-image:url(../assets/ui/pop/title2-victory.webp)}
#result .lose .ribbon{aspect-ratio:800/380;background-image:url(../assets/ui/pop/title2-lose.webp)}
#pause .ribbon{aspect-ratio:800/424;background-image:url(../assets/ui/pop/title2-paused.webp)}
#result .ribbon .title-text,#pause .ribbon .title-text{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
/* panel: 9-slice, gold rim with corner ornaments */
.rpanel{background:none;box-shadow:none;border:2px solid transparent;border-image:url(../assets/ui/pop/panel.webp) 64 fill / 32px;padding:44px 24px 24px}
/* candy buttons: 3-slice pills (the round ends keep their shape, the middle stretches) */
.overlay .b3d{background:none;box-shadow:none;border:2px solid transparent;border-radius:999px;border-image-slice:0 70 fill;border-image-width:0 calc(var(--bh,66px) / 2)}
.overlay .b3d::before{display:none}
.overlay .b3d.purple{border-image-source:url(../assets/ui/pop/btn-purple.webp)}
.overlay .b3d.green{border-image-source:url(../assets/ui/pop/btn-green.webp)}
.overlay .b3d.white{border-image-source:url(../assets/ui/pop/btn-white.webp)}
.overlay .b3d.blue{border-image-source:url(../assets/ui/pop/btn-purple.webp);filter:hue-rotate(-45deg)} /* pause menu: restart */
.overlay .b3d.small{--bh:54px}.overlay .b3d.cta{--bh:76px}
.overlay .b3d:active:not(:disabled){translate:0 2px}
.overlay .b3d img{width:44px;height:36px;object-fit:contain;margin:-4px 0}
/* stars, reward coin */
.stars img{width:70px;height:68px}
.stars img:nth-child(2){width:86px;height:84px;margin-bottom:14px}
.reward img{width:44px;height:45px}
#result .coinpill img{width:40px;height:41px;left:-12px;margin-top:-20px}
/* win: slowly turning sun rays behind the title (one small layer; off on defeat) */
.rays{position:absolute;left:50%;top:-110px;width:440px;height:440px;margin-left:-220px;pointer-events:none;z-index:0;opacity:.85}
.rays img{width:100%;height:100%;animation:raySpin 14s linear infinite}
@keyframes raySpin{to{transform:rotate(360deg)}}
#result .lose .rays{display:none}
@media (prefers-reduced-motion:reduce){.rays img{animation:none}}

/* CARD_3D (game.js): the panel, the cards and their heroes are drawn in the 3D canvas; the DOM keeps the layout, the
   taps, the counts and the card animations (its art hidden, its rects followed) */
body.c3d #panel{border-image:none}
body.c3d .crate{background-image:none!important;border-image:none!important}
body.c3d .crate>img{opacity:0}
