/* Layout and structure, shared by every look. Colours, fonts, borders, shadows and tilts live in
   themes/*.css (the list is in index.html); a theme styles the same elements on top of this.
   Decorative extras in the markup (.deco) stay hidden unless a theme shows them.
   Right-to-left languages set <html dir="rtl">: the menus, cards and the friends bar mirror, by
   logical properties (inline-start/end) and [dir="rtl"] rules. The game screen keeps its
   corners (the minimap, the yellow man, the compass over the gear), so its placing is physical
   left/right on purpose; what's inside its panels still follows the text. */
* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
body { overflow: hidden; }
[hidden] { display: none !important; }
.deco { display: none; }

button { cursor: pointer; }
button:disabled { cursor: default; }
button.big { width: 100%; }
input, select { display: block; width: 100%; margin-top: 6px; padding: 10px 12px; }
.error { min-height: 1.4em; margin: 8px 0; }

/* ---- landing and lobby ---- */

.screen {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  overflow-y: auto;
}
.card { position: relative; width: min(440px, 100%); margin: auto; }
.field { display: block; margin: 12px 0; font-size: 14px; }
.slider { display: block; margin: 12px 0; }
.slider span { display: flex; justify-content: space-between; align-items: baseline; }
.slider input { padding: 0; border: 0; background: none; }
.row-end { display: flex; justify-content: flex-end; gap: 10px; margin-top: 12px; }

/* Game, Leaderboard and More (or Home and More) along the top of the landing page, the settings gear bottom left. */
#landing { padding-top: 64px; }
#site-tabs { position: absolute; z-index: 5; top: 12px; left: 50%; transform: translateX(-50%); display: flex; gap: 8px; }
#site-tabs button { font-size: 15px; padding: 6px 14px; }
/* More's menu of pages, hung under its tab. */
#more { position: relative; }
#more-menu { position: absolute; top: calc(100% + 6px); inset-inline-end: 0; display: flex; flex-direction: column; gap: 4px; min-width: 140px; padding: 6px; }
#site-tabs #more-menu button { width: 100%; text-align: start; }
#more-menu [aria-current] { font-weight: 700; }
/* Friend requests waiting, in the friends bar and on its phone button. */
.tab-count { display: inline-block; min-width: 1.5em; margin-inline-start: 2px; padding: 0 5px; border-radius: 99px; font-size: 12px; line-height: 1.5; text-align: center; }
#home-menu-btn { position: fixed; z-index: 10; inset-inline-start: 12px; bottom: 12px; font-size: 18px; padding: 4px 10px; }
.card.legal { width: min(760px, 100%); }
.card.legal h1 { width: auto; font-size: 36px; }
.legal mark { padding: 0 .2em; border-radius: 3px; }
#esc-menu.home .game-only { display: none; }
@media (max-width: 640px) {
  #site-tabs { left: auto; inset-inline-start: 12px; transform: none; gap: 6px; }
  #site-tabs button { padding: 6px 10px; }
}
/* The tabs and the friends button top right don't fit across a narrow phone: the tabs get a row
   of their own under it, and wrap onto a second on the narrowest (all five, signed out,
   need about 355px, plus a scrollbar's width where it takes room). */
@media (max-width: 440px) {
  #landing { padding-top: 104px; }
  #site-tabs { top: 56px; left: 8px; right: 8px; flex-wrap: wrap; justify-content: center; gap: 6px 4px; }
  #site-tabs button { font-size: 13px; padding: 5px; }
}
@media (max-width: 384px) {
  #landing { padding-top: 140px; }
}

/* ---- the Account tab ---- */

.card.account { width: min(600px, 100%); }
.card.account h1 { width: auto; }
.small { font-size: 13px; }
.acct-sec { margin-top: 22px; }
.acct-sec h2 { margin: 0 0 6px; }
.acct-sec h3 { margin: 16px 0 6px; }
.acct-sec p { margin: 4px 0; }
/* Google's button is a light-scheme iframe; in a dark look Chrome would paint a white box behind it. */
#signup-gsi-btn, #signin-gsi-btn { color-scheme: light; }
/* An input with its button beside it, lined up along the bottom. */
.acct-inline { display: flex; align-items: flex-end; gap: 8px; }
.acct-inline .field { flex: 1; min-width: 0; margin: 12px 0 0; }
.acct-inline button { flex: none; }
.acct-sec .error { margin: 6px 0 0; }
/* The avatar editor: the preview beside the part tabs and their choices, which scroll; on a phone
   the preview sits on top. */
.av-editor { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 12px 16px; align-items: start; margin: 12px 0 16px; }
#av-preview { width: 132px; height: 132px; }
#av-preview .face svg { transform: none; }
.av-main { min-width: 0; }
.av-tabs { display: flex; gap: 6px; overflow-x: auto; padding: 2px 2px 8px; scrollbar-width: thin; }
.av-tabs button { flex: none; font-size: 13px; padding: 4px 10px; white-space: nowrap; }
.av-choices { display: grid; grid-template-columns: repeat(auto-fill, minmax(56px, 1fr)); gap: 8px; max-height: 228px; overflow-y: auto; padding: 4px; }
.av-choices.colors { grid-template-columns: repeat(auto-fill, minmax(36px, 1fr)); }
.av-thumb { position: relative; aspect-ratio: 1; padding: 0; border-radius: 50%; background: var(--avatar-bg); overflow: hidden; }
.av-thumb .face svg { transform: none; }
.av-swatch { aspect-ratio: 1; padding: 0; border-radius: 50%; }
.av-thumb[aria-pressed="true"], .av-swatch[aria-pressed="true"] { outline: 3px solid var(--avatar-pick); outline-offset: 2px; }
.av-actions { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
.av-actions #av-random { margin-inline-end: auto; }
.av-editor .error { grid-column: 1 / -1; }
@media (max-width: 520px) {
  .av-editor { grid-template-columns: minmax(0, 1fr); }
  #av-preview { justify-self: center; width: 112px; height: 112px; }
}
/* Lifetime stats, as a grid of labelled numbers. */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); gap: 8px; margin: 8px 0 0; }
.stat-grid div { padding: 8px 10px; }
.stat-grid dt { font-size: 13px; }
.stat-grid dd { margin: 0; font-size: 22px; font-variant-numeric: tabular-nums; }
.code-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.friend-code { font-size: 22px; letter-spacing: .08em; }
.code-btns { display: flex; gap: 6px; margin-inline-start: auto; }
.code-btns button { font-size: 14px; padding: 5px 10px; }
.inline-confirm { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 8px; }
.inline-confirm p { flex-basis: 100%; font-weight: 700; }
.toggle { display: inline-flex; align-items: center; gap: 8px; font-weight: 600; cursor: pointer; }
.toggle input { width: auto; margin: 0; }
.account-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
#friend-board th:nth-child(2), #friend-board td:nth-child(2) { text-align: start; overflow-wrap: anywhere; }

/* ---- billing: free games and Unlimited ---- */

/* On the Game tab, above Play: free games left, the wait for the next, or Unlimited. */
.quota-note { margin: 4px 0 10px; font-size: 14px; }
.quota-note button.link { padding: 0 2px; font-size: inherit; }
/* Subscribed (or comped), on the Game tab and by the name in the menu. */
.unlimited-badge { display: inline-block; padding: 1px 8px; font-size: 12px; font-weight: 800; line-height: 1.5; white-space: nowrap; }
/* A ticket on the icon of a lobby player out of free games: top left (top right in a
   right-to-left language), as the host's move arrow has the other top corner. */
.badge.needs-pass { inset-inline-start: -8px; inset-inline-end: auto; width: 22px; height: 22px; font-size: 12px; }
/* In the lobby, when we're the one out of free games. */
.lobby-pass { margin: 12px 0; padding: 10px 12px; }
.lobby-pass p { margin: 0 0 8px; font-weight: 700; }
#lobby-pass-note { margin: 6px 0 0; font-size: 14px; }
#paywall { width: min(440px, calc(100vw - 32px)); }
#paywall h2 { margin-top: 0; }
#paywall p { margin: 8px 0; }
#name-prompt { width: min(400px, calc(100vw - 32px)); }
#name-prompt h2 { margin-top: 0; }
#name-prompt p { margin: 8px 0; }

/* Signing in by email, under each Google button (or on its own): an address, then the code from
   the email. Its lines are divs, not p, so the Account tab's p margins stay off them. */
.email-box { flex-basis: 100%; }
.email-box form { margin: 0; }
/* Its label over the row, and the button as tall as the input beside it. */
.email-box .acct-inline { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: stretch; gap: 6px 8px; margin-top: 8px; font-size: 14px; }
.email-box .acct-inline .field { display: contents; }
.email-box .acct-inline .field span { grid-column: 1 / -1; }
.email-box .acct-inline input { margin: 0; }
.email-or { display: flex; align-items: center; gap: 10px; margin: 10px 0 2px; font-size: 13px; opacity: .7; }
.email-or::before, .email-or::after { content: ""; flex: 1; border-top: 1px solid currentColor; opacity: .5; }
.email-sent { margin: 8px 0 0; font-size: 14px; overflow-wrap: anywhere; }
.email-code input[name="code"] { letter-spacing: .3em; font-variant-numeric: tabular-nums; }
.email-gmail { margin-top: 8px; }
.email-back { margin-top: 6px; padding: 2px 0; font-size: 13px; }

/* People: friends, requests, and friends to invite. Their icon, a line or two, and buttons,
   which drop under the rest when there's no room. */
.people { list-style: none; margin: 6px 0 0; padding: 0; text-align: start; }
.people li { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; padding: 8px 0; }
.people .avatar { flex: none; width: 36px; height: 36px; }
.person-info { display: flex; flex-direction: column; flex: 1 1 140px; min-width: 0; overflow-wrap: anywhere; line-height: 1.3; }
.person-info span { font-size: 13px; }
.person-actions { display: flex; align-items: center; gap: 6px; margin-inline-start: auto; }
.person-actions button { font-size: 14px; padding: 5px 10px; }
.people li.offline .avatar { opacity: .5; }
.people li.empty { display: block; font-size: 14px; }
.confirm-q { font-weight: 700; font-size: 14px; }


#board-wrap summary { cursor: pointer; }
table { width: 100%; border-collapse: collapse; margin-top: 8px; font-variant-numeric: tabular-nums; }
th, td { text-align: end; }
th:first-child, td:first-child { text-align: start; }

#lobby .card { text-align: center; }
#lobby-friends { margin: 4px 0 10px; }
#lobby-friends h3 { margin: 0; }
.lobby-players { list-style: none; padding: 0; margin: 16px 0; display: flex; flex-wrap: wrap; gap: 14px; justify-content: center; }

/* Classic / Teams, side by side; the one picked is pressed (aria-pressed). */
.mode-switch { display: flex; gap: 8px; margin: 14px 0 4px; }
.mode-switch button { flex: 1; }

/* ---- teams ---- */

/* Each team's colour, from the theme, as --team (and a pale --team-soft) for whatever carries
   the class. */
.team-red { --team: var(--team-red); --team-soft: var(--team-red-soft); }
.team-blue { --team: var(--team-blue); --team-soft: var(--team-blue-soft); }
/* Red and Blue side by side in the lobby (and the mid-game team picker); a click joins one. */
.team-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin: 16px 0 6px; text-align: center; }
.team-col { display: flex; flex-direction: column; min-width: 0; min-height: 150px; padding: 10px 8px; cursor: pointer; }
.team-col.mine { cursor: default; }
.team-col h3 { margin: 0; }
.team-col .lobby-players { flex: 1; align-content: flex-start; gap: 10px; margin: 10px 0; }
.team-col .player { position: relative; }
.team-col .empty { width: 100%; font-size: 14px; }
.team-join { margin: 0; font-size: 13px; font-weight: 600; }
.team-loose { grid-column: 1 / -1; margin: 0; font-size: 14px; }
/* The host's arrow for moving a player across, on the corner of their icon. Right to left the
   teams swap sides, so the arrow (→ for Red, ← for Blue) is turned round to still point across;
   by `scale`, which leaves the theme's hover transform alone. */
.move-btn { position: absolute; z-index: 1; top: -6px; inset-inline-end: 0; padding: 0 6px; font-size: 13px; line-height: 1.5; }
[dir="rtl"] .move-btn { scale: -1 1; }
#lobby-shuffle { display: block; margin: 0 auto 6px; }
#lobby-start-note { margin: 6px 0 0; font-size: 14px; }

/* The word lists to deal from, as ticks that wrap. */
.list-picks { margin: 12px 0; padding: 0; border: 0; min-width: 0; }
.list-picks legend { padding: 0; font-size: 14px; }
.list-picks div { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-top: 6px; }
#lobby .list-picks div { justify-content: center; }
.list-pick { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; cursor: pointer; }
.list-pick input { margin: 0; }
.list-pick .count { opacity: .6; font-size: 12px; }

/* Home layout: matchmaking, single player, then the room row. */
.room-row { display: flex; align-items: center; gap: 10px; margin: 18px 0 6px; }
.room-row button { flex: 1; min-width: 0; font-size: 14px; padding: 7px 8px; }
#setup-back { display: block; margin: 10px auto 0; }
/* Google's sign-in button under the name, or who's signed in. */

/* ---- matchmaking ---- */

/* Quick Play, a big button with its Classic / Teams switch under it. */
.queue-pick { margin: 10px 0 0; }
.queue-pick .mode-switch { margin: 8px 0 0; }
.queue-pick .mode-switch button { font-size: 14px; padding: 5px 8px; }
.queue-note { min-height: 0; margin: 6px 0 0; font-size: 13px; }
.queue-note:empty { display: none; }
.queue-note button.link, #mm-error button.link { padding: 0 2px; font-size: inherit; }
#mm-back { margin-bottom: 6px; }
#mm-closed { margin: 10px 0 0; font-size: 14px; }
#mm-error { margin: 6px 0 0; }
#mm-error:empty { min-height: 0; }
#single-btn:not(.big) { width: 100%; margin-top: 4px; }
/* The party: who's in it, and friends to invite. */
.party-panel { margin: 12px 0 14px; }
.party-panel h3 { margin: 0; }
.party-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; margin-top: 8px; }
.party-actions button:not(.link) { font-size: 14px; padding: 5px 10px; }
/* Waiting in a queue, on the Game tab. */
#queue-view { text-align: center; }
#queue-view h2 { margin: 6px 0 0; }
.queue-waited { margin: 8px 0 0; font-size: 44px; line-height: 1.1; font-variant-numeric: tabular-nums; }
#queue-size, #queue-party { margin: 4px 0; font-size: 14px; }
.queue-solo { margin: 14px 0 4px; padding: 10px 12px; }
.queue-solo p { margin: 0 0 8px; font-size: 14px; }
/* Queued while playing solo: bottom left, clear of the map in the other corner (so physical
   left, in any language). */
#queue-chip { position: fixed; left: 60px; bottom: 12px; z-index: 12; display: flex; align-items: center; gap: 4px; max-width: calc(100vw - 72px); padding-block: 4px; padding-inline: 12px 4px; font-size: 14px; }
#queue-chip button.link { font-size: 14px; padding: 4px 8px; }
/* On a phone the camera buttons along the bottom reach across: the chip sits above them. */
@media (max-width: 600px) { #queue-chip { bottom: 100px; } }
/* The Leaderboard tab. */
.card.board { width: min(600px, 100%); }
.card.board h1 { width: auto; }
/* A matched lobby: its queue, settings and countdown. */
#lobby-match h2 { margin: 0; }
#lobby-match p { margin: 4px 0; }
.match-count { font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; }
.team-col.locked { cursor: default; pointer-events: none; }
.match-note p { margin: 4px 0; font-size: 14px; }
#results-lobby { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; min-width: 0; }

/* ---- game ---- */

#game { position: fixed; inset: 0; }
#pano { position: absolute; inset: 0; }
/* Capture mode, over the panorama but under the HUD: a vignette, corners framing the photo
   (sized by app.js, a guide to the judge's photo, which takes the view's full height; --frame-h
   is its height and --arm the corners' length), and a small box in the middle to aim with. */
#capture {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: radial-gradient(ellipse at center, transparent 50%, rgba(0, 0, 0, .55) 100%);
  filter: drop-shadow(0 0 1px rgba(0, 0, 0, .7));
}
/* A locked mouse is hidden already; this is for when it couldn't be locked. Left on while
   locked, the browser can keep the cursor hidden after the lock ends, until it's moved. */
#capture.free { cursor: none; }
#capture[hidden] { display: none; }
/* With the mouse on Capture: the same frame, fading in and out (PREVIEW_FADE in app.js), without
   the tips and with nothing to click, and the minimap fading out with it. */
#capture.preview { pointer-events: none; transition: opacity .12s ease; }
#capture.preview.faded { opacity: 0; }
#capture.preview #capture-tips { display: none; }
#game.previewing #map-box { opacity: 0; pointer-events: none; }
/* Nothing over the photo but the round's card and the corners' buttons. Capture is taken out
   altogether, not just hidden, so it doesn't come back still looking pressed from the click
   that raised the camera. */
#game.capturing #map-box { visibility: hidden; }
#game.capturing #street-actions { display: none; }
/* Just lowered, until the mouse moves: the click that lowered it mustn't press Capture. */
#game.settling #street-actions { pointer-events: none; }
/* The frame is the photo's, so its corners stay where they are right to left too. */
#capture-frame, #capture-box { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); }
.cap-corner { position: absolute; width: var(--arm); height: var(--arm); border: 0 solid #fff; }
.cap-corner.tl { top: 0; left: 0; border-width: 2px 0 0 2px; }
.cap-corner.tr { top: 0; right: 0; border-width: 2px 2px 0 0; }
.cap-corner.bl { bottom: 0; left: 0; border-width: 0 0 2px 2px; }
.cap-corner.br { bottom: 0; right: 0; border-width: 0 2px 2px 0; }
#capture-box { border: 2px solid #fff; border-radius: 6px; }
/* How far in we are, just inside the bottom right corner. */
#capture-zoom {
  position: absolute;
  right: calc(var(--arm) / 2);
  bottom: calc(var(--arm) / 2);
  color: #fff;
  font-family: "Share Tech Mono", ui-monospace, monospace;
  font-size: 18px;
  letter-spacing: .04em;
}
#capture-tips {
  position: absolute;
  left: 50%;
  top: calc(50% + var(--frame-h) / 2 + 16px);
  transform: translateX(-50%);
  display: flex;
  gap: 10px;
}
.capture-tip {
  margin: 0;
  padding: 7px 16px;
  border-radius: 999px;
  background: rgba(0, 0, 0, .55);
  color: #fff;
  font-size: 16px;
  white-space: nowrap;
}
/* Dark rather than white: the shutter closing, not a flash going off. */
#shutter { position: absolute; inset: 0; z-index: 50; background: #000; opacity: 0; pointer-events: none; }
#shutter.snap { animation: shutter 300ms ease-out; }
@keyframes shutter { 0% { opacity: 0; } 15% { opacity: .85; } 100% { opacity: 0; } }
/* The minimap's corner, the yellow man's and the re-drop pin's, the compass and the gear are
   where they are on the map, not in the text: physical left and right from here, in any
   language. */
#map-box {
  position: absolute;
  z-index: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
}
#map { width: 100%; height: 100%; }
/* In Street View the map tucks into the lower right, and grows once the cursor comes onto it
   (map-open, see trackMapOpen). The box's padding is the gap to the screen edge: invisible,
   but still counted as on the map. */
#game.street #map-box {
  z-index: 6;
  padding: 0 16px 16px 0;
  width: 376px;
  height: 271px;
  transition: width .2s ease, height .2s ease, opacity .12s ease;
}
#game.street #map { opacity: .8; transition: opacity .2s ease; }
#game.street.map-open #map-box { width: calc(66% + 16px); height: calc(79% + 16px); }
#game.street.map-open #map { opacity: 1; }
/* The map's + and − slide out from behind the re-drop pin once it has grown (map-grown), and
   back behind it as soon as it starts to shrink, straight up and down. --tuck-y is the way
   down to the pin (see watchMapGrow); they fade right at the end, in case they're bigger. */
#game.street #map .zoom-ctl {
  opacity: 0;
  visibility: hidden;
  transform: translateY(var(--tuck-y, 0)) scale(.6);
  transition: transform .2s ease-in, opacity .06s linear .14s, visibility 0s .2s;
}
#game.street.map-open.map-grown #map .zoom-ctl {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: transform .2s ease-out, opacity .06s linear, visibility 0s;
}
/* Spectating, the minimap is the watched player's, so it doesn't take the mouse. */
#game.spectating #map-box { pointer-events: none; }
/* In Street View, Google's yellow man standing on the map is twice as big. He's drawn as an
   image centred on his spot inside a clipping box, so scaling that box about its centre keeps
   him in place. The element names are Google's internals: if he stops growing, check them. */
#game.street #map gmp-internal-use-am > div > div { transform: scale(2); }
/* Resting on him for half a second makes him ready to pick up (see trackManHover). */
body.man-ready #map, body.man-ready #map *,
body.corner-ready #map, body.corner-ready #map * { cursor: grab !important; }
/* On the opening full-screen map the yellow man is bigger. */
#game:not(.street) .gm-svpc { transform: scale(4.8); transform-origin: right bottom; }
/* A black border round the yellow man's box. It's scaled with him, so it's drawn thin here; a
   shadow rather than a border, since Chrome would round a sub-pixel border up before scaling. */
#map .gm-svpc { box-shadow: 0 0 0 2px #000 !important; }
#map .gm-svpc.corner-hot { background: #ebebeb !important; }
#game:not(.street) .gm-svpc { box-shadow: 0 0 0 .5px #000 !important; }
/* In Street View the corner yellow man becomes a pin for dropping in somewhere else.
   It keeps Google's control look so it reads as part of the map, whatever the theme. */
.redrop {
  position: relative;
  width: 60px;
  height: 60px;
  margin: 0 10px 10px 0;
  padding: 0;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 2px;
  background: #fff;
  box-shadow: 0 0 0 2px #000;
  cursor: grab;
  touch-action: none;
  transform-origin: right bottom;
  transition: transform .2s ease;
}
.redrop:hover:not(:disabled), .redrop.corner-hot { background: #ebebeb; transform: none; box-shadow: 0 0 0 2px #000; }
.redrop:active { cursor: grabbing; }
/* Its label; the theme colours it. */
.redrop::after {
  content: "Re-drop";
  position: absolute;
  right: calc(100% + 6px);
  top: 50%;
  transform: translateY(-50%);
  padding: 3px 8px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 600;
  line-height: normal;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity .12s ease;
}
.redrop:hover::after, .redrop.corner-hot::after { opacity: 1; }
/* A tap leaves a touch screen "hovering" where it was, so no label there. */
@media (hover: none) { .redrop:hover:not(.corner-hot)::after { opacity: 0; } }
/* The Street View compass (see initMap), in the same control look. The needle points north,
   red end first. */
.compass {
  width: 48px;
  height: 48px;
  margin: 0 0 40px 16px; /* clear above the gear */
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 2px #000;
  cursor: pointer;
}
.compass:hover:not(:disabled) { background: #ebebeb; transform: none; box-shadow: 0 0 0 2px #000; }
.compass .needle {
  width: 100%;
  height: 100%;
  background:
    linear-gradient(to bottom, #d93025 50%, #555 50%) center / 8px 70% no-repeat;
  clip-path: polygon(50% 15%, 58% 50%, 50% 85%, 42% 50%);
}
/* Open, the minimap's pin is as big as the yellow man on the full map (its label scaled back). */
#game.map-open .redrop, #game.map-open .redrop:hover:not(:disabled) { transform: scale(3.2); box-shadow: 0 0 0 .7px #000; }
#game.map-open .redrop::after { font-size: 4px; padding: 1px 3px; right: calc(100% + 2px); border-radius: 1px; }
.redrop img { height: 44px; width: auto; pointer-events: none; }
/* The yellow man being carried: the box sits on the cursor, with him hanging over an ✕ there. */
.carry { position: fixed; z-index: 50; left: 0; top: 0; width: 0; height: 0; pointer-events: none; }
.carry img { position: absolute; left: -22px; bottom: 7px; width: 44px; height: 72px; filter: drop-shadow(0 4px 6px rgb(0 0 0 / .4)); }
/* Where he'll land: a bold dark X on the ground, like Google's own. */
.carry::after {
  content: "";
  position: absolute;
  left: -9px;
  top: -9px;
  width: 18px;
  height: 18px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 18'%3E%3Cpath d='M3 3l12 12M15 3L3 15' stroke='%23fff' stroke-width='6' stroke-linecap='round'/%3E%3Cpath d='M3 3l12 12M15 3L3 15' stroke='%23222' stroke-width='3.2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
}
body.carrying, body.carrying * { cursor: grabbing !important; }

#intro-dim {
  position: absolute;
  z-index: 3;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  backdrop-filter: blur(3px);
  transition: opacity .25s ease;
}
#game.intro #intro-dim { opacity: 1; pointer-events: auto; transition: none; }
/* The Street View keys, listed in the escape menu. */
#esc-keys { padding: 0 6px; display: grid; grid-template-columns: auto 1fr; gap: 6px 12px; align-items: center; margin: 0; font-size: 14px; }
#esc-keys[hidden] { display: none; }
#esc-keys dt { white-space: nowrap; }
#esc-keys dd { margin: 0; text-align: start; }
#esc-keys kbd { display: inline-block; min-width: 18px; margin-inline-end: 4px; padding: 0 4px; text-align: center; }

/* The round, the noun's card and the clock, at the top centre. The card, with the clock hanging
   under it, starts big in the middle of the screen (lifted by --lift, see liftCard), then rises
   to tuck in under the round, overlapping it a little. A theme that tilts the card repeats its
   transform with a rotate in. */
#banner {
  position: absolute;
  z-index: 5;
  left: 50%;
  top: 12px;
  transform: translate(-50%, 0);
  display: flex;
  flex-direction: column;
  align-items: center;
  max-width: calc(100% - 32px);
  text-align: center;
  transition: opacity .2s ease;
  pointer-events: none;
}
.banner-tile { position: relative; box-sizing: border-box; max-width: 100%; }
.banner-tile:empty { display: none; }
#banner-round {
  z-index: 0;
  padding: 1px 10px 8px;
  font-size: 12px;
  /* Once the card has landed up top, it slides up out from behind it. */
  transition: transform .45s cubic-bezier(.2, .8, .2, 1) .7s, opacity 0s .7s;
}
/* Through a round's intro it stays hidden, tucked behind the card. */
#banner.tiles-veiled #banner-round { opacity: 0; transform: translateY(100%); transition: none; }
/* The noun's tile: one box from the vote, through the flight to the middle, to the top of the
   screen. Only its size changes on the way, by scaling, so its text, shape and proportions
   stay the same. The theme draws it, the same everywhere. */
.noun-tile {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 120px;
  padding: 6px 22px 8px;
  white-space: nowrap;
  text-align: center;
}
.noun { font-size: 26px; line-height: 1.15; }
#banner-card {
  position: relative;
  z-index: 1;
  margin-top: -7px;
  transition: transform .7s ease, opacity .2s ease;
}
#banner-card > .noun-tile { position: relative; z-index: 1; }
#banner.center #banner-card { transform: translateY(var(--lift, 0)) scale(1.9); }
#banner.veiled { opacity: 0; }
/* The card fades out, but comes back at once: it appears in the winning tile's place, which
   is hidden in the same moment (see slideWinner). In the middle it's over the vote. */
#banner.center { z-index: 9; }
#banner.card-veiled #banner-card { opacity: 0; transition: transform .7s ease, opacity .2s ease; }
#banner:not(.card-veiled) #banner-card { transition: transform .7s ease; }
/* The countdown, then the clock: inside the card so it travels and grows with it, but hung
   below it as a tile of its own. In the middle it hangs clear of the card; up top it's a tab
   on the card's bottom edge, its top border on the card's and over the card's shadow. It
   fades in when it first shows. */
#banner-sub {
  position: absolute;
  z-index: 2;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  width: max-content;
  max-width: calc(100vw - 32px);
  margin-top: var(--tab-overlap, -2px);
  padding: 2.5px 12px 0;
  font-size: 12px;
  line-height: 1.25;
  transition: margin-top .7s ease;
  animation: tile-in .2s ease-out;
}
#banner.center #banner-sub { margin-top: 4px; }
@keyframes tile-in { from { opacity: 0; } }
.banner-small { font-size: 15px; font-variant-numeric: tabular-nums; }

/* The start of a round: voting on three nouns, over the dimmed, blurred map. No panel round
   them, just a small Choose or Vote tile above (drawn by the theme, like the round's). */
#chooser {
  position: absolute;
  z-index: 8;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: min(720px, calc(100% - 32px));
  text-align: center;
}
.chooser-title { width: fit-content; margin: 0 auto 18px; padding: 4px 20px 5px; }
#choices { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
/* Each choice is just the noun's tile with who voted for it underneath. The button itself is
   invisible, and hovering, picking, winning and losing only scale it. */
#choices .choice, #choices .choice:hover:not(:disabled), #choices .choice:active:not(:disabled), #choices .choice:disabled {
  min-height: 84px;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border: 0;
  background: none;
  box-shadow: none;
  color: inherit;
  font: inherit;
  transform: none;
  transition: transform .5s ease, opacity .5s ease;
}
#choices .choice:hover:not(:disabled) { transform: scale(1.04); }
#choices .choice.mine, #choices .choice.mine:hover:not(:disabled) { transform: scale(1.08); }
#choices .voters { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px; min-height: 0; }
#choices .voters .avatar { width: 32px; height: 32px; }
#choices .pick-mark { padding: 1px 8px; font-size: 13px; font-weight: 600; }
#choices .choice.win, #choices .choice.win:disabled { opacity: 1; transform: scale(1.12); }
#choices .choice.lose, #choices .choice.lose:disabled { opacity: .45; transform: scale(.94); }
/* Sliding the winner to the middle: the losers go quickly, the winner glides. */
#chooser.settle { pointer-events: none; }
#chooser.settle .choice.lose { opacity: 0; transition-duration: .25s; }
#chooser.revealed .chooser-title { visibility: hidden; }
/* The seconds left to pick, small after Choose or Vote in its tile. */
#chooser-time {
  margin-inline-start: 10px;
  font-size: 17px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
@media (max-width: 600px) {
  #choices { grid-template-columns: 1fr; }
  #choices .choice, #choices .choice:disabled { min-height: 52px; }
}
/* Time running low: a pulsing border round the whole screen (the theme draws it as a box-shadow). */
#game::after {
  content: "";
  position: absolute;
  z-index: 30;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity .3s ease;
}
#game.urgent::after { opacity: 1; animation: urgent-pulse 1s ease-in-out infinite alternate; }
@keyframes urgent-pulse { from { opacity: 1; } to { opacity: .6; } }

/* The HUD keeps its corners right to left (see the top): physical left and right. */
#hud-right {
  position: absolute;
  z-index: 4;
  top: 12px;
  right: 12px;
  display: flex;
  align-items: center;
  gap: 10px;
}
/* Bottom left, above the open minimap (z-index 6): the menu, and Give up beside it. */
#hud-left { position: absolute; z-index: 8; left: 12px; bottom: 24px; display: flex; align-items: center; gap: 8px; }
#menu-btn, #giveup { font-size: 18px; padding: 4px 10px; }
#giveup-yes { white-space: nowrap; }
.hud-btn { font-size: 14px; padding: 6px 12px; }
/* Above everything in the game, including the vote and the open minimap. */
#esc-backdrop {
  position: fixed;
  z-index: 20;
  inset: 0;
  display: grid;
  place-items: center;
}
#esc-backdrop[hidden] { display: none; }
#esc-menu {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
  width: min(300px, calc(100% - 32px));
  padding: 18px 20px 20px;
  text-align: center;
}
#esc-menu h2 { margin: 0 0 4px; }
#esc-menu button { font-size: 16px; padding: 8px 12px; }
#esc-menu .slider { margin: 4px 0; }
/* The languages, folded under their button, each in its own name. */
#lang-list { display: flex; flex-direction: column; gap: 4px; }
#lang-list[hidden] { display: none; }
#esc-menu #lang-list button { font-size: 14px; padding: 5px 10px; }
#lang-list [aria-pressed="true"] { font-weight: 700; }
#leave-confirm { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px; font-size: 15px; font-weight: 700; }
#leave-confirm[hidden] { display: none; }
/* The signed-in account in the menu: just the name and a link to the Account tab. */
#account-box { display: flex; align-items: center; justify-content: center; gap: 4px 10px; flex-wrap: wrap; padding: 4px 0 10px; font-size: 14px; overflow-wrap: anywhere; }
#esc-menu #account-box button { font-size: 14px; padding: 4px 6px; }
/* Friends to invite, folded under their button. */
#menu-friends-list { max-height: 40vh; overflow-y: auto; margin-top: 4px; }
#esc-menu .people button { font-size: 14px; padding: 5px 10px; }
/* Above the open minimap (z-index 6), which reaches under it. */
#spectate-bar {
  position: absolute;
  z-index: 7;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: calc(100% - 24px);
  padding: 8px 12px;
  white-space: nowrap;
}
/* Right to left, ◀ previous comes on the right: its arrow turns to point that way, and ▶ too. */
[dir="rtl"] #watch-prev, [dir="rtl"] #watch-next { scale: -1 1; }
#watch-shield { position: absolute; inset: 0; z-index: 1; display: none; cursor: default; }
#game.spectating #watch-shield { display: block; }
#game.spectating .street-only, #game.spectating #hint, #game.spectating #street-actions { display: none; }
.player.other-clickable { cursor: pointer; }
.eye {
  position: absolute;
  inset-inline-start: -8px;
  bottom: -8px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 11px;
}

#hint {
  position: absolute;
  z-index: 3;
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%);
  margin: 0;
  max-width: min(560px, calc(100% - 32px));
  padding: 8px 16px;
  pointer-events: none;
  text-align: center;
  font-size: 14px;
}
#hint:empty { display: none; }
/* Above the closed minimap, but under it once it's open (#game.map-open below). */
#street-actions {
  position: absolute;
  z-index: 7;
  left: 50%;
  bottom: 12px;
  transform: translateX(-50%);
  display: flex;
  gap: 12px;
}
#game.street.map-open #street-actions { z-index: 5; }
#street-actions button { padding: 10px 18px; font-size: 17px; }
#street-actions button.primary { font-size: 22px; }
/* A fifth bigger than the other buttons, everything included. */
#submit { position: relative; min-width: 130px; zoom: 1.2; }
/* The gap under Capture, down to the bottom of the screen, takes its clicks too (past the edge
   it's cut off, so it only needs to be long enough). */
#submit::after { content: ""; position: absolute; left: 0; right: 0; top: 100%; height: 16px; }
#game:not(.street) .street-only { display: none; }
#game:not(.playing) #hint, #game:not(.playing) #street-actions { display: none; }
#game.street .map-only { display: none; }

/* ---- a team game's words: in the middle as the hunt starts, then down the right ---- */
/* Down the right in any language: placed by physical left, to glide from the middle. */

#hunt-words {
  position: absolute;
  z-index: 4;
  left: calc(100% - 12px);
  top: 64px;
  width: 240px;
  max-height: calc(100% - 360px);
  overflow-y: auto;
  padding: 10px 14px 12px;
  transform: translate(-100%, 0) scale(1);
  transition: left .7s ease, top .7s ease, transform .7s ease;
}
/* On the full map only the yellow man's corner needs keeping clear. */
#game:not(.street) #hunt-words { max-height: calc(100% - 230px); }
/* Over the dimmed map at the start, as big as fits (--hw-scale, see renderHuntWords). */
#hunt-words.center {
  z-index: 8;
  left: 50%;
  top: 50%;
  max-height: none;
  overflow: visible;
  transform: translate(-50%, -50%) scale(var(--hw-scale, 1.4));
}
#game #hunt-words.final { max-height: calc(100% - 80px); }
.hw-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; margin: 0 0 6px; }
#hw-sub { font-size: 13px; font-variant-numeric: tabular-nums; white-space: nowrap; }
#hw-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
#hw-list li { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 24px; }
.hw-word { min-width: 0; overflow-wrap: anywhere; }
.hw-marks { flex: none; display: flex; align-items: center; gap: 4px; }
.hw-mark { display: grid; place-items: center; width: 20px; height: 20px; border-radius: 50%; font-size: 12px; font-weight: 800; line-height: 1; }
#hw-count { margin: 8px 0 0; font-size: 13px; }
/* At the end, each word is a button showing both teams' finds. */
#hunt-words.final #hw-list li { display: block; }
#hunt-words.final #hw-list button { width: 100%; display: flex; flex-direction: column; align-items: flex-start; gap: 2px; padding: 6px 10px; text-align: start; }
#hunt-words.final #hw-list li.hw-round { margin-top: 6px; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; }
#hunt-words.final #hw-list li.hw-round:first-child { margin-top: 0; }
.hw-finds { display: flex; flex-wrap: wrap; gap: 2px 10px; font-size: 12px; font-weight: 700; }
.hw-find.none { opacity: .5; }

/* Joining a hunt partway through: Red or Blue, over the dimmed map. */
#team-pick { position: absolute; z-index: 8; inset: 0; height: fit-content; width: min(480px, calc(100% - 32px)); margin: auto; text-align: center; }
#team-pick .team-pts { font-variant-numeric: tabular-nums; }

/* A team game's result, top middle. */
#team-final {
  position: absolute;
  z-index: 5;
  left: 50%;
  top: 12px;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Its own width, not what's left right of the middle. */
  width: max-content;
  max-width: calc(100% - 32px);
  padding: 6px 24px 8px;
  text-align: center;
  pointer-events: none;
}
.tf-head { font-size: 28px; line-height: 1.15; }
.tf-scores { font-size: 18px; font-weight: 700; font-variant-numeric: tabular-nums; }
.tf-sub { font-size: 14px; }
.team-score { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Teammates on the map (see drawMates): a dot in Street View, a ring on the map. Placed by left
   and top, so a hover can still use transform. */
.mates { position: absolute; left: 0; top: 0; }
.mate-dot {
  position: absolute;
  width: 32px;
  height: 32px;
  margin: -16px 0 0 -16px;
  padding: 0;
  border-radius: 50%;
  overflow: hidden;
  cursor: pointer;
}
.mate-dot.away { opacity: .45; }

/* The standings card, between rounds and at the end, each team's players ranked. The result up
   top stands in for the banner, and the card for the player list. */
#game.hunt-over #banner, #game.hunt-over #players, #game.hunt-over #players-pop { display: none; }
#game.hunt-over #overlay.recap { padding-left: 16px; padding-top: 64px; }
.team-standing { margin: 12px 0; padding-inline-start: 10px; }
#overlay .team-standing h3 { margin: 0 0 6px; }
#overlay .team-standing ol { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
#overlay .team-standing li { display: flex; align-items: center; gap: 8px; margin: 0; }
.team-standing .avatar { flex: none; width: 32px; height: 32px; }
.team-standing .name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.team-links { display: flex; flex-wrap: wrap; justify-content: center; gap: 0 12px; }

/* ---- players, top left, best score first ---- */
/* Top left in any language (the HUD keeps its corners); right to left each row runs from the
   icon on its right, and the rows line up on that side. */

#players {
  position: absolute;
  z-index: 4;
  left: 14px;
  top: 14px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  max-height: calc(100% - 28px);
  margin: 0;
  padding: 0;
  list-style: none;
}
.player { display: flex; flex-direction: column; align-items: center; width: 66px; }
/* In the game each player is a row: their icon, with name and score beside it. */
#players .player {
  zoom: 1.2;
  width: auto;
  display: grid;
  grid-template-columns: auto auto;
  grid-template-rows: auto auto;
  justify-content: start;
  justify-items: start;
  align-content: center;
  column-gap: 10px;
}
#players .avatar { grid-row: span 2; }
#players .player .name { align-self: end; max-width: 110px; margin-top: 0; }
#players .player .score { align-self: start; }
/* In a team game, each team's name and score above its players. */
.team-head { display: flex; align-items: baseline; gap: 8px; padding: 2px 10px; font-size: 13px; font-weight: 700; white-space: nowrap; }
#players .team-head { zoom: 1.2; margin-bottom: -4px; }
.team-head .score { font-variant-numeric: tabular-nums; }
/* A player's icon: their avatar on a plain background (the look's --avatar-bg), clipped round by
   the inner .face, so badges and status dots can hang off the edge of the .avatar itself. The
   drawing is head and shoulders, so small ones zoom in on the face. In a team game the ring is
   the team's colour (see the looks). */
.avatar {
  position: relative;
  flex: none;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--avatar-bg);
}
.face { position: absolute; inset: 0; border-radius: 50%; overflow: hidden; }
.face svg { display: block; width: 100%; height: 100%; transform: scale(1.15) translateY(5%); }
.people .face svg, #players-pop .face svg, #choices .voters .face svg, .team-standing .face svg, .entry > .avatar .face svg, #me-btn .face svg, .mate-dot .face svg {
  transform: scale(1.35) translateY(9%);
}
.player .name, .player .score {
  max-width: 66px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12px;
  line-height: 1.35;
  padding: 0 6px;
  margin-top: 6px;
}
.player .score { font-variant-numeric: tabular-nums; margin-top: 2px; }
.player.away { opacity: .45; }
.badge {
  position: absolute;
  inset-inline-end: -8px;
  top: -8px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 13px;
  font-weight: 700;
  line-height: normal;
}
.badge.judging::after {
  content: "";
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 2px solid;
  border-top-color: transparent;
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---- between-round and end-of-game overlay ---- */

#next-wrap {
  position: absolute;
  z-index: 9;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}
#next-wrap:empty { display: none; }
#next-wrap button { width: auto; min-width: 220px; margin: 0; padding: 13px 28px; }

#overlay {
  position: absolute;
  inset: 0;
  z-index: 8;
  display: flex;
  padding: 16px;
  overflow-y: auto;
}
#overlay h2 { margin: 0 0 4px; }
#overlay ol { padding-inline-start: 22px; }
#overlay li { margin: 4px 0; }
#overlay img { display: block; width: 100%; margin: 10px 0; }
#overlay-actions { display: flex; flex-direction: column; gap: 10px; margin-top: 14px; }
#overlay .card { width: min(760px, 100%); }
.entries {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 18px;
  margin: 14px 0 6px;
}
.entry { position: relative; margin: 0; }
#overlay .entry img { margin: 0; aspect-ratio: 4 / 3; object-fit: cover; cursor: zoom-in; }
.noimg { display: grid; place-items: center; aspect-ratio: 4 / 3; }
.entry figcaption { display: flex; flex-wrap: wrap; gap: 2px 8px; margin-top: 8px; font-size: 14px; }

/* ---- round recap on the map ---- */

#recap { position: absolute; inset: 0; z-index: 2; pointer-events: none; overflow: hidden; }
#recap.pass * { pointer-events: none !important; }
#recap-lines { position: absolute; inset: 0; width: 100%; height: 100%; }
.recap-pin {
  position: absolute;
  z-index: 1; /* above every card, so a pin is never hidden */
  left: -10px;
  top: -10px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  pointer-events: auto;
}
.recap-pin.top { width: 28px; height: 28px; left: -14px; top: -14px; }
/* Its width is set to suit the pane (see layoutRecap). */
.entry.recap-card {
  position: absolute;
  left: 0;
  top: 0;
  width: 380px;
  /* A card grows and shrinks with the map about its corner, where layoutRecap places it. */
  transform-origin: 0 0;
  cursor: grab;
  transform: none;
  pointer-events: auto;
}
.recap-card img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; cursor: zoom-in; user-select: none; }
.recap-card figcaption { font-size: 13px; }
.entry.recap-card.top-liked { z-index: 1; }
/* Our + and − for the map and Street View (see zoomButtons), in the same look as the compass. */
.zoom-ctl {
  display: flex;
  flex-direction: column;
  margin: 0 12px;
  border-radius: 10px;
  background: #fff;
  box-shadow: 0 0 0 2px #000, 0 3px 8px rgb(0 0 0 / .3);
  overflow: hidden;
}
.zoom-ctl button {
  width: 44px;
  height: 44px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: #fff;
  color: #222;
  box-shadow: none;
  font: 600 26px/1 system-ui, sans-serif;
  cursor: pointer;
}
.zoom-ctl button + button { border-top: 1.5px solid #c8c8c8; }
/* On a touch screen the ⟲ is on its own. */
.zoom-ctl button[hidden] + button { border-top: 0; }
.zoom-ctl .reset { font-size: 22px; }
/* While the recap is up its own copy of the map's buttons sits over its cards, where the map's
   were (see initMap). */
#recap-zoom { position: absolute; z-index: 3; right: 0; top: 50%; transform: translateY(-50%); }
#recap[hidden] + #recap-zoom { display: none; }
#game:has(> #recap:not([hidden])) #map .zoom-ctl { visibility: hidden; }
/* The dev-only place search (see devSearch), in the same look as the zoom buttons. */
.dev-search {
  /* Below the player badge in the top-left corner */
  margin: 76px 12px 12px;
  width: min(340px, calc(100vw - 100px));
  border-radius: 10px;
  background: #fff;
  color: #222;
  box-shadow: 0 0 0 2px #000, 0 3px 8px rgb(0 0 0 / .3);
  font: 14px/1.3 system-ui, sans-serif;
  overflow: hidden;
}
/* The map is only a minimap in Street View; search from the full map. */
#game.street .dev-search { display: none; }
.dev-search > div { display: flex; align-items: center; gap: 8px; padding: 6px 10px; }
.dev-search input[type="search"] { flex: 1; min-width: 0; margin: 0; padding: 6px 8px; border: 1.5px solid #c8c8c8; border-radius: 6px; font: inherit; color: inherit; background: #fff; }
.dev-search label { display: flex; align-items: center; gap: 4px; white-space: nowrap; font-size: 13px; }
.dev-search ol { margin: 0; padding: 0; list-style: none; max-height: 40vh; overflow-y: auto; }
.dev-search li { border-top: 1.5px solid #e2e2e2; padding: 6px 10px; font-size: 13px; }
.dev-search li:has(button) { padding: 0; }
.dev-search li button { display: block; width: 100%; margin: 0; padding: 6px 10px; border: 0; border-radius: 0; background: none; color: inherit; box-shadow: none; font: inherit; text-align: start; cursor: pointer; }
.dev-search li button:hover { background: #ebebeb; transform: none; box-shadow: none; }
.zoom-ctl button:hover:not(:disabled), .zoom-ctl button:active:not(:disabled) { background: #ebebeb; transform: none; box-shadow: none; }

.top-ribbon {
  position: absolute;
  top: -16px;
  left: 50%;
  transform: translateX(-50%);
  padding: 2px 12px;
  white-space: nowrap;
}

/* Between rounds the summary sits beside the map instead of covering it: right of the players'
   list, which is top left in any language, so physical. */
#overlay.recap { background: none; pointer-events: none; align-items: flex-start; padding-top: 100px; padding-left: calc(var(--players-w, 0px) + 28px); }
#game.final #overlay.recap { padding-left: 16px; }
#overlay.recap .card {
  width: 320px;
  margin: 0;
  max-height: calc(100% - 16px);
  overflow-y: auto;
  pointer-events: auto;
  transform: none;
}
#overlay.recap .entries { grid-template-columns: 1fr; }
.round-list { list-style: none; padding: 0 !important; margin: 8px 0; display: flex; flex-direction: column; gap: 8px; }
.round-list button { width: 100%; text-align: start; display: flex; flex-wrap: wrap; gap: 2px 8px; align-items: baseline; }
.entry-lines { list-style: none; padding: 0; margin: 8px 0; }
#overlay .entry-lines li { margin: 2px 0; }

/* ---- likes ---- */
.like-btn { margin-inline-start: auto; padding: 1px 10px; font-size: 14px; font-weight: 700; line-height: 1.4; }
.like-btn:disabled { cursor: default; opacity: 1; }

/* ---- final results: a bar along the top, and the rounds in a sidebar on the right ---- */
/* The podium says who played, and each submission wears its player's icon. */
#game.results #banner, #game.results #players, #game.results #players-pop { display: none; }
#results-bar {
  position: absolute;
  z-index: 4;
  top: 12px;
  left: 14px;
  right: 14px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  pointer-events: none;
}
#results-bar[hidden] { display: none; }
#results-bar > * { pointer-events: auto; }
.hud-note { padding: 6px 12px; border-radius: 6px; background: rgb(255 255 255 / .85); color: #333; font-size: 14px; }
/* On the right in any language, like the rest of the game screen. */
#rounds-panel {
  position: absolute;
  /* Over a solo game's results card, which a phone's sidebar would otherwise end under. */
  z-index: 9;
  top: 64px;
  right: 12px;
  bottom: 12px;
  width: min(320px, calc(100% - 24px));
  margin: 0;
  overflow-y: auto;
  animation: rounds-in .2s ease-out;
}
#rounds-panel[hidden] { display: none; }
@keyframes rounds-in { from { transform: translateX(40px); opacity: 0; } }
#rounds-panel h3 { margin-top: 0; }
.round-detail { padding: 6px 4px 2px; }
.round-detail .entries { display: grid; gap: 10px; }
/* A player's icon on the corner of their submission. */
.entry > .avatar { position: absolute; z-index: 1; inset-inline-start: -14px; top: -14px; width: 40px; height: 40px; }
/* On the map a card's placed by its top left corner (see layoutRecap), so its icon stays there. */
.entry.recap-card > .avatar { inset-inline-start: auto; left: -14px; }
.round-detail .entry { position: relative; }

/* ---- final podium, bottom middle ---- */
#game.final #players, #game.final #players-pop { display: none; }
#podium {
  position: absolute;
  z-index: 9;
  left: 50%;
  bottom: 0;
  transform: translateX(-50%);
  display: flex;
  align-items: flex-end;
  gap: 18px;
  max-width: calc(100% - 16px);
  pointer-events: none;
}
#podium[hidden] { display: none; }
#podium > * { pointer-events: auto; }
#podium .steps { display: flex; align-items: flex-end; }
#podium .sides { display: flex; flex-wrap: wrap-reverse; align-items: flex-end; gap: 10px; padding-bottom: 14px; max-width: calc(50vw - 220px); }
#podium .sides.left { justify-content: flex-end; }
#podium .step { display: flex; flex-direction: column; align-items: center; width: 130px; }
#podium .stander, #podium .side { display: flex; flex-direction: column; align-items: center; gap: 3px; padding-bottom: 8px; }
#podium .side { width: 78px; }
#podium .name, #podium .score, #podium .rank {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 0 8px;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.4;
}
#podium .name { margin-top: 6px; }
#podium .score { font-variant-numeric: tabular-nums; }
#podium .avatar { width: 64px; height: 64px; }
#podium .side .avatar { width: 48px; height: 48px; }
#podium .place-1 .avatar { width: 84px; height: 84px; }
#podium .crown { font-size: 30px; line-height: 1; margin-bottom: -4px; }
#podium .block { width: 100%; display: grid; place-items: start center; padding-top: 8px; font-size: 34px; line-height: 1; }
#podium .place-1 .block { height: 150px; }
#podium .place-2 .block { height: 105px; }
#podium .place-3 .block { height: 72px; }
.most-liked { padding: 1px 8px; font-size: 12px; font-weight: 800; white-space: nowrap; }

dialog { max-width: min(640px, calc(100vw - 32px)); padding: 20px; }
dialog h2 { margin: 12px 0 4px; }
#result-img { display: block; width: 100%; }
#result-reason { margin: 0 0 12px; }
/* A submission's photo seen large, sized to the screen by showResult. */
#result.big { box-sizing: border-box; max-width: none; }
#result.big #result-img { aspect-ratio: 4 / 3; object-fit: cover; }

/* Friends' invites, under where the toasts go. */
#invites {
  position: fixed;
  left: 50%;
  top: 160px;
  z-index: 21;
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: min(340px, calc(100vw - 32px));
  transform: translateX(-50%);
  pointer-events: none;
}
.invite-card { padding: 12px 14px; pointer-events: auto; overflow-wrap: anywhere; }
.invite-card p { margin: 0 0 8px; }
.invite-actions { display: flex; gap: 8px; }
.invite-actions button { flex: 1; }

#toast {
  position: fixed;
  left: 50%;
  top: 100px;
  z-index: 20;
  transform: translateX(-50%);
  max-width: calc(100vw - 32px);
  padding: 10px 16px;
}

@media (max-width: 600px) {
  #banner.center #banner-card { transform: translateY(var(--lift, 0)) scale(1.4); }
  .noun { font-size: 22px; }
  #banner { top: 8px; }
  /* No room beside the banner on a phone, so it goes under it. */
  #hud-right { top: 90px; flex-direction: column; align-items: flex-end; }
  .player { width: 54px; }
  .avatar { width: 40px; height: 40px; }
  .avatar .face svg { transform: scale(1.35) translateY(9%); }
  /* Under the banner on a phone. */
  #players { top: 150px; }
  #players .player { zoom: 1; }
  #overlay.recap { align-items: flex-end; padding-top: 16px; padding-left: 16px; }
  #overlay.recap .card { width: 100%; max-height: 40vh; }
  #podium { gap: 6px; zoom: .62; max-width: calc(161% - 16px); }
  #game.final #overlay.recap { align-items: flex-start; }
  #game.final #overlay.recap .card { max-height: 34vh; }
  #game.street #map-box { width: 226px; height: 181px; }
  #spectate-bar { bottom: 16px; flex-wrap: wrap; justify-content: center; white-space: normal; }
}

/* ---- phones ---- */

/* Phone-only pieces, off everywhere else. */
#map-icon { display: none; }
/* Hung under the players' icons, top left in any language. */
#players-pop {
  position: absolute;
  z-index: 10;
  left: 8px;
  top: 56px;
  width: min(300px, calc(100% - 16px));
  max-height: calc(100% - 140px);
  overflow-y: auto;
  padding: 10px 12px;
}
#players-pop ol { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
#players-pop .player { width: auto; flex-direction: row; gap: 10px; }
#players-pop .avatar { flex: none; width: 36px; height: 36px; }
#players-pop .badge { width: 18px; height: 18px; inset-inline-end: -6px; top: -6px; font-size: 10px; }
#players-pop .player .name { flex: 1; max-width: none; margin: 0; font-size: 15px; border: 0; background: none; }
#players-pop .player .score { margin: 0; max-width: none; font-size: 15px; }

/* Matches PHONE in app.js: a narrow screen, or a phone on its side. */
@media (max-width: 600px), (max-height: 500px) {
  /* The opening map's corner yellow man, 60% smaller than on a big screen. */
  #game:not(.street) .gm-svpc { transform: scale(1.92); }
  #game:not(.street) .gm-svpc { box-shadow: 0 0 0 1px #000 !important; }

  /* In Street View the minimap is a map icon in the corner, and a tap slides it up from the
     bottom across the lower three quarters of the screen. */
  #game.street #map-box, #game.street.map-open #map-box { padding: 0; transition: none; }
  #game.street:not(.map-open) #map-box { right: 12px; bottom: 24px; width: 56px; height: 56px; }
  #game.street:not(.map-open) #map { visibility: hidden; }
  #game.street:not(.map-open) #map-icon { display: grid; }
  #map-icon { position: absolute; inset: 0; place-items: center; padding: 0; }
  #map-icon svg { width: 30px; height: 30px; }
  #game.street.map-open #map-box { left: 8px; right: 8px; bottom: 16px; width: auto; height: 75%; animation: map-slide-up .25s ease-out; }
  @keyframes map-slide-up { from { transform: translateY(calc(100% + 16px)); } }
  /* On a phone on its side there's no room for that, so it reaches up to just under the noun,
     and Submit moves left of the map icon. */
  @media (max-height: 500px) {
    #game.street.map-open #map-box { bottom: 8px; height: calc(100% - 96px); }
    #street-actions { left: auto; right: 80px; transform: none; }
  }
  /* The re-drop pin, a little bigger than the corner yellow man on the opening map. */
  #game.map-open .redrop, #game.map-open .redrop:hover:not(:disabled) { transform: scale(1.28); box-shadow: 0 0 0 1.6px #000; }
  #game.map-open .redrop::after { font-size: 9px; padding: 2px 6px; right: calc(100% + 4px); }
  /* Clear of the map icon. */
  #street-actions { max-width: calc(100% - 160px); }
  #submit { min-width: 0; zoom: 1; }
  #street-actions button.primary { font-size: 20px; padding: 10px 22px; }

  /* Up top: the players' icons left of the noun and Spectate right of it. */
  #banner { top: 8px; max-width: calc(100% - 200px); }
  #banner-sub { max-width: calc(100vw - 200px); }
  .noun-tile { padding: 4px 12px 6px; }
  .noun { font-size: 20px; }
  #hud-right { top: 14px; right: 8px; flex-direction: column; align-items: flex-end; }
  #players {
    top: 18px;
    left: 8px;
    flex-direction: row;
    align-items: center;
    gap: 0;
    max-width: calc(50% - 104px);
    cursor: pointer;
  }
  /* Each icon takes less room as more players join, so they overlap to fit. */
  #players .player { zoom: 1; display: flex; flex: 0 1 34px; min-width: 6px; width: auto; }
  #players .avatar { width: 34px; height: 34px; flex: none; }
  #players .player .name, #players .player .score { display: none; }
  #players .badge { width: 16px; height: 16px; inset-inline-end: -5px; top: -5px; font-size: 9px; }
  #players .badge.judging::after { width: 6px; height: 6px; }
  #players .eye { width: 16px; height: 16px; inset-inline-start: -5px; bottom: -5px; font-size: 8px; }
  /* Spectating: ◀ name ▶ on one line, Stop under them, between the gear and the map icon. */
  #spectate-bar { left: 64px; right: 80px; transform: none; flex-wrap: wrap; justify-content: center; white-space: normal; }
  #spectate-bar > span { flex: 1; text-align: center; }
  #watch-stop { flex-basis: 100%; }
  /* Stacked down the right edge, they keep to it right to left too. */
  [dir="rtl"] #hud-right { align-items: flex-start; }
  /* The round summary sits above the Next round button, not under it. */
  #overlay.recap { padding-bottom: 96px; }

  /* A team game: just the icons up top, each ringed in its team's colour. */
  #players .team-head { display: none; }
  /* Just the scores and the clock in the banner. */
  #game.hunt #banner-round { display: none; }
  #game.hunt #banner-noun { font-size: 16px; }
  /* The words tuck in on the right, smaller. */
  #hunt-words { top: 104px; left: calc(100% - 8px); width: min(200px, 44vw); max-height: calc(100% - 200px); padding: 8px 10px; font-size: 13px; }
  #game:not(.street) #hunt-words { max-height: calc(100% - 220px); }
  /* At the end they're a strip along the top, under the result. */
  #game #hunt-words.final {
    top: 150px; left: 8px; width: auto; right: 8px; max-height: none; transform: none; transition: none;
  }
  #hunt-words.final #hw-list { flex-direction: row; overflow-x: auto; }
  #hunt-words.final #hw-list li { flex: none; }
  #hunt-words.final #hw-count { display: none; }
  #team-final { top: 52px; padding: 4px 14px 6px; }
  .tf-head { font-size: 20px; }
  .tf-scores { font-size: 15px; }
  #game.hunt-over #overlay.recap { padding-top: 16px; }
}

/* Home, signed out: signing up, or signing in. */
#signup-tab .field { margin: 14px 0 12px; }
#signup-gsi-btn, #signin-gsi-btn { min-height: 44px; display: flex; justify-content: center; }
.card.account p button.link { padding: 0 2px; font-size: inherit; }

/* ---- the friends bar, down the right of the landing page while signed in (the left, right to left) ---- */

:root { --bar-w: 288px; }
#friends-bar {
  position: fixed;
  top: 0;
  inset-inline-end: 0;
  bottom: 0;
  z-index: 6;
  display: flex;
  flex-direction: column;
  width: var(--bar-w);
  text-align: start;
}
.bar-top { display: flex; flex-direction: column; gap: 8px; padding: 14px 14px 8px; }
.bar-top input { margin: 0; padding: 8px 10px; }
#friend-add-btn { width: 100%; }
#friend-add-form { padding: 0 14px; }
#friend-add-form .field { margin: 0; }
#friend-my-code { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; margin: 8px 14px 0; font-size: 14px; }
#friend-my-code[hidden] { display: none; }
#friend-my-code .friend-code { font-size: 18px; }
#friend-my-code button { margin-inline-start: auto; padding: 4px 10px; }
#friend-error { margin: 6px 14px 0; font-size: 14px; }
.bar-body { flex: 1; min-height: 0; overflow-y: auto; padding: 0 14px 8px; }
.bar-body h3 { display: flex; align-items: center; gap: 6px; margin: 12px 0 0; font-size: 16px; }
#outgoing-wrap { margin-top: 12px; }
#outgoing-wrap summary { cursor: pointer; font-size: 14px; font-weight: 700; }
#friends-bar .people li { flex-wrap: nowrap; gap: 8px; padding: 6px 0; }
#friends-bar .people li.empty { white-space: normal; }
#friends-bar .person-info { flex: 1 1 auto; }
#friends-bar .person-actions button { font-size: 13px; padding: 4px 8px; }
#friends-bar #incoming li { flex-wrap: wrap; }
/* Online or not, on a friend's icon. */
.status-dot { position: absolute; inset-inline-end: -1px; bottom: -1px; width: 11px; height: 11px; border-radius: 50%; border: 2px solid; }
.people li.offline .avatar:has(.status-dot) { opacity: .6; }
/* A friend's ⋯ menu: Remove friend, under the button. */
.row-menu-wrap { position: relative; }
#friends-bar .row-more { padding: 4px 8px; line-height: 1; }
.row-menu { position: absolute; z-index: 2; top: calc(100% + 4px); inset-inline-end: 0; padding: 4px; white-space: nowrap; }
.row-menu button { width: 100%; text-align: start; }
/* You, at the bottom; the menu opens upward from it. */
#me-box { position: relative; padding: 10px 14px 14px; }
#me-btn { display: flex; align-items: center; gap: 10px; width: 100%; padding: 6px 10px; text-align: start; }
#me-btn .avatar { width: 32px; height: 32px; }
#me-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#me-btn[aria-expanded="true"] .me-arrow { transform: rotate(180deg); }
#me-menu { position: absolute; left: 14px; right: 14px; bottom: calc(100% - 4px); display: flex; flex-direction: column; gap: 4px; padding: 6px; }
#me-menu button { width: 100%; text-align: start; }
#friends-toggle { position: absolute; top: 12px; inset-inline-end: 12px; font-size: 18px; padding: 4px 10px; }
#friends-scrim { position: fixed; inset: 0; z-index: 6; }
/* On a phone it's a drawer, opened by the 👥 button top right. */
/* The rest of the landing page keeps out of its way. */
@media (min-width: 641px) {
  #friends-toggle { display: none; }
  #landing.has-bar { padding-inline-end: calc(var(--bar-w) + 16px); }
  #landing.has-bar #site-tabs { left: calc(50% - var(--bar-w) / 2); }
  [dir="rtl"] #landing.has-bar #site-tabs { left: calc(50% + var(--bar-w) / 2); }
}
@media (max-width: 640px) {
  #friends-bar { z-index: 12; width: min(var(--bar-w), 88vw); transform: translateX(100%); transition: transform .2s; visibility: hidden; }
  [dir="rtl"] #friends-bar { transform: translateX(-100%); }
  #friends-bar.open { transform: none; visibility: visible; }
  #friends-scrim { z-index: 11; }
}

/* Zoomed past what Street View draws: the scenery enlarged about the middle, drawn over
   Google's (see `enlarged` in app.js). The arrows along the road stay over it as they are:
   Google puts them in the same place at any zoom. */
#pano canvas.enlarged { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }

/* ---- challenges ---- */

/* A challenge's three words keep their colours everywhere, the same in every look: chips, the
   colour key and the dots on the map. Amber, blue and pink stand apart from each other, from
   the map's greens and blues and from the red circles. --word-ink is the text on a filled chip. */
:root { --word-1: #f08c00; --word-2: #1c7ed6; --word-3: #d6336c; }
:is(.word-chip, .ch-dot, .ch-face).w0 { --word: var(--word-1); --word-ink: #1f1a10; }
:is(.word-chip, .ch-dot, .ch-face).w1 { --word: var(--word-2); --word-ink: #fff; }
:is(.word-chip, .ch-dot, .ch-face).w2 { --word: var(--word-3); --word-ink: #fff; }
.word-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 0 8px;
  border: 2px solid var(--word);
  border-radius: 99px;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.45;
  white-space: nowrap;
}
.word-chip.found { background: var(--word); color: var(--word-ink); }
.word-chip.open { border-color: currentColor; opacity: .45; }
.word-chip.key::before { content: ""; width: 10px; height: 10px; border-radius: 50%; background: var(--word); }
.word-chip .tick { font-weight: 800; }

/* The menu, in the Game tab's card, made wider for the leaderboard. */
#game-tab.wide { width: min(640px, 100%); }
#challenges-btn { position: relative; width: 100%; margin-top: 8px; }
.new-dot {
  position: absolute;
  top: -5px;
  inset-inline-end: -5px;
  width: 14px;
  height: 14px;
  border: 2px solid var(--paper);
  border-radius: 50%;
  background: var(--map-danger);
}
#challenges-view h2 { margin: 6px 0 0; }
#challenges-view > p { margin: 2px 0 0; }
.ch-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin: 12px 0 0; }
.ch-card { display: flex; flex-direction: column; gap: 2px; min-width: 0; padding: 10px 14px 12px; cursor: pointer; text-align: start; }
.ch-card h3 { margin: 0; }
.ch-card p { margin: 0; }
.ch-card button { margin-top: 8px; }
.ch-status { font-weight: 700; }
.ch-cards > p { grid-column: 1 / -1; }
@media (max-width: 480px) { .ch-cards { grid-template-columns: 1fr; } }
.ch-switches { display: flex; flex-wrap: wrap; gap: 0 20px; }
.ch-switches .mode-switch { flex: 1 1 150px; gap: 4px; margin: 8px 0 0; }
.ch-switches .mode-switch button { font-size: 14px; padding: 5px 8px; }
.ch-board-words { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-height: 0; margin: 10px 0 0; font-size: 14px; }
.ch-board-words:empty { display: none; }
.ch-rows { list-style: none; margin: 6px 0 0; padding: 0; text-align: start; }
.ch-row {
  display: grid;
  grid-template-columns: 2em 36px minmax(0, 1fr) auto 3em;
  align-items: center;
  gap: 10px;
  padding: 6px 4px;
}
.ch-row .avatar { width: 36px; height: 36px; }
.ch-row .face svg { transform: scale(1.35) translateY(9%); }
.ch-rank { text-align: center; font-weight: 700; font-variant-numeric: tabular-nums; }
.ch-who { display: flex; flex-direction: column; min-width: 0; overflow-wrap: anywhere; line-height: 1.3; }
.ch-progress { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; margin-top: 3px; font-size: 12px; }
.ch-progress .word-chip { font-size: 12px; padding: 0 6px; border-width: 1.5px; }
.ch-time { font-weight: 700; font-variant-numeric: tabular-nums; }
.ch-streak { text-align: end; font-size: 14px; white-space: nowrap; }
.ch-row.opens { cursor: pointer; }
.ch-gap { text-align: center; line-height: 1; }
.ch-rows .empty { padding: 8px 0; font-size: 14px; }
#ch-back { display: block; margin: 10px auto 0; }

/* A run: the game screen without a room's pieces, the words as chips on the banner's card. */
#game.challenge :is(#players, #players-pop, #hud-right, #giveup, #giveup-yes, #chooser, #hunt-words, #team-pick,
  #team-final, #recap, #recap-zoom, #podium, #results-bar, #rounds-panel, #overlay, #next-wrap, #spectate-bar, #intro-dim) {
  display: none !important;
}
#game.challenge #banner-noun { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px 8px; }
#game.challenge .noun-tile { white-space: normal; }
#game.challenge #banner-noun .word-chip { padding: 1px 12px; font-size: 20px; line-height: 1.3; }
#game.challenge #banner-noun .word-chip.todo { border-style: dashed; }

/* The end, or a player's finds: a card top left over the world map, and no banner. */
#game.ch-map #banner { display: none; }
#ch-panel {
  position: absolute;
  z-index: 6;
  top: 12px;
  inset-inline-start: 12px;
  width: min(340px, calc(100% - 24px));
  max-height: calc(100% - 96px);
  margin: 0;
  overflow-y: auto;
  padding: 18px 20px;
}
#ch-panel h2 { margin: 0; }
.ch-big-time { margin: 6px 0; font-size: 40px; font-weight: 800; line-height: 1.1; font-variant-numeric: tabular-nums; }
.ch-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ch-stats dd { font-size: 20px; }
.ch-key { display: flex; flex-wrap: wrap; gap: 6px; margin: 12px 0 4px; }
#ch-panel .muted { margin: 6px 0 0; }
.ch-player { display: flex; align-items: center; gap: 12px; }
.ch-player h2 { overflow-wrap: anywhere; }
.ch-player p { margin: 0; }
@media (max-width: 600px) { #ch-panel { padding: 12px 14px; } .ch-big-time { font-size: 30px; } }

/* The finds on the map (see drawChallengeFinds): a dot in its word's colour, or a face in a ring
   of it, named on hover. Placed by left and top, like teammates' dots. */
.ch-finds { position: absolute; left: 0; top: 0; }
.ch-dot {
  position: absolute;
  width: 10px;
  height: 10px;
  margin: -5px 0 0 -5px;
  border-radius: 50%;
  background: var(--word);
  box-shadow: 0 0 0 1.5px #fff, 0 1px 3px rgb(0 0 0 / .4);
  pointer-events: none;
}
.ch-face {
  position: absolute;
  width: 30px;
  height: 30px;
  margin: -15px 0 0 -15px;
  border-radius: 50%;
  background: var(--avatar-bg);
  box-shadow: 0 0 0 3px var(--word), 0 0 0 4.5px #fff, 0 2px 6px rgb(0 0 0 / .45);
}
.ch-face.me { width: 38px; height: 38px; margin: -19px 0 0 -19px; }
.ch-face .face svg { transform: scale(1.35) translateY(9%); }
.ch-face:hover { z-index: 1; }
.ch-face::after {
  content: attr(data-name);
  position: absolute;
  left: 50%;
  bottom: calc(100% + 8px);
  transform: translateX(-50%);
  padding: 2px 8px;
  border-radius: 6px;
  background: rgb(0 0 0 / .8);
  color: #fff;
  font-size: 13px;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity .1s;
}
.ch-face:hover::after { opacity: 1; }
