@import url('https://fonts.googleapis.com/css2?family=DM+Mono:wght@400;500&family=Rye&family=Space+Grotesk:wght@500;600;700&display=swap');

:root{--ink:#171224;--cream:#fff4d8;--paper:#f2dca9;--emerald:#1e806b;--mint:#7ee2bd;--burgundy:#8e2945;--rose:#e95f76;--gold:#e3ad42;--shadow:#080711;--panel:rgba(23,18,36,.92)}
*{box-sizing:border-box}html,body{min-width:320px;min-height:100%;margin:0;background:#0b0912;color:var(--cream);font-family:"DM Mono",monospace}body{overflow-x:hidden;background:radial-gradient(circle at 50% -10%,#3c284e 0,#151020 42%,#08070c 100%)}button,select{font:inherit}.grain{position:fixed;inset:0;pointer-events:none;opacity:.08;z-index:99;background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 180 180' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.5'/%3E%3C/svg%3E")}.cabinet{width:min(1040px,100%);margin:auto;min-height:100vh;padding:0 18px}.topbar{height:64px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid rgba(255,244,216,.16)}.gridloch{display:flex;align-items:center;gap:10px;color:var(--cream);text-decoration:none;font-weight:700;font-size:11px;letter-spacing:.12em}.gridloch small{font-size:7px;color:var(--gold)}.grid-mark{display:grid;place-items:center;width:34px;height:34px;background:var(--cream);color:var(--ink);clip-path:polygon(0 0,80% 0,100% 20%,100% 100%,20% 100%,0 80%)}.run-readout{display:flex;gap:28px;align-items:center;font-size:9px;letter-spacing:.14em;color:#b8a984}.run-readout b{color:var(--mint);font-size:12px}.top-actions{display:flex;gap:7px}.icon-btn{width:36px;height:36px;border:1px solid rgba(255,244,216,.2);background:rgba(0,0,0,.2);color:var(--cream);cursor:pointer}.icon-btn:hover,.icon-btn:focus-visible{border-color:var(--gold);color:var(--gold)}.game-shell{display:grid;grid-template-columns:76px minmax(0,480px) 76px;justify-content:center;gap:18px;padding:16px 0}.screen-frame{position:relative;width:100%;aspect-ratio:2/3;max-height:calc(100vh - 112px);overflow:hidden;border:2px solid #b78839;outline:1px solid #4b3420;background:#05040a;box-shadow:0 16px 70px #000,0 0 0 7px #171120,0 0 0 8px rgba(255,235,188,.18)}canvas#game{display:block;width:100%;height:100%;image-rendering:auto;touch-action:none}.scanlines{position:absolute;inset:0;pointer-events:none;background:repeating-linear-gradient(0deg,transparent 0 3px,rgba(12,5,20,.1) 3px 4px);mix-blend-mode:multiply}.side-rail{align-self:center;height:min(500px,70vh);display:flex;flex-direction:column;align-items:center;gap:10px;color:#6e6175;font-size:7px;letter-spacing:.18em;writing-mode:vertical-rl}.side-rail i{display:block;width:1px;flex:1;background:linear-gradient(transparent,var(--gold),transparent)}.side-rail b{color:var(--gold);font-size:8px}.right-rail{transform:rotate(180deg)}footer{display:flex;justify-content:space-between;padding:4px 0 20px;color:#675b6b;font-size:7px;letter-spacing:.12em}.screen-overlay{position:absolute;inset:0;z-index:5}.hidden{display:none!important}.loading-screen{display:grid;place-content:center;text-align:center;background:#0c0913;color:var(--gold);font-size:10px;letter-spacing:.14em}.spinner{font-size:40px;animation:spin 1.4s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}
.title-screen{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:26px;background:radial-gradient(circle at 50% 24%,rgba(87,42,86,.4),transparent 45%),linear-gradient(rgba(12,9,19,.15),rgba(12,9,19,.88))}.title-sky{position:absolute;inset:0;overflow:hidden;opacity:.6}.title-sky:before,.title-sky:after,.title-sky i{content:"";position:absolute;width:190px;height:45px;border-radius:50%;background:rgba(255,244,216,.07);filter:blur(2px);animation:cloud 14s linear infinite}.title-sky:before{top:15%;left:-30%}.title-sky:after{top:36%;left:-45%;animation-delay:-8s}.title-sky i:nth-child(1){top:60%;left:-35%;animation-delay:-4s}.title-sky i:nth-child(2){top:72%;left:-20%;animation-delay:-10s}.title-sky i:nth-child(3){top:6%;left:-60%;animation-delay:-12s}@keyframes cloud{to{transform:translateX(760px)}}.title-lockup{position:relative;text-align:center;margin-bottom:24px}.eyebrow{display:block;color:var(--gold);font-size:8px;letter-spacing:.22em;margin-bottom:8px}.title-lockup h1{display:flex;align-items:center;justify-content:center;gap:8px;margin:0;font:400 clamp(42px,10vw,66px)/.82 "Rye",serif;letter-spacing:-.06em;text-shadow:0 4px 0 #52203a,0 7px 0 #130b17}.title-lockup h1 span{display:block}.title-lockup h1 em{font:400 26px "Rye";color:var(--gold);transform:rotate(-9deg)}.tagline{color:#ccb98d;font-size:7px;letter-spacing:.13em}.menu-panel{position:relative;width:min(330px,92%);display:grid;gap:8px}.big-btn{min-height:44px;border:1px solid rgba(255,244,216,.35);background:rgba(23,18,36,.86);color:var(--cream);padding:9px 14px;cursor:pointer;font-weight:700;font-size:10px;letter-spacing:.12em;box-shadow:inset 0 0 0 2px rgba(255,255,255,.025)}.big-btn:hover,.big-btn:focus-visible{border-color:var(--gold);transform:translateY(-1px)}.big-btn.primary{background:linear-gradient(180deg,#f0c665,#ca8b2b);border-color:#fff2bd;color:#291622;text-shadow:0 1px #fff1b4}.big-btn small{display:block;margin-top:4px;font-size:6px;font-weight:500;opacity:.65}.practice-row{display:grid;grid-template-columns:1fr 1fr;gap:8px}.practice-row select,.difficulty select{border:1px solid rgba(255,244,216,.3);background:#171224;color:var(--cream);padding:8px}.difficulty{display:flex;justify-content:space-between;align-items:center;color:#9b8da1;font-size:8px;letter-spacing:.12em}.high-score{text-align:center;color:#8c7c88;font-size:8px}.high-score b{color:var(--mint)}.controls-line{position:absolute;bottom:12px;font-size:6px;color:#817386;letter-spacing:.06em;text-align:center}
.story-screen{display:grid;place-items:center;background:#05040a;overflow:hidden}.story-slides{position:absolute;inset:0;display:grid;place-items:center;background:radial-gradient(circle at 50% 54%,#12101a 0,#05040a 68%)}.story-slides:after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;background:linear-gradient(transparent 43%,rgba(5,4,10,.12) 56%,rgba(5,4,10,.9) 79%,#05040a 100%),radial-gradient(circle,transparent 53%,rgba(0,0,0,.32) 100%)}.story-screen img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center;image-rendering:auto;opacity:0;transform:scale(1.018);transition:opacity .9s ease,transform 5.2s linear}.story-screen img.active{opacity:1;transform:scale(1)}.story-copy{position:absolute;z-index:2;left:7%;right:7%;bottom:9%;display:grid;gap:9px;text-align:center;text-wrap:balance;opacity:0;transform:translateY(8px);transition:opacity .75s ease .15s,transform .75s ease .15s;text-shadow:0 2px 5px #000,0 0 12px #000}.story-copy.active{opacity:1;transform:translateY(0)}.story-copy strong{color:var(--gold);font:400 clamp(14px,4.1cqw,24px)/1.05 "Rye",serif;letter-spacing:.025em}.story-copy span{color:#fff7e3;font:500 clamp(10px,2.25cqw,14px)/1.55 "Space Grotesk",sans-serif;letter-spacing:.015em}
.select-screen{display:flex;flex-direction:column;justify-content:center;padding:28px 20px;background:linear-gradient(rgba(18,12,21,.72),rgba(18,12,21,.97)),radial-gradient(circle at 50% 20%,#744f3b,#120c16 72%);text-align:center}.select-screen h2,.modal-card h2,dialog h2{margin:4px 0 24px;font:400 27px/1 "Rye",serif;letter-spacing:-.02em}.pilot-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}.pilot-card{position:relative;min-width:0;padding:10px 8px 18px;border:1px solid rgba(255,244,216,.16);background:rgba(12,8,17,.58);color:var(--cream);cursor:pointer;text-align:center;opacity:.48;filter:saturate(.6);transform:scale(.94);transition:opacity .16s ease,filter .16s ease,transform .16s ease,border-color .16s ease}.pilot-card.selected{opacity:1;filter:none;transform:scale(1);border-color:var(--gold);box-shadow:0 0 0 2px #3c2434,0 0 32px rgba(227,173,66,.28);background:linear-gradient(rgba(80,43,49,.82),rgba(21,15,27,.9))}.pilot-card.selected:before{content:"1P";position:absolute;top:-10px;left:50%;transform:translateX(-50%);padding:3px 9px;background:var(--gold);color:#27141f;font-size:8px;font-weight:700}.pilot-card canvas{display:block;width:100%;height:auto;image-rendering:auto}.pilot-card strong{display:block;font:400 16px/1.08 "Rye",serif;color:var(--paper);min-height:36px}.pilot-card>span{display:block;color:var(--gold);font-size:6px;letter-spacing:.11em;margin:8px 0}.pilot-card i{font-style:normal;color:var(--mint);font-size:7px;letter-spacing:.12em}.select-help{margin:25px 0 0;color:#b8a984;font-size:7px;letter-spacing:.12em;animation:selectPulse 1.2s steps(2,end) infinite}@keyframes selectPulse{50%{opacity:.45}}
.modal-screen{display:grid;place-items:center;background:rgba(8,6,12,.78);backdrop-filter:blur(3px)}.modal-card{width:80%;padding:28px 25px;border:1px solid var(--gold);background:linear-gradient(#2a1a2d,#130e19);text-align:center;box-shadow:0 16px 45px #000}.modal-card .big-btn{display:block;width:100%;margin-top:9px}.modal-card p{color:#b9a9ad;font-size:9px;line-height:1.7}.victory-card{border-color:var(--mint)}.touch-controls{display:none;justify-content:space-between;pointer-events:none}.touch-controls button{pointer-events:auto;width:64px;height:64px;border-radius:50%;border:1px solid rgba(255,244,216,.5);background:rgba(23,18,36,.52);color:var(--cream);font-size:7px;letter-spacing:.08em;touch-action:none}#fortuneTouch{border-color:var(--gold);color:var(--gold)}
dialog{width:min(390px,calc(100% - 30px));border:1px solid var(--gold);background:#171224;color:var(--cream);box-shadow:0 20px 80px #000;padding:0}dialog::backdrop{background:rgba(4,3,7,.78);backdrop-filter:blur(4px)}dialog form{padding:28px}dialog label{display:flex;align-items:center;justify-content:space-between;gap:18px;padding:13px 0;border-bottom:1px solid rgba(255,244,216,.1);font-size:9px;color:#c6b6b7}dialog input{accent-color:var(--gold)}dialog input[type=range]{width:145px}dialog p{font-size:8px;line-height:1.6;color:#817386}.dialog-x{position:absolute;right:12px;top:10px;border:0;background:none;color:var(--cream);font-size:24px;cursor:pointer}
@media(max-width:700px){.cabinet{padding:0 8px}.topbar{height:52px}.game-shell{grid-template-columns:minmax(0,480px);padding:8px 0}.side-rail{display:none}.screen-frame{max-height:calc(100svh - 76px)}footer{display:none}.run-readout{gap:10px}.gridloch span:last-child{display:none}.title-screen{padding:18px}.title-lockup{margin-bottom:16px}.title-lockup h1{font-size:clamp(36px,11vw,54px)}.controls-line{display:none}}
@media(max-height:760px) and (min-width:701px){.topbar{height:48px}.game-shell{padding:7px 0}.screen-frame{max-height:calc(100vh - 70px)}footer{display:none}}
@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.001ms!important;animation-iteration-count:1!important;scroll-behavior:auto!important}}

/* Preserve the portrait cabinet when viewport height, rather than width, is limiting. */
.screen-frame{container-type:inline-size;justify-self:center;width:min(100%,calc((100vh - 112px)*.666667));max-height:none}
.title-lockup h1{position:relative;display:grid;place-items:center;gap:0;font-size:clamp(42px,16cqw,66px);line-height:.8}
.title-lockup h1 em{position:absolute;left:8%;top:36%;font-size:23px;transform:rotate(-12deg);text-shadow:0 2px #52203a}
@media(max-width:700px){.screen-frame{width:min(100%,calc((100svh - 76px)*.666667))}.title-lockup h1{font-size:clamp(36px,16cqw,56px)}}
@media(max-height:760px) and (min-width:701px){.screen-frame{width:min(100%,calc((100vh - 70px)*.666667))}}

/* Full-height arcade presentation: the playfield is the entire cabinet. */
html,body{width:100%;height:100%;min-height:100%;overflow:hidden;background:#05040a}
body{display:grid;place-items:center}
.cabinet{display:grid;place-items:center;width:100vw;height:100dvh;min-height:0;margin:0;padding:0}
.game-shell{display:grid;grid-template-columns:1fr;place-items:center;width:100%;height:100%;padding:0;gap:0}
.screen-frame{width:min(100vw,66.666667dvh);height:min(100dvh,150vw);max-width:none;max-height:none;aspect-ratio:2/3;border:0;outline:0;box-shadow:none}
.arcade-status{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
.screen-actions{position:absolute;z-index:8;top:max(8px,env(safe-area-inset-top));right:8px;display:flex;gap:6px}
.screen-frame[data-mode="play"] .screen-actions,.screen-frame[data-mode="paused"] .screen-actions{right:auto;left:58.54%;transform:translateX(-50%);gap:clamp(4px,1cqw,6px)}
.screen-actions .icon-btn{width:32px;height:32px;border-color:rgba(255,244,216,.28);background:rgba(13,8,18,.74);box-shadow:0 2px 8px rgba(0,0,0,.35)}
.screen-frame[data-mode="play"] .screen-actions .icon-btn,.screen-frame[data-mode="paused"] .screen-actions .icon-btn{width:clamp(22px,6cqw,28px);height:clamp(22px,6cqw,28px);padding:0;font-size:clamp(10px,2.7cqw,13px)}
.screen-frame[data-mode="attract"] .screen-actions,.screen-frame[data-mode="story"] .screen-actions,.screen-frame[data-mode="select"] .screen-actions,.screen-frame.intro-mode .screen-actions{opacity:0;pointer-events:none}

/* Full-field character art frames the hangar selection. The controls sit low
   enough that neither portrait's face is covered by aircraft or copy. */
.select-screen{justify-content:flex-end;padding:28px 20px 30px;isolation:isolate;overflow:hidden}
.select-screen::before,.select-screen::after{content:"";position:absolute;z-index:0;inset:0;background-repeat:no-repeat;background-size:cover;background-position:center top;pointer-events:none;filter:saturate(.82) contrast(.96);transition:opacity .42s cubic-bezier(.22,.7,.18,1),transform .58s cubic-bezier(.22,.7,.18,1),filter .42s ease}
.select-screen::before{background-image:linear-gradient(to bottom,rgba(18,12,21,.02) 0,rgba(18,12,21,.14) 38%,rgba(18,12,21,.78) 66%,#120c16 100%),url("./assets/art/select/select-fable-portrait-v1.webp");opacity:1;transform:scale(1)}
.select-screen::after{background-image:linear-gradient(to bottom,rgba(18,12,21,.02) 0,rgba(18,12,21,.14) 38%,rgba(18,12,21,.78) 66%,#120c16 100%),url("./assets/art/select/select-babby-portrait-v2.webp");opacity:0;transform:scale(1.045) translateX(10px)}
.select-screen[data-pilot="babby"]::before{opacity:0;transform:scale(1.045) translateX(-10px);filter:saturate(.66) contrast(.9)}
.select-screen[data-pilot="babby"]::after{opacity:1;transform:scale(1);filter:saturate(.82) contrast(.96)}
.select-screen>*{position:relative;z-index:2}
.select-screen h2{margin-bottom:14px}
.select-screen .pilot-wipe{position:absolute;z-index:4;top:-8%;bottom:-8%;left:-42%;width:28%;opacity:0;pointer-events:none;transform:skewX(-13deg);background:linear-gradient(90deg,transparent,rgba(240,201,106,.08) 22%,rgba(255,244,216,.58) 50%,rgba(240,201,106,.08) 78%,transparent);mix-blend-mode:screen;filter:blur(1px)}
.select-screen.pilot-switching .pilot-wipe{animation:pilotWipe .52s cubic-bezier(.2,.72,.24,1)}
.select-screen.pilot-switching .pilot-grid{animation:pilotCards .42s cubic-bezier(.2,.72,.24,1)}
@keyframes pilotWipe{0%{opacity:0;transform:translateX(0) skewX(-13deg)}18%{opacity:.9}75%{opacity:.68}100%{opacity:0;transform:translateX(720px) skewX(-13deg)}}
@keyframes pilotCards{0%{transform:translateY(0)}45%{transform:translateY(4px)}100%{transform:translateY(0)}}
.pilot-card{overflow:hidden;isolation:isolate}
.pilot-card.selected::before{z-index:3}
.pilot-card canvas{filter:drop-shadow(0 5px 5px rgba(8,5,12,.78))}
.pilot-card strong,.pilot-card>span,.pilot-card i{text-shadow:0 2px 3px #09060d,0 0 8px #09060d}
@media(max-width:700px){.cabinet{padding:0}.game-shell{padding:0}.screen-frame{width:min(100vw,66.666667dvh);height:min(100dvh,150vw)}.screen-actions .icon-btn{width:30px;height:30px}}

/* Touch devices get a hardware-style layout: the playfield sits at the top of
   the cabinet and a virtual stick plus buttons occupy a dedicated pad beneath
   it, so thumbs never cover the action. The class is set by game.js from a
   coarse-pointer match (or ?touch=1), so pointer-fine machines keep the plain
   full-height screen and never see the pad. */
/* The pad takes only what a full-width playfield leaves over, so the screen
   keeps spanning the whole width; it claims its own minimum height only on
   screens too squat for that. Controls scale off the space they end up with. */
/* A long press anywhere on a touch layout was starting a selection that boxed
   the pad in blue; nothing on this screen is text to select. */
.touch-layout,.touch-layout *{-webkit-user-select:none;user-select:none;-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent}
.touch-layout{--pad-inset:env(safe-area-inset-bottom,0px);--pad-h:max(100px,calc(100dvh - 150vw + var(--pad-inset)));--pad-room:calc(var(--pad-h) - var(--pad-inset));--stick:min(calc(var(--pad-room)*.8),112px)}
.touch-layout .game-shell{grid-template-rows:auto 1fr;align-content:start;justify-items:center}
/* Every in-run mode keeps the same reduced screen so the pause, death and
   victory cards never resize the playfield mid-animation. */
.touch-layout .screen-frame[data-mode="play"],.touch-layout .screen-frame[data-mode="paused"],.touch-layout .screen-frame[data-mode="gameover"],.touch-layout .screen-frame[data-mode="victory"]{width:min(100vw,calc((100dvh - var(--pad-h))*.666667));height:min(calc(100dvh - var(--pad-h)),150vw)}
.touch-layout .touch-controls{display:flex;align-self:stretch;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none;align-items:center;justify-content:space-between;gap:clamp(10px,3vw,26px);width:100%;max-width:600px;min-height:var(--pad-h);padding:4px clamp(14px,5vw,34px) calc(4px + var(--pad-inset));pointer-events:auto;background:linear-gradient(#0d0a14,#08060d)}
/* Left-handed players put the stick on the right; the buttons mirror with it. */
.touch-layout.swap-touch .touch-controls,.touch-layout.swap-touch .touch-buttons{flex-direction:row-reverse}
.touch-layout .screen-frame.intro-mode+.touch-controls{visibility:hidden}
.touch-layout .screen-frame[data-mode="paused"]+.touch-controls{opacity:.35;pointer-events:none}
.joystick{position:relative;flex:0 0 auto;width:var(--stick);height:var(--stick);border-radius:50%;border:1px solid rgba(255,244,216,.26);background:radial-gradient(circle at 50% 34%,rgba(64,45,86,.6),rgba(11,8,17,.86));box-shadow:inset 0 3px 12px rgba(0,0,0,.6),0 1px 0 rgba(255,244,216,.06);touch-action:none;-webkit-user-select:none;user-select:none}
.joystick.active{border-color:var(--gold)}
.joy-ring{position:absolute;inset:15%;border-radius:50%;border:1px dashed rgba(255,244,216,.13)}
.joy-knob{position:absolute;left:50%;top:50%;width:46%;height:46%;margin:-23% 0 0 -23%;border-radius:50%;background:radial-gradient(circle at 50% 32%,#f7dc9d,#c58f31 66%,#7f5318);box-shadow:0 3px 9px rgba(0,0,0,.65),inset 0 -2px 6px rgba(0,0,0,.3);transition:transform .13s cubic-bezier(.2,.7,.2,1)}
.joystick.active .joy-knob{transition:none}
.touch-buttons{display:flex;align-items:center;gap:clamp(8px,2.4vw,15px)}
/* Buttons carry no text: holding one made the label select on touch, and the
   labels are on the elements themselves for screen readers. Both faces are the
   same size; only the gold edge tells fortune from focus. */
.touch-layout .touch-controls button{width:calc(var(--stick)*.52);height:calc(var(--stick)*.52);min-width:42px;min-height:42px;background:radial-gradient(circle at 50% 32%,rgba(46,33,62,.85),rgba(13,9,19,.9));box-shadow:0 2px 8px rgba(0,0,0,.5),inset 0 1px 0 rgba(255,244,216,.12);-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
.touch-layout #fortuneTouch{background:radial-gradient(circle at 50% 32%,rgba(96,56,30,.85),rgba(24,13,19,.92))}
/* Mobile browsers paint their own grey wash and keep a focus ring on a tapped
   button; both read as the control being stuck on. The pressed state is the
   inset shadow and brighter edge instead. */
.touch-layout .touch-controls,.touch-layout .touch-controls button,.joystick{-webkit-tap-highlight-color:transparent}
.touch-layout .touch-controls button{-webkit-appearance:none;appearance:none}
.touch-layout .touch-controls button:focus,.touch-layout .touch-controls button:focus-visible{outline:none}
.touch-layout .touch-controls button:active{border-color:#fff2bd;box-shadow:inset 0 3px 10px rgba(0,0,0,.6)}
/* Settings rows that only mean anything with the pad on screen. */
.touch-only{display:none!important}
.touch-layout .touch-only{display:flex!important}
