/* Fixed, non-zoomable frame: the page never scrolls, only the inner lists do. */
html, body { position: fixed; top: 0; right: 0; bottom: 0; left: 0; overflow: hidden; margin: 0;
  overscroll-behavior: none; touch-action: pan-x pan-y; -webkit-text-size-adjust: 100%; -webkit-touch-callout: none;
  background: #0b1020; color: #e9e6f5; font: 15px/1.4 system-ui, -apple-system, Segoe UI, Roboto, sans-serif; }
#root { position: absolute; top: 0; right: 0; bottom: 0; left: 0; overflow: hidden; }
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
[hidden] { display: none !important; }

.screen { position: absolute; inset: 0; display: flex; flex-direction: column; }
h1 { font-size: 26px; margin: 0; letter-spacing: 0.04em; background: linear-gradient(90deg, #c084fc, #67e8f9); -webkit-background-clip: text; background-clip: text; color: transparent; }
h2 { margin: 0 0 8px; } h3 { margin: 14px 0 6px; font-size: 16px; }
.muted { color: #9a95b3; } .tiny { font-size: 12px; } .error { color: #fb7185; min-height: 1.2em; margin: 4px 0; }
.row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
input { background: #171a2e; border: 1px solid #2d3252; color: #fff; border-radius: 10px; padding: 11px 12px; font-size: 15px; width: 100%; }
input:focus { outline: 2px solid #7c3aed55; border-color: #a78bfa; }
.btn { background: #232746; color: #fff; border: 1px solid #3a3f66; border-radius: 12px; padding: 11px 16px; font-size: 15px; font-weight: 600; cursor: pointer; }
.btn.primary { background: linear-gradient(135deg, #7c3aed, #0891b2); border-color: transparent; }
.btn.big { width: 100%; padding: 16px; font-size: 18px; }
.btn.small { padding: 7px 12px; font-size: 13px; }
.btn:disabled { opacity: 0.5; }
.link { background: none; border: none; color: #a78bfa; font-size: 13px; cursor: pointer; padding: 6px; }

/* auth */
#auth { align-items: center; justify-content: center; padding: 20px; }
.panel { width: 100%; max-width: 440px; background: #12152a; border: 1px solid #23274a; border-radius: 18px; padding: 22px; display: flex; flex-direction: column; gap: 12px; }
.vessel-pick { display: flex; gap: 10px; }
.vessel-pick label { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 8px; border-radius: 12px; border: 1px solid #2d3252; cursor: pointer; }
.vessel-pick label.on { border-color: #a78bfa; background: #1b1737; box-shadow: 0 0 14px #7c3aed55; }
.vessel-pick input { position: absolute; opacity: 0; width: 0; height: 0; }
.vessel-pick .vprev { display: block; width: 96px; height: 96px; } .vessel-pick .vprev svg, .vessel-pick .vprev canvas { width: 96px; height: 96px; display: block; }

/* home */
#home header { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px 6px; }
#admin header { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px 6px; }
/* The admin page (Tyson, 2026-09-07): sign-ins, practice matches per player and
   every settled PvP result. Its own screen, and the outer frame never scrolls --
   only this inner column does, like every other screen in the app. */
#admin .scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 0 14px calc(18px + env(safe-area-inset-bottom)); }
#admin h2 { font-size: 15px; margin: 16px 0 6px; color: #cbd5e1; letter-spacing: 0.04em; text-transform: uppercase; }
#admin .cards { display: flex; flex-wrap: wrap; gap: 8px; }
#admin .card { flex: 1 1 96px; background: #171a33; border: 1px solid #23274a; border-radius: 12px; padding: 10px 12px; }
#admin .card b { display: block; font-size: 20px; }
#admin .card span { font-size: 11px; color: #9a95b3; letter-spacing: 0.05em; text-transform: uppercase; }
#admin table { width: 100%; border-collapse: collapse; font-size: 13px; }
#admin th { text-align: left; font-weight: 600; color: #9a95b3; font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; padding: 6px 6px; border-bottom: 1px solid #23274a; }
#admin td { padding: 6px 6px; border-bottom: 1px solid #1b1e39; white-space: nowrap; }
#admin td.name { white-space: normal; word-break: break-word; }
#admin .tw { overflow-x: auto; -webkit-overflow-scrolling: touch; }
#admin .win { color: #86efac; } #admin .draw { color: #fcd34d; } #admin .muted { color: #9a95b3; }
#admin .empty { color: #9a95b3; font-size: 13px; padding: 8px 2px; }
/* the invisible way in, in the slot the install button had once it is installed */
.site-links { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px; margin: 2px 0 6px; font-size: 12px; }
.site-links a { color: #a5b4fc; text-decoration: none; }
.site-links a:hover { color: #e0e7ff; text-decoration: underline; }
#auth-admin.ghost { opacity: 0; transition: opacity 0.15s; }
#auth-admin.ghost:focus-visible { opacity: 1; outline: 2px solid #a78bfa; outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { #auth-admin.ghost { transition: none; } }
.hdr-right { display: flex; align-items: center; gap: 4px; }
.pill { display: inline-flex; align-items: center; gap: 6px; background: linear-gradient(135deg, #7c3aed, #0891b2); color: #fff; border: none; border-radius: 999px; padding: 7px 12px; font-size: 13px; font-weight: 700; cursor: pointer; box-shadow: 0 2px 10px #7c3aed55; white-space: nowrap; }
.pill svg { flex: none; }
.pill.mode { background: #12152a; border: 1px solid #a78bfa; color: #e9d5ff; box-shadow: none; padding: 6px 10px; letter-spacing: 0.04em; }
#result-mode { position: absolute; top: max(10px, env(safe-area-inset-top)); left: 12px; }
#install { position: absolute; inset: 0; background: #000a; display: flex; align-items: center; justify-content: center; padding: 20px; z-index: 15; }
.install-card { background: #12152a; border: 1px solid #23274a; border-radius: 18px; padding: 20px; max-width: 400px; width: 100%; max-height: 100%; overflow-y: auto; }
.install-card h3 { margin: 0 0 4px; font-size: 20px; } .install-card > p.muted, .install-head p.muted { margin: 0; font-size: 13px; }
.install-head { display: flex; gap: 12px; align-items: center; text-align: left; } .install-head img { flex: none; border-radius: 14px; box-shadow: 0 4px 14px #0008; }
.inline-icon { vertical-align: -5px; border-radius: 5px; margin-left: 4px; }
/* the app's name and the install button share the top row (Tyson, 2026-09-06) */
.auth-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.auth-head h1 { flex: none; }
#auth-install { margin: 0; flex: none; } #auth-install img { border-radius: 5px; }
#setup { position: absolute; inset: 0; background: #000b; display: flex; align-items: center; justify-content: center; padding: 20px; z-index: 31; }
.setup-card h3 { margin: 14px 0 8px; font-size: 15px; color: #cbd5e1; }
.setup-card .vessel-pick { gap: 10px; }
.setup-card .vessel-pick label { cursor: pointer; }
.setup-card .seg { justify-content: center; }
/* the landing-page demo: a phone-shaped window under the sign-in form */
/* The sign-in demo sits above the form and takes only the height the form has
   not claimed, so the login below it is always on screen (Tyson, 2026-09-06).
   The frame keeps the phone's shape, so its width follows from that height --
   never the other way round, which is what used to push the form off a short
   screen. On a short screen the panel trims itself (see the media rule below)
   rather than letting either half win. */
#auth { justify-content: center; overflow: hidden; }
#auth .panel { max-height: 100%; overflow-y: auto; overscroll-behavior: contain; }
#auth-demo { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; align-items: center; gap: 6px; width: 100%; margin: 2px 0 0; }
#auth-demo p { text-align: center; margin: 0; flex: none; }
/* Two frames side by side (Tyson, 2026-09-09): PvP on the left, The Gauntlet on the
   right, each phone-shaped; authDemoFit gives both one height, bounded by the row's
   width so they never wrap. His banner sits above them. */
#auth-demo .demo-row { display: flex; justify-content: center; align-items: flex-start; gap: 10px; width: 100%; flex: none; }
#auth-demo .demo-cell { margin: 0; display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0; }
#auth-demo .demo-banner { flex: none; width: 100%; box-sizing: border-box; text-align: center; padding: 7px 12px; border-radius: 12px; border: 1px solid #a78bfa66; background: linear-gradient(90deg, #7c3aed33, #12152a 30%, #12152a 70%, #0891b233); color: #e9e6ff; font-size: 13px; line-height: 1.3; font-weight: 600; }
#auth-demo .demo-banner b { background: linear-gradient(90deg, #c084fc, #67e8f9); -webkit-background-clip: text; background-clip: text; color: transparent; font-weight: 800; }
#auth-demo .demo-frame { position: relative; flex: none; height: 120px; aspect-ratio: 390 / 844; width: auto; max-width: 100%; border-radius: 16px; overflow: hidden; border: 1px solid #23274a; background: #0b1020; box-shadow: 0 12px 34px #0009; }
#auth-demo iframe { position: absolute; left: 0; top: 0; width: 390px; height: 844px; border: 0; transform-origin: 0 0; pointer-events: none; opacity: 0; transition: opacity 0.5s ease; }
#auth-demo iframe.on { opacity: 1; }
/* Short screens: the sign-in panel gives up its roomier spacing so that the
   demo above it and the Sign in button below it are both on screen at once. */
@media (max-height: 780px) {
  #auth { padding: 10px; }
  #auth .panel { gap: 8px; padding: 14px; }
  #auth .vessel-pick .vprev, #auth .vessel-pick .vprev svg, #auth .vessel-pick .vprev canvas { width: 62px; height: 62px; }
  #auth-mode-seg + p.tiny { display: none; }
  #auth-demo p { display: none; }
  #auth-demo .demo-banner { font-size: 12px; padding: 5px 10px; }
}
@media (max-height: 620px) {
  #auth h1 { font-size: 21px; }
  #auth .panel > p.muted:first-of-type { display: none; }
  #auth-install { display: none; }
}
.install-card .seg { margin: 14px 0; } .install-card .seg .btn svg, #install-now svg { width: 18px; height: 18px; vertical-align: -4px; margin-right: 6px; }
#install-now { margin: 10px 0 4px; }
.steps { list-style: none; padding: 0; margin: 12px 0; display: flex; flex-direction: column; gap: 10px; counter-reset: s; }
.steps li { display: flex; align-items: center; gap: 10px; background: #0f1226; border: 1px solid #23274a; border-radius: 12px; padding: 10px 12px; font-size: 14px; line-height: 1.35; }
.steps li::before { counter-increment: s; content: counter(s); flex: none; width: 24px; height: 24px; border-radius: 50%; background: #7c3aed; color: #fff; font-weight: 700; font-size: 13px; display: grid; place-items: center; }
.steps .ico { flex: none; width: 36px; height: 36px; border-radius: 10px; background: #1b1737; display: grid; place-items: center; color: #c4b5fd; }
.steps .ico svg { width: 22px; height: 22px; } .steps b { color: #fff; }
.install-note { color: #9a95b3; font-size: 13px; margin: 8px 0 12px; }
/* iPhone install walkthrough: pick your browser, then drawn steps for it */
.install-card .ask { margin: 14px 0 8px; font-size: 14px; font-weight: 600; }
.browsers { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.browsers .btn { flex: 1 1 30%; min-width: 92px; }
.browsers .btn.on { border-color: #22d3ee; background: #0b2a33; color: #a5f3fc; }
.picsteps li { display: grid; grid-template-columns: 24px 1fr; align-items: start; gap: 6px 10px; }
.picsteps .say { grid-column: 2; }
.picwrap { grid-column: 2; display: block; background: #0b1020; border: 1px solid #23274a; border-radius: 10px; padding: 8px; margin-top: 4px; }
.pic { width: 100%; height: auto; display: block; }
.pic.wide { width: 100%; max-width: 300px; margin: 4px auto 10px; }
.cant { background: #2a1020; border: 1px solid #f43f5e66; color: #fda4af; border-radius: 12px; padding: 12px; margin: 4px 0 10px; font-size: 14px; line-height: 1.4; }
.cant b { color: #fff; }
#copy-link { width: 100%; margin-bottom: 10px; }
.install-ok { display: flex; align-items: center; gap: 10px; background: #0f2a1e; border: 1px solid #14532d; color: #bbf7d0; border-radius: 12px; padding: 12px; margin: 12px 0; font-size: 14px; } .install-ok svg { width: 22px; height: 22px; flex: none; }
#install-close { width: 100%; }
#home main { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 8px 12px 12px; overscroll-behavior: contain; }
#tabs { display: flex; border-top: 1px solid #23274a; background: #0f1226; padding-bottom: env(safe-area-inset-bottom); }
#tabs button { flex: 1; background: none; border: none; color: #8f8aab; padding: 12px 2px; font-size: 12px; font-weight: 600; }
#tabs button.active { color: #fff; border-top: 2px solid #a78bfa; margin-top: -1px; }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 8px; margin-top: 10px; }
.item { position: relative; background: #12152a; border: 1px solid #23274a; border-radius: 14px; padding: 10px 6px 8px; display: flex; flex-direction: column; align-items: center; gap: 4px; color: #ddd; cursor: pointer; }
.item .nm { font-size: 11px; line-height: 1.2; text-align: center; min-height: 2.4em; }
.item .qty { position: absolute; top: 6px; right: 8px; font-size: 11px; color: #c4b5fd; font-weight: 700; }
.item .eq { position: absolute; top: 6px; left: 8px; font-size: 10px; color: #67e8f9; }
.item.t2 { border-color: #7c3aed88; } .item.t3 { border-color: #f59e0b99; box-shadow: 0 0 12px #f59e0b33; }
.detail-card.t2 { border-color: #7c3aed; } .detail-card.t3 { border-color: #f59e0b; }
.fslots { display: flex; gap: 10px; justify-content: center; margin: 0 -12px; padding: 8px 12px; position: sticky; top: -8px; z-index: 5; background: linear-gradient(180deg, #0b1020 82%, #0b102000); }
.fslot { width: 100px; height: 112px; border: 2px dashed #3a3f66; border-radius: 14px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; font-size: 11px; text-align: center; padding: 4px; }
.fslot.filled { border-style: solid; border-color: #a78bfa; background: #1b1737; }
.fslot.picking { border-color: #67e8f9; box-shadow: 0 0 0 3px #67e8f944; }
.fslot .ph { font-size: 28px; color: #3a3f66; }
/* z-index 14: above the sticky loadout slots (5) and rematch bar (6) — on an iPad they painted over the card — below the install sheet (15), toasts (20) and the welcome (30) */
#detail { position: absolute; inset: 0; z-index: 14; background: #000a; display: flex; align-items: center; justify-content: center; padding: max(18px, env(safe-area-inset-top)) 18px max(18px, env(safe-area-inset-bottom)); }
.detail-card { background: #12152a; border: 1px solid #23274a; border-radius: 18px; padding: 20px; max-width: 380px; width: 100%; max-height: 100%; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; text-align: center; box-shadow: 0 14px 40px #000a; }
.detail-card dl { display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; text-align: left; margin: 12px 0; }
.detail-card dt { color: #9a95b3; } .detail-card .tier { color: #c4b5fd; font-size: 13px; margin: 2px 0 6px; }
table { width: 100%; border-collapse: collapse; font-size: 14px; } td, th { padding: 6px 4px; text-align: left; border-bottom: 1px solid #23274a; } th { color: #9a95b3; font-weight: 600; }
#home:has(#detail:not([hidden])) ~ #toast, #home:has(#welcome:not([hidden])) ~ #toast { bottom: auto; top: max(14px, env(safe-area-inset-top)); }
#toast { position: absolute; left: 50%; bottom: 80px; transform: translateX(-50%); background: #2d1b69; color: #fff; padding: 10px 16px; border-radius: 12px; max-width: 90%; z-index: 20; box-shadow: 0 6px 20px #0008; pointer-events: none; }   /* text only, and it must never sit between a finger and a weapon slot (2026-09-10) */

/* battle */
#battle { background: #05070f; }
.hud { display: flex; align-items: center; gap: 8px; padding: 6px 12px; height: 40px; }
.hud .name { font-weight: 700; min-width: 60px; font-size: 13px; }
.hud .hp { font-variant-numeric: tabular-nums; width: 34px; text-align: right; font-size: 13px; }
/* health bars: a glossy, ten-segment gauge; the chunk just lost lingers as a pale
   ghost and drains a moment later, and the bar pulses when a player is nearly out */
.bar { flex: 1; height: 16px; background: #0b0e1f; border-radius: 8px; overflow: hidden; position: relative; border: 1px solid #2b3060; box-shadow: inset 0 2px 4px #000a; }
.bar div { height: 100%; width: 100%; }
.bar .ghost { position: absolute; inset: 0; background: #ffffff66; transition: width 0.9s ease-out 0.35s; }
.bar .fill { position: relative; transition: width 0.15s; }
.bar.opp .fill { background: linear-gradient(90deg, #f43f5e, #fb923c); box-shadow: 0 0 10px #f43f5e99; }
.bar.me .fill { background: linear-gradient(90deg, #22d3ee, #a3e635); box-shadow: 0 0 10px #22d3ee99; }
.bar::before { content: ''; position: absolute; inset: 0; background: repeating-linear-gradient(90deg, transparent 0 calc(10% - 1.5px), #0b1020cc calc(10% - 1.5px) 10%); pointer-events: none; z-index: 2; }
.bar::after { content: ''; position: absolute; left: 0; right: 0; top: 0; height: 45%; background: linear-gradient(180deg, #ffffff4d, transparent); border-radius: 8px 8px 0 0; pointer-events: none; z-index: 2; }
.bar.low .fill { animation: hplow 0.7s ease-in-out infinite; }
@keyframes hplow { 50% { filter: brightness(1.7) saturate(1.3); } }
.arena-wrap { flex: 1; position: relative; min-height: 0; display: flex; justify-content: center; }
#arena-bg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; pointer-events: none; }
#arena-bg[hidden] { display: none; }
/* positioned on purpose: WebKit paints an in-flow <svg> underneath the absolutely placed background, and
   only will-change used to lift it -- which Chrome on iOS (WebKit too) never got (2026-09-08) */
#arena { position: relative; z-index: 0; height: 100%; width: 100%; touch-action: none; display: block; }
#arena.hit { animation: shake 0.18s; }
@keyframes shake { 25% { transform: translateX(4px); } 75% { transform: translateX(-4px); } }
.mid { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); display: flex; flex-direction: column; align-items: center; pointer-events: none; opacity: 0.55; }
#timer { font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; }
#battle-status { position: absolute; inset: auto 16px 40% 16px; text-align: center; background: #12152acc; padding: 12px; border-radius: 12px; }
/* Weapon/special buttons on the left, movement pad on the right. The full-width
   angle row sits outside this bar, immediately above player health. */
#controls { display: flex; align-items: stretch; gap: 8px; padding: 6px 8px calc(8px + env(safe-area-inset-bottom)); height: 245px; user-select: none; }
.left-col { display: flex; flex-direction: column; flex: 1; min-width: 0; gap: 10px; }
.fire-row { display: flex; gap: 8px; flex: 1; min-height: 0; }
.btn-col { display: flex; flex-direction: column; gap: 5px; width: 96px; flex: none; }   /* the two SPECIAL buttons */
.pad-btn { flex: 1; border-radius: 18px; border: 2px solid #3a3f66; background: #12152a; color: #fff; font-weight: 800; letter-spacing: 0.08em; font-size: 13px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; touch-action: none; position: relative; overflow: hidden; }
@keyframes autoglow { 50% { box-shadow: 0 0 34px #fde68a, inset 0 0 18px #fff5; } }
.pad-btn.special { background: radial-gradient(circle at 50% 35%, #0e7490, #083344 75%); border-color: #22d3ee; }
.pad-btn.special .art { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0.9; }
.pad-btn.special .lbl, .pad-btn.special .sn { position: relative; z-index: 1; text-shadow: 0 1px 3px #000, 0 0 10px #000; }
.pad-btn.special .lbl { font-size: 11px; } .pad-btn.special .sn { font-size: 9px; font-weight: 500; opacity: 0.9; text-transform: uppercase; letter-spacing: 0.1em; }
.pad-btn.special.ready { box-shadow: 0 0 22px #22d3ee99; position: relative; }
.pad-btn.special.ready::after { content: ''; position: absolute; inset: -5px; border-radius: inherit; box-shadow: 0 0 30px #67e8f9; opacity: 0.5; animation: spready 1.6s ease-in-out infinite; will-change: opacity; pointer-events: none; }
@keyframes spready { 0%, 100% { opacity: 0.2; } 50% { opacity: 1; } }
.pad-btn.special.used, .pad-btn.special.none { opacity: 0.45; filter: grayscale(0.6); animation: none; box-shadow: none; }
.pad-btn.special.used::after, .pad-btn.special.none::after { display: none; }
/* the uses a special has left, as pips under its name: three for the first slot, one for the second (Tyson, 2026-09-10) */
.pad-btn.special .pips { position: relative; z-index: 1; display: flex; gap: 4px; margin-top: 2px; min-height: 7px; }
.pad-btn.special .pips i { width: 7px; height: 7px; border-radius: 50%; border: 1px solid #a5f3fc; background: #0b1020aa; box-shadow: 0 0 3px #000; }
.pad-btn.special .pips i.on { background: #a5f3fc; box-shadow: 0 0 6px #67e8f9; }
#slots { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 0; }
/* A weapon slot is its ability's picture, edge to edge, with the name on a scrim along the foot -- and it is
   the fire button for that weapon (Tyson, 2026-09-10): a tap fires it, a hold keeps firing and after a second
   stays on by itself (the slot turns gold and breathes; a tap on the lit slot stops it), and a heavy shell held
   by hand fills the slot gold as it charges. */
.slot { flex: 1; position: relative; min-height: 0; background: #12152a; border: 2px solid #23274a; border-radius: 12px; padding: 0; overflow: hidden; color: #eee; display: block; text-align: left; touch-action: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; }
.slot.active { border-color: #a78bfa; box-shadow: 0 0 0 1px #a78bfa66, 0 0 14px #a78bfa55; }
.slot.firing { transform: scale(0.97); border-color: #c084fc; box-shadow: 0 0 24px #c084fc, inset 0 0 14px #fff3; }
.slot.auto { transform: none; border-color: #fde68a; box-shadow: 0 0 22px #fbbf24aa, inset 0 0 12px #fff2; animation: autoglow 1.4s ease-in-out infinite; }
.slot.charged { border-color: #fde68a; box-shadow: 0 0 32px #fde68a, inset 0 0 18px #fff5; animation: autoglow 0.5s ease-in-out infinite; }
.slot .art { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.slot::before { content: ''; position: absolute; inset: 0; z-index: 1; background: conic-gradient(#fde68a var(--charge, 0%), transparent 0); opacity: 0.45; pointer-events: none; }
.slot .n { position: absolute; left: 0; right: 0; bottom: 0; z-index: 2; padding: 12px 6px 3px; font-size: 10px; line-height: 1.1; background: linear-gradient(180deg, transparent, #000d 75%); text-shadow: 0 1px 2px #000; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.slot .cd { position: absolute; left: 0; right: 0; bottom: 0; z-index: 1; background: #0009; height: 0; pointer-events: none; }
.slot .sub { position: absolute; left: 4px; top: 4px; z-index: 2; font-size: 8px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: #fde68a; background: #0b1020cc; border-radius: 6px; padding: 2px 5px; pointer-events: none; }
.slot .sub:empty { display: none; }
#pad { position: relative; width: 160px; flex: none; border-radius: 50%; background: radial-gradient(circle, #1b1e33 0%, #12152a 60%, #0b1020 100%); border: 2px solid #3a3f66; touch-action: none; align-self: center; height: 160px; }
#pad .ring { position: absolute; inset: 22px; border-radius: 50%; border: 1px dashed #3a3f66; }
#pad::before, #pad::after { content: ''; position: absolute; left: 50%; top: 50%; background: #3a3f66; }
#pad::before { width: 1px; height: 70%; transform: translate(-50%, -50%); } #pad::after { height: 1px; width: 70%; transform: translate(-50%, -50%); }
#pad .knob { position: absolute; left: 50%; top: 50%; width: 62px; height: 62px; margin: -31px 0 0 -31px; border-radius: 50%; background: linear-gradient(135deg, #a78bfa, #22d3ee); box-shadow: 0 4px 16px #0008, 0 0 14px #a78bfa88; pointer-events: none; transition: transform 0.05s; }
#pad.live { border-color: #a78bfa; } #pad.live .knob { box-shadow: 0 4px 16px #0008, 0 0 26px #c084fc; }
/* every pop-up box fits inside the app with a buffer all round and scrolls inside itself when it is
   too tall (Tyson, 2026-09-06): the result panel, the ability card, the install sheet, the welcome
   card and the favourite sheet all follow the same rule — container padding is the buffer, the box
   has max-height 100 % and its own scroller */
#result { align-items: center; justify-content: center; padding: max(20px, env(safe-area-inset-top)) 20px max(20px, env(safe-area-inset-bottom)); text-align: center; }
#result .panel { max-height: 100%; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; box-sizing: border-box; }
.drop { background: #1b1737; border: 1px solid #7c3aed; border-radius: 14px; padding: 12px; margin: 8px 0; }
.drop h3 { margin: 6px 0 2px; }

.chk { display: flex; gap: 10px; align-items: center; padding: 6px 0; } .chk input { width: 20px; height: 20px; }

/* In 3D the opponent's health and timer stay in the scene. Player health is
   anchored directly above the controls, independent of the camera position. */
#battle.gl .bar, #battle.gl .mid { display: none; }
#battle.gl .hud.bottom .bar { display: block; }
#battle.gl { background: #020617; }
.seg { display: flex; gap: 8px; } .seg .btn { flex: 1; } .seg .btn.on { border-color: #a78bfa; background: #1b1737; }

#arena-name { position: absolute; top: 14px; left: 50%; transform: translateX(-50%); padding: 6px 14px; border-radius: 999px; background: #12152acc; border: 1px solid #a78bfa66; font-size: 13px; letter-spacing: 0.06em; color: #e9d5ff; opacity: 0; pointer-events: none; white-space: nowrap; }
#arena-name.show { animation: arena-cap 5s ease forwards; }
@keyframes arena-cap { 0% { opacity: 0; transform: translate(-50%, -8px); } 12% { opacity: 1; transform: translate(-50%, 0); } 80% { opacity: 1; } 100% { opacity: 0; } }

/* countdown pops (2D) */
#arena .cd { transform-box: fill-box; transform-origin: center; }
#arena .cd.pop { animation: cdpop 0.9s cubic-bezier(.2,.9,.3,1.2); }
#arena .cd.fight { fill: #fde68a; stroke: #b45309; font-size: 96px; }
@keyframes cdpop { 0% { transform: scale(2.2); opacity: 0; } 30% { transform: scale(1); opacity: 1; } 100% { transform: scale(0.9); opacity: 0.8; } }

/* intro / outro splash layer */
#fx { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
.fx-flash { position: absolute; inset: 0; background: radial-gradient(circle at 50% 50%, #fff 0%, #c084fc55 30%, transparent 65%); animation: fxflash 0.9s ease-out forwards; }
@keyframes fxflash { 0% { opacity: 1; transform: scale(0.2); } 100% { opacity: 0; transform: scale(1.6); } }
.fx-banner { position: absolute; left: -10%; right: -10%; padding: 10px 0; text-align: center; font-weight: 800; font-size: 26px; letter-spacing: 0.08em; color: #fff; text-shadow: 0 2px 12px #000; transform: skewY(-6deg); opacity: 0; }
.fx-banner.left { top: 24%; background: linear-gradient(90deg, transparent, #7c3aedcc 30%, #7c3aedcc 70%, transparent); animation: fxleft 3.2s cubic-bezier(.2,.8,.2,1) forwards; }
.fx-banner.right { top: 60%; background: linear-gradient(90deg, transparent, #0891b2cc 30%, #0891b2cc 70%, transparent); animation: fxright 3.2s cubic-bezier(.2,.8,.2,1) forwards; }
@keyframes fxleft { 0% { transform: translateX(-110%) skewY(-6deg); opacity: 0; } 18% { transform: translateX(0) skewY(-6deg); opacity: 1; } 80% { opacity: 1; } 100% { transform: translateX(110%) skewY(-6deg); opacity: 0; } }
@keyframes fxright { 0% { transform: translateX(110%) skewY(-6deg); opacity: 0; } 18% { transform: translateX(0) skewY(-6deg); opacity: 1; } 80% { opacity: 1; } 100% { transform: translateX(-110%) skewY(-6deg); opacity: 0; } }
.fx-vs { position: absolute; top: 42%; left: 50%; transform: translate(-50%, -50%); font-size: 64px; font-weight: 900; font-style: italic; background: linear-gradient(180deg, #fde68a, #f59e0b); -webkit-background-clip: text; background-clip: text; color: transparent; filter: drop-shadow(0 0 18px #f59e0b); animation: fxvs 3.2s cubic-bezier(.2,.9,.3,1.3) forwards; opacity: 0; }
@keyframes fxvs { 0% { transform: translate(-50%, -50%) scale(4) rotate(-20deg); opacity: 0; } 22% { transform: translate(-50%, -50%) scale(1) rotate(-8deg); opacity: 1; } 80% { opacity: 1; } 100% { transform: translate(-50%, -50%) scale(0.6); opacity: 0; } }
.fx-arena { position: absolute; top: 12%; left: 50%; transform: translateX(-50%); text-align: center; font-size: 18px; letter-spacing: 0.12em; color: #e9d5ff; text-shadow: 0 0 14px #a78bfa; white-space: nowrap; animation: fxarena 3.4s ease forwards; opacity: 0; }
.fx-arena small { display: block; font-size: 10px; letter-spacing: 0.4em; opacity: 0.7; }
@keyframes fxarena { 0% { opacity: 0; letter-spacing: 0.6em; } 25% { opacity: 1; letter-spacing: 0.12em; } 85% { opacity: 1; } 100% { opacity: 0; } }
.fx-shade { position: absolute; inset: 0; animation: fxshade 0.6s ease forwards; }
.fx-shade.win { background: radial-gradient(circle, #fde68a22, #0b102099 70%); } .fx-shade.lose { background: radial-gradient(circle, #f43f5e22, #000000cc 70%); } .fx-shade.draw { background: #0b102088; }
@keyframes fxshade { from { opacity: 0; } to { opacity: 1; } }
.fx-result { position: absolute; top: 40%; left: 0; right: 0; text-align: center; font-size: 58px; font-weight: 900; letter-spacing: 0.1em; }
.fx-result.win { color: #fde68a; text-shadow: 0 0 24px #f59e0b, 0 4px 0 #92400e; } .fx-result.lose { color: #fb7185; text-shadow: 0 0 24px #e11d48, 0 4px 0 #4c0519; } .fx-result.draw { color: #e2e8f0; text-shadow: 0 0 18px #94a3b8; }
.fx-letter { display: inline-block; opacity: 0; animation: fxletter 0.7s cubic-bezier(.2,.9,.3,1.4) forwards; }
@keyframes fxletter { 0% { transform: translateY(-60px) scale(2.4) rotate(-12deg); opacity: 0; } 60% { transform: translateY(6px) scale(0.95); opacity: 1; } 100% { transform: none; opacity: 1; } }
.fx-result.lose .fx-letter { animation-name: fxletterfall; }
@keyframes fxletterfall { 0% { transform: translateY(-40px) scale(1.6); opacity: 0; } 50% { transform: translateY(0) scale(1); opacity: 1; } 100% { transform: translateY(10px) rotate(3deg); opacity: 0.9; } }
.fx-bit { position: absolute; top: -4%; left: var(--x); width: 8px; height: 14px; border-radius: 2px; background: hsl(var(--h), 90%, 65%); animation: fxconf var(--t) linear var(--d) forwards; opacity: 0; }
.fx-bit.lose { width: 5px; height: 5px; border-radius: 50%; background: hsl(20, 90%, 55%); box-shadow: 0 0 8px #f97316; animation-name: fxember; top: auto; bottom: -2%; }
.fx-bit.draw { background: #cbd5e1; width: 4px; height: 4px; border-radius: 50%; }
@keyframes fxconf { 0% { transform: translateY(0) rotate(0); opacity: 1; } 100% { transform: translateY(110vh) rotate(var(--r)); opacity: 0.9; } }
@keyframes fxember { 0% { transform: translateY(0); opacity: 0; } 20% { opacity: 1; } 100% { transform: translateY(-90vh) translateX(20px); opacity: 0; } }

/* social */
.panel.small { padding: 12px; gap: 8px; margin-bottom: 8px; }
.list { margin: 6px 0; }
.row-item { display: flex; align-items: center; gap: 8px; padding: 8px 0; border-bottom: 1px solid #23274a; flex-wrap: wrap; }
.row-item > span:nth-child(2) { flex: 1; min-width: 120px; }
.row-item.challenge { background: #1b1737; border: 1px solid #7c3aed; border-radius: 12px; padding: 10px; margin: 6px 0; }
.dot { width: 9px; height: 9px; border-radius: 50%; background: #3a3f66; flex: none; }
.dot.on { background: #4ade80; box-shadow: 0 0 8px #4ade80; }

.fslot .tag { font-size: 9px; letter-spacing: 0.15em; color: #9a95b3; } .fslot.special { border-color: #22d3ee88; } .fslot.special.filled { background: #0b2a33; border-color: #22d3ee; }
.item .spm { font-size: 9px; color: #67e8f9; text-transform: uppercase; letter-spacing: 0.08em; margin-top: -3px; }   /* under the name: the star owns the corner */
tr.me td { color: #c4b5fd; font-weight: 700; }

/* duplicate drops: the big X */
.dupwrap { position: relative; display: inline-block; } .dupwrap .icon { opacity: 0.55; filter: grayscale(0.5); }
.dupx { position: absolute; inset: 0; width: 100%; height: 100%; } .dupx line { stroke: #f43f5e; stroke-width: 9; stroke-linecap: round; filter: drop-shadow(0 0 6px #f43f5e); }
.drop.dup { border-color: #f43f5e; }
.dropcount { margin: 10px 0 2px; font-weight: 700; color: #c4b5fd; }
/* a forge result already in your inventory: marked before you commit the merge */
.havetag { font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: #fda4af; border: 1px solid #f43f5e66; border-radius: 999px; padding: 1px 7px; margin-left: 6px; white-space: nowrap; vertical-align: 2px; }
.odds .odd.have, .odds li.have { color: #fda4af; }
.detail-card .tier.have { color: #fda4af; }
/* forge odds */
.odds { text-align: left; margin: 10px 0; display: flex; flex-direction: column; gap: 6px; }
/* forge results are tappable: each opens its card with the live demo */
#forge-preview .see { cursor: pointer; }
#forge-preview .main-see { background: none; border: none; color: inherit; font: inherit; padding: 0; display: block; margin: 0 auto; }
#forge-preview .main-see h3 { margin: 6px 0 2px; }
#forge-preview .odd.see:hover, #forge-preview li.see:hover, #forge-preview .main-see:hover { filter: brightness(1.25); }
#forge-preview li.see { border-radius: 8px; padding: 2px 4px; }
.odd { padding: 8px 10px; border-radius: 10px; background: #171a2e; font-size: 13px; } .odd b { display: inline-block; min-width: 42px; color: #fff; }
.odd.main { border: 1px solid #a78bfa; } .odd.alt ul { margin: 4px 0 0; padding-left: 18px; } .odd.alt li { display: flex; align-items: center; gap: 6px; }
.odd.prime { border: 1px solid #f59e0b; color: #fde68a; }
.item.prime, .detail-card.prime { border-color: #f59e0b; box-shadow: 0 0 16px #f59e0b55; }

/* skins */
.skins { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; margin: 8px 0 14px; }
.skin { background: #12152a; border: 1px solid #23274a; border-radius: 14px; padding: 10px; text-align: center; display: flex; flex-direction: column; align-items: center; gap: 2px; }
.skin.on { border-color: #a78bfa; box-shadow: 0 0 14px #7c3aed55; }
.skin.other { opacity: 0.7; }
.skin.rare { border-color: #1d4ed8; } .skin.epic { border-color: #7e22ce; } .skin.legendary { border-color: #b45309; background: linear-gradient(180deg, #1c1503, #12152a); }
.sprev { display: block; width: 100%; max-width: 150px; aspect-ratio: 1; }
.sprev svg, .sprev canvas { width: 100%; height: 100%; display: block; }
.skin .nm { font-weight: 700; font-size: 14px; margin-top: 4px; }
.rar { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; font-weight: 700; color: #9a95b3; }
.rar.rare { color: #60a5fa; } .rar.epic { color: #c084fc; } .rar.legendary { color: #fbbf24; }
.skin .std { font-size: 12px; color: #9a95b3; min-height: 1.2em; }
.skin .btn { margin-top: 6px; }
.skins-empty { grid-column: 1 / -1; }
.drop.skin-drop { border-color: #fbbf24; } .drop.skin-drop .sprev { margin: 0 auto; max-width: 130px; }
.drop.skin-drop.common { border-color: #7c3aed; } .drop.skin-drop.rare { border-color: #60a5fa; } .drop.skin-drop.epic { border-color: #c084fc; }

.fx-arena em { display: block; font-style: normal; font-size: 12px; color: #c4b5fd; margin: 4px auto 0; letter-spacing: 0.02em; white-space: normal; max-width: 86vw; }
.fx-arena { max-width: 94vw; }
.fx-result { font-size: min(58px, 14vw); white-space: nowrap; }

/* rematch bar (Loadout tab) */
#rematch-bar { position: sticky; top: -8px; z-index: 6; margin: 0 -12px; padding: 10px 12px; background: #0b1020; border-bottom: 1px solid #23274a; }
.rematch { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; background: #12152a; border: 1px solid #7c3aed; border-radius: 14px; padding: 10px 12px; }
.rematch .who { flex: 1 1 160px; font-size: 14px; } .rematch .who b { color: #fff; }
.ready-pill { display: inline-flex; align-items: center; gap: 6px; border-radius: 999px; padding: 4px 10px; font-size: 12px; font-weight: 700; background: #1f2937; color: #9a95b3; border: 1px solid #374151; white-space: nowrap; }
.ready-pill::before { content: ''; width: 8px; height: 8px; border-radius: 50%; background: #6b7280; }
.ready-pill.on { background: #052e16; color: #86efac; border-color: #166534; } .ready-pill.on::before { background: #22c55e; box-shadow: 0 0 8px #22c55e; }
.ready-pill.wait::before { animation: pulse 1s infinite; } @keyframes pulse { 0%, 100% { opacity: 0.3; } 50% { opacity: 1; } }
.rematch .acts { display: flex; gap: 8px; }
.tab.has-rematch .fslots { top: 66px; }

/* mouse play */
#battle.mouse { cursor: crosshair; } #battle.mouse #pad { opacity: 0.3; } #battle.mouse .pad-btn { opacity: 0.8; }

/* nothing in the app is selectable text; only real inputs keep selection */
html, body { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; }
input, textarea, [contenteditable="true"] { -webkit-user-select: text; user-select: text; }
img, svg, canvas, button { -webkit-user-drag: none; user-select: none; }

/* the map pad: a small map of your half of the arena */
/* The PvP pad maps the near three quarters of the field (Tyson, 2026-09-10), and grew by exactly
   the factor the reachable field did -- 124 -> 193, the same 1.56 the reachable field grew by -- so a finger still travels
   the same arena distance per pixel and the movement feels as it did. The bar grew to hold it. */
#pad.map { width: 176px; height: 193px; border-radius: 16px; background: linear-gradient(180deg, #151935, #0b1020); }
/* Movement pad and the separate full-width angle row. */
.pad-col { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px; flex: none; }
/* Thirteen angle points: centre and six 15-degree steps on either side. */
#tilt { display: flex; align-items: center; gap: 8px; width: 100%; align-self: stretch; height: 44px; padding: 6px 12px; flex: none; touch-action: none; user-select: none; border-top: 1px solid #23274a; background: #0b1020; }
#tilt .tl, #tilt .tv { font-size: 10px; letter-spacing: 0.08em; color: #7b81b5; width: 38px; flex: none; }
#tilt .tv { text-align: right; font-variant-numeric: tabular-nums; color: #a5f3fc; }
#tilt .ticks { flex: 1; min-width: 0; height: 28px; display: flex; align-items: center; justify-content: space-between; padding: 0 4px; background: #0b1020; border: 1px solid #23274a; border-radius: 10px; position: relative; }
#tilt .ticks::before { content: ''; position: absolute; left: 10px; right: 10px; top: 50%; height: 1px; background: #23274a; }
#tilt .ticks i { position: relative; width: 8px; height: 8px; border-radius: 50%; background: #3a3f66; transition: transform 0.1s, background 0.1s; }
#tilt .ticks i.c { width: 10px; height: 10px; background: #5b6099; }
#tilt .ticks i.on { background: linear-gradient(135deg, #a78bfa, #22d3ee); transform: scale(1.35); box-shadow: 0 0 8px #67e8f9aa; }
#tilt.live .ticks { border-color: #67e8f9; }
#battle.wide #controls .pad-col { align-self: center; }
#pad.map .ring { inset: 8px; border-radius: 10px; border: 1px dashed #3a3f66; background: linear-gradient(90deg, transparent 49.5%, #23274a 49.5%, #23274a 50.5%, transparent 50.5%), linear-gradient(180deg, transparent 49.5%, #23274a 49.5%, #23274a 50.5%, transparent 50.5%); }
#pad.map::after { content: 'MOVE'; position: absolute; right: 9px; bottom: 5px; font-size: 10px; letter-spacing: 0.14em; color: #5b5f88; pointer-events: none; }
#pad.map.live { border-color: #a78bfa; }
#pad.map .knob { width: 26px; height: 26px; margin: -13px 0 0 -13px; box-shadow: 0 2px 8px #0008, 0 0 10px #a78bfa88; }

/* favourites and notes */
.item .fav { position: absolute; right: 5px; bottom: 3px; font-size: 15px; line-height: 1; color: #3a3f66; padding: 4px; cursor: pointer; }
/* violet = favourite weapon (a filled weapon slot), cyan = favourite special (the special slot), split = both */
#fav-sheet { position: fixed; inset: 0; z-index: 60; background: #0008; display: flex; align-items: flex-end; justify-content: center; padding: max(20px, env(safe-area-inset-top)) 16px calc(16px + env(safe-area-inset-bottom)); }
#fav-sheet[hidden] { display: none; }
.fav-card { background: #12152a; border: 1px solid #23274a; border-radius: 18px; padding: 16px; width: 100%; max-width: 380px; max-height: 100%; overflow-y: auto; overscroll-behavior: contain; display: grid; gap: 8px; box-shadow: 0 14px 40px #000a; text-align: center; box-sizing: border-box; }
.fav-title { margin: 0; font-weight: 700; } .fav-card .muted { margin: 0 0 4px; }
.item .memo { position: absolute; left: 6px; bottom: 5px; font-size: 12px; color: #67e8f9; }
.detail-card { position: relative; }
.favbig { flex: none; background: none; border: none; font-size: 24px; line-height: 1; color: #3a3f66; cursor: pointer; padding: 2px 4px; }
.notes { display: block; text-align: left; margin: 10px 0 12px; font-size: 13px; color: #9a95b3; }
.notes textarea { display: block; width: 100%; margin-top: 4px; background: #0b1020; color: #fff; border: 1px solid #23274a; border-radius: 10px; padding: 8px 10px; font: inherit; font-size: 14px; resize: vertical; min-height: 64px; }
.notes textarea:focus { outline: none; border-color: #a78bfa; }

/* saved builds */
.builds { background: #12152a; border: 1px solid #23274a; border-radius: 14px; padding: 10px 12px; margin: 10px 0 4px; }
.builds-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; } .builds-head b { flex: 1; }
#build-form { display: flex; gap: 8px; margin-top: 10px; } #build-form input { flex: 1; min-width: 0; background: #0b1020; color: #fff; border: 1px solid #23274a; border-radius: 10px; padding: 8px 10px; font: inherit; }
.build-list { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.build { display: grid; grid-template-columns: auto 1fr; grid-template-areas: 'icons name' 'icons acts'; gap: 4px 12px; align-items: center; background: #0b1020; border: 1px solid #23274a; border-radius: 12px; padding: 8px 10px; }
.build.on { border-color: #a78bfa; box-shadow: 0 0 12px #7c3aed44; }
.b-icons { grid-area: icons; display: flex; gap: 4px; }
.b-slot { width: 38px; height: 38px; border-radius: 9px; background: #12152a; border: 1px solid #23274a; display: grid; place-items: center; font-size: 11px; color: #3a3f66; font-weight: 700; position: relative; }
.b-slot.sp { border-color: #f59e0b88; } .b-slot.missing { opacity: 0.4; } .b-slot.missing::after { content: '✕'; position: absolute; color: #f43f5e; font-size: 20px; font-weight: 800; opacity: 1; }
.b-name { grid-area: name; font-weight: 700; font-size: 14px; }
.b-acts { grid-area: acts; display: flex; gap: 6px; flex-wrap: wrap; }
.btn.danger { border-color: #7f1d1d; color: #fca5a5; }

/* wide battle screens (landscape phones, tablets, desktops): the controls become a
   side column so the arena keeps the full height. The class is set from the battle
   screen's own size (see app.js), so it follows the actual frame, not the viewport. */
/* Wide screens keep the full-width angle and player health rows between the
   arena and controls. The opponent's row remains at the top. */
#battle.wide { display: grid; grid-template-rows: 40px minmax(0, 1fr) 44px 40px auto; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
#battle.wide .hud.top { grid-column: 1 / -1; grid-row: 1; }
#battle.wide #tilt { grid-column: 1 / -1; grid-row: 3; }
#battle.wide .hud.bottom { grid-column: 1 / -1; grid-row: 4; }
#battle.wide .arena-wrap { grid-row: 2; grid-column: 1 / -1; }
#battle.wide #controls { grid-row: 5; grid-column: 1 / -1; justify-self: center; width: min(100%, 1100px); height: 197px; padding: 6px 10px calc(6px + env(safe-area-inset-bottom)); gap: 10px; border-top: 1px solid #23274a; background: #0b1020; }
#battle.wide #controls .btn-col { flex-direction: row; width: auto; flex: none; gap: 8px; }
#battle.wide #controls .pad-btn { width: 112px; }
#battle.wide #controls #slots { flex-direction: row; flex: 1; min-width: 0; }
#battle.wide #controls .slot { min-height: 0; }
#battle.wide #controls .slot .n { font-size: 11px; padding-top: 16px; }
#battle.wide #controls #pad, #battle.wide #controls #pad.map { width: 168px; height: 159px; align-self: center; }   /* 102 -> 159, the same 1.56 */
#battle.wide #battle-status { inset: auto 22% 40% 22%; }
/* a landscape phone is short: a slimmer bar leaves the arena what height there is */
@media (max-height: 520px) {
  #battle.wide #controls { height: 144px; padding-top: 4px; gap: 8px; }
  #battle.wide #controls #pad, #battle.wide #controls #pad.map { width: 136px; height: 112px; }
  #battle.wide #tilt { height: 16px; }
  #battle.wide #controls .pad-btn { width: 96px; font-size: 12px; }
  #battle.wide #controls .slot .n { font-size: 10px; padding-top: 10px; }
}

/* first-login welcome */
#welcome { position: absolute; inset: 0; background: #000b; display: flex; align-items: center; justify-content: center; padding: 20px; z-index: 30; }
.welcome-card { background: linear-gradient(180deg, #171a33, #12152a); border: 1px solid #7c3aed; border-radius: 18px; padding: 22px 20px; max-width: 400px; width: 100%; max-height: 100%; overflow-y: auto; text-align: center; box-shadow: 0 12px 40px #0009; }
.welcome-card h2 { margin: 6px 0 10px; font-size: 24px; }
.welcome-card p { margin: 8px 0; font-size: 14px; line-height: 1.45; color: #cbd5e1; }
.welcome-card b { color: #fff; }
.w-hero { display: flex; gap: 18px; justify-content: center; align-items: flex-end; margin-bottom: 4px; }
.w-hero svg { width: 84px; height: 96px; display: block; filter: drop-shadow(0 6px 14px #0007); }
.w-nums { list-style: none; padding: 0; margin: 12px 0; display: flex; flex-direction: column; gap: 8px; }
.w-nums li { background: #0b1020; border: 1px solid #23274a; border-radius: 12px; padding: 10px 12px; font-size: 14px; color: #cbd5e1; }
.w-nums b { color: #a78bfa; font-size: 16px; }
.welcome-card .btn { margin-top: 12px; }

/* ability attack demo (detail card) */
.demo { width: 100%; max-width: 240px; margin: 4px auto 8px; aspect-ratio: 600 / 660; background: radial-gradient(circle at 50% 82%, #191d3a, #0b1020 70%); border: 1px solid #23274a; border-radius: 14px; overflow: hidden; }
.demo-svg { width: 100%; height: 100%; display: block; }
.demo.arena { max-width: 200px; aspect-ratio: 600 / 1000; background: radial-gradient(circle at 50% 90%, #191d3a, #0b1020 70%); }   /* the special demo shows the whole arena */
.demo-seg { max-width: 240px; margin: 0 auto 10px; } .demo-seg .btn.small { padding: 5px 6px; font-size: 12px; line-height: 1.15; white-space: nowrap; display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 40px; }
.demo-seg .btn .sub { font-size: 10px; font-weight: 500; color: #a5f3fc; letter-spacing: 0.04em; }
.detail-card .debuff b { color: #fbbf24; }

.tier.heavy { color: #fbbf24; }

/* the search for a player follows you round the home screen */
#queue-bar { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; margin: 0 12px 6px; padding: 8px 12px; border-radius: 12px; background: #7c3aed33; border: 1px solid #a78bfa66; font-size: 14px; }
#queue-bar .row { display: flex; gap: 6px; margin: 0; }
#queue-bar-text::after { content: ''; display: inline-block; width: 1.2em; text-align: left; animation: qdots 1.5s steps(4) infinite; }
@keyframes qdots { 0% { content: ''; } 25% { content: '.'; } 50% { content: '..'; } 75% { content: '...'; } }
.mode-toggle { position: relative; z-index: 3; font-size: 11px; line-height: 1; padding: 4px 7px; margin-right: 6px; border-radius: 7px; border: 1px solid #ffffff55; background: #ffffff1a; color: #fff; font-weight: 700; letter-spacing: 0.02em; }
.mode-toggle:active { background: #ffffff33; }
.mode-toggle.flip { padding: 4px 6px; display: inline-flex; align-items: center; }
.mode-toggle.flip svg { display: block; }
.mode-toggle.flip.on { background: #7c8cff; border-color: #a9b4ff; color: #0b1020; }
#controls.flip { flex-direction: row-reverse; }   /* pad on the left, weapon and special buttons on the right (Tyson, 2026-09-06) */
.tier.beam { color: #67e8f9; }

/* wide screens (tablets, desktops): the home content is a centred column that
   fills its width — panels stretch, grids get more columns — instead of a
   phone-width card hugging the left edge */
@media (min-width: 720px) {
  #home main > .tab { max-width: 1100px; margin: 0 auto; }
  #home main .panel { max-width: none; }
  #home main .grid { grid-template-columns: repeat(auto-fill, minmax(112px, 1fr)); }
  #home #queue-bar { max-width: 1100px; margin-left: auto; margin-right: auto; }
  #home main .fslots { justify-content: center; }
}

/* The Gauntlet (single-player roguelike) on the Play tab */
#gauntlet h2 { margin: 4px 0 6px; font-size: 20px; }
.gpaths { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px; margin-top: 8px; }
.gpath { background: #12152a; border: 1px solid #23274a; border-radius: 14px; padding: 12px; }
.gpath.wand { border-color: #7c3aed66; } .gpath.plane { border-color: #0891b266; }
.gpath h3 { margin: 0 0 4px; }
.gpath .btn { width: 100%; margin-top: 6px; }
.gboard { margin-top: 8px; line-height: 1.5; }

#bank-run { color: #fde68a; font-weight: 700; margin-right: 10px; animation: bankpulse 1.2s ease-in-out infinite; }
@keyframes bankpulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }

.gsi { display: flex; flex-direction: column; align-items: center; gap: 6px; margin: 4px 0 10px; }
.gsi .tiny { margin: 0; }
#name-form input { width: 100%; box-sizing: border-box; }
.acct-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 6px 0; }

/* The boss's reward: three cards over the field in the calm after a kill (Tyson, 2026-09-09).
   It sits inside the arena, above the HUD, and never covers the health bars. */
#boon-pick { position: absolute; inset: 0; display: grid; place-items: center; z-index: 12; background: radial-gradient(circle at 50% 45%, #0b1020cc, #0b1020ee); padding: 10px; }
.boon-card-wrap { width: 100%; max-width: 440px; text-align: center; }
.boon-head { margin: 0 0 8px; font-weight: 800; letter-spacing: 0.04em; color: #fff; font-size: clamp(14px, 4vw, 19px); text-shadow: 0 2px 12px #000; }
#boon-pick .boons { display: flex; flex-direction: column; gap: 8px; }
/* three explicit rows beside the badge: name, family, what it does -- each in its own cell, so
   the line that says what the boon does is never covered by the family label (found 2026-09-10) */
#boon-pick .boon { display: grid; grid-template-columns: 46px 1fr; grid-template-rows: auto auto auto; column-gap: 10px; row-gap: 2px; align-items: center; text-align: left; padding: 9px 12px; border-radius: 14px; border: 1px solid #2b3060; background: linear-gradient(180deg, #171b3a, #12152a); color: #e9e6ff; cursor: pointer; }
#boon-pick .boon .boon-ico { grid-area: 1 / 1 / 4 / 2; align-self: center; }
#boon-pick .boon b { grid-area: 1 / 2 / 2 / 3; font-size: 15px; color: #fff; }
#boon-pick .boon .tag { grid-area: 2 / 2 / 3 / 3; font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; opacity: 0.75; }
#boon-pick .boon .sub { grid-area: 3 / 2 / 4 / 3; font-size: 12px; line-height: 1.3; color: #b9b6d6; }
#boon-pick .boon.t-guard { border-color: #67e8f966; } #boon-pick .boon.t-gun { border-color: #fb718566; } #boon-pick .boon.t-run { border-color: #a78bfa66; }
#boon-pick .boon:active { transform: scale(0.985); }
/* what the run is carrying, in the corner of the field */
#boon-strip { position: absolute; left: 6px; top: 6px; display: flex; flex-wrap: wrap; gap: 3px; max-width: 40%; pointer-events: none; z-index: 6; }
.boon-chip { display: grid; place-items: center; width: 24px; height: 24px; border-radius: 8px; background: #12152acc; border: 1px solid #2b3060; }
@media (max-height: 620px) { #boon-pick .boon .sub { display: none; } #boon-pick .boon { grid-template-rows: auto auto; } #boon-pick .boon .boon-ico { grid-area: 1 / 1 / 3 / 2; } }

/* The Gauntlet's pad is a map of the whole field, so it has the field's shape: 600 x 1000 means a
   pad three units wide to five tall, and a finger crossing it moves the vessel the same fraction
   across as down -- one to one, the way the PvP pad maps a half (Tyson, 2026-09-10). The taller
   pad takes room from the field, which is what he asked for: "adjust the play field size until
   movement matches one to one". */
#battle.rogue #controls { height: 244px; }
#battle.rogue #pad.map { width: 132px; height: 220px; border-radius: 14px; }
#battle.rogue #pad.map .knob { width: 46px; height: 46px; margin: -23px 0 0 -23px; }
.pad-btn.special.picked { outline: 2px solid #a5f3fc; outline-offset: -2px; }
@media (max-height: 720px) { #battle.rogue #controls { height: 210px; } #battle.rogue #pad.map { width: 114px; height: 190px; } }
/* the wide layout puts the bar under a full-width arena and has its own pad rule (three ids), so
   the run's pad has to answer it at the same weight or it keeps the landscape shape */
#battle.wide.rogue #controls { height: 200px; }
#battle.wide.rogue #controls #pad, #battle.wide.rogue #controls #pad.map { width: 108px; height: 180px; }
@media (max-height: 520px) {
  #battle.wide.rogue #controls { height: 140px; }
  #battle.wide.rogue #controls #pad, #battle.wide.rogue #controls #pad.map { width: 72px; height: 120px; }
}

/* the build-out before a run */
#gbuild { align-items: flex-start; overflow-y: auto; }
.panel.gbuild { max-width: 560px; gap: 10px; }
.gbuild-head h2 { margin: 0; font-size: 20px; }
.gbuild-head p { margin: 2px 0 0; }
.gbuild-acts { display: flex; gap: 8px; }
.coop-tag { display: inline-block; vertical-align: middle; margin-left: 6px; padding: 2px 8px; border-radius: 10px; background: #0b2a33; border: 1px solid #22d3ee; color: #a5f3fc; font-size: 11px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; }
.gb-room { display: flex; gap: 6px; } .gb-room input { flex: 1; min-width: 0; }   /* a co-op room by code (Tyson, 2026-09-10) */
.gbuild-acts .btn { flex: 1; }

/* pause, and what a run is carrying */
#pause-run { font-size: 12px; letter-spacing: 1px; }
#pause-run.on { color: #fde68a; border-color: #fde68a88; }
#paused { position: absolute; inset: 0; display: grid; place-items: center; z-index: 14; background: #0b1020d9; }
.paused-card { text-align: center; display: flex; flex-direction: column; gap: 8px; padding: 18px 22px; border-radius: 16px; background: #12152a; border: 1px solid #2b3060; min-width: 220px; }
.paused-card h2 { margin: 0; font-size: 22px; letter-spacing: 0.06em; }
.boon-chip.kept { border-color: #fde68a; box-shadow: 0 0 8px #fde68a55; }
.buff-chip { position: relative; display: grid; place-items: center; width: 24px; height: 24px; border-radius: 8px; background: #12152acc; border: 1px solid hsl(var(--h), 80%, 55%); }
.buff-chip i { position: absolute; right: -2px; bottom: -4px; font-style: normal; font-size: 9px; font-weight: 700; color: #fff; background: #12152a; border-radius: 6px; padding: 0 2px; }

/* saved builds and previews on the build-out screen */
.gbuild-saved { display: flex; flex-direction: column; gap: 6px; }
.gb-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.gb-chips .chip { background: #171b3a; border: 1px solid #2b3060; color: #e9e6ff; border-radius: 999px; padding: 5px 12px; font-size: 12px; cursor: pointer; }
.gb-chips .chip:active { transform: scale(0.97); }
.gb-save { display: flex; gap: 6px; }
.gb-save input { flex: 1; min-width: 0; }
.fslot { position: relative; }
.peek { position: absolute; right: 3px; top: 3px; width: 18px; height: 18px; border-radius: 50%; border: 1px solid #3a3f66; background: #12152acc; color: #c7c9ee; font-size: 11px; font-weight: 700; line-height: 1; cursor: pointer; padding: 0; z-index: 2; }
.item .peek { right: auto; left: 4px; top: auto; bottom: 4px; }   /* the preview sits bottom-left; the in-use badge owns the top-left */
.item .peek ~ .memo { left: 26px; }
.peek:active { background: #2b3060; }

/* the sign-in pitch: two short paragraphs above the demos */
#auth .pitch { font-size: 12.5px; line-height: 1.35; margin: 0; }
@media (max-height: 780px) { #auth .pitch:last-of-type { display: none; } }
@media (max-height: 620px) { #auth .pitch { display: none; } }

/* the boss banner's hint: what its affix does (bosses.js) */
.fx-arena em.hint { display: block; font-style: normal; font-size: 12px; color: #c7d2fe; margin-top: 4px; letter-spacing: 0.01em; }

/* The loadout slots, on the Loadout tab and the Gauntlet's build-out alike: five across (three weapons,
   the three-use special, the one-use special), the ability's icon filling a filled slot edge to edge,
   the slot's label -- and a special's use count -- on a scrim along the top, and nothing else written
   on it (Tyson, 2026-09-10: "make sure the icons and not the writing for the ability fill out the
   loadout"; the name is the slot's title and on the card). Declared last so the grid wins over .fslots. */
.lslots { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; justify-content: stretch; }
.lslot { width: auto; height: auto; aspect-ratio: 5 / 6; min-height: 0; padding: 0; overflow: hidden; justify-content: center; }
.lslot .tag { position: absolute; top: 0; left: 0; right: 0; z-index: 1; padding: 4px 2px 9px; font-size: 8px; line-height: 1.2; letter-spacing: 0.12em; color: #d6d3ee; text-align: center; background: linear-gradient(180deg, #0b1020f2 40%, #0b102000); pointer-events: none; }
.lslot .tag .uses { display: block; font-size: 9px; font-weight: 800; letter-spacing: 0.08em; color: #67e8f9; }
.lslot.special .tag { color: #a5f3fc; }
.lslot.filled .icon { position: absolute; inset: 0; width: 100%; height: 100%; }
.lslot .ph { font-size: 26px; margin-top: 16px; }
.lslot .peek { top: auto; bottom: 3px; right: 3px; }

/* The mode explainer (Tyson, 2026-09-10): the first time a device goes into PvP or the Gauntlet -- and again the
   first time after the app updates or is reset -- a card explains the mode before it starts. Above every screen. */
#explain { position: absolute; inset: 0; z-index: 31; background: #000c; display: flex; align-items: center; justify-content: center; padding: max(18px, env(safe-area-inset-top)) 18px max(18px, env(safe-area-inset-bottom)); }
.explain-card { background: linear-gradient(180deg, #171a33, #12152a); border: 1px solid #22d3ee; border-radius: 18px; padding: 18px 18px 16px; max-width: 420px; width: 100%; max-height: 100%; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; box-sizing: border-box; box-shadow: 0 12px 40px #000a; display: flex; flex-direction: column; gap: 8px; }
.explain-card .eyebrow { margin: 0; font-size: 10px; letter-spacing: 0.18em; text-transform: uppercase; color: #67e8f9; }
.explain-card h2 { margin: 0; font-size: 22px; }
.explain-card ul { margin: 2px 0 6px; padding-left: 18px; display: flex; flex-direction: column; gap: 7px; }
.explain-card li { font-size: 13.5px; line-height: 1.4; color: #cbd5e1; }
.explain-card li b { color: #fff; }
.explain-card .btn.big { width: 100%; }
.explain-card .btn.small { align-self: center; }
.explain-card .offline-cards { margin-top: 6px; display: flex; flex-wrap: wrap; gap: 6px; }   /* what an offline run or match earned, reported once back online */

/* ---- favourites in four kinds (Tyson, 2026-09-10): a star's colours come inline from app.js favPaint -- one colour, or a
   band of each kind's colour; the card's border takes the first kind's colour */
.item.faved { border-color: var(--favc, #a78bfa66); }
.item .fav.multi, .favbig.multi, .bstar.multi, .fav-prev { filter: drop-shadow(0 0 4px #ffffff40); }
.fav-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.fav-k { display: flex; align-items: center; gap: 8px; text-align: left; border-color: #3a3f66; font-size: 13px; line-height: 1.25; padding: 10px; font-weight: 500; }
.fav-k b { font-weight: 800; }
.fav-k .sw { flex: none; width: 16px; height: 16px; border-radius: 50%; border: 2px solid var(--kc); }
.fav-k.on { border-color: var(--kc); background: #171a33; box-shadow: inset 0 0 0 1px var(--kc); }
.fav-k.on .sw { background: var(--kc); box-shadow: 0 0 8px var(--kc); }
.fav-prev { font-size: 22px; color: #3a3f66; vertical-align: -2px; }
.fav-acts { justify-content: flex-end; gap: 6px; }
.bstar { background: none; border: none; font-size: 18px; line-height: 1; color: #3a3f66; padding: 2px 5px 2px 0; cursor: pointer; vertical-align: -1px; }
.gb-chip { display: inline-flex; align-items: center; gap: 2px; }

/* ---- the ability menu (Tyson, 2026-09-10): a switch or a note, a search box, the pinned favourites, then folding groups */
.amenu { margin-top: 8px; }
.am-bar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 2px 0 4px; }
.am-role { flex: 1 1 200px; max-width: 320px; }
.am-fixed { margin: 0; font-size: 12px; color: #a5b4fc; flex: 1 1 200px; }
.am-q { flex: 1 1 150px; min-width: 0; background: #0b1020; color: #fff; border: 1px solid #23274a; border-radius: 10px; padding: 8px 10px; font: inherit; font-size: 16px; }   /* 16px: iOS zooms into anything smaller */
.am-q:focus { outline: none; border-color: #a78bfa; }
.am-sec { margin: 12px 2px 4px; font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase; color: #8f8aab; }
.am-favs .grid { margin-top: 4px; }
.am-group { border: 1px solid #23274a; border-radius: 12px; background: #0f1226; margin: 5px 0; overflow: hidden; }
.am-group.open { border-color: #3a3f66; background: #0d1024; }
.am-head { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 44px; padding: 6px 10px; background: none; border: none; color: #e9e6ff; font: inherit; text-align: left; cursor: pointer; }
.am-head:active { background: #171a33; }
.am-head .chev { flex: none; width: 10px; color: #8f8aab; font-size: 11px; transition: transform 0.15s; }
.am-group.open .chev { transform: rotate(90deg); }
.am-name { font-weight: 700; font-size: 14px; white-space: nowrap; }
.am-n { flex: none; font-size: 11px; color: #a5a1c4; background: #1b1e33; border-radius: 8px; padding: 1px 7px; font-weight: 600; }
.am-star { flex: none; font-size: 11px; color: #fde68a; white-space: nowrap; }
.am-use { flex: none; font-size: 10px; color: #67e8f9; border: 1px solid #22d3ee66; border-radius: 8px; padding: 0 6px; white-space: nowrap; }
.am-icons { margin-left: auto; display: flex; gap: 1px; overflow: hidden; min-width: 0; justify-content: flex-end; }
.am-icons .icon { flex: none; }
.am-blurb { margin: 0 10px 4px 28px; font-size: 12px; line-height: 1.35; color: #9a95b3; }
.am-body { margin: 4px 8px 10px; }

/* ---- the ability card fits the screen (Tyson, 2026-09-10): the demo keeps its size; the card takes nearly the whole screen,
   the switch sits beside the demo, the star and the close button share the title row, and each view says only its own part */
#detail { padding: max(8px, env(safe-area-inset-top)) 8px max(8px, env(safe-area-inset-bottom)); }
.detail-card { max-width: 660px; padding: 10px 12px 12px; text-align: left; }
.dc-top { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; }
.dc-top h3 { flex: 1; min-width: 0; margin: 0; font-size: 16px; line-height: 1.2; text-align: center; }
.dc-x { flex: none; width: 34px; height: 34px; border-radius: 50%; border: 1px solid #3a3f66; background: #0b1020; color: #c7c9ee; font-size: 15px; line-height: 1; cursor: pointer; }
.dc-body { display: flex; flex-direction: column; gap: 8px; }
.dc-media { display: flex; justify-content: center; align-items: flex-start; gap: 8px; }
.dc-media .demo { margin: 0; flex: none; width: 240px; }
.dc-media .demo.arena { width: 200px; }
.dc-side { flex: 1 1 96px; max-width: 150px; min-width: 0; display: flex; flex-direction: column; gap: 6px; }   /* beside the demo on a phone: the switch, then where it came from */
.dc-side .demo-seg { flex-direction: column; width: auto; max-width: none; margin: 0; }
.dc-side .demo-seg .btn.small { min-height: 48px; white-space: normal; }
.dc-side .tier { font-size: 12px; margin: 0; }
.dc-text { min-width: 0; }
.detail-card dl { gap: 3px 10px; margin: 4px 0 6px; font-size: 13px; line-height: 1.35; }
.detail-card .tier { margin: 2px 0 6px; line-height: 1.35; }
.detail-card .s-only { display: none; }
.detail-card.sp-view .s-only, .detail-card.both-view .s-only { display: block; }
.detail-card.sp-view .w-only { display: none; }
.detail-card.both-view .sp-hint { display: none; }
.detail-card .notes { margin: 6px 0 0; position: relative; }
.detail-card #note-state { position: absolute; right: 10px; top: -14px; }
.detail-card .notes textarea { min-height: 38px; height: 38px; resize: none; transition: height 0.15s; }
.detail-card .notes textarea:focus { height: 80px; }
@media (min-width: 600px) {
  .dc-body { flex-direction: row; align-items: flex-start; gap: 16px; }
  .dc-media { flex-direction: column; align-items: center; }
  .dc-side { flex: none; width: 240px; max-width: none; }
  .dc-side .demo-seg { flex-direction: row; }
  .dc-side .demo-seg .btn.small { min-height: 40px; }
  .dc-text { flex: 1; }
}
