/* Broadside.io UI: deep navy panels, parchment text, brass trim, crimson accents. */
:root {
  --ink: #07131f; --line: rgba(217, 164, 65, .5); --brass: #d9a441; --gold: #ffd36b; --danger: #ff4a3a; /* gold = value/score, brass = borders, danger = red, nothing else */
  --parch: #f1e4c3; --parch2: #d6c08c; --crimson: #c0302f; --crimson2: #7d161b; --text: #f4ecd8; --muted: #b4c2cf; --sea: #9fdcff;
  --r: 12px; --rc: 6px; --s1: 4px; --s2: 8px; --s3: 16px; --edge: 14px; /* panel / chip radius, the 4-8-16 grid, the gap to the screen corners */
  --outline: 1px 0 var(--ink), -1px 0 var(--ink), 0 1px var(--ink), 0 -1px var(--ink); /* a 1px dark text outline that reads over foam */
  --sat: env(safe-area-inset-top, 0px); --sab: env(safe-area-inset-bottom, 0px); --sal: env(safe-area-inset-left, 0px); --sar: env(safe-area-inset-right, 0px);
  --label: 12px; /* the type scale's label size (STYLE.md title / value / label): the floor for every small caps word on the HUD and cards */
  --display: 'Pirata One', Georgia, serif; --ui: 'Barlow Semi Condensed', system-ui, -apple-system, sans-serif;
}
body.mobile { --edge: 10px; --label: 11px; }
html, body { margin: 0; height: 100%; overflow: hidden; background: #0b3b5c; font-family: var(--ui); color: var(--text);
  touch-action: none; user-select: none; -webkit-user-select: none; -webkit-tap-highlight-color: transparent; }
canvas { display: block; }
#view { position: fixed; inset: 0; width: 100%; height: 100%; } /* the 3D view always covers the screen (core.js fit) */
.hidden { display: none !important; }
svg { width: 1em; height: 1em; fill: currentColor; flex: none; }
svg.ic { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
button { font: inherit; color: inherit; }
:focus-visible { outline: 3px solid var(--gold); outline-offset: 3px; }
body.mobile .only-desk, body:not(.mobile) .only-touch { display: none !important; }
/* nothing in-game shows behind the menu / death screen */
body:not(.playing) :is(#hud, #lb, #minimap, #feed, .farrow, #tags, #upgrades, #banner, #msg, #teams, #roundend) { display: none !important; }
#hud, #lb, #minimap, #feed, #teams { z-index: 3; } /* above name tags and popups */

.plate {
  background: repeating-linear-gradient(90deg, rgba(255, 255, 255, .018) 0 1px, transparent 1px 4px),
    linear-gradient(180deg, rgba(22, 53, 82, .9), rgba(8, 21, 34, .92));
  border: 1px solid var(--line); border-radius: var(--r);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .6), inset 0 1px 0 rgba(255, 236, 190, .1), 0 8px 22px rgba(0, 0, 0, .45);
}

/* --- menu and death screens --- */
.panel { position: fixed; inset: 0; z-index: 10; display: flex; overflow-y: auto; touch-action: pan-y; box-sizing: border-box;
  padding: calc(16px + var(--sat)) calc(16px + var(--sar)) calc(16px + var(--sab)) calc(16px + var(--sal));
  background: radial-gradient(ellipse 80% 70% at 50% 45%, rgba(4, 14, 26, .3), rgba(3, 10, 19, .88)); }
.card { margin: auto; width: min(460px, 100%); display: flex; flex-direction: column; gap: 12px; text-align: center; }
.emblem { align-self: center; font-size: 34px; color: var(--brass); margin-bottom: -10px; filter: drop-shadow(0 2px 2px #000); }
.logo { position: relative; align-self: center; }
.logo h1 { margin: 0; padding: 0 6px; font: 400 clamp(64px, 18vw, 104px)/.95 var(--display); letter-spacing: 1px;
  background: linear-gradient(180deg, #fff6d2 10%, var(--gold) 45%, #c98a2b 75%, #8a5a17); -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 3px 0 #2b1806) drop-shadow(0 10px 18px rgba(0, 0, 0, .6)); }
.logo .io { position: absolute; right: -22px; bottom: -4px; transform: rotate(-8deg); padding: 1px 8px; border-radius: var(--rc);
  font: 800 18px var(--ui); color: var(--parch); background: linear-gradient(180deg, var(--crimson), var(--crimson2));
  border: 1px solid var(--gold); box-shadow: 0 3px 8px rgba(0, 0, 0, .5); }
.tagline { margin: -4px 0 4px; font: 600 14px var(--ui); letter-spacing: 3px; text-transform: uppercase; color: var(--parch2); text-shadow: 0 1px 2px #000; }
input { user-select: text; -webkit-user-select: text; }
#name { box-sizing: border-box; width: 100%; height: 54px; padding: 0 16px; border-radius: var(--r); text-align: center;
  font: 700 20px var(--ui); color: #2a1a08; background: linear-gradient(180deg, #f7edd3, #e3cf9f); border: 2px solid #8a5a17;
  box-shadow: inset 0 2px 4px rgba(90, 60, 20, .35), 0 4px 12px rgba(0, 0, 0, .4); }
#name::placeholder { color: #806843; }
#name:focus { outline: 3px solid var(--gold); outline-offset: 2px; }
#sea { align-self: center; max-width: 100%; height: 34px; padding: 0 10px; border-radius: var(--rc); cursor: pointer; font: 600 15px var(--ui); color: var(--parch);
  background: rgba(8, 21, 34, .85); border: 1px solid var(--line); }
#sea[hidden], .seaform[hidden], #seanote[hidden] { display: none; }
.tsc[hidden], #fpips i[hidden], .crewpick label[hidden], .crewpick .any i[hidden] { display: none; } /* the small map (hud.js TEAM_N): no Emerald, two forts */
body.mobile #tbar.two { grid-template-columns: repeat(2, 1fr); } /* its two score cells, then the clock row */
/* private seas (hud.js initSeas): a button beside the picker opens a one-row form; a passworded link asks in the same row style */
.searow { display: flex; justify-content: center; gap: 6px; } .searow #sea { min-width: 0; }
#newsea { flex: none; height: 34px; padding: 0 10px; border-radius: var(--rc); cursor: pointer; font: 600 15px var(--ui); color: var(--gold); background: rgba(8, 21, 34, .85); border: 1px solid var(--line); }
.seaform { display: flex; flex-wrap: wrap; gap: 6px; }
.seaform :is(input, select) { flex: 1 1 110px; min-width: 0; box-sizing: border-box; height: 40px; padding: 0 10px; border-radius: var(--rc); font: 600 16px var(--ui); color: #2a1a08;
  background: linear-gradient(180deg, #f7edd3, #e3cf9f); border: 1px solid #8a5a17; } .seaform select { flex-basis: 30%; padding: 0 6px; cursor: pointer; } .seaform input::placeholder { color: #806843; }
.seaform button { flex: none; height: 40px; padding: 0 14px; border-radius: var(--rc); cursor: pointer; font: 800 14px var(--ui); letter-spacing: 1px; text-transform: uppercase; color: var(--ink);
  background: linear-gradient(180deg, var(--gold), var(--brass)); border: 1px solid #8a5a17; }
#seanote { margin: 0; font: 600 15px var(--ui); color: var(--parch); text-shadow: 0 1px 2px #000; } #seanote button { margin-left: 6px; font: 700 14px var(--ui); color: var(--gold); background: none; border: 0; text-decoration: underline; cursor: pointer; }
#newname, #newpw { flex-basis: 40%; } /* name + password on one row, the two bot pickers + Create under them; fixed bases: a pick never moves the row */
#seatag:not(.priv) .lock { display: none; }
.crewpick { display: flex; gap: 6px; } /* hud.js initCrew: the side we ask for, with its captains and bots (/seas); fixed tiles: a pick or a count only recolours or retypes */
.crewpick label { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; height: 64px; cursor: pointer; color: var(--tc); }
.crewpick label:not(:has(:checked)) { background: rgba(8, 21, 34, .72); border-color: rgba(217, 164, 65, .2); box-shadow: none; } /* unpicked: a dimmer tile, the name and counts kept full strength (an .6 opacity read at 2:1) */
.crewpick .auto { flex-grow: .62; } #deadcrew .auto { display: none; } #deadcrew { padding-top: 8px; } #deadcrew label:has(:checked) { display: none; } /* only the other sides: the big button is ours */ /* the death card: a side, or the one we had */
.crewpick input { position: absolute; opacity: 0; pointer-events: none; } /* the label is the target; the radio keeps the keys and the screen reader */
.crewpick b { display: flex; align-items: center; gap: 4px; font: 800 13px var(--ui); letter-spacing: 1px; text-transform: uppercase; white-space: nowrap; } .crewpick b svg { font-size: 16px; flex: none; }
.crewpick .n { display: flex; align-items: center; gap: 3px; font: 800 15px var(--ui); font-variant-numeric: tabular-nums; color: var(--parch); } .crewpick .n svg { width: 12px; height: 12px; fill: var(--parch2); }
.crewpick small { font: 600 var(--label) var(--ui); color: var(--muted); white-space: nowrap; }
.crewpick .any { display: flex; align-items: center; gap: 3px; height: 18px; } .crewpick .any i { width: 6px; height: 6px; border-radius: 50%; } /* Auto: any of the three */
.crewpick label:has(:checked) { border-color: var(--tc); box-shadow: 0 0 0 1px var(--tc), inset 0 0 14px color-mix(in srgb, var(--tc) 30%, transparent), 0 8px 22px rgba(0, 0, 0, .45); } /* a ring, not a thicker border: nothing moves */
.crewpick label:has(:focus-visible) { outline: 2px solid var(--gold); outline-offset: 2px; }
@media (hover: hover) { .crewpick label:not(:has(:checked)):hover { border-color: var(--line); background: rgba(8, 21, 34, .88); } }
#sea:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
/* "Invite · <sea>", quiet, tucked into the minimap square's empty bottom-left corner (off the action); a click copies an invite link. A real tap target: 24 px tall, 32 px on phones */
#seatag { position: fixed; z-index: 3; right: calc(var(--edge) + var(--sar)); bottom: calc(var(--edge) + var(--sab) + min(300px, 34vh, 34vw) + 6px); /* just over the chart, clear of its frame */ display: flex; align-items: center; gap: 5px;
  min-height: 24px; justify-content: center; padding: 0 8px; border: 0; border-radius: var(--rc); background: rgba(7, 19, 31, .35); cursor: pointer; font: 600 13px var(--ui); color: var(--parch2); opacity: .5; text-shadow: 0 1px 2px #000; }
#seatag:hover, #seatag:focus-visible { opacity: 1; background: rgba(7, 19, 31, .6); }
#seatag .ic { width: 13px; height: 13px; }
body:not(.playing) #seatag, #seatag:has(> span:empty) { display: none; }
body.mobile #seatag { display: none; } /* phone: prime space over the sea, and it looks like a control; the death card's Invite crew asks at the right moment */
#invited { margin: -2px 0 0; font: 700 16px var(--ui); color: var(--parch); text-shadow: 0 1px 2px #000; } /* an invite link's "Join the Azure Navy on Tortuga" */
/* the death card's quiet "Invite crew": the natural moment to bring a friend */
#deadinvite { align-self: center; min-height: 32px; padding: 0 12px; border: 0; background: none; cursor: pointer; font: 700 14px var(--ui); letter-spacing: 1px; color: var(--parch2);
  text-decoration: underline dotted; text-underline-offset: 4px; }
#deadinvite:hover, #deadinvite:focus-visible { color: var(--gold); }
#deadfoot { display: grid; } #deadfoot > * { grid-area: 1 / 1; } /* Invite crew beside the Switch side tab, one row; opened, the sides span the card under both */
#deadfoot #deadinvite { z-index: 1; align-self: start; justify-self: start; width: 120px; height: 40px; } #deadswitch summary { margin-left: 132px; }
.mirrorrow { align-self: center; display: flex; align-items: center; gap: 8px; min-height: 32px; cursor: pointer; font: 600 14px var(--ui); color: var(--parch2); text-shadow: 0 1px 2px #000; }
.mirrorrow select { font: 600 14px var(--ui); color: var(--parch); background: var(--ink); border: 1px solid var(--line); border-radius: var(--rc); padding: 2px 4px; } /* the button style picker (hud.js setBtnStyle) */
#leave { align-self: stretch; justify-content: center; margin-top: 4px; padding: 0 10px; color: var(--gold); background: none; border: 1px solid var(--line); border-radius: var(--rc); } /* settings: back to the start screen */
body:has(#menu:not(.hidden)) #leave { display: none; } /* already there */
.mirrorrow input { width: 18px; height: 18px; margin: 0; accent-color: var(--gold); } /* the phone menu's left-handed switch (hud.js setMirror) */
.big { height: 62px; border-radius: var(--r); cursor: pointer; font: 400 34px/1 var(--display); letter-spacing: 2px; color: #fff3d0;
  background: linear-gradient(180deg, #e04a3f, #a5181d 55%, #7a0f13); border: 2px solid var(--gold); text-shadow: 0 2px 0 rgba(0, 0, 0, .45);
  box-shadow: 0 5px 0 #4a0a0c, 0 12px 26px rgba(0, 0, 0, .5), inset 0 1px 0 rgba(255, 255, 255, .35); transition: transform .08s, translate .15s, box-shadow .15s, filter .15s; }
@media (hover: hover) { .big:hover { filter: brightness(1.15); translate: 0 -2px; box-shadow: 0 7px 0 #4a0a0c, 0 0 24px rgba(255, 190, 80, .35), 0 14px 28px rgba(0, 0, 0, .5), inset 0 1px 0 rgba(255, 255, 255, .35); }
  #mute:hover, #gear:hover, .tips:has(> summary:hover), .tips summary.plate:hover { border-color: var(--gold); } .tips summary:hover { color: #fff3d0; } } /* a lift and a glow: brightness alone is lost on the red */
.big:active { translate: 0; transform: translateY(4px); box-shadow: 0 1px 0 #4a0a0c, 0 6px 14px rgba(0, 0, 0, .5), inset 0 1px 0 rgba(255, 255, 255, .35); }

.howto { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.how { display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 10px 6px; }
.how svg { margin-bottom: 2px; font-size: 22px; padding: 8px; color: var(--gold); border-radius: 50%; border: 1px solid var(--line);
  background: radial-gradient(circle at 50% 35%, rgba(255, 211, 107, .22), rgba(0, 0, 0, .25)); }
.how h3 { margin: 0; font: 800 13px var(--ui); letter-spacing: 1.5px; text-transform: uppercase; color: var(--gold); }
.how p { margin: 0; font: 500 13px/1.25 var(--ui); color: var(--parch2); }
.how h3, .how p { text-wrap: balance; } /* no orphan word on the last line */
@media (max-width: 520px) { .tagline { font-size: 11.5px; letter-spacing: 1.5px; } }
@media (orientation: landscape) and (max-height: 500px) { /* landscape phone: a compact title so PLAY is on the first screen; the cards scroll below */
  #menu { padding-block: calc(8px + var(--sat)) calc(8px + var(--sab)); } #menu .card { gap: 8px; } #menu .emblem { display: none; }
  .logo h1 { font-size: 56px; } .logo .io { right: -16px; font-size: 14px; } .tagline { margin: -2px 0 0; font-size: 11.5px; letter-spacing: 1.5px; }
  #name { height: 44px; } #play { height: 52px; font-size: 30px; } }
.keys { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px 16px; font: 600 14px var(--ui); color: var(--muted); text-shadow: 0 1px 2px #000; }
.keys b { color: var(--parch); }
kbd { display: inline-block; min-width: 1em; margin-right: 2px; padding: 1px 6px; border-radius: var(--rc); font: 800 12px var(--ui); color: var(--ink);
  background: linear-gradient(180deg, #f6ecd2, #cdb98a); box-shadow: 0 2px 0 #7a5a26; text-shadow: none; }
.tips { text-align: left; }
.tips summary { display: flex; justify-content: space-between; padding: 11px 14px; cursor: pointer; list-style: none; border-radius: var(--r);
  font: 800 13px var(--ui); letter-spacing: 1.5px; text-transform: uppercase; color: var(--gold); }
.tips summary::-webkit-details-marker { display: none; }
.tips summary::after { content: '+'; font-size: 16px; line-height: 1; }
.tips[open] summary::after { content: '\2212'; }
.tips ul { margin: 0; padding: 0 16px 12px 32px; font: 500 14px/1.45 var(--ui); }
.tips b, .tip b { color: var(--gold); }

.kicker { font: 800 13px var(--ui); letter-spacing: 4px; text-transform: uppercase; color: var(--danger); text-shadow: 0 1px 2px #000; }
#deadmsg { margin: -6px 0 4px; font: 400 clamp(30px, min(12vw, 9vh), 72px)/1 var(--display); color: var(--parch); overflow-wrap: anywhere;
  text-shadow: 0 3px 0 #2b0a08, 0 10px 20px rgba(0, 0, 0, .6); }
#deadmsg span { display: inline-block; color: var(--danger); } /* one box: the killer's emblem never wraps away from the name */
#deadmsg span.neutral { color: var(--parch2); } /* a merchant isn't the enemy */
#deadteam { margin: 0 0 6px; font: 700 15px var(--ui); color: var(--muted); font-variant-numeric: tabular-nums; text-shadow: 0 1px 2px #000; } /* hud.js showDeath: the round's state */
#deadteam:empty { display: none; }
#deadsalvage { margin: 0; font: 700 15px var(--ui); color: #ffe08a; text-shadow: 0 1px 2px #000; } /* hud.js showDeath: game.rs salvage, hidden (not removed) when none */
#deadsalvage svg { width: 1.1em; height: 1.1em; margin-right: .3em; vertical-align: -.2em; }
#deadmsg small { display: block; margin-top: 6px; font: 700 15px var(--ui); letter-spacing: 2px; text-transform: uppercase; color: var(--muted); text-shadow: 0 1px 2px #000; }
.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.stat { display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 12px 6px 10px; }
.stat svg { font-size: 22px; color: var(--brass); }
.stat b { font: 800 30px/1.1 var(--ui); color: var(--gold); font-variant-numeric: tabular-nums; }
.stat small { font: 700 var(--label) var(--ui); letter-spacing: 1.5px; text-transform: uppercase; color: var(--muted); }
.stat em { font: 700 var(--label) var(--ui); font-style: normal; letter-spacing: 1px; text-transform: uppercase; color: var(--parch2); } /* hud.js showDeath: personal best */
.stat em.new { color: var(--gold); }
#dead:not(.hidden) { animation: fadein .3s ease-out; } #dead:not(.hidden) .card { animation: rein .4s cubic-bezier(.2, .8, .2, 1.2); } @media (prefers-reduced-motion: reduce) { #dead .card { animation: none !important; } } /* after the linger it arrives like the round card, not in one frame */
@media (max-height: 640px) { body:not(.mobile) #dead .card { gap: 8px; } body:not(.mobile) #dead .stat { padding-block: 8px 6px; } body:not(.mobile) #dead .keys { display: none; } } /* a short window (800x600): Switch side stays on the first screen under a two-line headline (the big button needs no key hint) */
.tip { margin: 0; padding: 10px 14px; font: 500 14px/1.4 var(--ui); color: var(--parch2); border: 1px dashed var(--line); border-radius: var(--r); background: rgba(7, 19, 31, .6); }

#mute { position: fixed; z-index: 20; top: calc(var(--edge) + var(--sat)); right: calc(var(--edge) + var(--sar)); width: 40px; height: 40px; padding: 0;
  display: grid; place-items: center; border-radius: 50%; cursor: pointer; font-size: 20px; color: var(--parch); transition: border-color .15s, scale .08s; }
#gear { position: fixed; z-index: 20; top: calc(var(--edge) + 44px + var(--sat)); right: calc(var(--edge) + var(--sar)); width: 40px; height: 40px; padding: 0;
  display: grid; place-items: center; border-radius: 50%; cursor: pointer; font-size: 20px; color: var(--parch); transition: border-color .15s, scale .08s; } /* under mute; on phones only with the death card up (below) */
#settings { position: fixed; z-index: 20; top: calc(var(--edge) + var(--sat)); right: calc(var(--edge) + 48px + var(--sar)); display: flex; flex-direction: column; align-items: flex-start; gap: 2px; padding: 6px 12px; } /* beside the column, over the leaderboard */
#settings[hidden] { display: none; }
#mute:active, #gear:active { scale: .9; }
#mute .off, #mute.muted .on { display: none; }
#mute.muted .off { display: block; }
#fps { position: fixed; z-index: 3; top: calc(var(--edge) + 88px + var(--sat)); right: calc(var(--edge) + var(--sar)); width: 40px; text-align: center; pointer-events: none;
  font: 600 10px/12px var(--ui); white-space: pre; font-variant-numeric: tabular-nums; color: var(--muted); opacity: .7; text-shadow: var(--outline); } /* under the mute and gear buttons, in their column (the leaderboard sits beside or below): fps */
#fps.low { color: var(--gold); opacity: 1; } #fps.bad { color: var(--danger); opacity: 1; }
#fps:empty { display: none; }
body.mobile #fps { top: calc(var(--edge) + 34px + var(--sat)); width: 32px; }
body.mobile:has(#dead:not(.hidden)) #fps { top: calc(var(--edge) + 72px + var(--sat)); } /* under the gear while it shows */
@media (min-width: 1700px) and (min-height: 950px) { body:not(.mobile) #fps { zoom: 1.2; } } @media (min-width: 2200px) and (min-height: 1250px) { body:not(.mobile) #fps { zoom: 1.4; } } /* stays under the mute button as it grows */

/* --- in-game status card --- */
#hud { position: fixed; left: calc(var(--edge) + var(--sal)); bottom: calc(var(--edge) + var(--sab)); width: 256px; box-sizing: border-box; padding: var(--s2) 12px; pointer-events: none;
  border-left: 4px solid var(--team, var(--line)); } /* our side's colour on the card's edge (hud.js --team), as on the score bar's YOU: no badge chip */
#hud .top { display: flex; align-items: center; gap: var(--s2); } /* fixed slots: the stats reserve their digits, the class name shrinks to fit the rest (hud.js fitName) */
#hud .vals { margin-left: auto; display: flex; align-items: center; gap: var(--s2); }
#tiername { flex: 1; min-width: 0; position: relative; overflow: hidden; white-space: nowrap; padding: 2px 0; margin: -2px 0; font: 400 28px/28px var(--display); color: var(--parch); } /* overflow clips the class-change roll; a px line height: a shrunk name keeps the row's height */
/* a class or gun-count change (hud.js roll): the old value drops and fades, the new one rises in; gold glow for a gain, a dull red for a loss */
.roll { position: relative; }
.roll span { display: inline-block; }
.roll .old { position: absolute; left: 0; top: 0; animation: tierout .6s ease-in forwards; }
.roll .up { animation: tierup .6s ease-out; }
.roll .down { animation: tierdown .6s ease-out; }
#nextcls.fresh { animation: fadein .6s ease-out; }
@keyframes tierout { to { translate: 0 14px; opacity: 0; } }
@keyframes tierup { from { translate: 0 -14px; opacity: 0; } 45% { color: var(--gold); text-shadow: 0 0 10px var(--gold), 0 0 2px #fff; } }
@keyframes tierdown { from { translate: 0 -14px; opacity: 0; } 45% { color: color-mix(in srgb, var(--danger) 55%, var(--parch)); } }
@media (prefers-reduced-motion: reduce) { /* a plain crossfade */
  .roll :is(.up, .down) { animation: fadein .6s; }
  .roll .old { animation: tierfade .6s forwards; }
}
@keyframes tierfade { to { opacity: 0; } }
.goldv { display: flex; align-items: center; gap: 6px; font: 800 24px/1 var(--ui); color: var(--gold); font-variant-numeric: tabular-nums; } /* gold and hull are the card's two primary readouts */
.killv { display: flex; align-items: center; gap: 3px; font: 800 14px/1 var(--ui); color: #e8dcc2; font-variant-numeric: tabular-nums; opacity: .6; }
.killv .ic, .gunv .ic { width: 13px; height: 13px; }
.gunv { display: flex; align-items: center; gap: 3px; font: 800 14px/1 var(--ui); color: #e8dcc2; font-variant-numeric: tabular-nums; opacity: .6; } /* guns and kills: secondary, beside the purse */
.goldv.drain { color: var(--danger); animation: drain .5s ease-in-out infinite alternate; } /* sprinting spends gold */
@keyframes drain { to { opacity: .55; } }
.coin { width: 13px; height: 13px; border-radius: 50%; background: radial-gradient(circle at 35% 35%, #fff2b0, #f2b632 55%, #a8700f); box-shadow: 0 0 0 1.5px #7a5208; }
.bar { flex: 1; height: 7px; border-radius: var(--rc); overflow: hidden; background: rgba(0, 0, 0, .5); box-shadow: inset 0 1px 2px rgba(0, 0, 0, .6), 0 0 0 1px rgba(255, 255, 255, .06); }
.bar i { display: block; height: 100%; border-radius: inherit; transition: transform .15s; background-image: linear-gradient(180deg, rgba(255, 255, 255, .35), transparent 60%); }
.xp { display: flex; align-items: center; gap: 6px; margin: 6px 0 2px; }
.xp .bar { height: 3px; }
#nextcls { display: flex; justify-content: flex-end; width: 100px; align-items: center; gap: 3px; font: 700 var(--label) var(--ui); letter-spacing: .2px; color: var(--muted); opacity: .8; white-space: nowrap; } /* the next ship class */
#nextcls .coin { width: 8px; height: 8px; box-shadow: 0 0 0 1px #7a5208; }
#xpbar { background-color: var(--gold); }
#hud .row { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
#hud .row small { width: 38px; font: 700 var(--label) var(--ui); letter-spacing: .5px; color: var(--muted); }
#hull { height: 12px; background: linear-gradient(90deg, rgba(255, 228, 196, .7) var(--g, 0%), rgba(0, 0, 0, .5) 0); } /* hull matters most: the thickest bar; --g = the hull a hit just took (hud.js), draining away */
#hud #hullrow > small { color: var(--parch); }
#hull.rep i { animation: rep .6s ease-in-out infinite alternate; } /* repairing */
/* value feedback (hud.js pulse, only on change): the purse punches, the hull row flinches on a hit, a low hull glows red */
#goldval { display: inline-block; min-width: 4.5ch; } /* reserved digits (left-aligned: the coin never moves), so 9 -> 1000 moves nothing */
#killval { display: inline-block; min-width: 2.5ch; }
#goldval.pulse { animation: punch .35s ease-out; }
@keyframes punch { 30% { scale: 1.3; } }
#hud .row.hit { animation: flinch .35s ease-out; }
@keyframes flinch { 30% { filter: brightness(1.6); } } /* a flash, never a scale: the full-width hull bar would poke out of the card */
#hullrow { position: relative; }
#hullrow::after { content: ''; position: absolute; left: 46px; right: 0; top: 50%; height: 12px; margin-top: -6px; border-radius: var(--rc); box-shadow: 0 0 0 1px var(--danger), 0 0 10px var(--danger); opacity: 0; pointer-events: none; } /* over #hull (label 38 + gap 8; the bar's clip would cut a glow of its own) */
#hullrow:has(> #hull.low)::after { animation: glow 1.1s ease-in-out infinite alternate; } /* the red ring fades in and out: opacity runs on the compositor, an animated box-shadow repaints the card every frame */
@keyframes glow { to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  #goldval.pulse, #hud .row.hit { animation: none; }
  #hull.low { box-shadow: 0 0 0 1px var(--danger); } #hullrow::after { animation: none !important; }
}
@keyframes rep { to { filter: brightness(1.6); } }
.spd { flex: 1; position: relative; padding-bottom: 12px; }
#speedfill { width: 100%; background-color: #6cc4ec; transition: none; will-change: transform; } /* hud.js slides it (translateX) under the bar's rounded clip: no layout or repaint per frame */
#speedbar.boost #speedfill { background-color: #ff8a3a; box-shadow: 0 0 8px #ff8a3a; }
#speedbar { position: relative; }
#stamina { position: absolute; left: 0; bottom: 0; width: 100%; height: 2px; background: #fff6dc; transition: opacity .4s; will-change: transform; } /* sprint stamina along the bar's foot (hud.js) */
#speedbar.rested #stamina { opacity: .25; }
#speedbar.winded #stamina { background: var(--danger); }
#notches span { position: absolute; top: 9px; transform: translateX(-50%); font: 700 var(--label)/10px var(--ui); letter-spacing: .3px; color: transparent; } /* the sail setting's word, just under its notch (the bar's 7 px + 2) */
#notches span::before { content: ''; position: absolute; left: 50%; top: -9px; width: 2px; height: 7px; margin-left: -1px; background: rgba(7, 19, 31, .8); } /* the other settings: dark cuts inside the bar, not marks over it */
#notches span.on { color: var(--gold); }
#notches span.on::before { top: -11px; height: 11px; border-radius: 1px; background: var(--gold); box-shadow: 0 0 0 1px rgba(7, 19, 31, .7); } /* ours: a gold pin through the bar */
#wind { display: flex; align-items: center; gap: 4px; margin-top: -12px; font: 800 13px var(--ui); font-variant-numeric: tabular-nums; }
#windfx { width: 36px; height: 16px; } /* a fixed slot for "+200%": the speed bar beside it never resizes */
#windarrow { width: 20px; height: 20px; box-sizing: border-box; border-radius: 50%; border: 1px solid var(--line);
  background: rgba(0, 0, 0, .35) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3 12h17M15 7l5 5-5 5M2 6.5c2.5-2 5 2 7.5 0M4 17.5c2.5-2 5 2 7.5 0' fill='none' stroke='%239fdcff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/15px no-repeat; } /* wind: an arrow with two wavy gusts trailing it, pointing +x (hud.js rotates it) */
/* faint until relevant (hud.js wake): speed after a sail/boost change, net speed while it matters, sinks after a sink, kegs when one drops or comes back; hull and gold stay full */
:is(#sinkrow, #wind, #spdrow > :not(#wind), #kegrow) { opacity: .3; transition: opacity .4s; }
:is(#sinkrow.hot, #wind.hot, #spdrow.hot > :not(#wind), #kegrow.hot, #kegrow:has(.boon), #spdrow:has(.boon) > :not(#wind)) { opacity: 1; } /* an upgrade's flash (upgrades.js) lights its row too */
/* the main cause of the net speed: the wind (rotated to its direction), a whirlpool, boost, torn sails, shallows, the storm, a wounded hull */
#windarrow.whirl { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 12a1.5 1.5 0 1 1 2 1.6 4 4 0 1 1-5.2-4.4 6.5 6.5 0 1 1 8 8.6' fill='none' stroke='%239fdcff' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
#windarrow.boost { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M13 3L6 13h5l-1 8 7-10h-5z' fill='none' stroke='%23ffd36b' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
#windarrow.torn { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7 3v18M7 4c6 2 10 7 10 13H7M10 8l2 3-2 2 2 3' fill='none' stroke='%23f1e4c3' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
#windarrow.shoal { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3 18c2-2 4-2 6 0s4 2 6 0 4-2 6 0M8 14l4-7 4 7' fill='none' stroke='%23f1e4c3' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
#windarrow.storm { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7 15a4 4 0 1 1 1-7.9A5 5 0 0 1 17.6 8 3.5 3.5 0 1 1 17 15zM9 18l-1 3M13 18l-1 3M17 18l-1 3' fill='none' stroke='%23b9c7d6' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
#windarrow.hurt { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 20.5S3.5 15.3 3.5 9.2A4.4 4.4 0 0 1 12 7a4.4 4.4 0 0 1 8.5 2.2c0 6.1-8.5 11.3-8.5 11.3z' fill='%23ff2a4a'/%3E%3C/svg%3E"); } /* wounded (rules.js WOUNDED_SPEED): the hurt popups' heart */
#windarrow:not(.wind, .whirl, .boost, .torn, .shoal, .storm, .hurt) { visibility: hidden; }
/* the sea's drift (hud.js netSpeed): chevrons pointing +x, rotated to the drift; 1-3 lit and pulsing tail to head, faster and brighter the stronger it pushes */
/* one <svg> per chevron, pulsing its own opacity on its own layer: the compositor runs it, no per-frame style recalc */
#windarrow { position: relative; transition: transform .35s ease-out, border-color .3s, box-shadow .3s; }
#windarrow svg { display: none; position: absolute; inset: 0; width: 100%; height: 100%; opacity: .12; }
#windarrow.wind { background-image: none; }
#windarrow.wind svg { display: block; }
#windarrow path { fill: none; stroke: #9fdcff; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
#windarrow[data-lv="1"] { --t: 1.6s; }
#windarrow[data-lv="2"] { --t: 1.1s; border-color: rgba(159, 220, 255, .55); }
#windarrow[data-lv="3"] { --t: .7s; border-color: #9fdcff; box-shadow: 0 0 7px rgba(159, 220, 255, .55); }
#windarrow[data-lv="3"] path { stroke: #e2f6ff; }
#windarrow[data-tone="good"] path { stroke: #7cc8ff; }
#windarrow[data-tone="bad"] path { stroke: #ff7a6a; }
#windarrow[data-tone="bad"][data-lv="2"] { border-color: rgba(255, 122, 106, .55); }
#windarrow[data-tone="bad"][data-lv="3"] { border-color: #ff7a6a; box-shadow: 0 0 7px rgba(255, 122, 106, .55); }
:is(#windarrow[data-lv="1"] svg:nth-child(3), #windarrow[data-lv="2"] svg:nth-child(n+2), #windarrow[data-lv="3"] svg) { opacity: 1; will-change: opacity; animation-name: drift; animation-duration: var(--t); animation-timing-function: ease-in-out; animation-iteration-count: infinite; } /* longhands: the shorthand would reset the stagger below */
#windarrow svg:nth-child(1) { animation-delay: calc(var(--t) * -.66); }
#windarrow svg:nth-child(2) { animation-delay: calc(var(--t) * -.33); }
#wind:is(.wait, :not(.hot)) #windarrow svg { animation: none; will-change: auto; } /* faint or hidden: hold still, no layers kept */
@keyframes drift { 0%, 100% { opacity: .45; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { #windarrow[data-lv] svg { animation: none !important; } }
#wind.wait { visibility: hidden; } /* hud.js netSpeed: until our speed settles after a spawn or a sail change */
.good { color: var(--sea); } .bad { color: var(--danger); } #windfx.head { color: #ffc46b; } /* a gain in sea blue, like the drift arrow: green would read as Emerald */

/* --- upgrade picker (built by upgrades.js) --- */
#upgrades { position: fixed; z-index: 11; left: 50%; bottom: calc(14px + var(--sab)); transform: translateX(-50%); display: none; flex-direction: column; align-items: center;
  gap: 6px; padding: 8px; box-sizing: border-box; max-width: calc(100vw - 20px); }
#upgrades.on { display: flex; }
#upgrades { transition: opacity .4s; } #upgrades.hush { opacity: .35; } /* hud.js: faint while it would cover the fight (a foe in reach, our ship and the water between); still tappable */
#upgrades h4 { position: relative; z-index: 1; margin: -22px 0 -2px; padding: 4px 14px 3px; border-radius: var(--rc); white-space: nowrap; font: 800 15px/1.2 var(--ui); letter-spacing: 1.5px; text-transform: uppercase;
  color: var(--ink); background: linear-gradient(180deg, var(--gold), var(--brass)); box-shadow: 0 2px 8px rgba(0, 0, 0, .5), 0 0 14px rgba(255, 211, 107, .4); } /* a gold ribbon on the top edge */
#upgrades::after { content: ''; position: absolute; inset: -1px; border-radius: inherit; border: 1px solid var(--gold); box-shadow: 0 0 16px 3px rgba(255, 211, 107, .55); opacity: 0; pointer-events: none;
  animation: upflash .9s ease-out, upglow 3.2s 1.2s ease-in-out infinite; } /* a gold flash as it pops in, then a soft glow every few seconds while a pick waits */
@keyframes upflash { from { opacity: 1; } }
@keyframes upglow { 50% { opacity: .85; } }
#upgrades .row { display: flex; gap: 6px; }
#upgrades button { position: relative; width: 110px; padding: 8px 4px 7px; display: flex; flex-direction: column; align-items: center; gap: 3px; cursor: pointer;
  border-radius: var(--r); border: 1px solid rgba(255, 211, 107, .6); color: var(--text); touch-action: manipulation; transition: transform .1s, border-color .1s;
  background: linear-gradient(180deg, rgba(52, 104, 150, .97), rgba(12, 32, 52, .97)); box-shadow: inset 0 1px 0 rgba(255, 236, 190, .2); }
#upgrades button > * { pointer-events: none; }
#upgrades button:hover:not(:disabled) { border-color: var(--gold); transform: translateY(-2px); }
#upgrades button:active:not(:disabled) { background: linear-gradient(180deg, var(--gold), var(--brass)); color: var(--ink); }
#upgrades button:disabled { opacity: .4; cursor: default; }
#upgrades svg { font-size: 28px; color: var(--gold); filter: drop-shadow(0 0 4px rgba(255, 211, 107, .45)); }
#upgrades b { font: 800 14px var(--ui); }
#upgrades small { min-height: 2.4em; font: 500 var(--label)/1.2 var(--ui); color: #d3dee7; text-align: center; text-wrap: balance; }
#upgrades kbd { position: absolute; top: 4px; left: 4px; padding: 0 4px; font-size: var(--label); }
@media (max-width: 1000px) { body:not(.mobile) #upgrades { bottom: calc(180px + var(--sab)); } } /* above the status card */
@media (max-width: 1150px) { body:not(.mobile) #upgrades button { width: 60px; } body:not(.mobile) #upgrades b { font-size: var(--label); } body:not(.mobile) #upgrades small { display: none; } } /* the compact (phone) row fits between the status card and the chart */
@media (max-width: 760px) { body:not(.mobile) #upgrades { bottom: calc(var(--edge) + min(300px, 34vh, 34vw) + 8px + var(--sab)); } } /* too narrow even for that: above the chart */
#upgrades.on { animation: upin .45s cubic-bezier(.2, 1.4, .4, 1), upnag 8s 8s infinite; } /* a new pick pops up, not just appears; unspent, it hops every 8 s (silently) */
@keyframes upin { from { opacity: 0; translate: 0 40px; scale: .8; } 50% { filter: brightness(1.5); } }
@keyframes upnag { 0%, 7%, 100% { translate: 0; } 2% { translate: 0 -8px; filter: brightness(1.3); } 4.5% { translate: 0 -3px; } }
#upgrades em { display: none; }
#upgrades .pips i { width: 8px; height: 8px; }
#upgrades .pips i.nx { animation: nx .6s ease-in-out infinite alternate; } /* the stack this pick would fill */
#upgrades button:hover .pips i.nx { animation: none; background: var(--gold); }
@keyframes nx { to { background: rgba(255, 211, 107, .55); } }
#upgrades button:disabled::after { content: 'MAX'; position: absolute; top: 4px; right: 5px; font: 800 var(--label) var(--ui); color: var(--gold); }
/* upgrades.js: what a pick improves flashes gold as it's taken (the button too, when more picks are left) */
:is(#upgrades button, #hull, #speedbar, #kegpips, #kegbtn).boon { animation: boon 1.1s ease-out; }
@keyframes boon { 20% { box-shadow: 0 0 0 2px var(--gold), 0 0 16px var(--gold); filter: brightness(1.4); } }
@media (prefers-reduced-motion: reduce) { #upgrades.on, #upgrades .pips i.nx { animation: none; } #upgrades::after { animation: none; opacity: .7; } }

#minimap { position: fixed; right: calc(var(--edge) + var(--sar)); bottom: calc(var(--edge) + var(--sab)); width: min(300px, 34vh, 34vw); height: min(300px, 34vh, 34vw); pointer-events: none; /* a narrow window: not half its width */
  filter: drop-shadow(0 6px 12px rgba(0, 0, 0, .5)); background: 0 0 / 100% 100% no-repeat; } /* hud.js puts the chart's fixed base here once: not blitted every redraw */

#lb { position: fixed; right: calc(var(--edge) + 40px + var(--s2) + var(--sar)); top: calc(var(--edge) + var(--sat)); width: 168px; padding: var(--s1) var(--s2) 6px; /* clear of the mute button, level with the score bar */ box-sizing: border-box; pointer-events: none; }
@media (max-width: 900px) { /* a narrow window (half a laptop screen): the leaderboard and kill feed drop under the score bar, the banners narrow between them */
  body:not(.mobile) :is(#lb, #feed) { top: calc(var(--edge) + 68px + var(--sat)); } body:not(.mobile) #lb { right: calc(var(--edge) + var(--sar)); } body:not(.mobile) #feed { max-width: 168px; } body:not(.mobile) #feed div { white-space: normal; max-height: 46px; } /* two lines: the plunder and streak at the end survive */
  body:not(.mobile) .note { max-width: min(max(300px, 100vw - 480px), 100vw - 2 * (var(--edge) + 176px)); } body:not(.mobile) #roundend h2 { font-size: clamp(24px, 4.2vw, 46px); } }
@media (max-width: 760px) { body:not(.mobile):has(> #roundend:not(.hidden)) :is(#lb, #feed) { visibility: hidden; } } /* the card spans the strip under the score bar; it has the scores */
@media (max-width: 1199px) { body:not(.mobile):has(> #roundend:not(.hidden)) #lb { visibility: hidden; } } /* the ~690 px card reaches under the board below ~1150 px */
#lb h3 { display: flex; align-items: center; justify-content: center; gap: 6px; margin: 0 0 3px; padding: 2px 0 3px; border-bottom: 1px solid var(--line); text-align: center; font: 800 var(--label) var(--ui); letter-spacing: 1.5px; text-transform: uppercase; color: var(--muted); } /* a label, like the card's: the board is quiet news */
#lb ol { list-style: none; margin: 0; padding: 0; font: 600 13px/1.5 var(--ui); }
#lb li { display: flex; align-items: center; gap: 6px; padding: 0 4px; border-radius: var(--rc); }
#lb em { width: 16px; font-style: normal; font-size: var(--label); text-align: center; color: var(--muted); }
#lb li span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#lb li b { min-width: 4.4ch; text-align: right; font-variant-numeric: tabular-nums; color: color-mix(in srgb, var(--gold) 70%, var(--parch)); } /* gold, like the purse */
#lb li:first-child :is(span, b, em) { color: var(--gold); }
#lb li.me { background: linear-gradient(90deg, rgba(255, 211, 107, .3), rgba(255, 211, 107, .06)); box-shadow: inset 2px 0 0 var(--gold); }
#lb li.me span { color: #fff; font-weight: 800; }
#lb li.you { box-shadow: inset 2px 0 0 var(--gold), 0 -1px 0 var(--line); } /* our row past the top: a hairline, not a gap (the board keeps its height) */

#feed { position: fixed; left: calc(var(--edge) + var(--sal)); top: calc(var(--edge) + var(--sat)); max-width: 30vw; display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
  pointer-events: none; font: 600 13px var(--ui); }
/* a chip: the flat dark variant of the panel, for kill-feed lines and the edge-arrow labels; the outline keeps it readable over foam */
#feed div, .farrow span { box-sizing: border-box; padding: 2px var(--s2); border-radius: var(--rc); background: rgba(7, 19, 31, .86); border: 1px solid var(--line);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .35), 0 2px 6px rgba(0, 0, 0, .35); text-shadow: var(--outline); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#feed div { max-width: 100%; max-height: 30px; transition: opacity .5s; animation: feedin .25s ease-out backwards; }
@keyframes feedin { from { max-height: 0; padding-block: 0; opacity: 0; translate: -10px 0; } } /* new lines push the rest down smoothly */
#feed div:not(.mine, .died, .ours, .lost) { opacity: .75; border-color: transparent; } /* someone else's fight (and minor news): quiet, no brass rim */
#feed .mine { background: color-mix(in srgb, var(--gold) 22%, rgba(7, 19, 31, .9)); border-color: var(--gold); color: #fff3cf; font-weight: 800; }
#feed .died { background: color-mix(in srgb, var(--danger) 26%, rgba(7, 19, 31, .9)); border-color: var(--danger); color: #ffe2dc; font-weight: 800; }
#feed .ours { border-left: 3px solid var(--gold); } /* our side scored */
#feed .lost { border-left: 3px dashed var(--danger); } /* our side lost one: dashed red, the foe style */
#feed .chip { margin-left: .2em; vertical-align: .1em; } /* a sink streak */

#warn { position: fixed; z-index: 15; left: 50%; top: 36%; /* below two stacked banners */ transform: translateX(-50%); width: max-content; max-width: min(520px, calc(100vw - 32px)); box-sizing: border-box;
  padding: 8px 18px; border-radius: var(--r); text-align: center; pointer-events: none; background: linear-gradient(180deg, rgba(150, 22, 26, .92), rgba(90, 10, 14, .92));
  border: 1px solid var(--danger); outline: 1px solid rgba(0, 0, 0, .6); } /* the dark rim as an outline: it stays over the glows below */
#warn::before, #warn::after { content: ''; position: absolute; inset: -1px; z-index: -1; border-radius: inherit; box-shadow: 0 8px 26px rgba(120, 0, 0, .5); pointer-events: none; animation: fade .9s ease-in-out infinite alternate; }
#warn::after { box-shadow: 0 0 34px rgba(255, 60, 40, .65); animation-direction: alternate-reverse; } /* the throb: a drop shadow crossfading into a red glow, both pre-rendered (opacity runs on the compositor; an animated box-shadow repaints the big blur every frame) */
@keyframes fade { to { opacity: 0; } }
#warn:empty { display: none; }
#warn b { display: block; font: 400 20px/1.1 var(--display); color: #fff1d6; }
body:not(.playing) #warn { top: calc(10px + var(--sat)); max-width: calc(100vw - 120px); padding: 8px 14px; } /* a toast clear of the menu */
body:not(.playing) #warn b { font-size: 16px; }
#warn.soft { background: rgba(7, 19, 31, .88); border-color: var(--line); box-shadow: 0 4px 14px rgba(0, 0, 0, .45); outline: 0; padding: 6px 14px; } #warn.soft::before, #warn.soft::after { display: none; } /* an advisory (Blocked, storm/eye ahead): quiet amber; the red throb is for what hurts */
#warn.soft b { font: 700 16px/1.2 var(--ui); color: #ffb43c; }
/* phones: the one message slot (hud.js say): banners, warnings, hints, our side's feed and tips, one line at a time by priority.
   A fixed box (only its content, colour and opacity change): landscape top centre between the minimap block and the board, portrait full width under the top strip */
#msg { display: none; --tc: var(--parch); }
body.mobile #msg { position: fixed; z-index: 12; top: calc(var(--edge) + var(--sat)); left: calc(var(--edge) + 236px + var(--sal)); right: calc(var(--edge) + 236px + var(--sar)); max-width: 300px; height: 26px; margin: 0 auto;
  display: flex; align-items: center; gap: 6px; box-sizing: border-box; padding: 0 8px 0 6px; border-radius: var(--rc); pointer-events: none;
  background: rgba(7, 19, 31, .86); border: 1px solid var(--line); border-left: 4px solid var(--tc); box-shadow: 0 0 0 1px rgba(0, 0, 0, .35), 0 2px 6px rgba(0, 0, 0, .35);
  font: 600 12px/1 var(--ui); color: var(--parch); text-shadow: var(--outline); transition: opacity .25s; }
body.mobile #msg.idle { opacity: 0; }
body.mobile.playing #warn { display: none; } /* the slot says it (the toast stays for the menu and death screens) */
#msg i { display: flex; width: 16px; height: 16px; color: var(--tc); } #msg i:empty { display: none; } #msg i svg { width: 100%; height: 100%; }
#msg span { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; animation: fadein .2s ease-out; }
#msg span > b:first-child { color: var(--tc); font-weight: 800; } /* a title in the tone */
#msg.good, #msg.news { --tc: var(--gold); } #msg.bad { --tc: var(--danger); } #msg.warn { --tc: #ffb43c; } #msg.info { --tc: var(--sea); } #msg.hint { --tc: var(--muted); } #msg.hint span b { color: var(--gold); }
body.mobile #msg.alarm { --tc: #fff1d6; border-color: var(--danger); background: linear-gradient(180deg, rgba(150, 22, 26, .92), rgba(90, 10, 14, .92)); } /* what hurts: the warning's red */
body.mobile #msg.alarm.soft { --tc: #ffb43c; border-color: var(--line); border-left-color: #ffb43c; background: rgba(7, 19, 31, .88); } /* an advisory: quiet amber */
@media (orientation: portrait) { body.mobile #msg { top: calc(104px + var(--sat)); left: calc(16px + var(--sal)); right: calc(16px + var(--sar)); max-width: none; } }
@keyframes throb { to { box-shadow: 0 0 0 1px rgba(0, 0, 0, .6), 0 0 34px rgba(255, 60, 40, .65); } }

/* announcements: a short stack under the score bar, clear of the ship (screen centre), the minimap and the leaderboard; newest lowest */
#banner { position: fixed; z-index: 12; top: calc(var(--edge) + 64px + var(--sat)); /* tucked under the score bar: the sea just ahead of our ship stays clear (mines) */ left: 0; right: 0; padding: 0 16px; display: flex; flex-direction: column; align-items: center;
  text-align: center; pointer-events: none; }
.note { --tc: var(--parch); --rib: linear-gradient(180deg, #2c5f8f, #163252); display: grid; grid-template-rows: 1fr; max-width: min(640px, 100%);
  animation: notein .25s cubic-bezier(.2, .8, .3, 1) backwards; transition: grid-template-rows .25s ease-out, opacity .25s ease-out, translate .25s ease-out; }
body:not(.mobile) .note { max-width: min(760px, max(300px, 100vw - 480px)); } /* keep the kill feed and leaderboard corners clear */
.note > div { min-height: 0; padding-bottom: 8px; } /* min-height 0 lets the row fold to nothing, so the stack closes up without a jump */
.note b { display: flex; align-items: center; justify-content: center; gap: .25em; font: 400 clamp(22px, min(4.2vw, 6vh), 44px)/1.05 var(--display); letter-spacing: 1px;
  color: var(--tc); overflow-wrap: anywhere; text-shadow: 0 2px 0 rgba(0, 0, 0, .6), 0 0 3px #000, 0 6px 22px rgba(0, 0, 0, .7); }
.note b svg { width: .68em; height: .68em; filter: drop-shadow(0 2px 0 rgba(0, 0, 0, .6)) drop-shadow(0 0 6px rgba(0, 0, 0, .5)); }
.note span { display: inline-block; margin-top: 5px; padding: 4px 22px 5px; font: 700 16px/1.25 var(--ui); letter-spacing: .3px; color: var(--parch); text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
  background: var(--rib); clip-path: polygon(0 0, 100% 0, calc(100% - 10px) 50%, 100% 100%, 0 100%, 10px 50%); }
.note span:empty { display: none; }
.note:not(:last-child) { opacity: .7; } /* the older note steps back */
.note.out { grid-template-rows: 0fr; opacity: 0; transition: grid-template-rows .2s .08s ease-out, opacity .1s ease-out; } /* fade first, then fold in place: never a half-clipped title sliding up under the score bar */
.note.out > div { overflow: hidden; } /* the folding note's text stays inside its row, not printed over the note taking its place */
@keyframes notein { from { grid-template-rows: 0fr; opacity: 0; translate: 0 -14px; } }
/* tone: gold on navy for our wins, red on black (with a shake) for our losses, amber warnings, blue news */
.note.good { --tc: var(--gold); } /* the gold title on the panel's navy ribbon: a green one read as Emerald */
.note.good b { text-shadow: 0 2px 0 #2b1606, 0 0 3px #000, 0 0 26px rgba(255, 200, 60, .45), 0 6px 22px rgba(0, 0, 0, .7); }
.note.bad { --tc: var(--danger); --rib: linear-gradient(180deg, #3a1414, #160606); }
.note.bad b { text-shadow: 0 2px 0 #2a0505, 0 0 3px #000, 0 0 26px rgba(255, 40, 20, .45), 0 6px 22px rgba(0, 0, 0, .75); }
.note.bad span { color: #ffb3a6; }
.note.bad > div { animation: shake .4s .15s ease-out; }
.note.warn { --tc: #ffb43c; --rib: linear-gradient(180deg, #a0601a, #5a3008); }
.note.info b { font-size: clamp(20px, 3vw, 28px); } /* side and sea news: a small note, not a headline (minor news is a feed line, hud.js banner) */
.note.info span { font-size: 13px; padding: 3px 18px; margin-top: 3px; }
@keyframes shake { 25% { transform: translateX(-6px); } 50% { transform: translateX(5px); } 75% { transform: translateX(-2px); } }
@media (prefers-reduced-motion: reduce) {
  .note, #feed div { animation-name: fadein; }
  .note.bad > div { animation: none; }
}
@keyframes fadein { from { opacity: 0; } }
#hurt { position: fixed; inset: 0; pointer-events: none; box-shadow: inset 0 0 min(120px, 16vmin) min(30px, 4vmin) rgba(220, 30, 20, .7); /* the edges, not the whole phone screen */ opacity: 0; visibility: hidden; } /* hidden between flashes (hud.js hurtFlash): no full-screen layer to commit every frame */

@keyframes beckon { to { scale: 1.2; } }
/* fort arrows: an open chevron in the fort owner's colour (incoming fire is the solid red triangle: Crimson's own forts mustn't look like it); red-edged and pulsing when it's ours under attack */
.farrow { position: fixed; z-index: 5; left: 0; top: 0; width: 0; height: 0; pointer-events: none; display: none; filter: drop-shadow(0 0 3px rgba(0, 0, 0, .8)); opacity: .45; transition: opacity .6s; will-change: transform; } /* moved by hud.js edgeArrow: its own layer, the shadow isn't re-filtered as it slides */
.farrow.hot { opacity: 1; } /* faint until relevant (hud.js wake): a new target, a fort changing hands, or ours under attack */
.farrow b { flex: none; width: 14px; height: 14px; color: var(--c); }
.farrow b svg { display: block; width: 100%; height: 100%; fill: currentColor; stroke: rgba(0, 0, 0, .8); stroke-width: 1.5px; paint-order: stroke; }
.farrow::before { content: ''; position: absolute; left: -13px; top: -13px; width: 26px; height: 26px; box-sizing: border-box; border-radius: 50%; background: rgba(7, 19, 31, .86); border: 1px solid var(--line); } /* the head's disc: the chip (hud.js edgeArrow) touches it, so pointer and label read as one pin */
.farrow.defend::before { border-color: var(--danger); }
.farrow i { position: absolute; left: -9px; top: -9px; width: 18px; height: 18px; background: var(--c); clip-path: polygon(100% 50%, 38% 2%, 8% 2%, 62% 50%, 8% 98%, 38% 98%); }
.farrow span { position: absolute; left: 0; top: -9px; display: flex; align-items: center; gap: 3px; width: max-content; padding: 1px var(--s1); translate: calc(var(--ox, 0px) - 50%) var(--oy, 22px); /* chip offsets from hud.js edgeArrow */
  font: 800 var(--label)/14px var(--ui); letter-spacing: .4px; font-variant-numeric: tabular-nums; color: color-mix(in srgb, var(--c) 50%, #fff); }
.farrow em { font-style: normal; }
.farrow.defend span { border-color: var(--danger); color: #ffb3a6; }
.farrow.defend i { animation: beckon .4s ease-in-out infinite alternate; }
.farrow.friend { --c: var(--gold); } /* the friend who invited us (hud.js ?from=) */
.farrow.friend b { border-radius: 50%; background: var(--c); font: 800 10px/14px var(--ui); color: #1b1305; text-align: center; } /* their initial: a captain, not a fort */
.farrow.friend.lost { opacity: .3; } /* out of range: their last known spot */
.farrow.rush { --c: var(--gold); } /* the gold rush, from its warning on (hud.js) */
/* phones: one pin, the chip itself, hugging the edge; its chevron sits in the chip's end nearest that edge (hud.js edgeArrow puts the pin there; .flip: the right end) */
body.mobile .farrow::before { display: none; }
body.mobile .farrow i { z-index: 1; left: -7px; top: -7px; width: 14px; height: 14px; }
body.mobile .farrow span { padding-left: 20px; } body.mobile .farrow.flip span { padding: 1px 20px 1px var(--s1); }
/* the warnings that say "back" (hud.js WARN_STORM / WARN_BAT): a dart turned the way out (--wa) */
.wdir { display: inline-block; width: 1em; height: 1em; margin-right: .35em; vertical-align: -.12em; background: currentColor; rotate: var(--wa, 0rad);
  clip-path: polygon(100% 50%, 0 6%, 30% 50%, 0 94%); } /* a dart, not a thin chevron: at phone size that read as a tick or an L */
#msg .wdir { width: 16px; height: 16px; vertical-align: -4px; } /* the phone slot's icon size: at 12 px it read as an L */
@media (orientation: landscape) and (max-height: 500px) { body.mobile #deadmsg small { display: inline; margin: 0 0 0 .6em; } } /* the class or the side beside the headline: the short screen has no row for it */

#tags canvas { position: fixed; inset: 0; width: 100%; height: 100%; pointer-events: none; } /* tags.js: the name tags and gold chips, under the popups */
.tp { position: fixed; left: 0; top: 0; pointer-events: none; transform: translate(-50%, -100%); will-change: transform, opacity; } /* hud.js holder: the positioner a popup sits in, centred over its foot (name tags and gold chips are drawn in the canvas: tags.js); script writes only its translate (a popup: its whole transform). Each its own layer: unpromoted, every move re-layerized and re-rastered the page's HUD layer (measured slower, with 60-90 ms stalls) */
/* floating numbers: one outline recipe, the tone sets fill (--c) and outline (--o) so they read over water, foam and sails */
.pop { --c: var(--parch); --o: #10202e; font: 800 20px var(--ui); color: var(--c); pointer-events: none; white-space: nowrap; /* hud.js moves and fades its .tp.pw holder every frame: its own layer, not a repaint of the page */
  text-shadow: 1.5px 0 var(--o), -1.5px 0 var(--o), 0 1.5px var(--o), 0 -1.5px var(--o), 1px 1px var(--o), -1px -1px var(--o), 1px -1px var(--o), -1px 1px var(--o), 0 3px 8px rgba(0, 0, 0, .7); }
.pop.dmg { --c: var(--danger); --o: #3a0600; font-size: 19px; } /* damage we dealt */
.pop.hurt { --c: #fff; --o: #c0102a; font: italic 800 17px var(--ui); } /* damage WE take: white on crimson, a heart, beside our own ship and sinking; dealt damage is red, over the target, rising */
.pop.hurt::before { content: '\2665'; margin-right: .18em; color: #ff2a4a; font-style: normal; }
.pop.gold { --c: var(--gold); --o: #3a2200; } /* plunder and pickups */
.pop:is(.gold, .spend)::before { content: ''; display: inline-block; width: .62em; height: .62em; margin-right: .22em; vertical-align: -.02em; border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #fff2b0, #f2b632 55%, #a8700f); box-shadow: 0 0 0 2px var(--o); }
.pop.huge { font: 400 36px var(--display); letter-spacing: .5px; }
.pop.boon { --c: var(--gold); --o: #3a2200; font: 400 26px var(--display); letter-spacing: .5px; } /* an upgrade taken: "Long Guns 2/3" */
.pop.boon::before { content: '\2605\00a0'; }
.pop.huge.gold { font-size: 38px; }
.pop.rank { --c: var(--gold); --o: #3a2200; } /* a new ship class over our ship (main.js) */
.pop .chip, :is(#feed, #msg) .chip { display: inline-block; margin-left: .4em; padding: 1px 5px; border-radius: var(--rc); vertical-align: .25em; font: 800 var(--label) var(--ui); color: #3a2200; background: var(--gold); text-shadow: none; } /* combo / rake beside a damage total */
.pop.spend { --c: #e3c57e; --o: #3a2200; font-size: 15px; font-weight: 700; } /* gold spent or lost (hud.js): a coin and a dull gold, small: gold, not hull (that's the heart), and not damage red */

/* --- phone controls: FIRE where the right thumb rests (in from the corner: the edges are the least accurate spot), SAIL and KEG on an arc ~98 px
   round it toward the screen, each one short roll of the thumb away; every button taps ~8-10 px past its rim (MOBA / brawler style) --- */
.touch { position: fixed; display: none; flex-direction: column; align-items: center; justify-content: center; gap: 1px; box-sizing: border-box; border-radius: 50%;
  font: 800 11px var(--ui); letter-spacing: 1px; color: var(--parch); text-shadow: 0 1px 2px #000; border: 2px solid rgba(217, 164, 65, calc(.5 * var(--bb, .65)));
  background: radial-gradient(circle at 50% 30%, rgba(34, 72, 108, var(--ba, .5)), rgba(7, 19, 31, var(--ba, .5)) 70%);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, calc(.6 * var(--bb, .65))), 0 6px 14px rgba(0, 0, 0, calc(.45 * var(--bb, .65))), inset 0 1px 0 rgba(255, 255, 255, .15); -webkit-touch-callout: none; }
/* button style (hud.js setBtnStyle): see-through by default so the sea under them still reads; the face's alpha (--ba) and rim's (--bb) only, the icon, label, ring and pips stay whole */
body[data-btn=solid] { --ba: .92; --bb: 1; }
.touch > b { align-self: stretch; text-align: center; font-variant-numeric: tabular-nums; } /* the label's box is the button's width: FULL/LOW, KEG x3/x0 change only the text */
.touch > * { pointer-events: none; } /* keep the button itself the pointer target so pointerleave fires on it */
.touch svg { font-size: 24px; filter: drop-shadow(0 1px 1px rgba(0, 0, 0, .8)); } /* reads over the sea through a see-through face */
.touch.on { color: var(--ink); border-color: #fff3c4; background: radial-gradient(circle at 50% 30%, var(--gold), var(--brass) 70%); }
body.mobile.playing .touch { display: flex; transition: scale .08s, filter .08s; }
.touch:is(.on, :active) { --ba: .94; --bb: 1; scale: .92; filter: brightness(1.2); } /* the same press on every button (FIRE and KEG keep their own colours), solid in every style */
body.sunk .touch { display: none !important; } /* main.js: gone with our ship, not lit over the killer cam */
#fire { right: calc(26px + var(--sar)); bottom: calc(22px + var(--sab)); width: 84px; height: 84px; font-size: 13px; border-color: rgba(255, 211, 107, var(--bb, .65));
  background: radial-gradient(circle at 50% 30%, rgba(214, 62, 52, var(--ba, .5)), rgba(110, 16, 20, var(--ba, .5)) 70%); }
#fire svg { font-size: 30px; }
#fire:not(.ready) { --ba: .92; --bb: 1; border-color: rgba(138, 138, 138, var(--bb, .65)); background: radial-gradient(circle at 50% 30%, rgba(120, 120, 120, var(--ba, .5)), rgba(52, 52, 52, var(--ba, .5)) 70%); } /* reloading: greyed and solid in every style, the gold ring shows how long */
#fire:not(.ready) > :not(.ring) { opacity: .45; }
.touch::before { content: ''; position: absolute; inset: -10px; border-radius: 50%; } #fire::before { inset: -12px; } /* a hit area past the rim (the ring's band too): a near miss still lands, never steers the ship (main.js stick) */
.ring { position: absolute; inset: -8px; border-radius: 50%; will-change: transform; /* reload ring: hud.js sets --r on it alone (inherited from the button it restyled 5 elements a frame) and its own layer repaints alone, not the page */
  background: conic-gradient(var(--gold) calc(var(--r, 1) * 1turn), rgba(0, 0, 0, .45) 0);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 5px), #000 calc(100% - 4px)); mask: radial-gradient(farthest-side, transparent calc(100% - 5px), #000 calc(100% - 4px)); }
#fire.ready > .ring, #kegbtn:not(.cool) > .ring { opacity: 0; transition: opacity .4s .1s; } /* faint until relevant: the ring only while reloading, and it fades as it closes */
/* KEG at 9 o'clock, SAIL at half past 10, each 92 px from FIRE's centre (pads just touching), in both orientations: the cluster stays under our ship's line (188x164, top ~H-164) */
#sail { right: calc(97px + var(--sar)); bottom: calc(108px + var(--sab)); width: 56px; height: 56px; }
#kegbtn { right: calc(132px + var(--sar)); bottom: calc(28px + var(--sab)); width: 56px; height: 56px;
  background: radial-gradient(circle at 50% 30%, rgba(120, 70, 30, var(--ba, .5)), rgba(50, 24, 10, var(--ba, .5)) 70%); }
#sail svg, #kegbtn svg { font-size: 20px; }
.pips { display: flex; gap: 3px; }
.pips i { width: 5px; height: 5px; border-radius: 50%; background: rgba(255, 255, 255, .25); }
.pips i.on { background: var(--gold); }
/* the touch steering stick (main.js): a faint ring where the thumb landed, the knob under the thumb */
#stick { position: fixed; left: -72px; top: -72px; width: 144px; height: 144px; box-sizing: border-box; border-radius: 50%; display: none; pointer-events: none; z-index: 2;
  border: 2px solid rgba(241, 228, 195, .3); background: rgba(7, 19, 31, .2); }
#stick i { position: absolute; left: 50%; top: 50%; width: 40px; height: 40px; margin: -20px; border-radius: 50%; background: rgba(241, 228, 195, .4); box-shadow: 0 2px 6px rgba(0, 0, 0, .4); }
#stick.boost { border-color: rgba(255, 200, 58, .55); } #stick.boost i { background: rgba(255, 200, 58, .6); } /* knob on the rim: sprinting */

/* big monitors: the HUD cards grow with the screen instead of shrinking into the corners (the chart sizes itself by vh) */
@media (min-width: 1700px) and (min-height: 950px) { body:not(.mobile) :is(#hud, #lb, #teams, #upgrades, #feed, #mute, #gear, #settings, #menu .card, #dead .card, #roundend) { zoom: 1.2; }
  body:not(.mobile) #banner { top: calc(var(--edge) + 78px + var(--sat)); } /* still under the score bar, now 1.2x taller */
  body:not(.mobile) #roundend { top: calc(var(--edge) + 67px + var(--sat)); } /* zoomed too: 1.2x this lands it just under the 1.2x score bar */
  /* JS places these in px: a bigger font, not zoom (hud.js edgeArrow reads the chip font size) */
  body:not(.mobile) #hint { font-size: 18px; bottom: calc(var(--edge) + 192px); }
  body:not(.mobile) .farrow span { top: -10.5px; font-size: 13px; line-height: 17px; } }
@media (min-width: 2200px) and (min-height: 1250px) { /* QHD: a second step */ body:not(.mobile) :is(#hud, #lb, #teams, #upgrades, #feed, #mute, #gear, #settings, #menu .card, #dead .card, #roundend) { zoom: 1.4; }
  body:not(.mobile) #banner { top: calc(var(--edge) + 90px + var(--sat)); }
  body:not(.mobile) #roundend { top: calc(var(--edge) + 67px + var(--sat)); }
  body:not(.mobile) #hint { font-size: 21px; bottom: calc(var(--edge) + 224px); }
  body:not(.mobile) .farrow span { top: -11.5px; font-size: 15px; line-height: 19px; }
  body:not(.mobile) .note span { font-size: 20px; } body:not(.mobile) .note.info span { font-size: 16px; } body:not(.mobile) #seatag { font-size: 16px; } }

/* --- phone layout --- */
/* the compact card, a fixed 150x62 box: class, kills, gold / hull / xp + sinks pips; our side's colour on its left edge (#hud) */
body.mobile #hud { width: 150px; height: 62px; padding: 6px 8px; display: grid; grid-template: 20px 10px 7px / 1fr 40px; align-content: space-between; column-gap: 6px; }
body.mobile #hud .top { grid-column: 1 / -1; }
body.mobile #hullrow { grid-area: 2 / 1 / 3 / -1; gap: 6px; }
body.mobile .xp { grid-area: 3 / 1; } body.mobile #sinkrow { grid-area: 3 / 2; }
body.mobile #hud .row, body.mobile .xp { margin: 0; }
body.mobile :is(#spdrow, #nextcls, #sinkrow > :not(#sinkpips)) { display: none; } /* cut on phones: speed and wind (the SAIL button has the setting), "Brig at 25" (the xp bar), the sinks label and star */
body.mobile #tiername { font-size: 20px; line-height: 20px; }
body.mobile .goldv { font-size: 16px; gap: 4px; }
body.mobile #hud :is(.top, .vals) { column-gap: var(--s1); }
body.mobile :is(.gunv, .killv) { font-size: 13px; }
body.mobile :is(.gunv, .killv) .ic { width: 12px; height: 12px; }
body.mobile #goldval { min-width: 3.5ch; } /* the narrow card: past 999 the class name shrinks instead (hud.js fitName) */
body.mobile .gunv { display: none; } /* the narrow card: the purse and kills need the room more (guns follow gold, and the ship shows them), so "Man-o'-War" still reads */
body.mobile #hud .row small { width: 22px; font-size: var(--label); letter-spacing: 0; } body.mobile #hull { height: 10px; } body.mobile #hullrow::after { left: 28px; height: 10px; margin-top: -5px; } /* the compact card's 10 px hull row */
body.mobile #upgrades { bottom: calc(184px + var(--sab)); padding: 6px; } /* portrait: above the SAIL / KEG arc and its tap margin (top at 174) */
body.mobile #upgrades svg { font-size: 26px; }
body.mobile #upgrades .row { gap: 5px; }
body.mobile #upgrades button { width: 64px; padding: 9px 2px 8px; }
body.mobile #upgrades b { font-size: 11px; }
body.mobile #upgrades :is(kbd, small) { display: none; }
body.mobile #upgrades em { display: block; font: 600 var(--label)/1.1 var(--ui); color: #d3dee7; white-space: nowrap; }
body.mobile #upgrades button:disabled::after { top: 2px; right: 3px; font-size: var(--label); }
body.mobile .pop.boon { font-size: 16px; }
body.mobile .pop.dmg { font-size: 15px; } /* fx.js sizes the dealt-damage total inline from 15 px on a phone */
body.mobile .pop.huge { font-size: 26px; } /* "+9 PLUNDER" at 36px spans most of a phone and buries the sink */
body.mobile .pop.huge.gold { font-size: 18px; }
/* landscape phone: the picker sits low between the status card (182 px) and the buttons (191 px), not over the sea ahead of our ship; its buttons narrow to fit down to 640 px */
@media (orientation: landscape) and (min-width: 640px) { body.mobile #upgrades { bottom: calc(var(--edge) + var(--sab)); transform: translateX(calc((var(--sal) - var(--sar)) / 2 - 50%)); }
  body.mobile #upgrades button { width: clamp(44px, (100vw - 430px - var(--sal) - var(--sar)) / 5, 60px); } }
@media (orientation: landscape) and (max-width: 639px) { /* iPhone 5 landscape: an icon-only row fits the 195 px gap between the status card and the buttons */
  body.mobile #upgrades { bottom: calc(var(--edge) + var(--sab)); left: calc(var(--edge) + 158px + var(--sal)); transform: none; padding: 4px; gap: 3px; }
  body.mobile #upgrades h4 { margin-top: -16px; padding: 2px 8px; font-size: 11px; letter-spacing: .5px; } body.mobile #upgrades svg { font-size: 22px; } body.mobile #upgrades .row { gap: 2px; }
  body.mobile #upgrades button { width: 34px; padding: 8px 0 7px; } body.mobile #upgrades :is(b, em) { display: none; } }
/* landscape phone: a short screen, so the death card tightens up to keep REJOIN in view (the tip can scroll) */
@media (orientation: landscape) and (max-height: 500px) { body.mobile #dead .card { gap: 5px; width: min(620px, 100%); } body.mobile #deadsalvage { margin-block: -3px; } /* the salvage line's row came out of the gaps: Switch side stays on a 360 px screen */ body.mobile #deadsalvage.none { display: none; } body.mobile #deadtip { order: 1; } /* none saved: no empty row; the tip goes under Invite crew / Switch side (it can scroll off, they can't) */ body.mobile .tip { padding: 6px 12px; } /* wider: the tip stays one line, so Invite crew fits under it */ body.mobile #deadmsg { font-size: 34px; }
  body.mobile #dead .kicker { display: none; } body.mobile #deadteam { margin-bottom: 0; } /* the headline says it: the Invite crew / Switch side row stays on the first screen */
  body.mobile .stat { position: relative; padding: 6px; } body.mobile .stat svg { position: absolute; left: 12px; top: 50%; translate: 0 -50%; font-size: 20px; } /* the icon beside the figure, not over it: no extra height on a short screen */ body.mobile .stat b { font-size: 22px; } }
body.mobile #minimap { width: 92px; height: 92px; right: auto; bottom: auto; left: calc(var(--edge) + var(--sal)); top: calc(var(--edge) + var(--sat)); }
body.mobile #lb { width: 104px; right: calc(var(--edge) + 36px + var(--sar)); padding: 3px var(--s1); } /* a compact pill: top 3 + you, the small mute tucked beside it */
body.mobile #lb h3 { display: none; }
body.mobile #lb ol { font-size: 11px; line-height: 1.4; }
body.mobile #lb li { gap: 4px; padding: 0 3px; }
body.mobile #lb em { width: 13px; } /* our row's rank can be "20": two digits, clear of the emblem */
@media (orientation: portrait) and (max-width: 899px) { /* the 104 px board: names, not "Mor…": no rank on the top rows (their order says it), "You" for us, a fade, not an ellipsis */
  body.mobile #lb li:not(.you) em { display: none; } body.mobile #lb li span { text-overflow: clip; mask-image: linear-gradient(90deg, #000 calc(100% - 8px), transparent); }
  body.mobile #lb li.me span { font-size: 0; } body.mobile #lb li.me span::before { content: 'You'; font-size: 11px; } }
body.mobile:not(:has(#dead:not(.hidden))) :is(#gear, #settings) { display: none; } /* phones: settings only on the death card, the play screen stays clear */
body.mobile #gear { top: calc(var(--edge) + 38px + var(--sat)); }
body.mobile #settings { right: calc(var(--edge) + 40px + var(--sar)); }
body.mobile :is(#mute, #gear) { width: 32px; height: 32px; font-size: 16px; }
body.mobile :is(#mute, #gear)::after { content: ''; position: absolute; inset: -6px; } /* a 44 px tap target around the small button */

/* --- teams: score bar, faction badge, fort meter, keg hint, round end --- */
#teams { position: fixed; top: calc(var(--edge) + var(--sat)); left: 0; right: 0; display: flex; justify-content: center; pointer-events: none; }
#tbar { display: flex; align-items: stretch; gap: 4px; padding: 4px 6px; border-radius: var(--r); }
.tsc { display: flex; flex-direction: column; align-items: center; justify-content: center; min-width: 58px; padding: 2px 6px 4px; border-radius: var(--rc); }
.tsc small { font: 800 var(--label)/1.2 var(--ui); letter-spacing: 1.2px; text-transform: uppercase; color: color-mix(in srgb, var(--tc) 55%, #fff); }
.tsc { min-width: 72px; }
.tsc b { min-width: 3.4ch; text-align: center; font: 800 20px/1 var(--ui); font-variant-numeric: tabular-nums; color: #fff; } /* 3 digits reserved: the score cells (and the phone bar) never resize */
.tb { align-self: stretch; height: 4px; margin-top: 3px; border-radius: var(--rc); overflow: hidden; background: rgba(0, 0, 0, .55); }
.tb i { display: block; height: 100%; background: var(--tc); transition: transform .4s; } /* hud.js slides the fill (translateX) under the rounded clip: the eased fill runs on the compositor (a layer only while it runs), no layout per frame */
.tsc.mine { background: color-mix(in srgb, var(--tc) 24%, transparent); box-shadow: inset 0 0 0 1px var(--tc); }
.tsc.mine { position: relative; }
.tsc.mine::before { content: 'YOU'; position: absolute; top: -9px; left: 50%; translate: -50% 0; padding: 0 5px; border-radius: var(--rc); /* our team */
  font: 800 var(--label)/13px var(--ui); letter-spacing: 1px; color: #fff; background: var(--tc); box-shadow: 0 0 0 1px rgba(0, 0, 0, .6); text-shadow: 0 1px 1px rgba(0, 0, 0, .5); }
.tsc.won b { color: var(--gold); text-shadow: 0 0 8px rgba(255, 211, 107, .7); }
.tclock { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px; padding: 0 2px 0 8px; border-left: 1px solid var(--line); }
#tgoal { margin-bottom: -3px; font: 800 var(--label)/1 var(--ui); letter-spacing: 1px; text-transform: uppercase; color: var(--gold); white-space: nowrap; }
#tbar.inter #tgoal { display: none; }
#tclock { min-width: 5ch; text-align: center; font: 800 16px/1 var(--ui); font-variant-numeric: tabular-nums; color: var(--parch); }
#fpips { display: flex; gap: 7px; }
#fpips i { position: relative; z-index: 0; display: block; width: 15px; height: 15px; border-radius: 50%; color: var(--c, #7d858e); }
#fpips i::after { content: ''; position: absolute; inset: 0; z-index: -1; border-radius: 50%; box-shadow: 0 0 0 2px var(--k), 0 0 7px var(--k); opacity: 0; pointer-events: none; } /* the capture glow, pre-rendered: its opacity pulses (z -1: under the icon and the ownership outline) */
#fpips svg { display: block; width: 100%; height: 100%; fill: currentColor; stroke: rgba(0, 0, 0, .75); stroke-width: 1.5px; paint-order: stroke; }
#fpips i.ours { outline: 1.5px solid rgba(255, 255, 255, .6); outline-offset: 1px; }
#fpips i.theirs { outline: 1.5px dashed var(--danger); outline-offset: 1px; } /* enemy-held: dashed red, like its ring at sea */
#fpips i.cap { animation: blink .5s steps(2) infinite alternate; }
#fpips i.cap::after { animation: glow .5s ease-in-out infinite alternate; }
@keyframes blink { to { opacity: .45; } }
#fpips i.cont { --k: #fff; }
#fpips i.cont::after { box-shadow: 0 0 0 1px rgba(255, 255, 255, .5), 0 0 3.5px rgba(255, 255, 255, .5); animation: glow .25s steps(2, jump-none) infinite alternate; } /* contested: a white flicker between nothing and half the glow */
#tbar.inter #fpips { display: none; }
#tbar.inter #tclock { color: var(--sea); }
#tbar.inter .tclock::after { content: 'Intermission'; font: 800 var(--label) var(--ui); letter-spacing: 1px; text-transform: uppercase; color: var(--sea); }

#hud .above { position: absolute; left: 0; right: 0; bottom: calc(100% + 8px); display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
#capmeter, #kegtip { width: max-content; max-width: min(300px, calc(100vw - 30px)); box-sizing: border-box; padding: 5px 10px; border-radius: var(--r); font: 700 13px var(--ui); }
#capmeter { align-self: stretch; width: auto; font-variant-numeric: tabular-nums; } /* the card's width, whatever the label says */
#capmeter span:first-child { display: block; color: color-mix(in srgb, var(--tc) 45%, #fff); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#capmeter .bar { display: block; height: 4px; margin-top: 4px; }
#capmeter .bar i { background-color: var(--tc); }
#capmeter.off { display: none; } /* desktop: out of a fort zone */
#capmeter.calm { opacity: .5; } #capmeter { transition: opacity .4s; } /* hud.js: nothing changing hands (HOLDING): faint until someone starts taking it */
#capmeter.cont { animation: throb .5s steps(2) infinite alternate; border-color: var(--danger); } /* the shadow lists don't interpolate (inset vs not), so it always flipped at the half: steps() says so (and hud.js animationstart keeps it from restyling every frame) */
#kegtip { color: var(--parch); border-color: var(--gold); animation: beckon .6s ease-in-out 3 alternate; transform-origin: 0 50%; } /* the beckon grows rightward: off the card's edge, never past the screen's */
#kegtip b { color: var(--gold); }
#kegtip kbd { margin: 0 2px; }
/* hints.js: a faint one-time line in a fixed slot well clear of our ship and the popups that rise or sink off it (desktop: low centre, above the upgrade picker);
   a soft pill keeps it legible over bright shallows and islands, and it fades (.hush) while a ship, its name tag or its popups pass through the slot */
#hint { position: fixed; left: 50%; bottom: calc(var(--edge) + 160px + var(--sab)); transform: translateX(-50%); width: max-content; max-width: calc(100vw - 32px); box-sizing: border-box; text-align: center; pointer-events: none; z-index: 2;
  padding: 4px 14px 5px; border-radius: var(--r); background: rgba(7, 19, 31, .5); box-shadow: 0 0 12px 2px rgba(7, 19, 31, .3);
  font: 600 15px/1.3 var(--ui); color: var(--parch); text-shadow: 0 1px 3px #000; opacity: 0; transition: opacity .6s; }
#hint.on { opacity: .85; }
#hint.on.hush { opacity: 0; }
#hint b { color: var(--gold); }
/* sinks and kegs share the speed row's grid: content | a 20px icon disc | a 36px value slot (the bars line up, nothing moves when values change) */
#sinkpips { flex: 1; gap: 2px; height: 7px; } /* a segmented bar: one segment per sink in this gap (1-4), gold = done */
#sinkpips i { flex: 1; width: auto; height: 100%; border-radius: var(--rc); background: rgba(0, 0, 0, .5); box-shadow: inset 0 1px 2px rgba(0, 0, 0, .6), 0 0 0 1px rgba(255, 255, 255, .06); }
#sinkpips i.on { background: var(--gold) linear-gradient(180deg, rgba(255, 255, 255, .35), transparent 60%); box-shadow: 0 0 0 1px rgba(0, 0, 0, .35); }
#sinkstar { position: relative; display: grid; place-items: center; width: 20px; height: 20px; box-sizing: border-box; border-radius: 50%; border: 1px solid var(--line); background: rgba(0, 0, 0, .35); transition: border-color .3s, box-shadow .3s; }
#sinkstar svg { width: 13px; height: 13px; fill: var(--parch2); opacity: .55; transition: opacity .3s; }
#sinkstar::after { content: ''; position: absolute; inset: -1px; border-radius: 50%; box-shadow: 0 0 9px rgba(255, 211, 107, .8); opacity: 0; pointer-events: none; }
#sinkrow.near #sinkstar { border-color: var(--gold); box-shadow: 0 0 2px rgba(255, 211, 107, .3); } /* one sink from a pick */
#sinkrow.near #sinkstar::after { animation: glow 1.2s ease-in-out infinite alternate; } /* the glint: a pre-rendered glow fading in and out over the faint one */
#sinkrow.near #sinkstar svg { fill: var(--gold); opacity: 1; }
@media (prefers-reduced-motion: reduce) { #sinkrow.near #sinkstar { box-shadow: 0 0 6px rgba(255, 211, 107, .6); } #sinkrow.near #sinkstar::after { animation: none; } }
:is(#sinktxt, #kegcd) { width: 36px; margin-left: -4px; font: 800 13px var(--ui); font-variant-numeric: tabular-nums; color: var(--parch2); white-space: nowrap; } /* -4px: #wind's 4px gap, not the row's 8 */
#sinkrow.near #sinktxt { color: var(--gold); }
#kegrow kbd { width: 20px; box-sizing: border-box; margin: 0; padding: 0; text-align: center; font-size: var(--label); line-height: 15px; }
#kegpips { display: flex; gap: 4px; margin-right: auto; border-radius: 3px; } /* hugs the barrels: the upgrade flash (.boon) rings them, not the empty row */
#kegpips i { width: 13px; height: 17px; /* a barrel: staves and two hoops over a fill that rises with --p while it recharges; empty = a dim ghost */
  --hoops: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 18' fill='none'%3E%3Cpath d='M3.5.5h7c3 5.5 3 11.5 0 17h-7c-3-5.5-3-11.5 0-17z' stroke='%233a1e06' stroke-width='1.8'/%3E%3Cpath d='M0 4.6h14M0 13.4h14' stroke='%233a1e06' stroke-width='1.7'/%3E%3Cpath d='M5.2 1c-1.3 5.5-1.3 10.5 0 16M8.8 1c1.3 5.5 1.3 10.5 0 16' stroke='%233a1e06' stroke-opacity='.45' stroke-width='.8'/%3E%3C/svg%3E") center/100% 100%;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 18'%3E%3Cpath d='M3.5.5h7c3 5.5 3 11.5 0 17h-7c-3-5.5-3-11.5 0-17z'/%3E%3C/svg%3E") center/100% 100%;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 18'%3E%3Cpath d='M3.5.5h7c3 5.5 3 11.5 0 17h-7c-3-5.5-3-11.5 0-17z'/%3E%3C/svg%3E") center/100% 100%;
  background: var(--hoops), linear-gradient(to top, rgba(224, 160, 80, .75) calc(var(--p, 0) * 100%), rgba(241, 228, 195, .1) 0); }
#kegpips i.on { background: var(--hoops), linear-gradient(90deg, #a8662a, #f2b86a 40%, #e0a050 60%, #a8662a); }
#kegcd { color: var(--muted); }
#kegrow:not(.ready) #kegcd { color: var(--parch); } /* no keg to drop: the wait is the news */
#kegbtn > .ring { inset: -6px; } #kegbtn > .ring { background: conic-gradient(#ffb04a calc(var(--r, 1) * 1turn), rgba(0, 0, 0, .45) 0); }
#kegbtn.cool > :not(.ring) { opacity: .45; }

#roundend { position: fixed; z-index: 13; left: 50%; top: calc(var(--edge) + 72px + var(--sat)); translate: -50% 0; width: max-content; max-width: calc(100vw - 32px); box-sizing: border-box;
  padding: 12px 22px 12px; text-align: center; pointer-events: none; animation: rein .5s cubic-bezier(.2, .8, .2, 1.2); background-color: #08151f; } /* under the plate's 90% gradient: opaque, so tags and the feed don't read through the scores */
@keyframes rein { from { opacity: 0; scale: .7; } }
/* the break: the card right under the score bar, the warning under the card, the banners (still coming: kills; one at a time, hud.js pump) below our ship */
body:has(> #roundend:not(.hidden)) #banner { top: 67%; }
@media (max-width: 1000px) { body:not(.mobile):has(> #roundend:not(.hidden)):has(> #upgrades.on) #banner { top: calc(var(--edge) + 400px + var(--sat)); } } /* the lifted picker is at 67%: right under the card instead */
@media (min-width: 760px) and (max-width: 1000px) { body:not(.mobile):has(> #roundend:not(.hidden)):has(> #upgrades.on) #banner { top: calc(var(--edge) + 500px + var(--sat)); } } /* under the scoreboard */
@media (max-width: 1000px) and (max-height: 699px) { body:not(.mobile):has(> #roundend:not(.hidden)):has(> #upgrades.on) .note span { display: none; } } /* only the title fits between card and picker */
body.playing:not(.mobile):has(> #roundend:not(.hidden)) #warn { top: calc(var(--edge) + 390px + var(--sat)); } /* under the card and its stats grid */
@media (min-width: 760px) { body.playing:not(.mobile):has(> #roundend:not(.hidden)) #warn { top: calc(var(--edge) + 490px + var(--sat)); } body:not(.mobile):has(> #roundend:not(.hidden)) #banner { top: max(67%, calc(var(--edge) + 500px)); } } /* the scoreboard makes it taller */
@media (min-width: 1700px) and (min-height: 950px) { body.playing:not(.mobile):has(> #roundend:not(.hidden)) #warn { top: calc(var(--edge) + 575px + var(--sat)); } } /* the card is 1.2x / 1.4x, under the zoomed score bar */
@media (min-width: 2200px) and (min-height: 1250px) { body.playing:not(.mobile):has(> #roundend:not(.hidden)) #warn { top: calc(var(--edge) + 670px + var(--sat)); } }
#roundend.win .kicker { color: var(--gold); }
#roundend h2 { margin: 2px 0 10px; font: 400 clamp(28px, 6vw, 46px)/1.05 var(--display); color: color-mix(in srgb, var(--tc) 70%, #fff); overflow-wrap: anywhere;
  text-shadow: 0 3px 0 rgba(0, 0, 0, .6), 0 8px 20px rgba(0, 0, 0, .6); }
.rscores { display: flex; justify-content: center; gap: 8px; }
.rscores div { min-width: 64px; padding: 4px 8px 6px; border-radius: var(--rc); background: rgba(0, 0, 0, .35); box-shadow: inset 0 -3px 0 var(--tc); display: flex; flex-direction: column; }
.rscores small { font: 800 var(--label) var(--ui); letter-spacing: 1px; text-transform: uppercase; color: color-mix(in srgb, var(--tc) 55%, #fff); }
.rscores b { font: 800 20px/1.1 var(--ui); font-variant-numeric: tabular-nums; }
.rscores .won { box-shadow: inset 0 -3px 0 var(--tc), 0 0 0 1px var(--gold); }
.rscores .won b { color: var(--gold); }
#renext { margin: 8px 0 0; font: 700 13px var(--ui); color: var(--muted); }
#renext:empty, #rstats:empty { display: none; }
#renext.soon { color: var(--gold); animation: punch .5s; }
#rstats { margin: 7px 0 0; font: 600 13px var(--ui); color: var(--parch2); }
/* extended stats (hud.js minis / drawTable): small cells in fixed columns, and the desktop scoreboard in a fixed box */
.stats.mini { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 2px; padding: 4px; } /* the finer numbers: small cells in one quiet panel (#deadmore is a plate; the round card's grid sits on its card) */
.stats.mini:empty { display: none; }
.mini .stat { gap: 0; padding: 3px 2px; min-width: 0; }
.mini .stat b { font-size: 16px; color: var(--parch); white-space: nowrap; }
.mini .stat small { font-size: var(--label); letter-spacing: .3px; white-space: nowrap; }
.stat.nil b { color: var(--muted); } .mini .stat.nil { opacity: .5; } /* hud.js nil: "0", "-", "0%" read quiet, so the real numbers stand out */
#rgrid { margin-top: 8px; grid-template-columns: repeat(4, 84px); justify-content: center; border-radius: var(--rc); background: rgba(0, 0, 0, .25); }
#rgrid .x { display: none; }
.rtab { display: none; position: relative; width: 640px; height: 178px; margin-top: 8px; overflow-y: auto; pointer-events: auto; border-radius: var(--rc); background: rgba(0, 0, 0, .3); scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
.rtab table { width: 100%; table-layout: fixed; border-collapse: collapse; font: 700 13px/22px var(--ui); font-variant-numeric: tabular-nums; color: var(--parch); }
.rtab th { position: sticky; top: 0; z-index: 1; height: 24px; padding: 0 6px; background: #0c1c29; border-bottom: 1px solid var(--line); font: 800 var(--label) var(--ui); letter-spacing: .4px; text-transform: uppercase; color: var(--muted); text-align: right; }
.rtab th:first-child { width: 150px; text-align: left; }
.rtab td { padding: 0 6px; text-align: right; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rtab td:first-child { text-align: left; }
.rtab td:first-child svg { width: 12px; height: 12px; margin-right: 4px; vertical-align: -1px; }
.rtab td span { color: var(--parch); }
.rtab tbody tr:nth-child(even) { background: rgba(255, 255, 255, .03); }
.rtab tr.me { background: rgba(255, 211, 107, .16) !important; } .rtab tr.me td, .rtab tr.me td span { color: var(--gold); }
.rtab button { all: unset; cursor: pointer; display: inline-flex; align-items: center; gap: 3px; } .rtab button:hover, .rtab button.on { color: var(--gold); }
.rtab button:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.rtab button i { width: 7px; height: 5px; background: currentColor; clip-path: polygon(50% 0, 100% 100%, 0 100%); visibility: hidden; } /* the sort arrow's slot is always there: headers never shift */
.rtab button.on i { visibility: visible; } .rtab button.down i { clip-path: polygon(0 0, 100% 0, 50% 100%); }
@media (min-width: 760px) { body:not(.mobile) .rtab { display: block; } body:not(.mobile) #rgrid { grid-template-columns: repeat(6, 1fr); width: 640px; } body:not(.mobile) #rgrid .t { display: none; } body:not(.mobile) #rgrid .x { display: flex; } }
#tbar.late #tclock { color: var(--danger); }
#tbar.final #tclock { animation: punch 1s infinite; }
.tsc b { position: relative; z-index: 0; }
.tsc.near b::before { content: attr(data-v); position: absolute; inset: 0; z-index: -1; color: transparent; text-shadow: 0 0 10px var(--tc), 0 0 2px #fff; opacity: 0; animation: glow .6s ease-in-out infinite alternate; } /* close to victory: the score's glow, a pre-rendered copy under it (hud.js data-v) fading in and out */
#lb .td { width: 13px; height: 13px; flex: none; margin-left: -3px; } /* the faction emblem: not hue alone */
#lb .td svg { display: block; width: 100%; height: 100%; filter: drop-shadow(0 1px 1px #000); }
/* team emblems inline with a team's name (hud.js emblemSvg: 1em of the text), never under 12 px */
:is(.tsc small, .rscores small, #deadteam, #deadmsg, #invited, #roundend h2) svg { min-width: 12px; min-height: 12px; margin-right: .2em; vertical-align: -.15em; }
#deadmsg svg, #roundend h2 svg { width: .75em; height: .75em; vertical-align: -.02em; }

/* phones: the bar squeezes between the minimap (top-left) and the leaderboard (top-right) */
body.mobile #teams { left: calc(var(--edge) + 96px + var(--sal)); right: calc(var(--edge) + 144px + var(--sar)); }
@media (max-width: 899px), (max-height: 699px) { /* a tablet keeps the full bar (tablet block below) */
body.mobile #tbar { display: grid; grid-template-columns: repeat(3, auto); gap: 2px; padding: 3px 2px 4px; } /* a grid, not a wrapping flex row: that sizes to all four cells on one line, leaving the bar half empty */
body.mobile .tsc { min-width: 0; padding: 1px 1px 2px; }
body.mobile .tsc { flex-direction: row; flex-wrap: wrap; column-gap: 1px; }
body.mobile .tsc small { font-size: 0; letter-spacing: 0; } /* just the team emblem */
body.mobile .tb { flex-basis: 100%; }
body.mobile .tsc b { font-size: 13px; color: var(--tc); text-shadow: var(--outline); } /* team colour says whose score */
body.mobile .tclock { grid-column: 1 / -1; flex-direction: row; gap: 5px; padding: 3px 0 0; border-left: 0; border-top: 1px solid var(--line); }
body.mobile #tclock { font-size: 13px; }
body.mobile #fpips { gap: 4px; }
body.mobile #fpips i { width: 10px; height: 10px; }
body.mobile #tgoal { display: none; } /* no room on the phone bar; the menu says it */
body.mobile .tsc.mine::before { top: -12px; font-size: var(--label); line-height: 12px; padding: 0 3px; } /* sits on the chip, not over its score */
@media (min-width: 520px) { body.mobile #tbar { column-gap: 4px; padding-inline: 5px; } body.mobile .tsc { padding-inline: 3px; } } /* landscape has the room: the chips clear of each other and of the bar's rim (portrait's gap is exactly the bar's width) */
body.mobile #tbar.inter .tclock::after { content: 'Break'; } }
/* phones: the capture meter is a 150x20 tab sitting on the card, its box always kept and only faded in a fort zone (hud.js .off) */
body.mobile #hud .above { left: -4px; right: -1px; bottom: calc(100% + 1px); }
body.mobile #capmeter { width: 150px; max-width: none; height: 20px; padding: 1px 6px; font: 700 var(--label)/11px var(--ui); border-radius: var(--rc) var(--rc) 0 0; transition: opacity .25s, visibility .25s; }
body.mobile #capmeter .bar { height: 3px; margin-top: 2px; }
body.mobile #capmeter.off { display: block; visibility: hidden; opacity: 0; }
@media (max-width: 370px) { body.mobile #tbar { padding-inline: 1px; } body.mobile .tsc { padding-inline: 0; } body.mobile .tsc b { font-size: 12px; } } /* 360 px phones: three 3-digit scores on one row */
/* phone round end: a compact card in the top strip (landscape: between the minimap and the leaderboard; portrait: under the minimap), clear of our ship and the capture meter */
body.mobile #roundend { top: calc(var(--edge) + 50px + var(--sat)); left: calc(var(--edge) + 96px + var(--sal)); right: calc(var(--edge) + 144px + var(--sar)); translate: none; margin-inline: auto; width: fit-content;
  max-width: none; padding: 5px 10px 6px; }
body.mobile #roundend .kicker { font-size: var(--label); letter-spacing: 1.5px; }
body.mobile #roundend h2 { margin: 0 0 4px; font-size: 20px; }
body.mobile .rscores { gap: 4px; }
body.mobile .rscores div { min-width: 44px; padding: 1px 6px 3px; }
body.mobile .rscores small { font-size: var(--label); letter-spacing: .5px; }
body.mobile .rscores b { font-size: 15px; }
body.mobile #renext, body.mobile #rstats { margin-top: 3px; font-size: 11px; }
@media (max-width: 519px) { body.mobile #roundend { top: calc(var(--edge) + 102px + var(--sat)); left: calc(var(--edge) + var(--sal)); right: calc(var(--edge) + var(--sar)); } body.mobile:has(> #roundend:not(.hidden)) #seatag { visibility: hidden; } } /* the card covers all but a stub of the sea tag */
body.mobile:has(> #roundend:not(.hidden)) #msg { top: 62%; } /* the break: the message slot below our ship, not on the card */
body.mobile:has(> #roundend:not(.hidden)):has(> #upgrades.on) #msg { top: calc(var(--edge) + 270px + var(--sat)); bottom: auto; } /* the picker has that spot (and the landscape gap): right under the card */
@media (max-width: 519px) { body.mobile:has(> #roundend:not(.hidden)):has(> #upgrades.on) #msg { top: calc(var(--edge) + 324px + var(--sat)); } } /* under the card and its stats grid */
@media (orientation: landscape) { body.mobile:has(> #roundend:not(.hidden)):has(> #upgrades.on) #msg { top: calc(var(--edge) + 172px + var(--sat)); } } /* under the card and its stats grid */
@media (orientation: landscape) { /* short screen: the card takes the score bar's place (it has the scores), the warning and banners the bottom gap between the status card and the buttons */
  body.mobile #roundend { top: calc(var(--edge) + var(--sat)); }
  body.mobile:has(> #roundend:not(.hidden)) #teams { visibility: hidden; }
  body.mobile:has(> #roundend:not(.hidden)) #msg { top: auto; bottom: calc(var(--edge) + 42px + var(--sab)); } }
@media (min-width: 900px) and (min-height: 700px) { /* a touch tablet: a real chart and the full score bar (touch controls stay) */
  body.mobile #lb { width: 168px; } body.mobile #lb h3 { display: flex; } body.mobile #lb ol { font-size: 13px; } /* the full top 5 (hud.js) */
  body.mobile #minimap { width: 150px; height: 150px; }
  body.mobile :is(#teams, #roundend) { left: calc(var(--edge) + 154px + var(--sal)); }
  body.mobile #msg { top: calc(var(--edge) + 160px + var(--sat)); left: calc(16px + var(--sal)); right: calc(16px + var(--sar)); max-width: 300px; } } /* under the big chart, clear of the full score bar */
@media (orientation: landscape) and (max-height: 699px) { body.mobile #lb { width: 128px; } body.mobile :is(#teams, #roundend) { right: calc(var(--edge) + 168px + var(--sar)); } } /* landscape has the width: names, not "Morg..." (the top strip stays clear of it) */
/* phone: the round card's own grid, smaller plates (no scoreboard) */
body.mobile #rgrid { margin-top: 4px; gap: 4px; grid-template-columns: repeat(4, 74px); }
body.mobile .mini .stat { padding: 3px 1px 3px; }
body.mobile .mini .stat b { font-size: 15px; }
body.mobile .mini .stat small { font-size: var(--label); letter-spacing: 0; }
@media (orientation: landscape) and (max-height: 500px) { body.mobile #rgrid .lo { display: none; } body.mobile #rgrid { margin-top: 3px; gap: 3px; } body.mobile #rgrid .stat { padding: 2px 1px; } body.mobile #rgrid .stat b { font-size: 13px; } } /* the short screen: two rows of the essentials, clear of our ship */
@media (orientation: landscape) and (max-height: 500px) { #deadmore { grid-template-columns: repeat(8, minmax(0, 1fr)); gap: 4px; } #deadmore .stat small { font-size: var(--label); letter-spacing: 0; } } /* landscape phone: one row, so PLAY AGAIN stays on the first screen */

/* --- left-handed phone (hud.js setMirror): every corner card and button swaps sides, its offset and safe-area inset with it (the stick floats under either thumb; the edge arrows measure the cards) --- */
body.mobile.mirror #hud { left: auto; right: calc(var(--edge) + var(--sar)); }
body.mobile.mirror #capmeter { align-self: flex-end; transform-origin: 100% 50%; } /* wider than the card: it overhangs its inner edge, not the screen's */
body.mobile.mirror #minimap { left: auto; right: calc(var(--edge) + var(--sar)); }
body.mobile.mirror #lb { right: auto; left: calc(var(--edge) + 36px + var(--sal)); }
body.mobile.mirror :is(#mute, #gear, #fps) { right: auto; left: calc(var(--edge) + var(--sal)); }
body.mobile.mirror #settings { right: auto; left: calc(var(--edge) + 40px + var(--sal)); }
body.mobile.mirror :is(#teams, #roundend) { left: calc(var(--edge) + 144px + var(--sal)); right: calc(var(--edge) + 96px + var(--sar)); }
body.mobile.mirror #fire { right: auto; left: calc(26px + var(--sal)); }
body.mobile.mirror #sail { right: auto; left: calc(97px + var(--sal)); }
body.mobile.mirror #kegbtn { right: auto; left: calc(132px + var(--sal)); }
@media (orientation: landscape) and (max-width: 639px) { body.mobile.mirror #upgrades { left: auto; right: calc(var(--edge) + 158px + var(--sar)); } }
@media (max-width: 519px) { body.mobile.mirror #roundend { left: calc(var(--edge) + var(--sal)); right: calc(var(--edge) + var(--sar)); } }
@media (min-width: 900px) and (min-height: 700px) { body.mobile.mirror :is(#teams, #roundend) { right: calc(var(--edge) + 154px + var(--sar)); } }
@media (orientation: landscape) and (max-height: 699px) { body.mobile.mirror :is(#teams, #roundend) { left: calc(var(--edge) + 168px + var(--sal)); } }
/* landscape phone: the score bar is a fixed 150x46 block beside the minimap (scores, then the clock and forts), so the top centre is open sea:
   a landscape screen is short, and main.js frames our broadside range up there (portrait keeps its top strip: there the width limits it) */
@media (orientation: landscape) and (max-height: 699px) {
  body.mobile #teams { right: auto; }
  body.mobile #tbar { width: 150px; height: 46px; box-sizing: border-box; grid-template-columns: repeat(3, 1fr); align-content: space-between; }
  body.mobile.mirror #teams { left: auto; right: calc(var(--edge) + 96px + var(--sar)); }
  /* the message slot fills the gap between the score block (edge+96..246) and the board (edge+36..164), not the screen's centre: centred it ran under the block */
  body.mobile #msg { left: calc(var(--edge) + 254px + var(--sal)); right: calc(var(--edge) + 172px + var(--sar)); }
  body.mobile.mirror #msg { left: calc(var(--edge) + 172px + var(--sal)); right: calc(var(--edge) + 254px + var(--sar)); } }
