/* Frontline: Fragline's layout (games/fragline/client/style.css), in the colours of 1944, dressed in Synty's
   Modern Menus: its plates, frames, shields and icons, tinted olive, khaki and brass (games/frontline/ui.mjs
   makes assets/ui/*.webp). Framed boxes are nine-sliced border-images, so one frame fits any size. */

:root {
	--bg: #0b0c08;
	--panel: rgba(18, 18, 12, 0.84);
	--panel-solid: #17170f;
	--line: rgba(255, 255, 255, 0.09);
	--line-strong: rgba(255, 255, 255, 0.2);
	--text: #ece6d6;
	--muted: #9a9482;
	--accent: #c9a24a;
	--accent-2: #e3cf8c;
	--good: #6dff8f;
	--bad: #ff5147;
	--red: #8fbf6a;
	--blue: #a9b4bd;
	--gold: #f2c14e;
	--font: 'Trebuchet MS', 'Gill Sans', 'Segoe UI', system-ui, sans-serif;
	--mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
	/* Notches and the home bar (index.html asks for viewport-fit=cover); zero on desktops. */
	--sat: env(safe-area-inset-top, 0px);
	--sar: env(safe-area-inset-right, 0px);
	--sab: env(safe-area-inset-bottom, 0px);
	--sal: env(safe-area-inset-left, 0px);
	color-scheme: dark;
}

* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; background: var(--bg); color: var(--text); font-family: var(--font); overflow: hidden; user-select: none; -webkit-user-select: none;
	overscroll-behavior: none; -webkit-text-size-adjust: 100%; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; }
/* The same box as the HUD (fixed, inset 0), so the crosshair sits at the view's centre. Not 100vh: iOS
   Safari makes that the height without its toolbars, which put the view's centre below the crosshair. */
canvas#view { position: fixed; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; }
button, input, select { font: inherit; color: inherit; }
[hidden] { display: none !important; }

/* ---------- menu ---------- */
/* The game's own font (assets/fonts: Oxanium, as the HUD's), not the system's: the same everywhere. */
#menu { font-family: var(--hud); position: fixed; inset: 0; display: grid; place-items: center; overflow-y: auto; padding: calc(24px + var(--sat)) calc(16px + var(--sar)) calc(24px + var(--sab)) calc(16px + var(--sal));
	touch-action: manipulation; overscroll-behavior: contain;
	background: radial-gradient(1200px 700px at 70% 10%, rgba(210, 171, 92, 0.1), transparent 60%), radial-gradient(900px 600px at 10% 90%, rgba(110, 130, 70, 0.12), transparent 60%), linear-gradient(180deg, rgba(7, 9, 12, 0.55), rgba(7, 9, 12, 0.92)); }
#menu.over-game { background: rgba(5, 7, 10, 0.72); backdrop-filter: blur(6px); }
/* The pack's pointer in the menus (and on what can be clicked). */
:root { --arrow: url(/assets/ui/cursor.png) 2 1, default; --hand: url(/assets/ui/cursor.png) 2 1, pointer; }
#menu, #hud .classmenu { cursor: var(--arrow); }
.shell { width: min(1080px, 100%); display: grid; gap: 18px; }
.brand { display: flex; align-items: baseline; gap: 14px; }
.brand h1 { margin: 0; font-size: clamp(44px, 8vw, 88px); letter-spacing: 0.06em; font-weight: 700; line-height: 0.9;
	background: linear-gradient(180deg, #fff 0%, #efe2bd 45%, var(--accent) 100%); -webkit-background-clip: text; background-clip: text; color: transparent;
	text-shadow: 0 0 40px rgba(210, 171, 92, 0.25); }
.brand .tag { color: var(--muted); letter-spacing: 0.2em; text-transform: uppercase; font-size: 13px; }
/* The desktop app's downloads: a box beside the first screen's card, its top in line with it (beside
   the name card, as tall); this computer's a button, the rest links. Under the card on a narrow screen. */
.beside { display: flex; flex-wrap: wrap; gap: 18px; align-items: stretch; }
.beside > .card:first-child { flex: 1 1 440px; min-width: 0; }
.beside.browser { align-items: flex-start; }
.dlbox { flex: 0 0 250px; display: flex; flex-direction: column; gap: 10px; }
.dlbox h2 { margin-bottom: 0; }
.dlbox p { margin: 0; line-height: 1.45; }
.dlbox .dl-mine { margin-top: auto; }
.dl-mine { flex-direction: column; gap: 1px; padding-top: 8px; padding-bottom: 11px; }
.dl-mine small { font-size: 10px; letter-spacing: 0.08em; opacity: 0.8; white-space: nowrap; }
.dl-others { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 13px; }
.dl-others a { color: var(--text); text-decoration: none; border-bottom: 1px solid var(--line-strong); padding: 1px 0; cursor: var(--hand); }
.dl-others a:hover { color: var(--gold); border-color: var(--gold); }
.dl-others a.dl-more { color: var(--muted); border-color: transparent; }
/* Settings, Keys, where the browser keeps Ctrl+W: why, and the app. */
.keysnote { display: grid; grid-template-columns: 1fr auto; gap: 10px 18px; align-items: center; margin: 0 0 14px; padding: 10px 12px; border: 1px solid rgba(201, 162, 74, 0.45); background: rgba(201, 162, 74, 0.07); }
.keysnote p { margin: 0; font-size: 13px; line-height: 1.45; grid-row: span 2; }
.keysnote .dl-others { justify-content: flex-end; }
.card { border: 16px solid transparent; padding: 6px 12px 14px 8px; border-image: url(/assets/ui/panel.webp) 75 62 90 260 fill / 30px 25px 36px 104px; filter: drop-shadow(0 6px 14px rgba(0, 0, 0, 0.45)); }
.card h2 { margin: 0 0 14px; padding-bottom: 8px; font-size: 14px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--accent-2); font-weight: 600;
	background: linear-gradient(90deg, var(--accent), rgba(210, 171, 92, 0.35) 40%, transparent 85%) left bottom / 100% 2px no-repeat; }
.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.grow { flex: 1; }
/* Buttons: an olive plate (a brass one for the thing to do), its lip at the foot; a ghost is a frame. */
.btn { appearance: none; border: 0; background: url(/assets/ui/btn.webp) center / 100% 100% no-repeat; padding: 10px 18px 13px; cursor: var(--hand); display: inline-flex; align-items: center; justify-content: center; gap: 8px;
	text-transform: uppercase; letter-spacing: 0.12em; font-weight: 700; font-size: 13px; color: var(--text); text-decoration: none; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.6); transition: filter 0.12s, transform 0.06s; }
.btn:hover { background-image: url(/assets/ui/btn_hi.webp); }
.btn:active { transform: translateY(2px); }
.btn.primary { background-image: url(/assets/ui/btn_go.webp); color: #1d1607; text-shadow: 0 1px 0 rgba(255, 240, 200, 0.35); }
.btn.primary:hover { filter: brightness(1.1); }
.btn.ghost { background: none; border: 9px solid transparent; border-image: url(/assets/ui/field.webp) 18 fill / 9px; padding: 1px 9px 2px; }
.btn.ghost:hover { filter: brightness(1.35); }
.btn:disabled { opacity: 0.45; cursor: default; filter: saturate(0.4); }
/* Icons on the buttons that have one (the pack's flat icons, coloured as the text). */
.btn[data-act]::before { width: 15px; height: 15px; flex: none; background: currentColor; -webkit-mask: var(--i) center / contain no-repeat; mask: var(--i) center / contain no-repeat; }
.btn:is([data-act=join], [data-act=quick], [data-act=resume], [data-act=create], [data-act=practice], [data-act=settings], [data-act=help], [data-act=refresh], [data-act=leave], [data-act=back], [data-act=copylink], [data-act=rename])::before { content: ''; }
.btn[data-act=join], .btn[data-act=resume] { --i: url(/assets/ui/i_play.webp); }
.btn[data-act=quick] { --i: url(/assets/ui/i_chevrons.webp); }
.btn[data-act=create] { --i: url(/assets/ui/i_plus.webp); }
.btn[data-act=practice] { --i: url(/assets/ui/i_target.webp); }
.btn[data-act=settings] { --i: url(/assets/ui/i_settings.webp); }
.btn[data-act=help] { --i: url(/assets/ui/i_keyboard.webp); }
.btn[data-act=refresh] { --i: url(/assets/ui/i_reload.webp); }
.btn[data-act=leave] { --i: url(/assets/ui/i_exit.webp); }
.btn[data-act=back] { --i: url(/assets/ui/i_back.webp); }
.btn[data-act=copylink] { --i: url(/assets/ui/i_flag.webp); }
.btn[data-act=rename] { --i: url(/assets/ui/i_medal.webp); }
.btn.primary[data-act=back]::before { content: none; }
.field { display: grid; gap: 6px; }
.field label, .label { font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); }
.input, select.input { background: none; border: 9px solid transparent; border-image: url(/assets/ui/field.webp) 18 fill / 9px; padding: 2px 4px; min-width: 0; outline: none; }
.input:focus { filter: brightness(1.3) sepia(0.4); }
select.input option { background: var(--panel-solid); }
.grid2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; }
.muted { color: var(--muted); }
.error { color: var(--bad); min-height: 1.2em; font-size: 14px; }
.small { font-size: 12px; }

table.servers { width: 100%; border-collapse: collapse; font-size: 14px; }
table.servers th { text-align: left; font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); font-weight: 600; padding: 8px; border-bottom: 1px solid var(--line); }
table.servers td { padding: 10px 8px; border-bottom: 1px solid var(--line); }
table.servers tr.srv { cursor: pointer; }
table.servers tr.srv:hover td { background: rgba(210, 171, 92, 0.08); }
table.servers tr.srv.sel td { background: rgba(210, 171, 92, 0.18); }
table.servers tr.srv.sel td:first-child { box-shadow: inset 3px 0 var(--accent); }
.ping-good { color: var(--good); } .ping-ok { color: var(--gold); } .ping-bad { color: var(--bad); }
.pill { display: inline-block; padding: 2px 8px; border: 1px solid var(--line-strong); border-radius: 999px; font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; }
.empty { padding: 28px; text-align: center; color: var(--muted); }
.tabs { display: flex; gap: 4px; border-bottom: 2px solid rgba(210, 171, 92, 0.5); margin-bottom: 14px; flex-wrap: wrap; }
.tab { padding: 8px 16px 6px; cursor: var(--hand); color: var(--text); letter-spacing: 0.12em; text-transform: uppercase; font-size: 12px; font-weight: 700; background: url(/assets/ui/tab.webp) center / 100% 100% no-repeat; opacity: 0.75; }
.tab:hover { opacity: 1; }
.tab.on { color: #1d1607; background-image: url(/assets/ui/tab_on.webp); opacity: 1; }
.setting { display: grid; grid-template-columns: minmax(140px, 1fr) minmax(160px, 1.4fr) 64px; gap: 10px; align-items: center; padding: 6px 0; }
/* Sliders: a framed slot that fills with brass up to the value, under a ridged grip (--v, 0 to 1, from
   the menu; --g the grip's width, so the fill ends under its middle). The pieces are nine-sliced, so the
   slot's cut ends keep their shape at any length. */
.slide { --g: 40px; position: relative; height: 28px; border: solid transparent; border-width: 0 14px; border-image: url(/assets/ui/slider_bed.webp) 0 64 fill / 0 14px; margin: 0 -14px 0 0; }
.slide::before, .slide::after { content: ''; position: absolute; inset: 0 -14px; border: solid transparent; border-width: 0 14px; pointer-events: none; }
.slide::before { border-image: url(/assets/ui/slider_fill.webp) 0 64 fill / 0 14px; clip-path: inset(0 calc(100% - 14px - var(--g) / 2 - var(--v) * (100% - 28px - var(--g))) 0 0); }
.slide::after { border-image: url(/assets/ui/slider_frame.webp) 0 64 fill / 0 14px; z-index: 1; }
.slide input[type=range] { position: absolute; inset: 0 -14px; width: calc(100% + 28px); height: 100%; margin: 0; padding: 0 14px; box-sizing: border-box; -webkit-appearance: none; appearance: none; background: none; cursor: var(--hand); z-index: 2; }
.slide input[type=range]::-webkit-slider-runnable-track { height: 100%; background: none; }
.slide input[type=range]::-moz-range-track { height: 100%; background: none; }
.slide input[type=range]::-moz-range-progress { background: none; }
.slide input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: var(--g); height: 26px; margin-top: 1px; border: 0; background: url(/assets/ui/slider_grip.webp) center / contain no-repeat; filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.6)); }
.slide input[type=range]::-moz-range-thumb { width: var(--g); height: 26px; border: 0; border-radius: 0; background: url(/assets/ui/slider_grip.webp) center / contain no-repeat; filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.6)); }
.slide input[type=range]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.setting .val { font-family: var(--mono); font-size: 13px; color: var(--gold); text-align: right; }
/* Switches: Off and On in a framed slot, the one it's at lit (pale steel off, brass on) and lettered dark. */
.switch { position: relative; justify-self: start; margin: -5px 0; cursor: var(--hand); }
.switch input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: var(--hand); z-index: 1; }
.switch .sw { display: grid; grid-template-columns: 1fr 1fr; align-items: center; width: 108px; height: 50px; padding: 0 9px; box-sizing: border-box; background: url(/assets/ui/switch_off.webp) center / 100% 100% no-repeat; }
.switch .sw b { text-align: center; font-size: 13px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: rgba(191, 176, 138, 0.45); }
.switch .sw b:first-child { color: #15160f; }
.switch input:checked + .sw { background-image: url(/assets/ui/switch_on.webp); }
.switch input:checked + .sw b:first-child { color: rgba(191, 176, 138, 0.45); }
.switch input:checked + .sw b:last-child { color: #1d1607; }
.switch input:focus-visible + .sw { outline: 2px solid var(--accent); outline-offset: 2px; }
/* The settings say a change was kept; the Voice tab says where voice stands, with a lamp, and a
   microphone check's level in a slot like a slider's. */
.saved { margin-left: auto; align-self: center; font-size: 12px; color: var(--muted); transition: color 0.2s; }
.saved.on { color: var(--good); }
.vstatus { display: grid; grid-template-columns: 110px 1fr; gap: 5px 12px; padding: 10px 12px; margin-bottom: 10px; font-size: 13px; border: 8px solid transparent; border-image: url(/assets/ui/field.webp) 18 fill / 8px; }
.vstatus > span:nth-child(odd) { color: var(--muted); text-transform: uppercase; letter-spacing: 0.1em; font-size: 11px; padding-top: 2px; }
.lamp { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 8px; vertical-align: 0; background: #4a4a40; }
.lamp.good { background: var(--good); box-shadow: 0 0 6px var(--good); }
.lamp.warn { background: var(--gold); box-shadow: 0 0 6px var(--gold); }
.lamp.bad { background: var(--bad); box-shadow: 0 0 6px var(--bad); }
.meter { --v: 0; position: relative; height: 22px; border: solid transparent; border-width: 0 11px; border-image: url(/assets/ui/slider_bed.webp) 0 64 fill / 0 11px; }
.meter::before, .meter::after { content: ''; position: absolute; inset: 0 -11px; border: solid transparent; border-width: 0 11px; }
.meter::before { border-image: url(/assets/ui/slider_fill.webp) 0 64 fill / 0 11px; clip-path: inset(0 calc((1 - var(--v)) * 100%) 0 0); transition: clip-path 0.08s linear; }
.meter::after { border-image: url(/assets/ui/slider_frame.webp) 0 64 fill / 0 11px; }
.btn.mini { padding: 5px 8px 7px; font-size: 11px; justify-self: stretch; }
.bind { display: grid; grid-template-columns: 1fr auto; gap: 10px; align-items: center; padding: 5px 0; border-bottom: 1px solid var(--line); }
.keycap { font-family: var(--mono); font-size: 12px; padding: 0 4px; border: 8px solid transparent; border-image: url(/assets/ui/field.webp) 18 fill / 8px; cursor: var(--hand); min-width: 110px; text-align: center; }
.keycap.wait { color: var(--accent); filter: brightness(1.4) sepia(0.5); }
.help-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 8px 20px; font-size: 14px; }
.help-grid div { display: flex; justify-content: space-between; border-bottom: 1px dashed var(--line); padding: 4px 0; }

/* ---------- HUD: Synty's Military Combat HUD ---------- */
/* Its font (Oxanium, SIL OFL), its gunmetal frames (border-images), its white shapes and icons coloured
   through masks (--icon on an element, or a ::before), its effects and badges. */
@font-face { font-family: Oxanium; src: url(/assets/fonts/Oxanium-Medium.woff2) format('woff2'); font-weight: 400 600; font-display: swap; }
@font-face { font-family: Oxanium; src: url(/assets/fonts/Oxanium-Bold.woff2) format('woff2'); font-weight: 700 900; font-display: swap; }
:root { --hud: Oxanium, var(--font); --hp: #9cc46a; --allies: #8fbf5a; --axis: #a9b6bf; --neutral: #cfc6a6; --frame: url(/assets/ui/mc_frame.webp) 100 80 75 80 fill / 40px 32px 30px 32px round; }
#hud { position: fixed; inset: 0; pointer-events: none; font-family: var(--hud); text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8); }
/* Each HUD and touch element on a small compositor layer of its own: #hud and #touch, full-screen and
   fixed, then paint nothing, and Safari doesn't blend two full-screen layers over the game each frame. */
#hud > *, #touch > * { will-change: transform; }
@keyframes pulse { 50% { opacity: 0.55; } }
@keyframes fadein { from { opacity: 0; transform: translateY(-3px); } }
@keyframes spin { to { transform: rotate(360deg); } }
/* A white shape from the pack, coloured: the element's background through the mask in --icon. */
.ic, #hud .cross i, #hud .hitmark i, .feed .gunico, .feed .cause, .feed .head, .ammo .gun, .ammo .rico, .ammo .nades i, .ammo .hico, .stat .ico, .stat .sico, .stat .status i,
.note i, .center-msg .spin, .tip i, .voicebar i, .topbar .clock .time, .radar .cone, .radar .me, .radar .blips i.mate, .radar .blips i.foe, .gren b, .killmark::after,
.deathcard .skull, .deathcard .gun, .scores .hi, .classmenu .cls .gun, .rack .guns i {
	-webkit-mask: var(--icon) center / contain no-repeat; mask: var(--icon) center / contain no-repeat; }

/* The crosshair: four lines round a dot, opening with the spread (--gap), in the setting's colour and size. */
#hud .cross { position: absolute; left: 50%; top: 50%; width: 0; height: 0; --gap: 0px; --xs: calc(var(--xk, 1) * 1px); filter: drop-shadow(0 0 1px #000) drop-shadow(0 0 1px #000); transition: opacity 0.1s; }
#hud .cross i { position: absolute; background: var(--xc, #fff); }
#hud .cross .ln { --icon: url(/assets/ui/r_line.webp); width: calc(var(--xs) * 11); height: calc(var(--xs) * 4); }
#hud .cross .ln.l { right: calc(var(--xs) * 5 + var(--gap)); top: calc(var(--xs) * -2); }
#hud .cross .ln.r { left: calc(var(--xs) * 5 + var(--gap)); top: calc(var(--xs) * -2); }
#hud .cross .ln.t, #hud .cross .ln.b { left: calc(var(--xs) * -5.5); transform: rotate(90deg); }
#hud .cross .ln.t { bottom: calc(var(--xs) * 9 + var(--gap)); }
#hud .cross .ln.b { top: calc(var(--xs) * 9 + var(--gap)); }
#hud .cross .dot { --icon: url(/assets/ui/r_dot.webp); width: calc(var(--xs) * 4); height: calc(var(--xs) * 4); left: calc(var(--xs) * -2); top: calc(var(--xs) * -2); }
#hud .cross .dot.big { width: calc(var(--xs) * 7); height: calc(var(--xs) * 7); left: calc(var(--xs) * -3.5); top: calc(var(--xs) * -3.5); }
#hud .cross .ring { --icon: url(/assets/ui/r_ring.webp); --d: calc(var(--xs) * 22 + var(--gap) * 2); width: var(--d); height: var(--d); left: calc(var(--d) / -2); top: calc(var(--d) / -2); }
#hud .cross .chev { --icon: url(/assets/ui/r_chev.webp); width: calc(var(--xs) * 14); height: calc(var(--xs) * 14); left: calc(var(--xs) * -7); top: calc(var(--xs) * -2); transform: rotate(90deg); }
/* Hit: four short strokes on the diagonals, red for the head; a kill: the pack's skull pops. */
#hud .hitmark { position: absolute; left: 50%; top: 50%; width: 0; height: 0; opacity: 0; transition: opacity 0.2s; }
#hud .hitmark i { --icon: url(/assets/ui/r_line.webp); position: absolute; width: 12px; height: 4px; margin: -2px 0 0 -6px; background: #fff; filter: drop-shadow(0 0 1px #000); }
#hud .hitmark i:nth-child(1) { transform: rotate(45deg) translateX(12px); }
#hud .hitmark i:nth-child(2) { transform: rotate(135deg) translateX(12px); }
#hud .hitmark i:nth-child(3) { transform: rotate(225deg) translateX(12px); }
#hud .hitmark i:nth-child(4) { transform: rotate(315deg) translateX(12px); }
#hud .hitmark.on { opacity: 1; transition: none; }
#hud .hitmark.head i { background: var(--bad); width: 15px; }
#hud .killmark { position: absolute; left: 50%; top: 50%; width: 30px; height: 30px; margin: 22px 0 0 -15px; opacity: 0; }
#hud .killmark::before { content: ''; position: absolute; inset: -18px; background: url(/assets/ui/fx_glow.webp) center / contain no-repeat; opacity: 0.55; }
#hud .killmark::after { --icon: url(/assets/ui/h_versus.webp); content: ''; position: absolute; inset: 0; background: #f1ead6; filter: drop-shadow(0 0 2px #000); }
#hud .killmark.on { animation: killpop 0.7s ease-out forwards; }
#hud .killmark.head::after { background: var(--bad); }
#hud .killmark.head::before { filter: sepia(1) saturate(8) hue-rotate(-40deg); }
@keyframes killpop { 0% { opacity: 1; transform: scale(1.8); } 25% { opacity: 1; transform: scale(1); } 75% { opacity: 1; } 100% { opacity: 0; transform: translateY(-6px); } }
/* Where a hit came from: the pack's arc round the middle, turned toward it. */
.dmg { position: absolute; left: 50%; top: 50%; width: 260px; height: 260px; margin: -130px 0 0 -130px; }
.dmg i { position: absolute; left: 50%; top: 0; width: 120px; height: 30px; margin-left: -60px; transform-origin: 60px 130px; filter: drop-shadow(0 0 5px rgba(255, 30, 10, 0.9)); }
.dmg i::before, .dmg i::after { content: ''; position: absolute; inset: 0; -webkit-mask: url(/assets/ui/fx_dmg.webp) center / contain no-repeat; mask: url(/assets/ui/fx_dmg.webp) center / contain no-repeat; }
.dmg i::before { inset: -5px -8px; background: rgba(90, 0, 0, 0.7); -webkit-mask-image: url(/assets/ui/fx_dmg_base.webp); mask-image: url(/assets/ui/fx_dmg_base.webp); }
.dmg i::after { background: #ff3a22; }
/* Badly hurt: red at the edges and the pack's blood up the sides. */
.hurt { position: absolute; inset: 0; pointer-events: none; opacity: 0; transition: opacity 0.35s;
	background: radial-gradient(ellipse at center, transparent 50%, rgba(110, 6, 0, 0.5) 80%, rgba(90, 0, 0, 0.85) 100%); }
.hurt i { position: absolute; top: 0; bottom: 0; width: 22vh; background: url(/assets/ui/fx_blood1.webp) center / 100% 100% no-repeat; filter: sepia(1) saturate(9) hue-rotate(-40deg) brightness(0.55); opacity: 0.85; }
.hurt .bl { left: 0; }
.hurt .br { right: 0; background-image: url(/assets/ui/fx_blood2.webp); transform: scaleX(-1); }
/* Live grenades close by: the pack's warning round the crosshair, on their side. */
.gren { position: absolute; left: 50%; top: 50%; width: 0; height: 0; }
.gren i { position: absolute; left: -22px; top: -22px; width: 44px; height: 44px; transform-origin: 22px 22px; }
.gren b { --icon: url(/assets/ui/i_grenade.webp); position: absolute; left: 4px; top: -106px; width: 36px; height: 36px; background: #ff5a3a; filter: drop-shadow(0 0 2px #000) drop-shadow(0 0 6px rgba(255, 60, 30, 0.8)); animation: pulse 0.5s infinite; }
.gren i::before { content: ''; position: absolute; left: 6px; top: -128px; width: 32px; height: 18px; background: #ff6a4a; -webkit-mask: url(/assets/ui/h_bearing.webp) center / contain no-repeat; mask: url(/assets/ui/h_bearing.webp) center / contain no-repeat; }

/* The capture points along the top: pennants in their holders' colours, filling from the foot for the
   side taking them; a lock when they can't be taken yet; a glow on the one you're in. */
.caps { position: absolute; top: calc(6px + var(--sat)); left: 50%; transform: translateX(-50%); display: flex; gap: 4px; }
.caps .cap { position: relative; width: 70px; display: grid; justify-items: center; text-align: center; }
.caps .cap b { position: relative; isolation: isolate; display: grid; place-items: center; width: 36px; height: 40px; padding-bottom: 7px; font-size: 18px; font-weight: 800; line-height: 1; color: #fff; text-shadow: 0 1px 2px #000, 0 0 3px #000; }
.caps .cap b::before, .caps .cap b::after { content: ''; position: absolute; inset: 0; z-index: -1; -webkit-mask: url(/assets/ui/h_flag.webp) center / contain no-repeat; mask: url(/assets/ui/h_flag.webp) center / contain no-repeat; }
.caps .cap b::before { background: linear-gradient(180deg, rgba(255, 255, 255, 0.18), transparent 40%), var(--c, #3a3a30); filter: drop-shadow(0 1px 1px #000); }
.caps .cap.allies b { --c: #5f8a37; } .caps .cap.axis b { --c: #6e7c86; } .caps .cap.neutral b { --c: #46443a; }
.caps .cap[data-by=allies] b::after { background: linear-gradient(0deg, rgba(143, 191, 90, 0.95) var(--p), transparent var(--p)); }
.caps .cap[data-by=axis] b::after { background: linear-gradient(0deg, rgba(169, 182, 191, 0.95) var(--p), transparent var(--p)); }
.caps .cap span { display: block; max-width: 100%; margin-top: 1px; font-size: 9px; letter-spacing: 0.08em; text-transform: uppercase; opacity: 0.9; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-shadow: 0 1px 2px #000; }
.caps .cap.contested b { animation: pulse 0.6s infinite; }
.caps .cap.locked { opacity: 0.7; }
.caps .cap.locked::after { content: ''; position: absolute; right: 10px; top: 0; width: 12px; height: 12px; background: #ddd; filter: drop-shadow(0 0 1px #000); -webkit-mask: url(/assets/ui/m_lock.webp) center / contain no-repeat; mask: url(/assets/ui/m_lock.webp) center / contain no-repeat; }
.caps .cap.here b { filter: drop-shadow(0 0 4px var(--gold)) drop-shadow(0 0 1px var(--gold)); }
/* The compass: a strip scrolled under the pack's bearing, the points on it as squares in their colours. */
.compass { position: absolute; top: calc(70px + var(--sat)); left: 50%; width: 320px; height: 28px; margin-left: -160px; overflow: hidden;
	background: url(/assets/ui/h_line.webp) center bottom / 100% 6px no-repeat, linear-gradient(180deg, rgba(8, 10, 8, 0.15), rgba(8, 10, 8, 0.55));
	-webkit-mask: linear-gradient(90deg, transparent, #000 18%, #000 82%, transparent); mask: linear-gradient(90deg, transparent, #000 18%, #000 82%, transparent); }
.compass .strip { position: absolute; left: 0; top: 0; height: 100%; width: 2880px; }
.compass .strip span { position: absolute; top: 0; transform: translateX(-50%); font-size: 12px; }
.compass .strip .tick { width: 4px; height: 8px; background: rgba(255, 255, 255, 0.6); -webkit-mask: url(/assets/ui/h_tick.webp) center / contain no-repeat; mask: url(/assets/ui/h_tick.webp) center / contain no-repeat; }
.compass .strip .lab { top: 6px; font-weight: 700; }
.compass .strip .mark, .radar .blips i.obj { isolation: isolate; font-weight: 800; text-align: center; color: #111; text-shadow: none; }
.compass .strip .mark::before, .radar .blips i.obj::before { content: ''; position: absolute; inset: 0; z-index: -1; background: var(--c); -webkit-mask: url(/assets/ui/h_obj.webp) center / contain no-repeat; mask: url(/assets/ui/h_obj.webp) center / contain no-repeat; }
.compass .strip .mark.neutral, .radar .blips i.obj.neutral { color: var(--neutral); text-shadow: 0 1px 1px #000; }
.compass .strip .mark.neutral::before, .radar .blips i.obj.neutral::before { -webkit-mask-image: url(/assets/ui/h_obj_off.webp); mask-image: url(/assets/ui/h_obj_off.webp); }
.compass .strip .mark { top: 12px; width: 15px; height: 15px; font-size: 10px; line-height: 15px; }
.compass .strip .mark.allies { --c: var(--allies); } .compass .strip .mark.axis { --c: var(--axis); } .compass .strip .mark.neutral { --c: var(--neutral); }
.compass .pin { position: absolute; left: 50%; top: 0; width: 12px; height: 8px; margin-left: -6px; background: var(--accent); transform: rotate(180deg); -webkit-mask: url(/assets/ui/h_bearing.webp) center / contain no-repeat; mask: url(/assets/ui/h_bearing.webp) center / contain no-repeat; }
/* The sides' scores either side of the clock: trapezoid headers in their colours; the clock in a gunmetal
   bar, the pack's red clock when a minute's left. */
.topbar { position: absolute; top: calc(102px + var(--sat)); left: 50%; transform: translateX(-50%); display: flex; gap: 8px; align-items: center; }
.topbar .clock { position: relative; display: flex; align-items: center; gap: 6px; font-size: 21px; font-weight: 700; font-variant-numeric: tabular-nums; padding: 1px 6px; border: 12px solid transparent; border-image: url(/assets/ui/mc_bar.webp) 30 fill / 12px; }
.topbar .clock.low { color: #ff8a70; animation: pulse 1s infinite; }
.topbar .clock .time { --icon: url(/assets/ui/h_time.webp); width: 20px; height: 20px; background: #e04a3a; }
.topbar .team { position: relative; isolation: isolate; min-width: 96px; text-align: center; padding: 5px 18px 6px; line-height: 1; }
.topbar .team::before { content: ''; position: absolute; inset: 0; z-index: -1; background: linear-gradient(180deg, rgba(255, 255, 255, 0.2), transparent 50%), var(--c); opacity: 0.9;
	-webkit-mask: url(/assets/ui/h_header_trap.webp) center / 100% 100% no-repeat; mask: url(/assets/ui/h_header_trap.webp) center / 100% 100% no-repeat; }
.topbar .team.red { --c: #4f7a2a; } .topbar .team.blue { --c: #5e6c76; }
.topbar .team b { font-size: 24px; font-weight: 800; }
.topbar .flagst { font-size: 9px; letter-spacing: 0.18em; text-transform: uppercase; display: block; margin-top: 1px; opacity: 0.9; }

/* The radar, top left: the pack's big gunmetal dial round a dark disc, its range ring, the view's cone,
   you; your squad in green, an enemy heard firing in red, the points in their colours (at the rim when
   further than it reaches); an aerial and dials bolted on. */
.radar { position: absolute; left: calc(14px + var(--sal)); top: calc(12px + var(--sat)); width: 184px; height: 184px; }
.radar .disc { position: absolute; left: 17px; top: 17px; width: 150px; height: 150px; border-radius: 50%; overflow: hidden;
	background: url(/assets/ui/h_ring.webp) center / 52% no-repeat, radial-gradient(circle, rgba(30, 38, 24, 0.55), rgba(8, 12, 8, 0.82) 70%); }
.radar .disc::after { content: ''; position: absolute; inset: 0; background: url(/assets/ui/h_ring.webp) center / 100% no-repeat; opacity: 0.25; }
.radar::before { content: ''; position: absolute; inset: 0; z-index: 1; background: url(/assets/ui/mc_dial.webp) center / contain no-repeat; }
.radar .aerial { position: absolute; right: 6px; top: -34px; width: 28px; height: 62px; background: url(/assets/ui/mc_antenna.webp) center bottom / contain no-repeat; transform: rotate(18deg); }
.radar .cone { --icon: url(/assets/ui/m_cone.webp); position: absolute; left: 50%; top: 50%; width: 120px; height: 110px; margin: -110px 0 0 -60px; background: linear-gradient(0deg, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0)); }
.radar .me { --icon: url(/assets/ui/m_player.webp); position: absolute; left: 50%; top: 50%; width: 16px; height: 16px; margin: -8px 0 0 -8px; background: var(--gold); filter: drop-shadow(0 0 1px #000); }
.radar .blips { position: absolute; left: 50%; top: 50%; width: 0; height: 0; }
.radar .blips i { position: absolute; display: block; font-style: normal; }
.radar .blips i.mate { --icon: url(/assets/ui/m_dot.webp); width: 9px; height: 9px; margin: -4.5px 0 0 -4.5px; background: var(--allies); }
.radar .blips i.foe { --icon: url(/assets/ui/m_dot.webp); width: 10px; height: 10px; margin: -5px 0 0 -5px; background: #ff4a3a; }
.radar .blips i.obj { width: 15px; height: 15px; margin: -7.5px 0 0 -7.5px; font-size: 10px; line-height: 15px; }
.radar .blips i.obj.allies { --c: var(--allies); } .radar .blips i.obj.axis { --c: var(--axis); } .radar .blips i.obj.neutral { --c: var(--neutral); }
/* The points out in the world: the pack's hexagon in their colours, the letter in it, how far under it. */
.markers { position: absolute; inset: 0; }
.markers .wm { position: absolute; left: 0; top: 0; width: 34px; margin: -17px 0 0 -17px; display: grid; justify-items: center; }
.markers .wm b { position: relative; isolation: isolate; display: grid; place-items: center; width: 34px; height: 34px; font-size: 15px; font-weight: 800; color: #fff; text-shadow: 0 1px 2px #000; }
.markers .wm b::before { content: ''; position: absolute; inset: 0; z-index: -1; background: var(--c); filter: drop-shadow(0 0 2px #000); -webkit-mask: url(/assets/ui/h_world.webp) center / contain no-repeat; mask: url(/assets/ui/h_world.webp) center / contain no-repeat; }
.markers .wm span { font-size: 11px; font-weight: 600; white-space: nowrap; }
.markers .wm.allies { --c: var(--allies); } .markers .wm.axis { --c: var(--axis); } .markers .wm.neutral { --c: var(--neutral); }
.markers .wm.taking b::before { animation: pulse 0.6s infinite; }

/* Health, bottom left, on a gunmetal bar: the pack's heart, the number, its bar (green, amber, red),
   stamina under it with the pack's runner; what ails or helps you over it. The stance in a gunmetal box. */
.vitals { position: absolute; left: calc(20px + var(--sal)); bottom: calc(18px + var(--sab)); display: flex; gap: 8px; align-items: flex-end; }
.vitals .stance { display: grid; justify-items: center; align-content: center; gap: 2px; width: 62px; height: 62px; background: url(/assets/ui/mc_box.webp) center / 100% 100% no-repeat; }
.vitals .stance svg { width: 28px; height: 28px; fill: var(--text); }
.vitals .stance span { font-size: 8px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }
.stat { position: relative; display: grid; grid-template-columns: auto 1fr; grid-template-rows: auto auto auto; column-gap: 10px; align-items: center; width: 230px; padding: 4px 8px 6px; border: 12px solid transparent; border-image: url(/assets/ui/mc_bar.webp) 30 fill / 12px; }
.stat .ico { --icon: url(/assets/ui/s_health.webp); grid-row: 1; width: 26px; height: 26px; background: var(--hp); }
.stat .v { font-size: 38px; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums; }
.stat.low .v { color: var(--bad); animation: pulse 0.8s infinite; }
.stat.low .ico { background: var(--bad); }
.stat::before { content: ''; position: absolute; left: -4px; right: -4px; bottom: calc(100% + 4px); height: 14px; background: url(/assets/ui/mc_plate.webp) left bottom / 100% 100% no-repeat; opacity: 0.95; }
.stat .hbar { grid-column: 1 / 3; height: 9px; margin-top: 4px; background: rgba(255, 255, 255, 0.12); -webkit-mask: url(/assets/ui/h_bar.webp) left / 100% 100%; mask: url(/assets/ui/h_bar.webp) left / 100% 100%; }
.stat .hbar i { display: block; height: 100%; width: 100%; background: var(--hp); transition: width 0.15s; }
.stat .stamina { grid-column: 1 / 3; display: flex; align-items: center; gap: 5px; margin-top: 4px; }
.stat .stamina .sico { --icon: url(/assets/ui/st_speed.webp); width: 12px; height: 12px; background: #d9c98f; flex: none; }
.stat .stamina b { flex: 1; height: 5px; background: rgba(255, 255, 255, 0.12); -webkit-mask: url(/assets/ui/h_trap.webp) left / 100% 100%; mask: url(/assets/ui/h_trap.webp) left / 100% 100%; }
.stat .stamina b i { display: block; height: 100%; width: 100%; background: #d9c98f; transition: width 0.1s linear; }
.stat .stamina.low b i, .stat .stamina.low .sico { background: var(--bad); }
.stat .status { position: absolute; left: 0; bottom: calc(100% + 24px); display: flex; gap: 5px; }
.stat .status i { width: 22px; height: 22px; background: #f0e6c8; filter: drop-shadow(0 0 2px #000); }
.stat .status .s-critical { --icon: url(/assets/ui/s_critical.webp); background: var(--bad); animation: pulse 0.8s infinite; }
.stat .status .s-bleeding { --icon: url(/assets/ui/s_bleeding.webp); background: var(--bad); animation: pulse 0.5s infinite; }
.stat .status .s-defense { --icon: url(/assets/ui/s_defense.webp); background: #8fc3ff; }
.stat .status .s-speed { --icon: url(/assets/ui/s_speed.webp); background: #d9c98f; }
.stat .status .s-burning { --icon: url(/assets/ui/s_burning.webp); background: #ff8a3a; }
/* The magazine, bottom right, on a gunmetal bar with the pack's rifle plate over it: the gun, the rounds
   (red, on warning stripes, when it's nearly empty), the reserve by its rounds' icon, grenades; a machine
   gun's heat. */
.ammo { position: absolute; right: calc(20px + var(--sar)); bottom: calc(18px + var(--sab)); display: grid; grid-template-columns: auto auto; grid-template-rows: auto auto auto; column-gap: 12px; align-items: center; justify-items: end; padding: 4px 8px 6px 12px; border: 12px solid transparent; border-image: url(/assets/ui/mc_bar.webp) 30 fill / 12px; }
.ammo::before { content: ''; position: absolute; left: 4px; right: 4px; bottom: calc(100% + 4px); height: 24px; background: url(/assets/ui/mc_plate_gun.webp) right bottom / contain no-repeat; opacity: 0.95; }
.ammo .gun { grid-row: 1 / 3; width: 104px; height: 40px; background: var(--text); opacity: 0.9; }
.ammo .v { font-size: 38px; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums; padding: 0 4px; }
.ammo.low .v { color: #ff6a50; background: url(/assets/ui/h_hazard.webp) center / 14px 14px; background-color: rgba(60, 0, 0, 0.5); }
.ammo .res { display: flex; align-items: center; gap: 4px; font-size: 13px; font-weight: 600; color: var(--muted); font-variant-numeric: tabular-nums; }
.ammo .res .rico { width: 14px; height: 14px; background: var(--muted); --icon: url(/assets/ui/i_bullets.webp); }
.ammo .res[data-kind=sniper] .rico { --icon: url(/assets/ui/i_sniper.webp); }
.ammo .res[data-kind=rocket] .rico { --icon: url(/assets/ui/i_rocket.webp); }
.ammo .res[data-kind=''] .rico { display: none; }
.ammo .nades { grid-column: 1 / 3; display: flex; gap: 3px; justify-content: flex-end; min-height: 16px; }
.ammo .nades i { --icon: url(/assets/ui/i_grenade.webp); width: 16px; height: 16px; background: #a9b46c; }
.ammo .nades i.smoke { --icon: url(/assets/ui/i_smoke.webp); background: #d6d6cc; }
.ammo .heat { grid-column: 1 / 3; display: flex; align-items: center; gap: 5px; width: 100%; }
.ammo .heat .hico { --icon: url(/assets/ui/s_burning.webp); width: 13px; height: 13px; background: #d9a441; flex: none; }
.ammo .heat b { flex: 1; height: 5px; background: rgba(255, 255, 255, 0.12); }
.ammo .heat b i { display: block; height: 100%; background: linear-gradient(90deg, #d9a441, #ff5a2a); }
.ammo .heat.hot .hico { background: #ff5a2a; animation: pulse 0.4s infinite; }

/* The kill feed, top right: rows fading in from the left, the gun between the names, the pack's skull for
   a head shot, its icons for a rifle butt, a fall and the rest. */
.feed { position: absolute; right: calc(20px + var(--sar)); top: calc(14px + var(--sat)); display: grid; gap: 4px; justify-items: end; font-size: 14px; }
.feed div { display: flex; align-items: center; gap: 8px; padding: 3px 10px 3px 30px; border-right: 3px solid var(--accent); animation: fadein 0.15s;
	background: linear-gradient(90deg, transparent, rgba(8, 10, 8, 0.7) 30%, rgba(8, 10, 8, 0.8)); }
.feed .gunico { display: inline-block; width: 52px; height: 22px; background: #fff; }
.feed .cause { display: inline-block; width: 18px; height: 18px; background: #e8dfc4; }
.feed .head { --icon: url(/assets/ui/m_skull.webp); display: inline-block; width: 16px; height: 16px; margin-left: -4px; background: var(--bad); }
.feed .me { border-color: var(--gold); background: linear-gradient(90deg, transparent, rgba(80, 64, 20, 0.6) 30%, rgba(90, 72, 22, 0.75)); }
/* Big news across the middle: on the pack's angled banner, with a badge over it (a promotion, a run of kills). */
.announce { position: absolute; top: 22%; left: 0; right: 0; display: grid; justify-items: center; gap: 4px; text-align: center; }
.announce .badge { width: 72px; height: 72px; object-fit: contain; filter: drop-shadow(0 2px 6px #000); animation: killpop 3s ease-out forwards; animation-name: badgepop; }
@keyframes badgepop { 0% { opacity: 0; transform: scale(2); } 12% { opacity: 1; transform: scale(1); } 100% { opacity: 1; } }
.announce .banner { position: relative; isolation: isolate; padding: 6px 60px 8px; font-size: 28px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: #fff; text-shadow: 0 0 18px rgba(210, 171, 92, 0.7), 0 2px 3px #000; }
.announce .banner::before { content: ''; position: absolute; inset: 0; z-index: -1; background: linear-gradient(90deg, transparent, rgba(10, 12, 8, 0.75) 22%, rgba(10, 12, 8, 0.75) 78%, transparent); }
.announce .banner::after { content: ''; position: absolute; left: 10%; right: 10%; bottom: 0; height: 6px; background: var(--accent); opacity: 0.8; -webkit-mask: url(/assets/ui/h_line.webp) center / 100% 100% no-repeat; mask: url(/assets/ui/h_line.webp) center / 100% 100% no-repeat; }
.announce .sub { display: block; font-size: 15px; letter-spacing: 0.12em; opacity: 0.85; font-weight: 600; }
/* Coming back: the pack's spinner and how long. A note under the crosshair with its status icon. */
.center-msg { position: absolute; top: 60%; left: 0; right: 0; display: flex; justify-content: center; align-items: center; gap: 10px; font-size: 18px; letter-spacing: 0.08em; }
.center-msg .spin { --icon: url(/assets/ui/h_load.webp); width: 26px; height: 26px; background: var(--accent); animation: spin 1.4s linear infinite; }
.note { position: absolute; top: calc(50% + 46px); left: 0; right: 0; display: flex; justify-content: center; align-items: center; gap: 6px; font-size: 13px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--gold); }
.note i { width: 16px; height: 16px; background: var(--gold); }
.note .s-defense { --icon: url(/assets/ui/s_defense.webp); } .note .s-burning { --icon: url(/assets/ui/s_burning.webp); background: #ff8a3a; }
.note .s-targeted { --icon: url(/assets/ui/s_targeted.webp); } .note .s-critical { --icon: url(/assets/ui/s_critical.webp); }
/* Dead: who killed you, on a gunmetal panel: the pack's skull, his rank and name, the gun, how far. */
.deathcard { position: absolute; left: 50%; top: calc(60% + 34px); transform: translateX(-50%); display: grid; grid-template-columns: auto auto auto; grid-template-rows: auto auto; column-gap: 14px; align-items: center; padding: 0 8px 2px; border: 16px solid transparent; border-image: url(/assets/ui/mc_card.webp) 28 fill / 12px; animation: fadein 0.3s; }
.deathcard .skull { --icon: url(/assets/ui/h_versus.webp); grid-row: 1 / 3; width: 34px; height: 34px; background: var(--bad); }
.deathcard .who { display: grid; }
.deathcard .who .k { font-size: 10px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted); }
.deathcard .who b { display: flex; align-items: center; gap: 6px; font-size: 20px; font-weight: 800; }
.deathcard .who b.allies { color: var(--allies); } .deathcard .who b.axis { color: var(--axis); }
.deathcard .who .rank { width: 22px; height: 22px; object-fit: contain; }
.deathcard .gun { grid-row: 1 / 3; width: 90px; height: 32px; background: var(--text); }
.deathcard .cause { grid-row: 1 / 3; font-size: 14px; color: var(--muted); }
.deathcard .how { grid-column: 2; display: flex; gap: 10px; font-size: 12px; color: var(--muted); }
.deathcard .how .head { color: var(--bad); font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; }
/* Tips for new players: low in the middle, one at a time, on the pack's dog-eared box with its "!". */
.tip { position: absolute; bottom: 19%; left: 50%; transform: translate(-50%, 8px); display: flex; align-items: center; gap: 10px; max-width: min(560px, 80vw); padding: 2px 6px;
	border: 10px solid transparent; border-image: url(/assets/ui/mc_card.webp) 28 fill / 10px; color: #efe6cf; font-size: 15px; line-height: 1.35;
	opacity: 0; transition: opacity 0.4s, transform 0.4s; pointer-events: none; }
.tip i { --icon: url(/assets/ui/h_tip.webp); flex: none; width: 24px; height: 24px; background: var(--gold); }
.tip.on { opacity: 1; transform: translate(-50%, 0); }
/* Chat and voice. */
.chatlog { position: absolute; left: calc(22px + var(--sal)); bottom: calc(130px + var(--sab)); width: min(520px, 60vw); display: grid; gap: 3px; font-size: 15px; }
.chatlog div { animation: fadein 0.15s; }
.chatlog .who { font-weight: 700; }
.chatlog .sys { color: var(--muted); font-style: italic; }
.chatlog .teamtag { color: var(--gold); }
.chatbox { position: absolute; left: calc(22px + var(--sal)); bottom: calc(100px + var(--sab)); width: min(520px, 60vw); pointer-events: auto; display: flex; gap: 8px; align-items: center; border: 10px solid transparent; border-image: url(/assets/ui/mc_card.webp) 28 fill / 10px; padding: 0 3px; }
.chatbox input { flex: 1; background: transparent; border: 0; outline: none; font-size: 15px; font-family: var(--hud); }
.voicebar { position: absolute; left: calc(22px + var(--sal)); top: 50%; display: grid; gap: 4px; font-size: 13px; }
.voicebar div { display: flex; align-items: center; gap: 6px; padding: 3px 10px; border-left: 3px solid var(--good); background: url(/assets/ui/fx_scan.webp) center / 100% 100%, rgba(0, 0, 0, 0.5); }
.voicebar i { --icon: url(/assets/ui/h_sound.webp); width: 14px; height: 14px; background: var(--good); }
.net { position: absolute; left: calc(14px + var(--sal)); top: calc(212px + var(--sat)); font-family: var(--mono); font-size: 12px; color: var(--muted); }
.spec { position: absolute; bottom: calc(118px + var(--sab)); left: 0; right: 0; text-align: center; font-size: 16px; letter-spacing: 0.1em; }
.charge { position: absolute; left: 50%; top: calc(50% + 26px); transform: translateX(-50%); width: 80px; height: 4px; background: rgba(255, 255, 255, 0.15); }
.charge i { display: block; height: 100%; background: var(--accent); }
.loading { position: fixed; inset: 0; display: grid; place-items: center; align-content: center; gap: 14px; background: var(--bg); font-family: var(--hud); font-size: 14px; letter-spacing: 0.2em; text-transform: uppercase; color: var(--muted); }
.loading::before { content: ''; width: 44px; height: 44px; background: var(--accent); animation: spin 1.4s linear infinite; -webkit-mask: url(/assets/ui/h_load.webp) center / contain no-repeat; mask: url(/assets/ui/h_load.webp) center / contain no-repeat; }

/* A scope: black past the lens, the pack's vignette shading its rim, and the reticle in its tapering
   arms: the German scope's three posts (the top one missing); the M1C's fine crosshair over a post. */
.scope { position: absolute; inset: 0; background: radial-gradient(circle at 50% 50%, transparent 0 35.2vh, #000 35.6vh); }
.scope .vig { position: absolute; left: 50%; top: 50%; width: 72vh; height: 72vh; margin: -36vh 0 0 -36vh; background: #000; opacity: 0.9; -webkit-mask: url(/assets/ui/v_scope.webp) center / 100% 100%; mask: url(/assets/ui/v_scope.webp) center / 100% 100%; }
.scope .ret { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); overflow: hidden; border-radius: 50%; }
.scope .ret .wire { stroke: #080808; stroke-width: 1.3px; shape-rendering: crispEdges; }
.scope .ret .post { fill: #080808; }
.scope .ret .mark { fill: #101010; font: 700 9px var(--font); }

/* The class picker, in the pack's gunmetal: a card for each class with its insignia (shield, rim, emblem),
   the chosen one lit; a full one crossed out. */
.classmenu { position: absolute; left: 50%; top: 20%; transform: translateX(-50%); width: min(840px, 94vw); pointer-events: auto; cursor: url(/assets/ui/mc_pointer.png) 2 2, default; font-family: var(--hud); border: 30px solid transparent; border-width: 36px 26px 26px; padding: 4px 8px 8px; border-image: var(--frame); }
.classmenu h3 { margin: 0 0 12px; font-size: 15px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--accent-2); }
.classmenu .classes { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 6px; }
.classmenu .cls { position: relative; appearance: none; text-align: left; display: grid; grid-template-columns: 1fr auto; gap: 3px 6px; padding: 2px 4px; border: 12px solid transparent; border-image: url(/assets/ui/mc_card.webp) 28 fill / 12px; background: none; cursor: inherit; color: var(--text); font-family: var(--hud); }
.classmenu .cls > * { grid-column: 1; }
.classmenu .cls .ins { grid-column: 2; grid-row: 1 / 4; width: 46px; height: 52px; object-fit: contain; filter: drop-shadow(0 2px 3px #000); }
.classmenu .cls:hover { filter: brightness(1.2); }
.classmenu .cls.on { border-image-source: url(/assets/ui/mc_card_on.webp); }
.classmenu .cls.full { cursor: default; }
.classmenu .cls.full > * { opacity: 0.4; }
.classmenu .cls.full::after { content: ''; position: absolute; right: -2px; top: 2px; width: 40px; height: 40px; background: var(--bad); -webkit-mask: url(/assets/ui/x_off.webp) center / contain no-repeat; mask: url(/assets/ui/x_off.webp) center / contain no-repeat; }
.classmenu .cls b { font-size: 11px; color: var(--muted); }
.classmenu .cls .n { font-size: 16px; font-weight: 700; }
.classmenu .cls .kit { grid-column: 1 / 3; font-size: 12px; color: var(--muted); }
.classmenu .cls .cnt { grid-column: 1 / 3; font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
.classmenu .cls .gun { display: block; height: 30px; background: var(--accent-2); -webkit-mask-position: left center; mask-position: left center; }
/* The scoreboard, in the pack's gunmetal: each side under its colour and flag, each man's rank insignia,
   the best man's wreath, the columns' icons. */
.scores { position: absolute; left: 50%; top: 12%; transform: translateX(-50%); width: min(920px, 94vw); font-family: var(--hud); border: 30px solid transparent; border-width: 36px 26px 26px; padding: 2px 8px 6px; border-image: var(--frame); }
.scores h3 { margin: 0 0 10px; letter-spacing: 0.14em; text-transform: uppercase; font-size: 15px; display: flex; justify-content: space-between; }
.scores table { width: 100%; border-collapse: collapse; font-size: 14px; }
.scores td, .scores th { padding: 4px 8px; text-align: left; font-variant-numeric: tabular-nums; }
.scores th { color: var(--muted); font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; white-space: nowrap; }
.scores .hi { display: inline-block; width: 12px; height: 12px; margin-right: 4px; vertical-align: -2px; background: var(--muted); }
.scores .hi.score { --icon: url(/assets/ui/m_star.webp); } .scores .hi.deaths { --icon: url(/assets/ui/h_versus.webp); } .scores .hi.ping { --icon: url(/assets/ui/i_comms.webp); }
.scores tr.me td { background: rgba(210, 171, 92, 0.22); }
.scores tr:nth-child(2n + 3) td { background-color: rgba(255, 255, 255, 0.035); }
.scores td:first-child { white-space: nowrap; }
.scores .rk { display: inline-block; width: 20px; height: 18px; margin-right: 6px; vertical-align: -4px; text-align: center; }
.scores .rank { width: 20px; height: 18px; object-fit: contain; }
.scores .best { width: 22px; height: 18px; margin-left: 5px; vertical-align: -4px; object-fit: contain; }
.scores .cols { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.scores .teamhead { position: relative; isolation: isolate; justify-content: flex-start; gap: 8px; align-items: center; padding: 4px 10px; }
.scores .teamhead::after { content: ''; position: absolute; inset: 0; z-index: -1; background: linear-gradient(90deg, var(--c), transparent); opacity: 0.55; }
.scores .teamhead.red { color: #c7e69a; --c: #4f7a2a; } .scores .teamhead.blue { color: #dfe7ec; --c: #5e6c76; }
.scores .teamhead::before { content: ''; width: 16px; height: 16px; background: currentColor; -webkit-mask: url(/assets/ui/m_flag.webp) center / contain no-repeat; mask: url(/assets/ui/m_flag.webp) center / contain no-repeat; }
/* The firing range: the rack of every gun under the clock (the one in hand lit), what the gun does
   under it, and where rounds hit down the right. */
.rack { position: absolute; left: 50%; top: calc(156px + var(--sat)); transform: translateX(-50%); display: grid; gap: 6px; justify-items: center; pointer-events: none; }
.rack .what { display: flex; flex-wrap: wrap; justify-content: center; column-gap: 10px; align-items: baseline; max-width: min(600px, 52vw); font-size: 11px; line-height: 1.35; text-align: center; color: var(--muted); }
.rack .what b { font-size: 15px; color: var(--accent-2); letter-spacing: 0.06em; }
.rack .what .key { font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; border: 1px solid var(--line-strong); padding: 1px 6px; }
.rack .guns { display: flex; gap: 3px; padding: 2px 4px; border: 10px solid transparent; border-image: url(/assets/ui/mc_bar.webp) 30 fill / 10px; }
.rack .guns i { width: 38px; height: 19px; background: #fff; opacity: 0.35; }
.rack .guns i.on { opacity: 1; background: var(--gold); }
.rangelog { position: absolute; right: calc(22px + var(--sar)); top: 38%; display: grid; gap: 3px; justify-items: end; font-size: 14px; font-variant-numeric: tabular-nums; pointer-events: none; }
.rangelog div { padding: 2px 10px 2px 30px; border-right: 3px solid var(--accent); animation: fadein 0.15s; background: linear-gradient(90deg, transparent, rgba(8, 10, 8, 0.75) 30%); }
.rangelog div.down { color: var(--gold); font-weight: 700; }
.classmenu .classes.guns { grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); }
.classmenu .classes.guns .kit { font-size: 11px; line-height: 1.3; }

/* ---------- controller and touch ---------- */
/* The pad's focus ring in menus (pad.js). */
.padfocus { outline: 2px solid var(--accent); outline-offset: 2px; }
tr.srv.padfocus, .tab.padfocus { outline-offset: -2px; }
tr.srv.padfocus td { background: rgba(210, 171, 92, 0.2); }
.tab.padfocus { color: var(--text); }
.toast { position: fixed; left: 0; right: 0; margin: 0 auto; width: fit-content; top: calc(16px + var(--sat)); z-index: 10; pointer-events: none; display: grid; justify-items: center; gap: 2px; max-width: calc(100vw - 32px);
	padding: 0 10px; text-align: center; border: 9px solid transparent; border-image: url(/assets/ui/field.webp) 18 fill / 9px; animation: fadein 0.15s; }
.toast b { font-size: 13px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--accent-2); }
.toast span { font-size: 12px; color: var(--muted); }
/* On-screen controls; touch.js places and sizes the buttons: the pack's gunmetal dials, FIRE in red. */
#touch { position: fixed; inset: 0; touch-action: none; font-family: var(--hud); }
#touch .tsafe { position: absolute; visibility: hidden; padding: var(--sat) var(--sar) var(--sab) var(--sal); }
.tbtn { position: absolute; display: grid; place-items: center; isolation: isolate; font-size: 11px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
	color: rgba(255, 255, 255, 0.9); text-shadow: 0 1px 2px #000; }
.tbtn::before { content: ''; position: absolute; z-index: -1; inset: 0; background: url(/assets/ui/mc_dial_btn.webp) center / 100% 100% no-repeat; opacity: 0.85; }
.tbtn.on::before { opacity: 1; filter: brightness(1.7) sepia(0.6); }
/* By data-a, not class: .scores already means the scoreboard. */
.tbtn[data-a=fire] { font-size: 15px; }
.tbtn[data-a=fire]::before { background-image: url(/assets/ui/mc_dial_fire.webp); opacity: 0.9; }
.tbtn[data-a=menu], .tbtn[data-a=scores] { font-size: 9px; opacity: 0.8; }
.tstick { position: absolute; left: 0; top: 0; width: calc(var(--r) * 2); height: calc(var(--r) * 2); margin: calc(var(--r) * -1) 0 0 calc(var(--r) * -1); border-radius: 50%; pointer-events: none;
	background: url(/assets/ui/h_ring.webp) center / 100% no-repeat, radial-gradient(circle, rgba(8, 11, 16, 0.1), rgba(8, 11, 16, 0.4)); }
.tstick i { position: absolute; left: 50%; top: 50%; width: 56px; height: 56px; margin: -28px 0 0 -28px; background: url(/assets/ui/mc_dial_btn.webp) center / contain no-repeat; }
.tstick.idle { opacity: 0.3; }
/* Thumbs own the bottom corners and the top left: the ammo to the middle, the radar smaller under the buttons. */
.touch-on #hud .ammo { right: 50%; bottom: calc(8px + var(--sab)); transform: translateX(50%) scale(0.8); transform-origin: 50% 100%; }
.touch-on #hud .vitals { bottom: calc(8px + var(--sab)); transform: scale(0.8); transform-origin: 0 100%; }
.touch-on #hud .radar { top: calc(64px + var(--sat)); transform: scale(0.62); transform-origin: 0 0; }
.touch-on #hud .rack { top: calc(132px + var(--sat)); }
@media (max-width: 700px) {
	.stat .v, .ammo .v { font-size: 30px; }
	.stat { width: 180px; }
	.setting { grid-template-columns: 1fr; }
	.radar { transform: scale(0.7); transform-origin: 0 0; }
}

/* Short screens (a phone on its side): the class picker in one row, the scoreboard tighter, both up top. */
@media (max-height: 520px) {
	.classmenu, .scores { top: calc(52px + var(--sat)); }
	.classmenu h3 { margin-bottom: 6px; }
	.classmenu .classes { grid-template-columns: repeat(auto-fit, minmax(104px, 1fr)); gap: 4px; }
	.classmenu .cls { gap: 1px; }
	.classmenu .cls .gun { height: 22px; }
	.classmenu .cls .n { font-size: 14px; }
	.classmenu .cls .kit { display: none; }
	.classmenu p { display: none; }
	.scores td, .scores th { padding: 2px 6px; }
	.scores td:nth-child(2), .scores th:nth-child(2), .scores td .muted.small { display: none; }
	.scores h3 { margin-bottom: 4px; }
}
@media (max-width: 700px) {
	.rack .guns i { width: 26px; height: 14px; }
	.rack .what span:not(.key) { display: none; }
}
