/* Shared design system — palette + glass panels + resets, lifted from the fish demo. */
:root{
  /* This app IS dark. Declaring the scheme stops mobile "auto/force dark" from re-inverting our own
     dark design — that browser inversion was turning the WHITE poker cards black on some phones.
     Belt-and-braces with <meta name="color-scheme" content="dark"> in index.html. */
  color-scheme:dark;
  --bg0:#02121f; --bg1:#04263c; --bg2:#063a5a;
  --gold:#ffd34d; --gold2:#ffb020;
  --cyan:#38e6ff; --red:#ff5a6e; --green:#54e08a; --purple:#c58bff;
  --panel:rgba(2,18,31,.72); --stroke:rgba(56,230,255,.25);
  --ink:#eaf6ff; --dim:#8fb6cc;
  --accent:var(--cyan);
  /* Modern surfaces — gradient glass panels with a soft edge + depth shadow, shared across cards,
     list containers and rows so every screen reads as one polished system. */
  --surface:linear-gradient(180deg, rgba(11,40,60,.66), rgba(3,20,33,.80));
  --surface-hi:linear-gradient(180deg, rgba(16,52,78,.82), rgba(6,28,44,.9));
  --edge:rgba(120,205,255,.16);
  --card-shadow:0 18px 44px -20px rgba(0,0,0,.72), inset 0 1px 0 rgba(255,255,255,.05);
  /* Backdrop tokens — cosmetic THEMES override these to repaint the whole app (see shop/catalog.js). */
  --glow1:rgba(56,230,255,.12); --glow2:rgba(255,211,77,.07); --glow3:rgba(88,224,138,.06);
  --deep1:#063049; --deep2:#03192a; --deep3:#010b14;
  /* Layer scale — every fixed/body-level overlay uses one of these tokens. Never invent numbers.
     Order: topbar(40) < badge(45) < menu(70) < win-FX(75) < notices(78) < modal(80)
          < system dialog(90) < theme flash(95) < toast(100).
     Fixes baked into the order: toasts must beat modals (admin confirmations were invisible
     behind the Manage panel); win FX / coin flights sit UNDER blocking dialogs; grant notices
     never cover the idle-logout countdown; the TEST badge never covers anything interactive. */
  --z-topbar:40; --z-badge:45; --z-menu:70; --z-fx:75; --z-notice:78;
  --z-modal:80; --z-system:90; --z-flash:95; --z-toast:100;
  /* Live topbar height — single source of truth for anything anchored beneath it (menu, toast,
     notices). The max-height:500px media block flips it to the compact bar's height. */
  --topbar-h:60px;
  font-synthesis:none;
}
@media (max-height:500px){ :root{ --topbar-h:42px; } }
*{box-sizing:border-box; -webkit-tap-highlight-color:transparent;}
/* Themed scrollbars site-wide — replace the OS default with a slim, on-brand bar: an accent thumb
   (theme-aware via --accent, so cosmetic themes recolour it too) on a faint track. Firefox reads
   scrollbar-width/color; WebKit/Blink read the ::-webkit-scrollbar pseudos. Elements that hide their
   bar on purpose (e.g. .card-actions) override scrollbar-width:none and win by specificity. */
*{scrollbar-width:thin; scrollbar-color:var(--accent,#38e6ff) transparent;}
::-webkit-scrollbar{width:11px; height:11px;}
::-webkit-scrollbar-track{background:rgba(2,18,31,.35);}
::-webkit-scrollbar-thumb{background:var(--accent,#38e6ff); border:3px solid transparent; background-clip:padding-box; border-radius:999px;}
::-webkit-scrollbar-thumb:hover{background:var(--gold,#ffd34d); background-clip:padding-box;}
::-webkit-scrollbar-corner{background:transparent;}
html,body{
  margin:0; height:100%; overflow:hidden; overscroll-behavior:none;
  /* Disable iOS Safari text autosizing ("font boosting"): on a phone it inflates text in wide-ish
     blocks — e.g. the 2-up lobby game-card blurbs — past their declared px size, so the text spills
     outside the card. Desktop never autosizes, which is why this bug was iPhone-only. Keep 100%
     (not `none`) so user-initiated pinch-zoom still scales text. */
  -webkit-text-size-adjust:100%; text-size-adjust:100%;
  color:var(--ink);
  /* Ambient deep-ocean backdrop so no screen reads as a flat black void — soft cyan/gold/green
     light blooms over a vertical depth gradient. .admin-screen/.history/.lobby are transparent and
     inherit this; canvas games paint over it. */
  background:
    radial-gradient(1200px 760px at 12% -12%, var(--glow1), transparent 60%),
    radial-gradient(1000px 820px at 102% -4%, var(--glow2), transparent 55%),
    radial-gradient(1200px 900px at 50% 118%, var(--glow3), transparent 60%),
    linear-gradient(180deg, var(--deep1) 0%, var(--deep2) 52%, var(--deep3) 100%);
  background-attachment:fixed;
  font-family:system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  font-variant-numeric:tabular-nums;
}
#app{
  position:fixed; inset:0; display:flex; flex-direction:column;
  padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}
/* Reset native button chrome. Mobile Safari/Chrome draw a subtle top bevel/highlight on
   <button> elements (visible as a hairline across the top edge of our round bet steppers);
   every button here paints its own background, so stripping the native appearance is safe. */
/* touch-action:manipulation — iOS Safari ignores user-scalable=no and double-tap-to-zooms on rapid
   taps (e.g. jabbing the bet stepper's − / +), which zooms the page and blocks further taps until you
   zoom back out. This opts every button out of the double-tap-zoom gesture (and the 300ms click delay). */
button{font-family:inherit; -webkit-appearance:none; appearance:none; touch-action:manipulation;}

/* Selects: keep the native popup dark to match the site. `color-scheme:dark` makes the browser
   draw the dropdown chrome dark, and an explicit SOLID option background fixes the "white/invisible
   options until highlighted" bug (options don't inherit the select's translucent rgba background,
   so they fell back to the OS default white with our light ink text). */
select{color-scheme:dark;}
select option, select optgroup{background:var(--bg1); color:var(--ink);}

/* glass chip / panel */
.chip{
  background:var(--panel); border:1px solid var(--stroke);
  border-radius:12px; padding:8px 12px; backdrop-filter:blur(6px);
}
.chip .k{font-size:10px; letter-spacing:.14em; text-transform:uppercase; color:var(--dim);}
.chip .v{font-size:20px; font-weight:800; line-height:1.1;}

/* buttons — smooth spring-y press (via .tap-press from ui/tapfx.js), soft hover lift, and a
   material tap ripple. The cubic-bezier gives a lively settle instead of a linear snap. */
.btn{
  position:relative; overflow:hidden;               /* clip the ripple to the button shape */
  background:var(--panel); border:1px solid var(--stroke); color:var(--ink);
  border-radius:12px; padding:11px 16px; font-weight:700; font-size:15px;
  cursor:pointer; user-select:none; min-height:44px;
  transition:transform .16s cubic-bezier(.34,1.56,.5,1), filter .14s, border-color .14s, box-shadow .16s, opacity .18s;
}
@media (hover:hover){ .btn:not(:disabled):hover{ filter:brightness(1.08); transform:translateY(-1px); } }
.btn:active, .btn.tap-press{ transform:scale(.94); filter:brightness(1.04); transition-duration:.05s; }
.btn.sel{border-color:var(--gold); box-shadow:0 0 0 1px var(--gold), 0 0 18px rgba(255,211,77,.25);}
.btn.primary{
  background:linear-gradient(180deg, var(--gold), var(--gold2));
  color:#241800; border-color:transparent; font-weight:800;
}
.btn.danger{border-color:var(--red); color:var(--red);}
.btn.good{border-color:var(--green); color:var(--green);}
.btn:disabled{opacity:.45; cursor:not-allowed; transform:none;}
.btn.wide{width:100%;}

/* --- shared tap ripple (spawned by ui/tapfx.js at the touch point) --- */
.tap-ripple{
  position:absolute; border-radius:50%; pointer-events:none;
  background:radial-gradient(circle, rgba(255,255,255,.42), rgba(255,255,255,0) 70%);
  transform:scale(0); opacity:.7; animation:tap-ripple .55s ease-out forwards;
}
@keyframes tap-ripple{ to{ transform:scale(1); opacity:0; } }
/* On light/gold buttons a dark ripple reads better than a white one. */
.btn.primary .tap-ripple, .dice-modebtn.sel .tap-ripple{
  background:radial-gradient(circle, rgba(40,24,0,.34), rgba(40,24,0,0) 70%);
}
@media (prefers-reduced-motion:reduce){
  .tap-ripple{ display:none; }
  .btn{ transition:filter .12s, border-color .12s, box-shadow .12s; }
  .btn:active, .btn.tap-press{ transform:none; filter:brightness(1.12); }
  @media (hover:hover){ .btn:not(:disabled):hover{ transform:none; } }
}

/* token coin — a small horizontal margin so it never jams against adjacent text (e.g. "won🪙+6")
   wherever coinMarkup() sits inline. Flex-gap containers (balance/bet-pill/chip-coin) already
   space it, so the extra couple px is harmless there. */
.coin{display:inline-block; width:16px; height:16px; line-height:0; vertical-align:-3px; flex:0 0 auto; margin:0 3px;}
.coin svg{width:100%; height:100%; display:block;}
/* amountMarkup() unit: coin + digits locked together as one inline-flex atom so a tight/centered
   cell (e.g. the admin HOLD-BY-GAME table) wraps them as a whole instead of splitting the number
   onto its own line with the coin sitting on top of the digits. */
.amt-inline{display:inline-flex; align-items:center; vertical-align:middle; white-space:nowrap;}
.chip-coin{display:inline-flex; align-items:center; gap:5px;}
#topbar .balance .v{display:inline-flex; align-items:center; gap:5px;}
.hist-amt, .hist-bal, .ubal{display:inline-flex; align-items:center; gap:4px; justify-content:flex-end;}

/* value bar */
.bar{height:6px; border-radius:4px; background:rgba(255,255,255,.08); overflow:hidden;}
.bar > i{display:block; height:100%; width:0; background:linear-gradient(90deg,var(--cyan),var(--gold));}

/* toast — glass pill with POSITIONAL variants (see src/ui/toast.js):
   default = status, anchored top-center just under the topbar — never over the dock/bet
   controls (the old bottom-7% anchor sat exactly on them); .pos-center = win/info moments,
   floating clear of both the topbar and the dock. Above modals (--z-toast) so confirmations
   fired from a dialog are visible. pointer-events:none — it can never block a tap. */
#toast{
  position:fixed; left:50%; transform:translateX(-50%);
  top:calc(env(safe-area-inset-top, 0px) + var(--topbar-h) + 8px);
  pointer-events:none; font-weight:800; font-size:17px; color:var(--gold);
  text-shadow:0 2px 10px #000; opacity:0; transition:opacity .2s; z-index:var(--z-toast); text-align:center;
  max-width:82vw; padding:10px 18px; border-radius:14px;
  background:rgba(2,14,24,.74); border:1px solid var(--stroke); backdrop-filter:blur(7px);
  box-shadow:0 12px 40px rgba(0,0,0,.45);
}
#toast.err{color:var(--red); border-color:rgba(255,90,110,.5);}
#toast.win{color:var(--green); border-color:rgba(84,224,138,.5); font-size:20px;}
#toast.pos-center{top:42%; transform:translate(-50%,-50%); font-size:20px; padding:13px 22px; border-radius:16px;}
#toast.pos-center.win{font-size:24px;}
@media (max-height: 500px){
  #toast{ font-size:14px; padding:7px 14px; max-width:70vw; }
  #toast.pos-center{ font-size:15px; padding:8px 16px; border-radius:12px; }
  #toast.pos-center.win{ font-size:17px; }
}

/* modal */
.modal-back{
  position:fixed; inset:0; z-index:var(--z-modal); display:flex; align-items:center; justify-content:center;
  background:rgba(2,10,18,.66); backdrop-filter:blur(4px); padding:20px;
}
.modal{
  background:linear-gradient(180deg, var(--bg1), var(--bg0));
  border:1px solid var(--stroke); border-radius:18px; padding:22px; max-width:440px; width:100%;
  box-shadow:0 24px 60px rgba(0,0,0,.5);
  /* Never taller than the viewport — a tall modal (weapon shop, info, bonus) must scroll inside,
     not push its buttons off a short LANDSCAPE screen. `vh` fallback first for browsers without `dvh`
     (an invalid calc() drops the whole rule, leaving the modal uncapped). */
  max-height:calc(100vh - 32px);
  max-height:calc(100dvh - 32px); overflow-y:auto; overscroll-behavior:contain;
}
@media (max-height: 500px){
  .modal-back{ padding:10px; align-items:flex-start; }
  .modal{ padding:14px 16px; max-height:calc(100vh - 20px); max-height:calc(100dvh - 20px); }
  .modal h2{ font-size:17px; margin-bottom:6px; }
}
.modal h2{margin:0 0 8px; font-size:20px;}
.modal p{color:var(--dim); line-height:1.6; font-size:14px;}
.row{display:flex; gap:10px;}

/* Terms-of-Play agreement gate (src/ui/disclaimer.js) */
.policy-scroll{
  max-height:min(46vh, 340px); overflow-y:auto; overscroll-behavior:contain;
  border:1px solid var(--stroke); border-radius:12px; padding:12px 14px; margin:4px 0 14px;
  background:rgba(0,0,0,.18);
}
.policy-scroll .policy-h{margin:12px 0 3px; font-size:14px; color:var(--fg); font-weight:700;}
.policy-scroll .policy-h:first-child{margin-top:0;}
.policy-scroll .policy-p{margin:0; color:var(--dim); font-size:13px; line-height:1.55;}
.policy-check{display:flex; gap:9px; align-items:flex-start; margin:9px 2px; font-size:13px; color:var(--fg); line-height:1.45; cursor:pointer;}
.policy-check input{margin-top:2px; width:17px; height:17px; flex:0 0 auto; accent-color:var(--accent, #33d6c8);}

/* Admin: on-demand live ledger-integrity check (src/screens/admin.js) */
.ledger-verify{display:flex; gap:10px; align-items:center; flex-wrap:wrap; margin-top:12px;}
.ledger-verify-result{font-size:13px; color:var(--dim);}
.ledger-verify-result.ok{color:#37d39b;}
.ledger-verify-result.bad{color:#ff6b6b;}
.row > *{flex:1;}
