/* Soldat TV (spectate.html): the look of Soldat 1.7's own menus (slate panels, flat green buttons, Play) */
@font-face {
  font-family: "Play";
  src: url("play-regular.ttf") format("truetype");
  font-display: swap;
}
:root {
  --bg: #313d4f;           /* the menu background */
  --panel: #3d4b61;        /* fields, lists, the raised tab */
  --deep: #2c3341;         /* the tab strip, list headers */
  --tab: #2d3342;          /* tabs that are not selected */
  --row: #3c4b61;
  --row-alt: #303e54;
  --row-hover: #475a76;
  --line: #4a5a72;
  --text: #e9e9e9;
  --muted: #a3adbb;
  --dim: #6c7c92;
  --green: #3c8e37;        /* buttons, radio dots, progress */
  --green-hi: #47a241;
  --green-lo: #377531;
  --green-text: #cfffce;
  --orange: #ff8728;       /* the outline of the selected server */
  --alpha: #d8473a;        /* team shirts of the game, a little brighter */
  --bravo: #3f74e0;
  --charlie: #d6c33a;
  --delta: #3fb35a;
  --alpha-text: #ff8a7e;   /* the team colours on dark panels */
  --bravo-text: #8ab0ff;
  --charlie-text: #f4e27a;
  --delta-text: #8ee09e;
  --glass: rgba(45, 54, 70, .9);
  --kill: #7fdc52;         /* the game's killer and death colours, for dark panels */
  --death: #ff6b5e;
  --chat: #effeea;         /* the console's chat, team chat and server colours */
  --teamchat: #feda7c;
  --server: #fbda22;
  color-scheme: dark;
}
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; background: var(--bg); color: var(--text);
  font: 14px/1.45 "Play", system-ui, -apple-system, "Segoe UI", sans-serif; -webkit-text-size-adjust: 100%; }
[hidden] { display: none !important; }
/* read out and indexed, not shown */
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; }
/* a link to a match: the loading screen until the page script takes over */
html.direct #guide { display: none !important; }
html.direct #loading { display: grid !important; }
a { color: inherit; }
button, input { font: inherit; color: inherit; }
button { cursor: pointer; }
:focus-visible { outline: 1px solid var(--orange); outline-offset: 1px; }
kbd { display: inline-block; min-width: 1.7em; padding: 0 .35em; background: var(--tab); border: 1px solid var(--line);
  font: 12px/1.6 "Play", monospace; text-align: center; color: var(--text); }
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: var(--deep); }
::-webkit-scrollbar-thumb { background: var(--line); border: 3px solid var(--deep); }
* { scrollbar-color: var(--line) var(--deep); }

/* flat green, like Join Game and Start Game */
.btn { background: var(--green); border: 0; color: #f2f2f2; padding: 6px 22px; min-height: 30px; }
.btn:hover { background: var(--green-hi); }
.btn:active { background: var(--green-lo); }

/* ---------- logo ---------- */
.logo { display: inline-flex; align-items: center; gap: 8px; text-decoration: none; line-height: 1; user-select: none; }
.logo-icon { width: 22px; height: 22px; border-radius: 3px; }
.logo-word { font-size: 17px; font-weight: 700; letter-spacing: .02em; }
.logo-tv { font-size: 12px; font-weight: 700; letter-spacing: .1em; background: var(--green); color: #fff; padding: 3px 5px 2px 6px; }

/* ---------- guide ---------- */
#guide { min-height: 100%; display: flex; flex-direction: column; }
.tabs { display: flex; align-items: stretch; background: var(--bg); padding: 0 max(0px, env(safe-area-inset-right)) 0 max(0px, env(safe-area-inset-left)); }
.tab { display: inline-flex; align-items: center; padding: 0 16px; height: 34px; background: var(--tab); color: #7686a0;
  font-size: 16px; font-weight: 700; text-decoration: none; border-right: 2px solid var(--bg); }
.tab:hover { color: var(--muted); }
.tab.active { background: var(--panel); color: var(--text); }
/* the logo leads to Live, but is not a tab of its own */
.tab.logo { padding-left: 8px; color: var(--text); }
.tabs .fill-tab { flex: 1; background: var(--bg); }
/* the way to the game: a green button at the end of the bar */
.play-link { display: inline-flex; align-items: center; gap: 6px; align-self: center; margin-right: 10px; padding: 4px 12px;
  background: var(--green); color: #fff; font-size: 14px; font-weight: 700; text-decoration: none; white-space: nowrap; }
.play-link:hover { background: var(--green-hi); }
.play-link svg { width: 12px; height: 12px; }
/* news under the tabs (the demo player): a slim strip in the green of the Play button */
.ribbon { display: flex; align-items: center; justify-content: center; gap: 10px; flex-wrap: wrap; padding: 6px 44px 6px 16px;
  position: relative; background: var(--green-lo); color: var(--green-text); font-size: 13px; line-height: 1.4; }
.ribbon-new { flex: none; background: var(--green-text); color: var(--green-lo); font-size: 11px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; padding: 1px 6px; }
.ribbon-link { color: #fff; font-weight: 700; white-space: nowrap; }
.ribbon-link:hover { color: var(--green-text); }
.ribbon-close { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); width: 28px; height: 28px; padding: 0;
  background: none; border: 0; color: var(--green-text); font-size: 18px; line-height: 1; cursor: pointer; opacity: .8; }
.ribbon-close:hover { opacity: 1; background: rgba(0, 0, 0, .12); }
#guide.on-viewer .ribbon { display: none; }
.viewer .listing-head h1 { flex: none; white-space: nowrap; }
@media (max-width: 600px) { .ribbon-text { display: none; } }

.guide-main { flex: 1; display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 24px;
  width: 100%; max-width: 1180px; margin: 0 auto; padding: 22px 16px 32px; }
.listing-head { display: flex; align-items: center; gap: 14px; margin-bottom: 8px; }
.listing-head h1 { margin: 0; font-size: 14px; font-weight: 400; color: var(--text); }
.summary { margin: 0; color: var(--muted); font-size: 13px; font-variant-numeric: tabular-nums; }
.summary b { color: var(--text); font-weight: 400; }
.status { color: var(--muted); font-size: 13px; }
.status.error { color: var(--orange); }
.listing-head .btn { margin-left: auto; }
/* the green strip above the server list: runs while the hub requests the servers */
.meter { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.meter-bar { flex: 1; height: 9px; background: var(--deep); }
.meter-bar i { display: block; height: 100%; width: 0;
  background: repeating-linear-gradient(90deg, var(--green) 0 11px, transparent 11px 14px); }
.meter.loading .meter-bar i { width: 85%; transition: width 2.5s cubic-bezier(.2, .7, .3, 1); }
.meter.done .meter-bar i { width: 100%; transition: width .25s ease-out; }
.meter-text { color: var(--muted); font-size: 12px; white-space: nowrap; font-variant-numeric: tabular-nums; }
.meter-text.error { color: var(--orange); white-space: normal; }

.columns, .channel { display: grid; grid-template-columns: minmax(0, 1fr) 170px 90px 90px; gap: 12px; align-items: center; }
.columns { padding: 5px 40px 5px 10px; background: var(--deep); color: var(--muted); font-size: 13px; border-bottom: 1px solid var(--line); }
.num { text-align: right; font-variant-numeric: tabular-nums; }
.channels { list-style: none; margin: 0; padding: 0; background: var(--panel); }
/* a row: the server (a button that opens the match), the arrow that shows who plays, and
   under them, when open, the names */
.channels > li { display: grid; grid-template-columns: minmax(0, 1fr) 34px; background: var(--row); }
.channels > li:nth-child(even) { background: var(--row-alt); }
.channel { width: 100%; min-height: 44px; text-align: left; background: none; border: 0; padding: 9px 6px 9px 10px; border-radius: 0; font-size: 14px; }
.channels .channel:hover { background: var(--row-hover); box-shadow: inset 0 0 0 1px var(--orange); }
.peek { align-self: center; justify-self: center; width: 28px; height: 28px; color: var(--muted); }
.peek svg { width: 16px; height: 16px; transform: rotate(90deg); transition: transform .15s; }
.channels .peek[aria-expanded="true"] { color: var(--text); background: rgba(255, 255, 255, .08); }
.peek[aria-expanded="true"] svg { transform: rotate(-90deg); }
.names { grid-column: 1 / -1; list-style: none; margin: 0; padding: 7px 10px 9px 34px; columns: 150px; column-gap: 18px;
  background: rgba(0, 0, 0, .12); border-top: 1px solid rgba(0, 0, 0, .15); font-size: 13px; }
.names li { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 20px; }
.ch-main { min-width: 0; display: flex; flex-direction: column; }
.ch-title { display: flex; align-items: center; gap: 8px; min-width: 0; }
.ch-label { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* flags.png: 32x24 cells, 16 to a row (js/spectate/flags.js) */
.cflag { flex: none; width: 16px; height: 12px; background: url("flags.png") 0 0 / 256px 204px no-repeat;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .25); }
.cflag.none { background: var(--deep); }
/* small labels after the server's name, the size of the LIVE tally */
.chip { flex: none; display: inline-flex; align-items: center; gap: 5px; height: 17px; padding: 0 6px;
  background: var(--deep); color: var(--muted); font-size: 11px; white-space: nowrap; }
/* the green ping dot of the server list: the server is on air */
.chip.on-air { background: var(--green-lo); color: var(--green-text); }
.chip.on-air::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: #7fdc52; }
.chip.off-air { color: var(--dim); }
/* the map and mode under the name: only on a phone, where their columns are gone */
.ch-sub { display: none; margin-top: 2px; padding-left: 24px; color: var(--muted); font-size: 12px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ch-map, .ch-mode { color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ch-players { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.ch-players b { font-weight: 400; }
.ch-players .unknown { color: var(--dim); }
.fill { width: 56px; height: 4px; background: var(--deep); }
.fill i { display: block; height: 100%; background: var(--green); }
.channel.quiet .ch-label, .channel.quiet .ch-map { color: var(--muted); }
.list-empty { color: var(--muted); padding: 22px 12px; margin: 0; background: var(--row); }

/* the recorded matches under the servers: the same rows, a download arrow before the names' */
.demos { margin-top: 26px; }
.demos h2 { margin: 0; font-size: 14px; font-weight: 400; color: var(--text); }
.demo-list > li { grid-template-columns: minmax(0, 1fr) 34px 34px; }
.demo-list .dl { color: var(--muted); }
.demo-list .dl svg { transform: none; }
.demo-list .dl:hover { color: var(--text); }
.score-line { font-variant-numeric: tabular-nums; }
.score-line b { font-weight: 700; }
.score-line i { font-style: normal; color: var(--dim); margin: 0 4px; }
.demos .listing-head .btn { min-height: 0; padding: 4px 12px; font-size: 13px; }
.all-link { display: block; margin-top: 8px; text-align: right; color: var(--muted); font-size: 13px; text-decoration: none; }
.all-link:hover { color: var(--text); text-decoration: underline; text-underline-offset: 3px; }
#viewer-back { margin-left: auto; min-height: 0; padding: 4px 12px; font-size: 13px; }

/* the demo viewer: the drop zone for a demo file, and the demos opened since the page loaded */
.on-viewer .listing > :not(#viewer) { display: none !important; }
.drop-zone { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  min-height: 190px; padding: 24px 16px; background: var(--row); border: 2px dashed var(--line); color: var(--muted);
  text-align: center; cursor: pointer; transition: border-color .12s, background .12s; }
.drop-zone svg { width: 34px; height: 34px; margin-bottom: 6px; color: var(--dim); }
.drop-zone b { font-size: 16px; font-weight: 400; color: var(--text); }
.drop-zone u { color: var(--green-text); text-underline-offset: 2px; }
.drop-zone:hover, .drop-zone.over { border-color: var(--orange); background: var(--row-hover); }
.drop-zone:hover svg, .drop-zone.over svg { color: var(--orange); }
.drop-zone:focus-within { outline: 1px solid var(--orange); outline-offset: 1px; }
.drop-note { margin: 8px 0 0; color: var(--muted); font-size: 13px; }
.opened { margin-top: 26px; }
.opened h2 { margin: 0 0 8px; font-size: 14px; font-weight: 400; color: var(--text); }
.opened-list > li { grid-template-columns: minmax(0, 1fr); }
.opened .columns { padding-right: 6px; }
.opened .ch-sub { padding-left: 0; }
.drop-touch { display: none; }
@media (hover: none) {
  .drop-mouse { display: none; }
  .drop-touch { display: inline; }
}

.notes { font-size: 13px; color: var(--muted); }
.notes h2 { margin: 6px 0 6px; font-size: 14px; font-weight: 400; color: var(--text); }
.notes .box { background: var(--panel); padding: 12px 14px; margin-bottom: 20px; }
.notes p { margin: 0; }
.notes p + p { margin-top: 10px; }
.notes .nick { color: var(--green-hi); }
/* Soldat TV's chat on the guide: everyone on the site */
.tv-chat .box { padding: 0; }
.tv-chat .chat-scroll { height: 260px; overflow: auto; padding: 6px 0; }
.tv-chat .line { padding: 1px 12px; color: var(--text); overflow-wrap: anywhere; }
.tv-chat .chat-empty { margin: 0; padding: 2px 12px; text-shadow: none; }
.tv-chat .say { border-top: 1px solid var(--line); }
.tv-chat .say-nick, .tv-chat .say-text { height: 32px; }
.tv-chat .say-text { background: var(--deep); }
.keys { display: grid; grid-template-columns: auto 1fr; gap: 8px 12px; margin: 0; align-items: center; }
.keys dt { color: var(--text); white-space: nowrap; }
.keys dd { margin: 0; }
.credits { padding: 14px 16px calc(14px + env(safe-area-inset-bottom)); color: var(--dim); font-size: 12px;
  background: var(--deep); text-align: center; }
.credits a { color: var(--muted); }

/* ---------- watching ---------- */
#watch { position: fixed; inset: 0; background: #000; overflow: hidden; user-select: none; -webkit-user-select: none; }
#canvas { width: 100%; height: 100%; display: block; object-fit: contain; outline: none; touch-action: none; cursor: grab; }
#canvas.dragging { cursor: grabbing; }
#canvas.cover { object-fit: cover; }

.ui { transition: opacity .25s, transform .25s; }
#watch.idle .ui { opacity: 0; pointer-events: none; }
#watch.idle .topbar { transform: translateY(-8px); }
#watch.idle .dock:not(.placed) { transform: translate(-50%, 8px); }
#watch.idle #canvas { cursor: none; }

.icon-btn { position: relative; display: inline-grid; place-items: center; width: 34px; height: 34px; padding: 0; background: none;
  border: 0; color: var(--text); font-size: 20px; line-height: 1; }
.icon-btn:hover { background: rgba(255, 255, 255, .1); }
.icon-btn svg { width: 19px; height: 19px; }
.icon-btn[aria-expanded="true"] { background: var(--green); }
.unread { position: absolute; top: 6px; right: 6px; width: 7px; height: 7px; border-radius: 50%; background: var(--orange); }

.topbar { position: absolute; left: 0; right: 0; top: 0; display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 6px max(8px, env(safe-area-inset-right)) 8px max(8px, env(safe-area-inset-left));
  background: linear-gradient(rgba(36, 43, 56, .4), rgba(36, 43, 56, 0)); pointer-events: none; z-index: 4; }
.topbar > * { pointer-events: auto; }
/* a light shade only: the icons and the name carry their own shadow over a bright sky */
.topbar .icon-btn svg { filter: drop-shadow(0 1px 1px rgba(0, 0, 0, .8)); }
.topbar #back { flex: none; }
.channel-id { display: flex; align-items: center; gap: 9px; min-width: 0; max-width: calc(50vw - 230px); margin-right: auto;
  font-size: 14px; text-shadow: 0 1px 2px rgba(0, 0, 0, .8); }
.tally { background: var(--green-lo); color: var(--green-text); font-size: 11px; letter-spacing: .1em; padding: 2px 6px 1px; text-shadow: none; }
.ch-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ch-delay { color: var(--muted); font-size: 12px; white-space: nowrap; }
.topbar-end { display: flex; gap: 2px; }
/* the volume: slides out to the left of the sound button on hover (touch screens: .open) */
.volume { display: flex; align-items: center; }
.volume input { width: 0; margin: 0; opacity: 0; accent-color: var(--green); cursor: pointer;
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, .8)); transition: width .15s, opacity .15s, margin .15s; }
.volume:hover input, .volume input:focus-visible, .volume.open input { width: 90px; margin: 0 6px; opacity: 1; }
/* what is shown over the match: a list under its button */
.visuals { position: relative; }
.visuals-menu { position: absolute; right: 0; top: calc(100% + 4px); z-index: 5; display: grid; padding: 3px 0;
  background: var(--glass); border: 1px solid var(--line); font-size: 12px; }
.visuals-menu[hidden] { display: none; }
.visuals-title { margin: 0; padding: 2px 10px 3px; color: var(--muted); font-size: 11px; }
.visuals-menu label { display: flex; align-items: center; gap: 7px; padding: 3px 10px; cursor: pointer; white-space: nowrap; }
.visuals-menu label:hover { background: rgba(255, 255, 255, .08); }
.visuals-menu input { width: 12px; height: 12px; margin: 0; accent-color: var(--green); cursor: pointer; }
.visuals-menu .pick { gap: 10px; }
.visuals-menu select { margin-left: auto; padding: 1px 2px; background: var(--deep); border: 1px solid var(--line); color: var(--text);
  font: inherit; cursor: pointer; }
/* a finger needs taller rows */
@media (pointer: coarse) { .visuals-menu label { padding: 7px 12px; } }

/* ---------- the panels over the match: the menus' slate boxes and dark title bars, the
   game's own text shadows. All of them can be dragged (main.js: movable panels). */
.win { background: rgba(49, 61, 79, .88); border: 1px solid var(--line); }
.win-head { display: flex; align-items: center; gap: 6px; height: 20px; padding: 0 3px 0 8px; background: var(--deep);
  color: var(--muted); font-size: 12px; white-space: nowrap; }
.win-head > span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.handle, .scorebug, .banners, .vote { cursor: move; touch-action: none; }
.grip { flex: none; width: 10px; height: 14px; opacity: .8;
  background: radial-gradient(circle, var(--dim) 1px, transparent 1.4px) 0 1px / 4px 4px; }
.move.moving { opacity: .8; transition: none; }
/* a panel the viewer moved: placed by its left and top (main.js) */
.move.placed { right: auto; bottom: auto; transform: none; }

/* the score: the team box of the game, bigger */
.scorebug { position: absolute; left: 50%; top: max(6px, env(safe-area-inset-top)); transform: translateX(-50%); z-index: 1;
  display: flex; flex-direction: column; background: rgba(49, 61, 79, .9); border: 1px solid var(--line);
  font-variant-numeric: tabular-nums; text-shadow: 1px 1px 0 rgba(0, 0, 0, .7); }
.sb-row { display: flex; align-items: stretch; height: 36px; }
.side, .leader { display: flex; align-items: center; gap: 12px; padding: 0 12px; border-top: 3px solid var(--tc, var(--green)); }
.clock ~ .side { flex-direction: row-reverse; }
.side.t1 { --tc: var(--alpha); --tt: var(--alpha-text); }
.side.t2 { --tc: var(--bravo); --tt: var(--bravo-text); }
.side.t3 { --tc: var(--charlie); --tt: var(--charlie-text); }
.side.t4 { --tc: var(--delta); --tt: var(--delta-text); }
.tname { color: var(--tt, var(--green-text)); font-size: 15px; font-weight: 700; }
.score { min-width: 26px; text-align: center; color: #fff; font-size: 24px; font-weight: 700; line-height: 1; }
.clock { display: flex; align-items: center; padding: 0 12px; background: var(--deep); border-top: 3px solid var(--deep);
  color: var(--text); font-size: 15px; }
.leader .who { max-width: 180px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* as wide as the score above it (width 0, then stretched): a long carrier's name is cut, not the box widened */
.sb-flags { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); width: 0; min-width: 100%;
  background: rgba(44, 51, 65, .9); font-size: 12px; border-top: 1px solid var(--line); }
.fstat { display: flex; align-items: center; gap: 5px; min-width: 0; padding: 2px 10px; color: var(--muted); white-space: nowrap; }
.fstat > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.sb-flags > :last-child { justify-content: flex-end; }
.fstat .flag { width: 13px; height: 13px; flex: none; }
.fstat.taken { color: #fff; }
.fstat.taken .flag { animation: blink 1s steps(2, jump-none) infinite; }
.fstat.dropped { color: var(--orange); }
@keyframes blink { 50% { opacity: .25; } }

/* flag news: console lines on a dark strip, the newest two */
.banners { position: absolute; left: 50%; top: 86px; transform: translateX(-50%); z-index: 1; list-style: none; margin: 0;
  padding: 0; display: flex; flex-direction: column; align-items: center; gap: 2px; }
.banners[data-align="start"] { align-items: flex-start; }
.banners[data-align="end"] { align-items: flex-end; }
.banner { display: flex; align-items: center; gap: 6px; padding: 2px 10px 2px 6px; background: rgba(44, 51, 65, .8);
  border-left: 3px solid var(--c); font-size: 14px; white-space: nowrap; text-shadow: 1px 1px 0 #000;
  animation: fade-in .2s ease-out; transition: opacity .4s; }
.banner b { font-weight: 700; }
.banner .flag { width: 14px; height: 14px; flex: none; }
.banner.gone { opacity: 0; }
@keyframes fade-in { from { opacity: 0; } }

/* a vote: one slim line under the score, its time running out along the bottom */
.vote { position: absolute; left: 50%; top: 66px; transform: translateX(-50%); z-index: 1; display: flex; align-items: center;
  gap: 6px; height: 20px; max-width: min(460px, calc(100% - 20px)); padding-right: 8px; overflow: hidden;
  background: rgba(44, 51, 65, .85); font-size: 12px; white-space: nowrap; text-shadow: 1px 1px 0 #000;
  animation: fade-in .2s ease-out; transition: opacity .4s; }
.vote .v-kind { flex: none; align-self: stretch; display: flex; align-items: center; padding: 0 6px; background: var(--green-lo);
  color: #fff; font-size: 10px; font-weight: 700; letter-spacing: .08em; text-shadow: none; }
.vote.kick .v-kind { background: #b23a30; }
.vote b { flex: none; font-weight: 700; }
.vote .v-by { min-width: 0; color: var(--muted); overflow: hidden; text-overflow: ellipsis; }
.vote .v-left { flex: none; color: var(--text); font-variant-numeric: tabular-nums; }
.vote::after { content: ""; position: absolute; left: 0; bottom: 0; height: 2px; width: var(--p, 0%); background: var(--orange);
  transition: width .25s linear; }
.vote.done::after { display: none; }
.vote.gone { opacity: 0; }
.chip.vote { height: 15px; padding: 0 5px; background: #b23a30; color: #fff; font-size: 10px; font-weight: 400; }

/* a team scores: the game's big message, in the middle */
.bigmsg { position: absolute; left: 0; right: 0; top: 24%; z-index: 1; text-align: center; pointer-events: none;
  text-shadow: 2px 2px 0 #000, 0 0 10px rgba(0, 0, 0, .5); animation: fade-in .2s ease-out; transition: opacity .6s; }
.bigmsg .big { display: block; color: var(--c); font-size: 34px; font-weight: 700; line-height: 1.2; }
.bigmsg .by { color: var(--text); font-size: 16px; }
.bigmsg.gone { opacity: 0; }

/* the followed player */
.card { position: absolute; left: max(12px, env(safe-area-inset-left)); bottom: max(12px, env(safe-area-inset-bottom));
  z-index: 1; width: 220px; border-left: 3px solid var(--c); font-variant-numeric: tabular-nums; }
.card .win-head { height: 24px; gap: 5px; }
.card .win-head .flag { width: 14px; height: 14px; flex: none; }
.c-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; color: var(--tt); font-size: 14px; font-weight: 700;
  text-shadow: 1px 1px 0 #000; }
.c-body { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 36px; padding: 4px 8px; }
.c-weapon { min-width: 0; color: var(--muted); font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.c-weapon img { display: block; height: 26px; max-width: 120px; object-fit: contain; object-position: left center; }
.kd { display: flex; align-items: baseline; gap: 4px; font-size: 17px; text-shadow: 1px 1px 0 #000; }
.kd b { font-weight: 700; }
.k { color: var(--kill); }
.d { color: var(--death); }
.kd .k::after { content: "/"; margin-left: 4px; color: var(--dim); font-weight: 400; }
.c-hp { height: 5px; margin: 0 8px 7px; background: var(--deep); }
.c-hp i { display: block; height: 100%; background: var(--green); transition: width .25s; }
.c-hp.low i { background: var(--orange); }
.card.dead .c-name { color: var(--muted); }

.notice { position: absolute; left: 50%; top: 46%; transform: translate(-50%, -50%); z-index: 2; background: var(--glass);
  border: 1px solid var(--line); padding: 12px 18px; font-size: 14px; max-width: min(520px, 86vw); text-align: center; pointer-events: none; }

.unmute { position: absolute; right: max(12px, env(safe-area-inset-right)); top: calc(max(6px, env(safe-area-inset-top)) + 46px); z-index: 4;
  display: flex; align-items: center; gap: 8px; height: 34px; padding: 0 12px; background: var(--glass); border: 1px solid var(--line);
  color: var(--text); font-size: 14px; cursor: pointer; }
.unmute:hover { background: rgba(70, 84, 106, .95); }
.unmute svg { width: 17px; height: 17px; }

.dock { position: absolute; left: 50%; bottom: max(12px, env(safe-area-inset-bottom)); transform: translateX(-50%); z-index: 2;
  display: flex; align-items: center; gap: 4px; padding: 4px; background: rgba(49, 61, 79, .9); border: 1px solid var(--line);
  max-width: calc(100vw - 20px); }
.dock > .grip { align-self: stretch; height: auto; width: 12px; margin-right: -1px; }
/* Auto and Map are the menu's tabs: green when on */
.seg { height: 34px; padding: 0 14px; background: var(--tab); border: 0; color: #8593a8; font-size: 14px; font-weight: 700; }
.seg:hover { color: var(--text); }
.seg[aria-pressed="true"] { background: var(--green); color: #fff; }
.target { display: flex; align-items: center; }
.target-name { position: relative; display: flex; align-items: center; gap: 8px; min-width: 150px; max-width: 220px; height: 34px;
  padding: 0 10px; background: var(--panel); border: 0; font-size: 14px; }
.target-name:hover { background: var(--row-hover); }
.target-name span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.target-name .hp { display: none; position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: var(--deep); }
.target-name .hp i { display: block; height: 100%; background: var(--green); }
.swatch { flex: none; width: 10px; height: 10px; background: var(--dim); }
.zoom { display: flex; align-items: center; gap: 2px; }

/* a recorded match: the bar along the bottom, the dock above it */
.tally.replay { background: var(--deep); color: var(--orange); }
#watch.replaying .dock:not(.placed), #watch.replaying .card:not(.placed) { bottom: calc(max(12px, env(safe-area-inset-bottom)) + 48px); }
.replaybar { position: absolute; left: max(10px, env(safe-area-inset-left)); right: max(10px, env(safe-area-inset-right));
  bottom: max(10px, env(safe-area-inset-bottom)); z-index: 3; display: flex; align-items: center; gap: 6px; height: 40px;
  padding: 0 4px; background: rgba(49, 61, 79, .9); border: 1px solid var(--line); }
#watch.idle .replaybar { transform: translateY(8px); }
.rp-time { flex: none; min-width: 96px; color: var(--text); font-size: 13px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.rp-speed { flex: none; min-width: 46px; height: 30px; padding: 0 8px; background: var(--tab); border: 0; color: var(--text);
  font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; }
.rp-speed:hover { background: var(--row-hover); }
/* the timeline: a tall hit area around a thin track that thickens under the pointer */
.rp-line { position: relative; flex: 1; align-self: stretch; min-width: 60px; margin: 0 8px; cursor: pointer; touch-action: none; outline: none; }
.rp-track { position: absolute; left: 0; right: 0; top: 50%; height: 4px; transform: translateY(-50%); background: var(--deep);
  transition: height .1s; }
.rp-line:hover .rp-track, .rp-line.scrubbing .rp-track, .rp-line:focus-visible .rp-track { height: 8px; }
.rp-done { display: block; height: 100%; width: 0; background: var(--green); }
.rp-thumb { position: absolute; top: 50%; width: 4px; height: 18px; margin-left: -2px; transform: translateY(-50%);
  background: #fff; box-shadow: 0 0 0 1px rgba(0, 0, 0, .5); pointer-events: none; }
.rp-marks { position: absolute; left: 0; right: 0; top: 50%; pointer-events: none; }
.rp-marks .mark { position: absolute; width: 3px; height: 14px; margin-left: -1.5px; transform: translateY(-50%);
  background: var(--alpha-text); box-shadow: 0 0 0 1px rgba(0, 0, 0, .45); }
.rp-marks .mark.t2 { background: var(--bravo-text); }
.rp-marks .hl { position: absolute; top: -12px; width: 7px; height: 7px; margin-left: -3.5px; border-radius: 50%;
  background: var(--orange); box-shadow: 0 0 0 1px rgba(0, 0, 0, .45); }
.rp-hl { flex: none; display: flex; align-items: center; gap: 5px; height: 30px; padding: 0 9px; background: var(--tab); border: 0;
  color: var(--text); font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.rp-hl svg { width: 15px; height: 15px; color: var(--orange); }
.rp-hl:hover { background: var(--row-hover); }
.rp-hl[aria-pressed="true"] { background: var(--orange); color: #1b1f27; }
.rp-hl[aria-pressed="true"] svg { color: inherit; }
/* the highlight being played: a lower third over the match */
.clipcap { position: absolute; left: 50%; bottom: calc(max(12px, env(safe-area-inset-bottom)) + 104px); transform: translateX(-50%);
  z-index: 1; display: flex; align-items: center; gap: 8px; max-width: calc(100% - 20px); padding: 4px 12px 4px 0;
  background: rgba(44, 51, 65, .85); border-left: 3px solid var(--orange); font-size: 15px; white-space: nowrap;
  text-shadow: 1px 1px 0 #000; pointer-events: none; animation: fade-in .2s ease-out; transition: opacity .6s; }
.clipcap .n { align-self: stretch; display: flex; align-items: center; padding: 0 8px; background: var(--deep); color: var(--muted);
  font-size: 12px; font-variant-numeric: tabular-nums; text-shadow: none; }
.clipcap b { display: flex; align-items: center; gap: 6px; font-weight: 700; }
.clipcap b img { display: block; width: auto; max-height: 24px; filter: drop-shadow(1px 1px 0 #000); }
.clipcap .by { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.clipcap.gone { opacity: 0; }
.ch-sub .hl-count, .ch-map .hl-count { color: var(--orange); }
.ch-sub .rating, .ch-map .rating { padding: 0 5px; border: 1px solid var(--line); border-radius: 3px; color: var(--text); font-size: 12px;
  font-variant-numeric: tabular-nums; }
.rp-tip { position: absolute; bottom: calc(100% + 6px); transform: translateX(-50%); padding: 3px 7px; background: var(--deep);
  border: 1px solid var(--line); color: var(--text); font-size: 12px; font-variant-numeric: tabular-nums; white-space: nowrap;
  pointer-events: none; }

/* the chat: closed until the viewer opens it; see-through, like the game's console */
.chat { position: absolute; left: max(10px, env(safe-area-inset-left)); top: 52px; z-index: 2; width: 340px; max-height: 40%;
  display: flex; flex-direction: column; background: rgba(44, 51, 65, .55); border-color: rgba(74, 90, 114, .7); font-size: 13px; }
.chat .win-head { background: rgba(44, 51, 65, .85); }
.chat-scroll { overflow: auto; padding: 3px 0; }
.chat-lines { list-style: none; margin: 0; padding: 0; }
.chat .line { padding: 1px 8px; overflow-wrap: anywhere; color: var(--chat); text-shadow: 1px 1px 0 #000; }
.chat .line b { font-weight: 700; }
.chat .line.team { color: var(--teamchat); }
.chat .line.server { color: var(--server); }
.chat-empty { margin: 0; padding: 4px 8px; color: var(--muted); text-shadow: 1px 1px 0 #000; }
.has-lines .chat-empty { display: none; }
.chat .line.tv { color: var(--text); }
.line.note { color: var(--orange); }
/* Soldat TV's chat over the match: low on the left, clear of the game's chat and the dock */
.tvchat { top: auto; bottom: 70px; }
/* the channels shown, and the nickname */
.chat-filters { display: flex; align-items: center; gap: 12px; padding: 0 0 0 8px; background: rgba(44, 51, 65, .7);
  font-size: 12px; color: var(--muted); text-shadow: 1px 1px 0 #000; }
.chat-filters label { display: inline-flex; align-items: center; gap: 4px; height: 24px; white-space: nowrap; cursor: pointer; }
.chat-filters input { margin: 0; accent-color: var(--green); }
.chat-filters .say-nick { margin-left: auto; height: 24px; }
/* the channel of a line, and the one to write to */
.ch-tag { color: var(--muted); }
.ch-tag.server { color: var(--green-text); }
/* what to say, after the nickname or the channel (they change them) */
.say { display: flex; border-top: 1px solid rgba(74, 90, 114, .7); }
.say-nick, .say-to { flex: none; max-width: 40%; height: 28px; padding: 0 8px; background: var(--deep); border: 0;
  color: var(--green-text); font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.say-to { color: var(--muted); }
.say-to.server { color: var(--green-text); }
.say-nick:hover, .say-to:hover { background: var(--row-hover); }
.say-text { flex: 1; min-width: 0; height: 28px; padding: 0 8px; background: rgba(30, 36, 47, .7); border: 0; border-radius: 0;
  outline: none; user-select: text; -webkit-user-select: text; }
.say-text:focus { box-shadow: inset 0 0 0 1px var(--orange); }
.say-text::placeholder { color: var(--dim); }
.say-text:disabled { opacity: .7; }

/* the players: the scoreboard, under its button */
.roster { position: absolute; right: max(10px, env(safe-area-inset-right)); top: 52px; z-index: 3; width: 240px;
  max-height: calc(100% - 122px); display: flex; flex-direction: column; font-variant-numeric: tabular-nums; }
.roster-list { overflow: auto; }
/* a team: its name and score, then the column labels of its players */
.roster h3, .player { display: grid; grid-template-columns: minmax(0, 1fr) 24px 24px; gap: 6px; align-items: center; }
.roster h3 { margin: 0; padding: 2px 10px; background: rgba(44, 51, 65, .9); font-size: 11px; font-weight: 400; color: var(--muted);
  border-bottom: 1px solid var(--line); }
.roster h3 .who { display: flex; align-items: center; gap: 6px; min-width: 0; font-size: 13px; font-weight: 700; color: var(--tt, var(--text)); }
.roster h3 .who b { margin-left: auto; font-size: 14px; color: #fff; }
.roster h3 i { flex: none; width: 8px; height: 8px; }
.roster h3 .num { text-align: right; }
.player { width: 100%; padding: 2px 10px; background: rgba(60, 75, 97, .7); border: 0; text-align: left;
  font-size: 13px; line-height: 1.4; }
.player:nth-of-type(even) { background: rgba(48, 62, 84, .7); }
.roster .player:hover { background: var(--row-hover); }
.player .who { display: flex; align-items: center; gap: 6px; min-width: 0; }
.player .who span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.player .swatch { width: 8px; height: 8px; }
.player .flag { width: 12px; height: 12px; flex: none; }
.player .n { text-align: right; }
.player.dead .who span { color: var(--dim); }
.roster .spec-head .who { font-weight: 400; }
.roster .spec-head .who b { font-size: 13px; color: var(--muted); }
.player.spectator { display: block; color: var(--muted); cursor: default; }
.player.spectator .who { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.roster .player.spectator:hover { background: rgba(60, 75, 97, .7); }
.roster .player.spectator:nth-of-type(even):hover { background: rgba(48, 62, 84, .7); }
.roster .player.followed { background: rgba(0, 0, 0, .25); box-shadow: inset 0 0 0 1px var(--orange); }

.rotate { display: none; }

/* ---------- loading ---------- */
#loading { position: fixed; inset: 0; display: grid; place-items: center; background: var(--bg); }
.loading-box { width: min(360px, 84vw); text-align: center; }
.loading-box .logo { margin-bottom: 16px; }
.loading-box .logo-word { font-size: 22px; }
.loading-box .logo-icon { width: 30px; height: 30px; }
#loading p { color: var(--muted); min-height: 1.4em; font-size: 13px; }
.bar { height: 10px; background: var(--deep); overflow: hidden; }
#loading-bar { height: 100%; width: 0; transition: width .2s;
  background: repeating-linear-gradient(90deg, var(--green) 0 11px, transparent 11px 14px); }

/* ---------- a server's password: a menu window ---------- */
.pw { width: min(340px, calc(100vw - 32px)); padding: 0; background: var(--bg); color: var(--text); border: 1px solid var(--line); }
.pw::backdrop { background: rgba(20, 25, 34, .6); }
.pw .win-head { height: 24px; font-size: 13px; }
.pw-body { display: grid; gap: 10px; padding: 14px; }
.pw-body label { color: var(--muted); }
.pw-body label b { color: var(--text); font-weight: 400; }
.pw input { width: 100%; height: 32px; padding: 0 8px; background: var(--panel); border: 1px solid var(--line); }
.pw input:focus { outline: none; border-color: var(--orange); }
.pw-error { margin: 0; color: var(--orange); font-size: 13px; }
.pw-buttons { display: flex; justify-content: flex-end; gap: 8px; margin-top: 4px; }
.btn.quiet { background: var(--tab); color: var(--muted); }
.btn.quiet:hover { background: var(--row-hover); color: var(--text); }

/* ---------- small screens ---------- */
@media (max-width: 960px) {
  .guide-main { grid-template-columns: 1fr; align-content: start; gap: 24px; padding: 16px 12px 24px; }
  .notes > :not(.tv-chat) { display: none; }
}
@media (max-width: 760px) {
  .columns, .channel { grid-template-columns: minmax(0, 1fr) 140px 56px 82px; }
}
@media (max-width: 560px) {
  .tab { padding: 0 12px; font-size: 15px; }
  .play-link { margin-right: 8px; padding: 4px 10px; }
}
/* phones: the logo is its icon and the TV badge, so that the bar fits */
@media (max-width: 420px) {
  .tabs .logo-word { display: none; }
  .columns { display: none; }
  .channel { grid-template-columns: minmax(0, 1fr) auto; gap: 10px; padding: 11px 6px 11px 8px; }
  .channel .ch-map, .channel .ch-mode { display: none; }
  .ch-sub { display: block; }
  .listing-head { flex-wrap: wrap; }
}
/* phones and small tablets held sideways: tighter bars, bigger touch targets */
@media (max-height: 520px) {
  .topbar { padding-top: 4px; padding-bottom: 6px; }
  .topbar #back { top: 4px; }
  .sb-row { height: 28px; }
  .side, .leader { gap: 8px; padding: 0 8px; }
  .score { font-size: 19px; }
  .tname { font-size: 13px; }
  .clock { font-size: 13px; padding: 0 9px; }
  .sb-flags { font-size: 11px; }
  .fstat { max-width: 130px; padding: 1px 7px; }
  .banners { top: 68px; }
  .vote { top: 52px; }
  .banner { font-size: 12px; }
  .bigmsg .big { font-size: 24px; }
  .bigmsg .by { font-size: 14px; }
  .dock { bottom: max(8px, env(safe-area-inset-bottom)); gap: 2px; padding: 3px; }
  .seg { height: 40px; padding: 0 12px; }
  .target-name { min-width: 110px; max-width: 150px; font-size: 13px; height: 40px; }
  .icon-btn { width: 40px; height: 40px; }
  .chat { top: 46px; width: 280px; max-height: 45%; }
  .replaybar { height: 44px; }
  .rp-time { min-width: 0; font-size: 12px; }
  .rp-hl { padding: 0 7px; }
  .clipcap { bottom: calc(max(8px, env(safe-area-inset-bottom)) + 104px); font-size: 13px; }
  #watch.replaying .dock:not(.placed) { bottom: calc(max(8px, env(safe-area-inset-bottom)) + 52px); }
  .tvchat { top: auto; bottom: 60px; }
  .roster { top: 46px; max-height: calc(100% - 110px); width: 220px; }
  .channel-id .ch-delay { display: none; }
}
@media (max-width: 700px) and (max-height: 520px) {
  .channel-id .ch-name { display: none; }
}
/* no room for the player card: the player's health is a line under the name in the dock */
@media (max-width: 960px), (max-height: 520px) {
  .card { display: none; }
  .target-name .hp { display: block; }
}
/* the chat stays clear of the score in the middle */
@media (max-width: 960px) {
  .chat { width: max(180px, calc(50vw - 150px)); font-size: 12px; }
}
/* a phone held upright: the match is a landscape picture */
@media (orientation: portrait) and (max-width: 600px) {
  #watch .rotate { display: grid; place-content: center; justify-items: center; gap: 18px; position: absolute; inset: 0;
    background: rgba(49, 61, 79, .97); color: var(--muted); font-size: 14px; z-index: 5; }
  .rotate .phone { width: 34px; height: 56px; border: 2px solid var(--green); border-radius: 5px;
    animation: turn 2.4s ease-in-out infinite; }
  .rotate p { margin: 0; }
  #watch .dock, #watch .replaybar, #watch .roster, #watch .scorebug, #watch .banners, #watch .bigmsg, #watch .card, #watch .chat, #watch .channel-id,
  #watch .topbar-end { visibility: hidden; }
  #watch .topbar, #watch.idle .topbar { z-index: 6; opacity: 1; transform: none; background: none; }
  #watch.idle .topbar #back { pointer-events: auto; }
}
/* touch screens zoom into a text field smaller than 16px */
@media (pointer: coarse) {
  .say-text { font-size: 16px; }
}
/* touch only: a pinch zooms, the dock keeps the room of its zoom buttons */
@media (hover: none) and (pointer: coarse) {
  .zoom { display: none; }
}
@keyframes turn { 0%, 30% { transform: rotate(0); } 55%, 85% { transform: rotate(-90deg); } 100% { transform: rotate(0); } }
@media (prefers-reduced-motion: reduce) {
  .ui { transition: none; }
  .rotate .phone { animation: none; transform: rotate(-90deg); }
  .meter .meter-bar i { transition: none; }
  .banner, .bigmsg, .fstat.taken .flag { animation: none; transition: none; }
}
