:root{--glass:rgba(12,18,38,.52);--line:rgba(255,255,255,.18);--text:#fff;--accent:#baff78}
/* No text-select/callout anywhere by default - this is a game, not a page
   of text, and a long-press or double-tap-drag anywhere on the HUD or
   canvas (the "JUMP"/"DOWN"/nameplate text, the coords readout, even the
   canvas's own blank area) was landing on iOS's normal text-selection
   behaviour: blue selection handles, sometimes the whole visible screen,
   plus the Copy/Look Up callout menu - all of it fighting the same taps
   that are supposed to move the joystick or press a button. touch-action
   above already stops scroll/zoom gestures, but that's a separate thing
   from text selection and doesn't prevent it. The auth form's two real
   text fields (username/password) explicitly opt back in below, since
   those genuinely need to be selectable/pasteable. */
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
input,textarea{-webkit-user-select:text;user-select:text;-webkit-touch-callout:default}
*::selection{background:transparent;color:inherit}
input::selection,textarea::selection{background:rgba(80,160,255,.35)}
.action{-webkit-user-drag:none;touch-action:none}
html,body{margin:0;width:100%;height:100%;overflow:hidden;background:#75cfff;color:var(--text);font-family:-apple-system,BlinkMacSystemFont,"SF Pro Display","Segoe UI",sans-serif;touch-action:none}
canvas{display:block;width:100%;height:100%;position:fixed;inset:0;z-index:0}
#hud{position:fixed;inset:0;pointer-events:none;padding:max(12px,env(safe-area-inset-top)) max(12px,env(safe-area-inset-right)) max(12px,env(safe-area-inset-bottom)) max(12px,env(safe-area-inset-left));z-index:10}
.pill{background:var(--glass);border:1px solid var(--line);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);border-radius:15px;padding:9px 12px;box-shadow:0 8px 28px rgba(0,0,0,.16)}
/* The minimap now owns the top-left slot the "MAXIMUS WORLD" wordmark used
   to sit in - the wordmark told a player who was already inside the world
   nothing they didn't know, where a map answers the one question this game
   is actually about ("what's over there?"). layoutHud() measures this
   element to find where the top HUD band ends, exactly as it measured the
   title before it. */
#minimap{position:absolute;left:max(14px,env(safe-area-inset-left));top:max(14px,env(safe-area-inset-top));padding:6px;border-radius:17px;line-height:0;pointer-events:auto;cursor:pointer}
#minimapCanvas{width:174px;height:174px;border-radius:50%;display:block}
/* Tap-to-expand full map. Square, not round - a circular clip on a view this
   large would hide too much of the corners for what's meant to be the
   "actually plan a route" view, where the round pill is just a glance. */
#minimapOverlay{position:fixed;inset:0;z-index:27;display:none;align-items:center;justify-content:center;background:rgba(4,9,24,.6);backdrop-filter:blur(10px);padding:20px;pointer-events:auto}
#minimapOverlay.open{display:flex}
#minimapOverlay .box{padding:14px;border-radius:20px}
#minimapCanvasLarge{width:min(86vmin,560px);height:min(86vmin,560px);border-radius:12px;display:block}
#minimapOverlay .hint{text-align:center;margin-top:10px;font-size:12px;opacity:.75}
/* The right-hand HUD column (stats/online/settings) used to be three
   independently absolute-positioned elements stacked with hand-tuned
   top offsets - correct only as long as none of them ever changed
   height, which broke the moment the online badge appeared (it could
   push the settings button down into the hotbar). A flex column with
   a real gap can't drift out of alignment like that, whatever height
   any child ends up being. */
#hudRight{position:absolute;right:max(14px,env(safe-area-inset-right));top:max(14px,env(safe-area-inset-top));display:flex;flex-direction:column;align-items:flex-end;gap:8px;pointer-events:none}
#stats{text-align:right;line-height:1.25}
#biome{font-weight:800}
#prompt{position:absolute;left:50%;bottom:142px;transform:translateX(-50%);opacity:0;transition:opacity .2s;white-space:nowrap}
#quest{position:absolute;left:14px;bottom:18px;max-width:390px;font-size:13px}
#settingsBtn{width:46px;height:46px;border-radius:50%;pointer-events:auto;border:1px solid var(--line);background:var(--glass);color:#fff;display:flex;align-items:center;justify-content:center;flex-shrink:0}
#settingsBtn svg{width:20px;height:20px}
/* Vertical, left edge, centred in the open gap between the top HUD row
   and the joystick zone below it - both measured at runtime by layoutHud()
   since that gap's size depends on device, orientation and safe-area
   insets. top here is only the pre-JS fallback. */
#controls{position:fixed;inset:0;z-index:5;pointer-events:none}
#stickZone{overscroll-behavior:none;z-index:30;z-index:30;position:absolute;left:18px;bottom:28px;width:140px;height:140px;border-radius:50%;pointer-events:auto;touch-action:none;z-index:20}
#stickBase{position:absolute;inset:16px;border-radius:50%;background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.25);backdrop-filter:blur(8px)}
#stickKnob{position:absolute;width:62px;height:62px;left:39px;top:39px;border-radius:50%;background:rgba(255,255,255,.3);border:1px solid rgba(255,255,255,.45);box-shadow:0 6px 20px rgba(0,0,0,.22)}
#look{overscroll-behavior:none;position:absolute;inset:0;width:100%;height:100%;pointer-events:auto;touch-action:none;z-index:5}
.action{position:absolute;right:max(14px,env(safe-area-inset-right));bottom:max(20px,env(safe-area-inset-bottom));width:78px;height:56px;border-radius:18px;border:1px solid rgba(255,255,255,.28);background:rgba(8,14,28,.55);color:#fff;font-weight:900;pointer-events:auto;touch-action:none;z-index:25}
/* RUN (sprint) sits closest to the thumb at the bottom, JUMP just above,
   USE above that when it's showing - a real, deliberate 14px gap between
   each. Was a 4px gap between jump and use and an 82px gulf between
   sprint and jump, neither of which read as an intentional layout. */
#jump{bottom:calc(max(20px,env(safe-area-inset-bottom)) + 62px)}.small{width:74px;height:48px;font-size:11px}.small#use{bottom:calc(max(20px,env(safe-area-inset-bottom)) + 180px)}.small#sprint{bottom:max(20px,env(safe-area-inset-bottom));right:max(14px,env(safe-area-inset-right))}
/* Small - half the height of the .small buttons either side of it - and
   docked in its own slot between JUMP and USE, the same 14px gap pattern
   the rest of this column already uses, rather than reusing an existing
   button's spot (that's what put a control on top of another one the
   first time flying got a HUD button). */
.tiny{height:34px;font-size:10px;letter-spacing:.03em}
#flyToggle{bottom:calc(max(20px,env(safe-area-inset-bottom)) + 132px)}
#flyToggle.on{background:rgba(126,209,255,.4);border-color:#7ed1ff}
.hidden{display:none!important}
/* z-index 28, not 20: the hotbar and the jump/run/use action buttons sit
   at 25 (see #hotbar/.action below) so their own on-screen position stays
   reachable over the HUD in normal play. Left at 20, this dialog was
   visually on top of them but STACKED UNDER them, so a tap in that corner
   still hit the game underneath and could launch a portal, jump, or start
   sprinting while the player thought they were safely in a menu. 28 still
   sits below the title card (30) and the portal-launch overlay (40), so
   those keep covering settings too, as intended. */
/* =====================================================================
   SETTINGS PANEL
   ---------------------------------------------------------------------
   One dark surface, one accent, four sections. The panel is a product
   UI rather than a HUD element: sectioned into tabs (character,
   graphics, controls, audio) because a single scrolling column of
   fifteen unrelated controls is where the old one fell over - a player
   hunting for the volume slider had to scroll past every hair colour.

   Colour discipline is deliberate. --brand carries selection and
   nothing else, --gold means MXC and nothing else, --good means owned.
   Anything that isn't communicating one of those three things is a
   neutral, so the things that DO carry meaning stay legible.

   z-index 28, not 20: the hotbar and the jump/run/use buttons sit at 25
   so they stay reachable in normal play. Left at 20, this dialog was
   visually on top of them but STACKED UNDER them, so a tap in that
   corner still hit the game underneath and could launch a portal, jump
   or start sprinting while the player thought they were in a menu. 28
   still sits below the title card (30) and the portal-launch overlay
   (40), so those keep covering settings, as intended.
   ===================================================================== */
:root{--surface:#12141b;--surface2:#171a23;--surface3:#1d212c;--edge:rgba(255,255,255,.08);--edge2:rgba(255,255,255,.14);--ink:#e9ebf2;--muted:#98a0b2;--brand:#7a5cff;--gold:#ffc94d;--good:#4ad391}
#settings,#tutorial,#leaderboard{position:fixed;inset:0;z-index:28;display:none;align-items:center;justify-content:center;background:rgba(6,8,14,.62);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);padding:18px;pointer-events:auto}
#settings.open,#tutorial.open,#leaderboard.open{display:flex}
.panel{width:min(880px,100%);max-height:min(92vh,760px);display:flex;flex-direction:column;background:var(--surface);border:1px solid var(--edge);border-radius:18px;box-shadow:0 32px 90px rgba(0,0,0,.6),0 2px 0 rgba(255,255,255,.04) inset;overflow:hidden}
.panelTop{display:flex;align-items:center;gap:14px;padding:16px 16px 15px 20px;border-bottom:1px solid var(--edge);background:var(--surface2)}
.panelHeading{flex:1;min-width:0}
.panelHeading h2{margin:0;font-size:17px;font-weight:700;letter-spacing:-.01em}
.panelHeading p{margin:2px 0 0;font-size:12px;color:var(--muted)}
.wallet{display:flex;align-items:center;gap:6px;padding:7px 12px;border-radius:999px;border:1px solid rgba(255,201,77,.28);background:rgba(255,201,77,.1);color:var(--gold);font-size:13px;font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap}
.walletUnit{font-size:10px;letter-spacing:.08em;opacity:.72}
.walletMark{font-size:11px}
.iconBtn{width:34px;height:34px;flex-shrink:0;border-radius:10px;border:1px solid var(--edge);background:transparent;color:var(--muted);font-size:14px;line-height:1;cursor:pointer;transition:background .15s,color .15s}
.iconBtn:hover{background:rgba(255,255,255,.06);color:var(--ink)}
.panelBody{display:flex;min-height:0;flex:1}
/* A rail, not a row: four sections read as a table of contents down the
   side, and it leaves the full width of the pane for the content. */
.tabRail{display:flex;flex-direction:column;gap:2px;padding:12px 10px;width:148px;flex-shrink:0;border-right:1px solid var(--edge);background:var(--surface2)}
.tab{appearance:none;text-align:left;padding:10px 12px;border:0;border-radius:9px;background:transparent;color:var(--muted);font:inherit;font-size:13px;font-weight:600;cursor:pointer;transition:background .15s,color .15s}
.tab:hover{background:rgba(255,255,255,.05);color:var(--ink)}
.tab.active{background:rgba(122,92,255,.16);color:#fff;box-shadow:inset 2px 0 0 var(--brand)}
.panes{flex:1;min-width:0;overflow-y:auto;overscroll-behavior:contain;padding:18px 20px 22px}
.pane{display:none}.pane.active{display:block}
.group{padding:16px 0;border-top:1px solid var(--edge)}
.group:first-child{border-top:0;padding-top:2px}
.groupHead{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin-bottom:12px}
.groupHead h3{margin:0;font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
.groupMeta{font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums}
.groupMeta b{color:var(--good);font-weight:700}
/* ---- character ---- */
.charTop{display:flex;gap:18px;align-items:stretch;margin-bottom:4px}
#charPreviewWrap{position:relative;flex-shrink:0;border-radius:14px;overflow:hidden;border:1px solid var(--edge);background:radial-gradient(120% 90% at 50% 12%,#2a2f47 0%,#141722 62%,#0f1118 100%)}
/* Overrides the page-wide canvas{position:fixed;inset:0} rule, which
   exists for the one full-screen game canvas and would otherwise pin
   this preview to the viewport corner, outside its own panel - and
   collapse its container to zero height, since a fixed-position child
   contributes nothing to its parent's layout. */
#charPreview{display:block;position:static;width:232px;height:300px;touch-action:none;cursor:grab}
#charPreview:active{cursor:grabbing}
.previewHint{position:absolute;right:9px;top:8px;font-size:9.5px;letter-spacing:.08em;text-transform:uppercase;color:rgba(255,255,255,.34);pointer-events:none}
.charSide{flex:1;min-width:0;display:flex;flex-direction:column;align-items:flex-start;gap:14px}
.paneNote{margin:0;font-size:12.5px;line-height:1.6;color:var(--muted)}
.ownStats{display:flex;gap:10px;width:100%}
.ownStats div{flex:1;padding:11px 13px;border-radius:11px;border:1px solid var(--edge);background:var(--surface2)}
.ownStats b{display:block;font-size:19px;font-weight:700;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.ownStats span{display:block;margin-top:2px;font-size:10.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
/* ---- swatches and chips ---- */
.swatchGrid{display:flex;flex-wrap:wrap;gap:10px}
.swatch{position:relative;width:38px;height:38px;border-radius:11px;border:1px solid rgba(0,0,0,.35);padding:0;cursor:pointer;box-shadow:0 1px 2px rgba(0,0,0,.4)}
.swatch::after{content:"";position:absolute;inset:-4px;border-radius:14px;border:2px solid transparent;transition:border-color .15s}
.swatch:hover::after{border-color:var(--edge2)}
.swatch.selected::after{border-color:var(--brand)}
.swatch.pending::after{border-color:var(--gold);border-style:dashed}
.swatch.locked{opacity:.42}
.swatch.locked:hover{opacity:.7}
.swatch .lock{position:absolute;right:-3px;bottom:-3px;width:15px;height:15px;border-radius:50%;background:var(--surface3);border:1px solid var(--edge2);color:var(--gold);font-size:8px;line-height:13px;text-align:center}
.chipGrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(104px,1fr));gap:8px}
.chip{position:relative;display:flex;align-items:center;justify-content:space-between;gap:6px;padding:10px 12px;border-radius:10px;border:1px solid var(--edge);background:var(--surface2);color:var(--ink);font:inherit;font-size:12.5px;font-weight:600;cursor:pointer;transition:background .15s,border-color .15s,color .15s}
.chip:hover{background:var(--surface3);border-color:var(--edge2)}
.chip.selected{background:rgba(122,92,255,.18);border-color:var(--brand);color:#fff}
.chip.pending{border-color:var(--gold);border-style:dashed}
.chip.locked{color:var(--muted)}
.chip .tag{font-size:10px;font-weight:700;letter-spacing:.02em;color:var(--gold);font-variant-numeric:tabular-nums;opacity:.9}
.chip.selected .tag{color:#fff}
/* ---- fields ---- */
.field{display:block;margin:0 0 14px}
.field:last-child{margin-bottom:0}
.field.row{display:flex;align-items:center;justify-content:space-between;gap:12px}
.fieldLabel{display:flex;align-items:baseline;justify-content:space-between;gap:12px;font-size:13px;font-weight:600;margin-bottom:8px}
.field.row .fieldLabel{margin-bottom:0}
.fieldLabel em{font-style:normal;color:var(--muted);font-variant-numeric:tabular-nums;font-weight:600}
.field small,.group>small{display:block;margin-top:7px;font-size:11.5px;line-height:1.55;color:var(--muted)}
.field select{width:100%;padding:10px 12px;border-radius:10px;border:1px solid var(--edge);background:var(--surface2);color:var(--ink);font:inherit;font-size:13px}
.field input[type=range]{-webkit-appearance:none;appearance:none;width:100%;height:20px;margin:0;background:transparent;cursor:pointer}
.field input[type=range]::-webkit-slider-runnable-track{height:5px;border-radius:999px;background:var(--surface3);border:1px solid var(--edge)}
.field input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:16px;height:16px;margin-top:-7px;border-radius:50%;background:var(--brand);border:2px solid rgba(255,255,255,.85);box-shadow:0 1px 3px rgba(0,0,0,.5)}
.field input[type=range]::-moz-range-track{height:5px;border-radius:999px;background:var(--surface3);border:1px solid var(--edge)}
.field input[type=range]::-moz-range-progress{height:5px;border-radius:999px;background:var(--brand)}
.field input[type=range]::-moz-range-thumb{width:14px;height:14px;border:2px solid rgba(255,255,255,.85);border-radius:50%;background:var(--brand)}
.field input[type=checkbox]{width:18px;height:18px;accent-color:var(--brand);flex-shrink:0}
.statLine{margin-top:12px;padding-top:12px;border-top:1px solid var(--edge);font-size:11.5px;color:var(--muted)}
.statLine span{color:var(--ink);font-weight:600}
.keyList{display:grid;gap:1px;background:var(--edge);border:1px solid var(--edge);border-radius:10px;overflow:hidden}
.keyRow{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:9px 12px;background:var(--surface2);font-size:12.5px}
.keyRow span{color:var(--muted)}
.keyRow b{font-weight:600}
/* ---- footer and buying ---- */
.panelFoot{border-top:1px solid var(--edge);background:var(--surface2)}
.buyBar{display:flex;align-items:center;gap:12px;padding:12px 16px;border-bottom:1px solid var(--edge);background:linear-gradient(180deg,rgba(255,201,77,.07),transparent)}
.buyBar.hidden{display:none}
.buyPreviewDot{width:30px;height:30px;border-radius:9px;flex-shrink:0;border:1px solid rgba(0,0,0,.4);box-shadow:0 1px 2px rgba(0,0,0,.4)}
.buyText{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.buyText strong{font-size:13px;font-weight:650}
.buyText span{font-size:11.5px;color:var(--muted)}
.buyText span.warn{color:#ffb4a8}
.panelActions{display:flex;gap:10px;justify-content:flex-end;padding:13px 16px}
.btn{padding:10px 16px;border-radius:10px;border:1px solid var(--edge);background:var(--surface3);color:var(--ink);font:inherit;font-size:13px;font-weight:600;cursor:pointer;transition:background .15s,border-color .15s,opacity .15s}
.btn:hover{border-color:var(--edge2)}
.btn.ghost{background:transparent;color:var(--muted)}
.btn.ghost:hover{background:rgba(255,255,255,.05);color:var(--ink)}
.btn.wide{width:100%}
.btn.primary{background:var(--brand);border-color:var(--brand);color:#fff}
.btn.primary:hover{background:#8a6fff}
.btn.buy{display:flex;align-items:center;gap:6px;background:var(--gold);border-color:var(--gold);color:#241a02;font-weight:750;font-variant-numeric:tabular-nums}
.btn.buy:hover{background:#ffd469}
.btn:disabled{opacity:.45;cursor:default}
/* ---------------------------------------------------------------
   LEADERBOARD - top-3 podium (fixed, decorative order) plus a
   paginated ranking of every remaining MDT account by MXC balance.
   .lbPanel wider than the settings .panel (880px) now, not narrower -
   720px, up from 600 and 520 before that across two widening passes
   that both turned out to still read as cramped with real usernames in
   it. A two-column name/balance list doesn't strictly NEED this much
   room, but there's no real downside to it having more than it needs,
   and there was a real downside (clipped/wrapped names) to it having
   less.
   --------------------------------------------------------------- */
.lbPanel{width:min(720px,100%)}
.lbBody{flex-direction:column;overflow-y:auto;overscroll-behavior:contain;padding:20px 22px 8px}
.lbStatus{padding:34px 0;text-align:center;color:var(--muted);font-size:13px}
.lbStatus.warn{color:#ffb4a8}
.lbStatus.hidden,.lbPodium.hidden,.lbRows.hidden,.lbPager.hidden{display:none}
.lbPodium{display:flex;align-items:flex-end;justify-content:center;gap:10px;margin-bottom:20px}
.lbSpot{display:flex;flex-direction:column;align-items:center;width:32%;padding:14px 10px 14px;border-radius:14px 14px 0 0;background:var(--surface2);border:1px solid var(--edge);border-bottom:0;text-align:center;min-width:0}
.lbSpot .lbRankBadge{width:28px;height:28px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:13px;margin-bottom:8px;background:var(--surface3);color:var(--ink);flex-shrink:0}
/* A long username now wraps onto a second line instead of ellipsis-
   truncating on one - the extra panel width above covers most names
   already, this just stops the rest from clipping mid-word. */
.lbSpot .lbName{font-weight:700;font-size:13px;max-width:100%;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;line-height:1.25;word-break:break-word}
.lbSpot .lbBalance{margin-top:4px;font-size:12px;font-weight:700;color:var(--gold);font-variant-numeric:tabular-nums}
.lbSpot.rank1{order:2;padding-top:6px}
.lbSpot.rank1 .lbRankBadge{background:linear-gradient(180deg,#ffe28a,#ffc94d);color:#2b2103;width:34px;height:34px;font-size:15px}
.lbSpot.rank2{order:1}
.lbSpot.rank2 .lbRankBadge{background:linear-gradient(180deg,#e7ebf4,#c3cad9);color:#20242e}
.lbSpot.rank3{order:3}
.lbSpot.rank3 .lbRankBadge{background:linear-gradient(180deg,#e3ad84,#c78455);color:#2b1a0c}
.lbRows{display:flex;flex-direction:column;gap:1px;background:var(--edge);border:1px solid var(--edge);border-radius:12px;overflow:hidden;margin-bottom:14px}
.lbRow{display:flex;align-items:center;gap:10px;padding:10px 14px;background:var(--surface2);font-size:13px}
.lbRow.me{background:rgba(122,92,255,.16)}
.lbRow .lbRank{width:24px;flex-shrink:0;text-align:center;font-weight:700;color:var(--muted);font-variant-numeric:tabular-nums}
/* flex:2/flex:1 (not flex:1 alone) so the name column actually claims
   the panel's extra width above rather than leaving it to whatever's
   left over after the balance - a bare number never needs more than its
   own content width, but a name might. */
.lbRow .lbRowName{flex:2;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600}
.lbRow .lbRowBalance{flex:1;flex-shrink:0;text-align:right;font-weight:700;color:var(--gold);font-variant-numeric:tabular-nums}
.lbPager{display:flex;align-items:center;justify-content:center;gap:14px;padding:2px 0 16px}
.lbPager span{font-size:12px;color:var(--muted);font-variant-numeric:tabular-nums}
.lbPager .btn{padding:9px 14px}
@media(max-width:720px){
 #leaderboard{padding:0}
 .lbPanel{width:100%;max-height:100%;height:100%;border-radius:0;border:0}
}
/* Narrow screens: the rail becomes a scrollable row of tabs across the
   top, and the preview stacks above the copy instead of beside it. */
@media(max-width:720px){
 #settings,#tutorial{padding:0}
 .panel{width:100%;max-height:100%;height:100%;border-radius:0;border:0}
 .panelBody{flex-direction:column}
 .tabRail{flex-direction:row;width:auto;gap:6px;padding:8px 10px;border-right:0;border-bottom:1px solid var(--edge);overflow-x:auto;scrollbar-width:none}
 .tabRail::-webkit-scrollbar{display:none}
 .tab{white-space:nowrap;padding:9px 14px;border-radius:999px}
 .tab.active{box-shadow:none;background:var(--brand)}
 .panes{padding:16px 14px 20px}
 .charTop{flex-direction:column;gap:12px}
 #charPreviewWrap{align-self:center}
 .panelActions{padding:11px 14px}
 .buyBar{flex-wrap:wrap}
 .buyText{flex-basis:100%;order:-1}
}
/* The tutorial keeps the old simple card - it is a wall of text, not a
   control surface, and does not need tabs. */
.settingsBox{width:min(560px,100%);max-height:90%;overflow:auto;background:var(--surface);border:1px solid var(--edge);border-radius:18px;padding:22px;box-shadow:0 32px 90px rgba(0,0,0,.6)}
.settingsHead{display:flex;justify-content:space-between;align-items:center;margin-bottom:6px}
.settingsHead h2{margin:0;font-size:17px;font-weight:700}
.closeBtn{width:34px;height:34px;border-radius:10px;font-size:18px;background:none;border:1px solid var(--edge);color:var(--muted);cursor:pointer}
.setting{margin:16px 0}
.setting label{display:block;font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
.setting p{margin:7px 0 0;font-size:13px;line-height:1.6}
.settingsActions{display:flex;gap:10px;justify-content:flex-end;margin-top:20px}
.settingsActions button{padding:10px 16px;border-radius:10px;border:1px solid var(--edge);background:var(--surface3);color:var(--ink);font:inherit;font-size:13px;font-weight:600;cursor:pointer}
.settingsActions button:last-child{background:var(--brand);border-color:var(--brand);color:#fff}
#titleCard{position:fixed;inset:0;z-index:30;display:flex;align-items:center;justify-content:center;text-align:center;background:linear-gradient(180deg,#6fd2ff 0%,#caa7ff 48%,#ffbd88 100%);padding:24px;transition:opacity .7s}
#titleCard .box{max-width:500px;background:rgba(7,13,30,.25);padding:28px;border-radius:28px;border:1px solid rgba(255,255,255,.3);backdrop-filter:blur(12px)}
#titleCard h1{font-size:clamp(48px,13vw,92px);line-height:.86;margin:0 0 15px;letter-spacing:-.06em;text-shadow:0 12px 40px rgba(25,30,80,.25)}
#titleCard p{font-size:15px;line-height:1.5}
#enter,#authSubmit{display:block;width:100%;margin-top:10px;padding:16px 22px;border:0;border-radius:999px;background:#fff;color:#171229;font-weight:900;font-size:15px;min-width:210px;touch-action:manipulation}
#authSubmit:disabled{opacity:.6}
#authChecking.hidden{display:none}
@media(max-width:700px){#quest{display:none}
.pill{font-size:12px}.action{right:max(12px,env(safe-area-inset-right))}}
@media(max-width:480px){.action{width:72px}.small{width:70px;height:46px}.tiny{height:32px}#minimapCanvas{width:141px;height:141px}}
/* Landscape's bottom offsets used flat px numbers instead of the
   safe-area-aware max() used everywhere else in this file, so on a
   Face ID/Dynamic Island iPhone rotated sideways they sat under the
   ~21px home-indicator inset instead of clear of it. #jump and #use
   also used to land exactly edge-to-edge (204px met jump's own 148+56
   top with zero gap) - bumped to a real 10px gap between them.
   #hudRight also moves to the left, under the title, in landscape:
   short viewports don't have enough vertical room for a top-anchored
   column and the bottom-anchored jump/use/sprint column to both live
   on the right edge without eventually meeting in the middle. */
/* The vertical left-edge hotbar (see #hotbar above) needs a left column
   already shared with the title and, in landscape, #hudRight too (below)
   - there isn't room left for a third thing stacked in that same column
   on the shortest landscape phones. Landscape keeps the hotbar horizontal
   instead, top-centre, which is genuinely open space: title+hudRight are
   over on the left, the jump/use/sprint column is on the right. */
/* Top-right, not top-centre: #stats also moves onto this same top band in
   landscape (into a horizontal row, further right than it looks - see its
   own comment below), and top-right is the one spot left genuinely open
   once #hudRight moves to the left and the jump/use/sprint column stays
   down at the bottom-right. */
@media(orientation:landscape) and (max-height:520px){.action{bottom:max(12px,env(safe-area-inset-bottom))}#jump{bottom:calc(max(12px,env(safe-area-inset-bottom)) + 62px)}.small#use{bottom:calc(max(12px,env(safe-area-inset-bottom)) + 180px)}#flyToggle{bottom:calc(max(12px,env(safe-area-inset-bottom)) + 132px)}.small#sprint{bottom:max(12px,env(safe-area-inset-bottom))}
#hudRight{left:max(14px,env(safe-area-inset-left));right:auto;align-items:flex-start;gap:6px;top:calc(max(10px,env(safe-area-inset-top)) + 46px)}
/* Landscape phones have the least vertical room of anything, and #hudRight
   stacks directly under the minimap here (measured by layoutHud) - so the
   map shrinks rather than pushing the stats pill off the bottom. */
#minimapCanvas{width:117px;height:117px}
/* The full-height stats pill (4 stacked readouts) plus the online badge
   plus the settings button don't fit in the ~200px of vertical room
   between the title and the joystick zone on the shortest iPhones
   (SE, mini) in landscape - laying the 4 readouts out in a row instead
   of stacked saves most of that height back. */
#stats{display:flex;gap:10px;text-align:left}}
#authWrap{margin-top:14px;text-align:left}
#authWrap.hidden{display:none!important}
.authField{margin:10px 0}
.authField label{display:block;font-size:11px;font-weight:800;letter-spacing:.08em;opacity:.75;margin-bottom:5px;text-transform:uppercase}
.authField input{width:100%;padding:13px 14px;border-radius:12px;border:1px solid rgba(255,255,255,.3);background:rgba(0,0,0,.28);color:#fff;font-size:15px;font-family:inherit}
.authField input:focus{outline:2px solid var(--accent)}
#authError{color:#ffb4b4;font-size:12.5px;font-weight:700;margin:2px 0 4px;min-height:1em}
#authGoogle .mdtx-gbtn{border-radius:999px;min-height:50px;color:#fff;font-size:15px}
#authGoogle .mdtx-or{color:#fff}
#authToggle{background:none;border:0;color:#fff;text-decoration:underline;font-size:12.5px;padding:8px;opacity:.85}
#authStatus{font-size:12.5px;opacity:.8;margin-top:6px}
.authSpinner{width:26px;height:26px;border-radius:50%;border:3px solid rgba(255,255,255,.25);border-top-color:#fff;animation:authspin .8s linear infinite;margin:14px auto 0}
@keyframes authspin{to{transform:rotate(360deg)}}
#portalOverlay{position:fixed;inset:0;z-index:40;display:flex;align-items:center;justify-content:center;background:radial-gradient(circle at 50% 50%,rgba(255,255,255,.9),rgba(120,90,255,.55) 45%,rgba(10,4,30,.96) 100%);opacity:0;pointer-events:none;transition:opacity .35s}
#portalOverlay.show{opacity:1;pointer-events:auto}
#portalOverlay .msg a{pointer-events:auto;text-decoration:underline}
#portalOverlay .msg{font-weight:900;font-size:clamp(22px,5vw,40px);letter-spacing:.05em;text-shadow:0 8px 30px rgba(0,0,0,.35);text-align:center}
#lockHint{position:absolute;left:50%;top:14px;transform:translateX(-50%);opacity:0;transition:opacity .25s;pointer-events:none;font-size:12px}
#lockHint.show{opacity:1}
#online{font-size:11px;text-align:right;opacity:.9}
#online .dot{display:inline-block;width:7px;height:7px;border-radius:50%;background:#7cff8a;margin-right:5px;box-shadow:0 0 8px #7cff8a}
/* Updates pane */
#updStatus{margin:0 0 12px;padding:0;border-top:0;font-size:13px;color:var(--ink)}
.btnRow{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px}
/* Radio (Settings -> Audio) */
.radioNow{display:flex;align-items:center;gap:10px;padding:10px 12px;margin-bottom:10px;border-radius:10px;background:var(--surface3);font-size:13px;color:var(--muted)}
.radioNow b{color:var(--ink)}
.radioDot{width:8px;height:8px;border-radius:50%;background:var(--edge);flex-shrink:0}
.radioDot.live{background:#3ed98c;box-shadow:0 0 0 4px rgba(62,217,140,.18)}
.radioList{display:flex;flex-direction:column;gap:6px;margin-bottom:10px}
.radioRow{display:flex;align-items:center;gap:10px;padding:9px 10px 9px 12px;border-radius:10px;border:1px solid var(--edge)}
.radioRow.now{border-color:var(--brand)}
.radioInfo{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.radioInfo b{font-size:13.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.radioInfo span{font-size:11.5px;color:var(--muted)}
.radioRow.muted .radioInfo{opacity:.5}
.radioMute{flex-shrink:0;min-width:78px;padding:7px 10px;border-radius:8px;border:1px solid var(--brand);background:rgba(122,92,255,.16);color:#fff;font:inherit;font-size:12px;font-weight:700;cursor:pointer}
.radioMute[aria-pressed="true"]{border-color:var(--edge);background:transparent;color:var(--muted)}
.radioEmpty{font-size:12.5px;color:var(--muted);padding:6px 0}

/* ---------- Now playing (always visible, top of the HUD) ----------
   Centred pill at the top on wide screens, top-right on short landscape phones; a
   slim full-width strip across the very top on portrait phones, where
   the gap between the minimap and the stats column is too narrow for a
   title - the minimap and stats column shift down just under it. */
#nowPlaying{position:absolute;left:50%;top:max(14px,env(safe-area-inset-top));transform:translateX(-50%);display:flex;align-items:center;gap:4px;padding:4px 4px 4px 6px;border-radius:999px;pointer-events:auto;max-width:min(440px,calc(100vw - 480px));min-width:220px;z-index:26}
.npMain{display:flex;align-items:center;gap:10px;min-width:0;flex:1;background:none;border:0;color:#fff;padding:3px 8px 3px 6px;border-radius:999px;cursor:pointer;text-align:left;font:inherit}
.npMain:hover{background:rgba(255,255,255,.06)}
.npText{display:flex;flex-direction:column;min-width:0;line-height:1.2}
.npLabel{font-size:9.5px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.55)}
.npTitle{font-size:13px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.npEq{display:flex;align-items:flex-end;gap:2px;width:16px;height:14px;flex-shrink:0}
.npEq i{flex:1;height:3px;border-radius:1px;background:rgba(255,255,255,.45)}
#nowPlaying.playing .npEq i{background:var(--accent);animation:npEq 1.1s ease-in-out infinite}
#nowPlaying.playing .npEq i:nth-child(2){animation-delay:-.3s}
#nowPlaying.playing .npEq i:nth-child(3){animation-delay:-.65s}
#nowPlaying.playing .npEq i:nth-child(4){animation-delay:-.15s}
@keyframes npEq{0%,100%{height:3px}50%{height:14px}}
@media (prefers-reduced-motion:reduce){#nowPlaying.playing .npEq i{animation:none;height:9px}}
.npLike{display:flex;align-items:center;gap:5px;flex-shrink:0;height:34px;padding:0 12px 0 10px;border-radius:999px;border:1px solid var(--line);background:rgba(255,255,255,.06);color:rgba(255,255,255,.75);font:700 12.5px/1 system-ui,-apple-system,sans-serif;cursor:pointer}
.npLike:disabled{opacity:.35;cursor:default}
.npLike.liked{color:#ff6b93;border-color:rgba(255,107,147,.55);background:rgba(255,107,147,.14)}
.npLike.liked svg{animation:npPop .35s ease-out}
@keyframes npPop{0%{transform:scale(.6)}60%{transform:scale(1.25)}100%{transform:scale(1)}}
#lockHint{top:calc(max(14px,env(safe-area-inset-top)) + 58px)}
@media (max-width:700px) and (orientation:portrait){
 #nowPlaying{left:max(12px,env(safe-area-inset-left));right:max(12px,env(safe-area-inset-right));transform:none;max-width:none;min-width:0;top:max(10px,env(safe-area-inset-top))}
 #minimap,#hudRight{top:calc(max(10px,env(safe-area-inset-top)) + 58px)}
 #lockHint{top:calc(max(10px,env(safe-area-inset-top)) + 58px)}
}
/* Short landscape: the stats column moves under the minimap on the left,
   and the top-right corner (where the old hotbar row sat) is free. */
@media (orientation:landscape) and (max-height:520px){
 #nowPlaying{top:max(10px,env(safe-area-inset-top));left:auto;right:max(14px,env(safe-area-inset-right));transform:none;max-width:min(360px,calc(50vw - 24px));min-width:200px}
 #lockHint{top:calc(max(10px,env(safe-area-inset-top)) + 52px)}
}
/* Radio list: likes + built-in theme tag */
.radioLike{flex-shrink:0;min-width:52px;padding:7px 9px;border-radius:8px;border:1px solid var(--edge);background:transparent;color:var(--muted);font:inherit;font-size:12px;font-weight:700;cursor:pointer}
.radioLike.liked{color:#ff6b93;border-color:rgba(255,107,147,.55);background:rgba(255,107,147,.12)}
.radioTag{font-style:normal;font-size:9.5px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--brand);margin-right:2px}

/* Radio: choose the Maximus World album or Player made songs */
.playlistPick{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin:2px 0 10px}
.playlistPick button{display:flex;flex-direction:column;align-items:flex-start;gap:2px;text-align:left;padding:10px 12px;border-radius:10px;border:1px solid var(--edge);background:rgba(255,255,255,.03);color:inherit;font:inherit;cursor:pointer}
.playlistPick button b{font-size:13px}
.playlistPick button span{font-size:11px;opacity:.65}
.playlistPick button.on{border-color:var(--brand);background:rgba(255,255,255,.07);box-shadow:inset 0 0 0 1px var(--brand)}

/* Beta map: "Now entering" region banner */
#zoneBanner{--zc:#baff78;position:fixed;left:50%;top:22%;transform:translate(-50%,-8px);z-index:30;pointer-events:none;text-align:center;opacity:0;max-width:min(560px,90vw)}
#zoneBanner small{display:block;font-size:11px;font-weight:800;letter-spacing:.32em;text-transform:uppercase;color:rgba(255,255,255,.75);text-shadow:0 2px 8px rgba(0,0,0,.6)}
#zoneBanner b{display:block;font-size:clamp(28px,5.4vw,52px);font-weight:900;letter-spacing:.06em;text-transform:uppercase;color:#fff;margin:4px 0 6px;text-shadow:0 0 22px var(--zc),0 3px 14px rgba(0,0,0,.65)}
#zoneBanner b::after{content:'';display:block;height:3px;width:40%;margin:8px auto 0;border-radius:3px;background:linear-gradient(90deg,transparent,var(--zc),transparent)}
#zoneBanner span{display:block;font-size:14px;font-weight:600;color:rgba(255,255,255,.9);text-shadow:0 2px 10px rgba(0,0,0,.7)}
#zoneBanner.show{animation:zoneIn 4.6s ease forwards}
@keyframes zoneIn{0%{opacity:0;transform:translate(-50%,-8px)}10%{opacity:1;transform:translate(-50%,0)}78%{opacity:1;transform:translate(-50%,0)}100%{opacity:0;transform:translate(-50%,4px)}}
