/* PinPonder solo interface — visual polish layer. Loaded LAST by interface-preview.html.
 *
 * Scope: presentation only. This file restyles the chrome around the photograph — header, HUD,
 * dialogs, result and map panel, passport badges — so the game reads as one finished product in
 * the same palette as the public site, and adds the one "Play with friends" entry point to
 * /multiplayer that the markup already carries.
 *
 * Deliberately NOT touched here:
 *   - the photographs and the MapLibre tiles: no filter, overlay or tint is applied to either;
 *   - the map's own attribution strip (.maplibregl-ctrl-attrib) and the map-overlay legends, which
 *     stay legible against the light map;
 *   - any [hidden] rule, round guard, saved-game field, DOM id or controller behaviour. Every
 *     selector below is a paint change, and no rule adds or removes layout that the tested
 *     interface depends on.
 *
 * Palette: Destination Earth. Ground #101C34, panel #172B49, soft panel #13243E, muted #B7C9E2,
 * text #F7FAFF, a blue primary action with white copy (#2363D7 / #2B70DF), link and display accent
 * #87BDFF, rewards and earned marks #78DDA5, and the red-pin alert #FF7D87.
 */

/* ------------------------------------------------------------------------------------------------
 * Ground and surfaces
 * ---------------------------------------------------------------------------------------------- */

:root {
  /* The game's own chrome is dark, so native controls, scrollbars and carets follow suit. The map
   * and its attribution keep their own explicit light colours and are not affected. */
  color-scheme: dark;
  --pp-polish-ink: #101c34; /* ground */
  /* The flat surface the opaque brand lockup sits on. It is the artwork's own background navy, so a
   * header painted with it shows no contrasting rectangle around the logo. */
  --pp-brand-surface: #0c1e3c;
  --pp-polish-panel: #172b49; /* panel */
  --pp-polish-panel-soft: #13243e; /* soft panel */
  --pp-polish-panel-raised: #1d3556; /* raised panel, for a hover on a panel */
  --pp-polish-muted: #b7c9e2;
  --pp-polish-text: #f7faff;
  --pp-polish-primary: #2363d7;
  --pp-polish-primary-hover: #2b70df;
  --pp-polish-primary-deep: #1e56bc;
  --pp-polish-on-primary: #ffffff;
  --pp-polish-accent: #87bdff; /* links, hovers and display accents */
  --pp-polish-accent-hover: #b9dbff;
  --pp-polish-success: #78dda5; /* score, rewards, earned badges, progress */
  --pp-polish-alert: #ff7d87; /* the red-pin family: errors and destructive actions */
  --pp-polish-alert-text: #ffb3ba;
  --pp-polish-line: #2b4669;
  --pp-polish-line-strong: #3c5c88;
  /* The lighter hairline is for panel and section rules. Outlines that identify a control — a
   * button edge, a select, a focus ring — use this, which clears 3:1 on the ink ground. */
  --pp-polish-line-control: #6687b2;
  --pp-polish-focus: #a8d5ff;
  --pp-polish-dim: #7e92b4; /* a visibly muted disabled control */
  --pp-polish-shadow: 0 20px 46px rgb(3 9 22 / 46%);
  --pp-polish-radius: 14px;
  --pp-polish-radius-lg: 18px;
  --pp-polish-radius-sm: 12px;
  --pp-polish-fast: 160ms;
  /* The second ink of the light controls: the phone map launcher's 10px hint line, which cannot
   * take the full-strength ground navy without reading as loud as its own label. */
  --pp-polish-ink-soft: #53647b;

  /* tokens.css describes a light photographic surface. The chrome around the photograph is dark, so
   * the interface tokens are re-pointed at the Destination Earth palette here, in the last-loaded
   * presentation layer, instead of editing tokens.css. This is also what stops the last few
   * uncovered rules in interface.css and solo.css (a caption here, a disabled select there) from
   * painting dark-on-dark. The light map surface keeps its own explicit colours; the three tokens it
   * does read — the answer marker, the guess pin and the focus ring — are handled below. */
  --pp-canvas: #101c34;
  --pp-surface: #172b49;
  --pp-ink: #f7faff;
  --pp-muted: #b7c9e2;
  --pp-line: #2b4669;
  --pp-primary: #2363d7;
  --pp-primary-hover: #2b70df;
  --pp-primary-soft: #13243e;
  --pp-success: #78dda5;
  --pp-success-soft: #13243e;
  --pp-guess: #ff7d87;
  --pp-focus: #a8d5ff;
}

/* The guess pin and its legend swatch keep the logo's own red-pin family, and stay distinct from the
 * blue answer marker. Both are markers drawn over the map, never tiles, so only their fill changes. */
.draft-marker svg path {
  fill: var(--pp-polish-alert);
}

.map-legend i {
  background: var(--pp-polish-alert);
}

/* The answer marker's soft halo follows the theme's primary blue instead of the retired one. */
.answer-marker {
  box-shadow: 0 0 0 3px rgb(35 99 215 / 16%);
}

/* The map canvas, its attribution, the skip link and every control floating on the picture or the
 * light map sit on light surfaces, so their focus rings keep a darker blue than the one the dark
 * chrome uses. */
.world-map .maplibregl-canvas:focus-visible,
.world-map .maplibregl-ctrl-attrib a:focus-visible,
.view-controls > .icon-button:focus-visible,
.control-stack .icon-button:focus-visible,
.map-zoom button:focus-visible,
#map-retry:focus-visible,
.skip:focus-visible {
  outline-color: var(--pp-polish-primary-hover);
}

body {
  background: var(--pp-polish-ink);
}

.game {
  background: var(--pp-polish-ink);
}

.panorama,
.pnlm-container {
  background: #0b1427;
}

/* ------------------------------------------------------------------------------------------------
 * Header
 * ---------------------------------------------------------------------------------------------- */

#topbar {
  /* The header's own surface and the tokens interface.css scopes to it are the last inherited
   * teal chrome in the game: the panel fill and these five values bring the header onto the
   * Destination Earth palette without touching interface.css itself. */
  --pp-surface: var(--pp-polish-panel);
  --pp-ink: var(--pp-polish-text);
  --pp-muted: var(--pp-polish-muted);
  --pp-line: var(--pp-polish-line);
  --pp-primary: var(--pp-polish-accent);
  --pp-primary-soft: var(--pp-polish-panel-soft);
  --pp-focus: var(--pp-polish-focus);
  background: var(--pp-brand-surface);
  color: var(--pp-polish-text);
  border-bottom-color: var(--pp-polish-line);
  box-shadow: 0 10px 30px rgb(3 9 22 / 38%);
}

/* The approved full lockup — rounded Earth, pin and wordmark in one image. Intrinsic ratio comes
 * from the artwork, whose width/height attributes are the real 900x300 export: no tile, radius or
 * shadow, and no live type beside it, so the name is never printed twice. The link itself keeps the
 * accessible name "PinPonder home". */
#topbar .brand-lockup {
  display: block;
  width: 176px;
  height: auto;
  max-width: 100%;
  object-fit: contain;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}

#topbar .round-label {
  color: var(--pp-polish-muted);
}

#topbar .round-value,
#topbar .score-top strong {
  color: var(--pp-polish-text);
  font-variant-numeric: tabular-nums;
}

#topbar .score-top {
  border-left-color: var(--pp-polish-line);
}

/* Round progress: the round in play takes the accent, finished rounds take the reward green, and
 * the rest sit on the hairline. interface.css paints the first dot in the header's primary colour,
 * which the #topbar token scope above already points at the accent, and reverts it to a teal once a
 * later dot is current — that one teal is replaced here. */
#topbar .round-dots i,
#topbar .round-dots:has(.current) i:first-child:not(.current):not(.complete) {
  background: var(--pp-polish-line-strong);
}

#topbar .round-dots i.complete {
  background: var(--pp-polish-success);
  opacity: 0.6;
}

#topbar .round-dots i.current {
  background: var(--pp-polish-accent);
  opacity: 1;
}

/* The header's mode and timer chips still carry light-theme fills from solo.css; both live only in
 * the topbar, so a scoped repaint is enough. The urgent timer is the one genuine alert there. */
#topbar .solo-mode {
  color: var(--pp-polish-muted);
  background: var(--pp-polish-panel-soft);
  border-color: var(--pp-polish-line);
}

#topbar .solo-timer {
  color: var(--pp-polish-text);
}

#topbar .solo-timer[data-urgent='true'] {
  color: var(--pp-polish-alert-text);
  background: rgb(255 125 135 / 14%);
  border-color: rgb(255 125 135 / 45%);
}

#topbar .nav-divider {
  background: var(--pp-polish-line);
}

/* On phones solo.css draws the header's second row with a light-theme hairline, and interface.css
 * only replaces that colour in its 681-980px range. This carries it to every width. */
#topbar:has(#solo-menu-button) .progress {
  border-top-color: var(--pp-polish-line);
}

#topbar .nav-controls .icon-button {
  border-radius: var(--pp-polish-radius-sm);
  color: var(--pp-polish-muted);
  transition:
    background-color var(--pp-polish-fast) ease,
    color var(--pp-polish-fast) ease;
}

#topbar .nav-controls .icon-button:hover {
  background: var(--pp-polish-panel-raised);
  color: var(--pp-polish-text);
}

#topbar .nav-controls #solo-menu-button {
  color: var(--pp-polish-accent);
  background: var(--pp-polish-panel);
  border-radius: var(--pp-polish-radius-sm);
  box-shadow: inset 0 0 0 1px var(--pp-polish-line-strong);
}

#topbar .nav-controls #solo-menu-button:hover {
  background: #24406b;
}

#topbar .nav-controls #solo-menu-button[aria-expanded='true'] {
  color: var(--pp-polish-ink);
  background: var(--pp-polish-accent);
}

/* The one new entry point: a real link back to the other way to play, with no controller hook. */
#topbar .topbar-party-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 14px;
  border: 1px solid rgb(135 189 255 / 45%);
  border-radius: 999px;
  color: var(--pp-polish-accent);
  background: rgb(135 189 255 / 11%);
  font-size: 12px;
  font-weight: 650;
  line-height: 1.2;
  text-decoration: none;
  white-space: nowrap;
  transition:
    background-color var(--pp-polish-fast) ease,
    border-color var(--pp-polish-fast) ease,
    color var(--pp-polish-fast) ease;
}

#topbar .topbar-party-link:hover {
  border-color: var(--pp-polish-accent);
  background: rgb(135 189 255 / 16%);
  color: var(--pp-polish-accent-hover);
}

/* Still centred when pressed: the anchor's own transform is left alone. */
#topbar .topbar-party-link:active {
  background: rgb(135 189 255 / 24%);
}

#topbar .topbar-party-link .icon {
  width: 18px;
  height: 18px;
}

/* ------------------------------------------------------------------------------------------------
 * Photograph chrome — controls floating on the picture keep their light, high-contrast treatment.
 * ---------------------------------------------------------------------------------------------- */

.view-controls > .icon-button,
.control-stack {
  border-color: var(--pp-polish-line-strong);
  border-radius: var(--pp-polish-radius);
  background: var(--pp-photo-control);
  box-shadow: 0 6px 20px rgb(3 9 22 / 46%);
}

/* Every control that floats on the light picture or the light map takes dark navy ink. The reset
 * button already did; the zoom stack beside it and the map's own +/- pair are the two that did not,
 * because they inherit the dark chrome's near-white ink and paint white strokes on a white fill. */
.view-controls > .icon-button,
.control-stack .icon-button,
.map-zoom button {
  color: var(--pp-polish-ink);
}

/* Hover and focus keep that ink. The light fills they land on are already right, so the glyph must
 * not flip back to the chrome's white while the pointer or the focus ring is on it. */
.view-controls > .icon-button:hover,
.view-controls > .icon-button:focus-visible,
.control-stack .icon-button:hover,
.control-stack .icon-button:focus-visible,
.map-zoom button:hover,
.map-zoom button:focus-visible {
  color: var(--pp-polish-ink);
}

.view-direction {
  border-color: var(--pp-polish-line-strong);
  border-radius: var(--pp-polish-radius-sm);
  background: rgb(16 28 52 / 88%);
  color: var(--pp-polish-text);
  box-shadow: 0 6px 18px rgb(3 9 22 / 42%);
}

.view-direction small {
  color: var(--pp-polish-muted);
}

.view-direction svg {
  color: var(--pp-polish-accent);
}

.intro-hint {
  border-color: var(--pp-polish-line-strong);
  border-radius: var(--pp-polish-radius-sm);
  background: rgb(16 28 52 / 92%);
  box-shadow: 0 8px 22px rgb(3 9 22 / 44%);
}

.intro-hint .icon {
  color: var(--pp-polish-accent);
}

.intro-hint button:hover {
  color: var(--pp-polish-accent);
}

.credit {
  border-radius: var(--pp-polish-radius-sm);
  background: rgb(16 28 52 / 88%);
}

.credit a {
  color: var(--pp-polish-text);
}

.credit a:hover {
  color: var(--pp-polish-accent);
}

/* The phone map launcher is the one light control the chrome paints dark ink on: interface.css
 * leaves its white fill and its blue, dark-grey and hairline details alone, but sets no colour on
 * the button itself, so its label and hint inherit the chrome's near-white ink and disappear on
 * that white fill at 320px. The button's own colour is set here, in the last-loaded layer, and
 * every state keeps that ink on the light fill rather than flipping back to white under the
 * pointer. The glyphs inside already carry explicit colours — the blue map mark, the dark grey
 * chevron — so they are untouched, and only paint changes: no id, layout or behaviour. */
.mobile-map-button,
.mobile-map-button:hover,
.mobile-map-button:focus-visible {
  color: var(--pp-polish-ink);
}

.mobile-map-button .mobile-map-sub {
  color: var(--pp-polish-ink-soft);
}

/* 16.97:1 for the label and 6.04:1 for the 10px hint, both against the retained white fill, and the
 * dark focus ring below is the same dark blue the other controls on light surfaces use (4.68:1
 * against white). */
.mobile-map-button:focus-visible {
  outline-color: var(--pp-polish-primary-hover);
}

/* Movement arrows: same shape and 44px target, sharper edge and a blue accent on hover. */
.street-hotspot {
  border-width: 2px;
  border-color: rgb(247 250 255 / 92%);
  background: rgb(16 28 52 / 88%);
  box-shadow: 0 4px 18px rgb(3 9 22 / 52%);
}

.street-hotspot:hover:not(:disabled) {
  background: var(--pp-polish-primary);
  border-color: var(--pp-polish-text);
  color: var(--pp-polish-on-primary);
  box-shadow: 0 6px 22px rgb(3 9 22 / 56%);
}

.street-hotspot:active:not(:disabled) {
  background: #1e56bc;
}

.street-hotspot:disabled,
.street-hotspot[aria-busy='true'] {
  background: rgb(30 50 83 / 92%);
  border-color: rgb(183 201 226 / 70%);
  color: var(--pp-polish-muted);
}

.street-hotspot-label {
  border-color: var(--pp-polish-line-strong);
  border-radius: 8px;
  background: rgb(16 28 52 / 94%);
  color: var(--pp-polish-text);
}

/* The movement failure notice is the only visible state of its region. It is an alert, so it takes
 * the red-pin coral rather than the accent blue. */
.viewpoint-controls[data-state='error'] .viewpoint-feedback {
  border-color: rgb(255 125 135 / 45%);
  border-radius: var(--pp-polish-radius-sm);
  background: rgb(16 28 52 / 94%);
  color: var(--pp-polish-text);
  box-shadow: 0 10px 30px rgb(3 9 22 / 48%);
}

.viewpoint-controls[data-state='error'] .viewpoint-state-icon {
  color: var(--pp-polish-alert);
}

.viewpoint-retry {
  border-color: var(--pp-polish-line-control);
  border-radius: 10px;
  background: var(--pp-polish-primary);
  color: var(--pp-polish-on-primary);
  font-weight: 700;
}

.viewpoint-retry:hover {
  background: var(--pp-polish-primary-hover);
}

/* ------------------------------------------------------------------------------------------------
 * Map panel and result
 * ---------------------------------------------------------------------------------------------- */

.map-panel {
  border-color: var(--pp-polish-line-strong);
  border-radius: var(--pp-polish-radius-lg);
  background: var(--pp-polish-panel);
  box-shadow: var(--pp-polish-shadow);
}

.map-panel-header {
  border-bottom-color: var(--pp-polish-line);
}

.map-panel-header h2 {
  color: var(--pp-polish-text);
}

.map-panel-header p {
  color: var(--pp-polish-muted);
}

.panel-header-buttons .icon-button {
  border-radius: 10px;
  color: var(--pp-polish-muted);
}

.panel-header-buttons .icon-button:hover {
  background: var(--pp-polish-panel-soft);
  color: var(--pp-polish-text);
}

.map-panel.revealed .map-panel-header {
  background: var(--pp-polish-panel);
}

.map-panel.revealed .result {
  background: var(--pp-polish-panel);
  color: var(--pp-polish-text);
}

.map-panel.revealed .map-footer {
  background: var(--pp-polish-panel-soft);
  border-top-color: var(--pp-polish-line);
}

.map-panel.revealed .source-panel-photo-credit {
  background: var(--pp-polish-panel-soft);
  border-top-color: var(--pp-polish-line);
  color: var(--pp-polish-muted);
}

.map-panel.revealed .source-panel-photo-credit::before {
  color: var(--pp-polish-muted);
}

.map-panel.revealed .source-panel-photo-credit a,
.map-panel.revealed .result-credit a {
  color: var(--pp-polish-accent);
}

.result {
  border-top-color: var(--pp-polish-line);
}

.result .eyebrow {
  color: var(--pp-polish-accent);
}

.result .eyebrow .icon {
  color: var(--pp-polish-accent);
}

.result h3 {
  color: var(--pp-polish-text);
}

.result-region,
.result-note,
.result-credit,
.map-panel .reference-label {
  color: var(--pp-polish-muted);
}

.result-note b {
  color: var(--pp-polish-text);
}

.result-stats {
  border-block-color: var(--pp-polish-line);
}

.result-stats .stat span {
  color: var(--pp-polish-muted);
}

.result-stats .stat strong {
  color: var(--pp-polish-text);
  font-variant-numeric: tabular-nums;
}

/* Distance and points are the round's two numbers: the score gets the reward green. The panel
 * prefix is deliberate — interface.css colours the same cell through a longer selector. */
.map-panel .result-stats .stat + div strong,
.game-round-points {
  color: var(--pp-polish-success);
}

.pin-status {
  color: var(--pp-polish-muted);
}

.pin-status.selected {
  color: var(--pp-polish-text);
}

.pin-status.selected .icon {
  color: var(--pp-polish-accent);
}

.map-keyboard,
.map-keyboard kbd {
  color: var(--pp-polish-muted);
}

.map-panel .reference-label::before {
  background: var(--pp-polish-line-strong);
}

.result-provenance {
  border-top-color: var(--pp-polish-line);
}

.result-provenance summary {
  color: var(--pp-polish-muted);
}

.result-provenance summary:hover {
  color: var(--pp-polish-accent);
}

/* ------------------------------------------------------------------------------------------------
 * Buttons
 * ---------------------------------------------------------------------------------------------- */

.primary-button {
  border-color: var(--pp-polish-primary);
  border-radius: var(--pp-polish-radius-sm);
  background: var(--pp-polish-primary);
  color: var(--pp-polish-on-primary);
  font-weight: 700;
  transition:
    background-color var(--pp-polish-fast) ease,
    border-color var(--pp-polish-fast) ease,
    transform var(--pp-polish-fast) ease;
}

.primary-button:hover:not(:disabled) {
  border-color: var(--pp-polish-primary-hover);
  background: var(--pp-polish-primary-hover);
  transform: translateY(-1px);
}

.primary-button:active:not(:disabled) {
  border-color: var(--pp-polish-primary-deep);
  background: var(--pp-polish-primary-deep);
  transform: translateY(0);
}

.primary-button:disabled {
  border-color: #1e3253;
  background: #1e3253;
  color: var(--pp-polish-dim);
}

.subtle-button {
  border-color: var(--pp-polish-line-control);
  border-radius: var(--pp-polish-radius-sm);
  background: transparent;
  color: var(--pp-polish-text);
  transition:
    background-color var(--pp-polish-fast) ease,
    border-color var(--pp-polish-fast) ease,
    color var(--pp-polish-fast) ease;
}

.subtle-button:hover:not(:disabled) {
  border-color: var(--pp-polish-accent);
  background: var(--pp-polish-panel);
  color: var(--pp-polish-accent);
}

.subtle-button:disabled {
  border-color: var(--pp-polish-line-strong);
  color: var(--pp-polish-dim);
}

.dialog-actions .subtle-button,
.dialog-actions .primary-button {
  min-height: 46px;
}

/* The exit dialog's three ways out share one row: a link, a link and a button, all the same
 * height, with the destructive action keeping the solid treatment. */
.dialog-actions--exit {
  flex-wrap: wrap;
  align-items: center;
}

.dialog-actions--exit .subtle-button,
.dialog-actions--exit .primary-button {
  min-height: 46px;
  margin: 0;
}

.dialog-actions--exit .dialog-actions-party {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  text-decoration: none;
}

.dialog-actions--exit .dialog-actions-party .icon {
  width: 17px;
  height: 17px;
}

/* ------------------------------------------------------------------------------------------------
 * Dialogs
 * ---------------------------------------------------------------------------------------------- */

.dialog {
  border-color: var(--pp-polish-line-strong);
  border-radius: var(--pp-polish-radius-lg);
  background: var(--pp-polish-panel);
  color: var(--pp-polish-text);
  box-shadow: var(--pp-polish-shadow);
}

.dialog::backdrop {
  background: rgb(6 12 26 / 76%);
}

.dialog h2,
.dialog .dialog-header h2 {
  color: var(--pp-polish-text);
}

.dialog p,
.dialog ol,
.dialog li {
  color: var(--pp-polish-muted);
}

.dialog li b,
.dialog p b {
  color: var(--pp-polish-text);
}

.dialog .icon-button {
  border-radius: 10px;
  color: var(--pp-polish-muted);
}

.dialog .icon-button:hover {
  background: var(--pp-polish-panel-soft);
  color: var(--pp-polish-text);
}

.dialog .primary-button {
  color: var(--pp-polish-on-primary);
}

.dialog .help-preview-note {
  border: 1px solid var(--pp-polish-line);
  border-radius: var(--pp-polish-radius-sm);
  background: var(--pp-polish-panel-soft);
  color: var(--pp-polish-muted);
}

.setting-row {
  border-bottom-color: var(--pp-polish-line);
}

.setting-row b {
  color: var(--pp-polish-text);
}

.setting-row small {
  color: var(--pp-polish-muted);
}

.setting-row select {
  border-color: var(--pp-polish-line-control);
  border-radius: 10px;
  background: var(--pp-polish-ink);
  color: var(--pp-polish-text);
}

.setting-row select:hover:not(:disabled) {
  border-color: var(--pp-polish-accent);
}

.setting-row input {
  accent-color: var(--pp-polish-accent);
}

.toast {
  border-color: var(--pp-polish-line-strong);
  border-radius: var(--pp-polish-radius-sm);
  background: rgb(16 28 52 / 96%);
  color: var(--pp-polish-text);
  box-shadow: var(--pp-polish-shadow);
}

/* ------------------------------------------------------------------------------------------------
 * Solo dialog: tabs, daily block, form, passport
 * ---------------------------------------------------------------------------------------------- */

.solo-dialog .solo-notice {
  border-color: var(--pp-polish-line);
  background: var(--pp-polish-panel-soft);
  color: var(--pp-polish-muted);
}

.solo-tabs {
  border-color: var(--pp-polish-line);
  background: var(--pp-polish-panel-soft);
}

.solo-tabs button {
  border-radius: 10px;
  color: var(--pp-polish-muted);
}

.solo-tabs button:hover {
  background: var(--pp-polish-panel);
  color: var(--pp-polish-text);
}

.solo-tabs button[aria-selected='true'] {
  border-color: var(--pp-polish-line-strong);
  background: var(--pp-polish-panel);
  color: var(--pp-polish-accent);
  box-shadow: none;
}

.solo-dialog .solo-intro {
  color: var(--pp-polish-muted);
}

.solo-dialog .daily-block {
  border-color: var(--pp-polish-line-strong);
  background: var(--pp-polish-panel-soft);
}

.solo-dialog .daily-block h3 {
  color: var(--pp-polish-text);
}

.solo-dialog .daily-block p,
.solo-dialog .daily-block #daily-state {
  color: var(--pp-polish-muted);
}

.solo-dialog .daily-block #daily-result {
  border-color: rgb(120 221 165 / 42%);
  background: rgb(120 221 165 / 12%);
  color: var(--pp-polish-success);
}

/* solo.css paints this message a light-theme grey through an id, so the confirmation copy needs the
 * same strength of selector to stay readable on the dark dialog. */
.solo-confirm #solo-confirm-message {
  color: var(--pp-polish-muted);
}

/* Skip round is a quiet, secondary action whose own id rule in solo.css is a light-theme grey. */
#skip-round {
  color: var(--pp-polish-muted);
}

#skip-round:hover:not(:disabled) {
  border-color: var(--pp-polish-line);
  background: var(--pp-polish-panel-soft);
  color: var(--pp-polish-text);
}

.solo-field {
  color: var(--pp-polish-muted);
}

.solo-field select {
  border-color: var(--pp-polish-line-control);
  border-radius: var(--pp-polish-radius-sm);
  background-color: var(--pp-polish-ink);
  color: var(--pp-polish-text);
}

.solo-field select:hover:not(:disabled) {
  border-color: var(--pp-polish-accent);
}

.solo-rules {
  border-color: var(--pp-polish-line);
  border-left-color: var(--pp-polish-accent);
  background: var(--pp-polish-panel-soft);
  color: var(--pp-polish-muted);
}

.solo-rules strong,
.solo-rules b {
  color: var(--pp-polish-text);
}

.solo-dialog #solo-active-note,
.solo-dialog #solo-share-status {
  color: var(--pp-polish-muted);
}

.solo-dialog .solo-actions {
  border-top-color: var(--pp-polish-line);
  background: var(--pp-polish-panel);
  box-shadow: 0 -8px 18px rgb(11 20 39 / 60%);
}

.solo-dialog button:disabled {
  color: var(--pp-polish-dim);
}

/* Passport: the reward green marks what has been earned, and nothing else. */
.solo-level {
  border-color: var(--pp-polish-line-strong);
  background: var(--pp-polish-panel-soft);
}

.solo-level h3 {
  color: var(--pp-polish-text);
}

.solo-level p {
  color: var(--pp-polish-muted);
}

.solo-level progress {
  background: #1e3253;
  color: var(--pp-polish-success);
  accent-color: var(--pp-polish-success);
}

.solo-level progress::-webkit-progress-bar {
  background: #1e3253;
}

.solo-level progress::-webkit-progress-value {
  background: var(--pp-polish-success);
}

.solo-level progress::-moz-progress-bar {
  background: var(--pp-polish-success);
}

.solo-stats {
  border-color: var(--pp-polish-line);
  background: var(--pp-polish-panel);
}

.solo-stats > div {
  border-right-color: var(--pp-polish-line);
  border-bottom-color: var(--pp-polish-line);
}

.solo-stats dt {
  color: var(--pp-polish-muted);
}

.solo-stats dd {
  color: var(--pp-polish-text);
}

.solo-dialog #solo-passport-panel h3:not(.solo-level h3) {
  color: var(--pp-polish-text);
}

.solo-dialog .solo-badges > li {
  border-color: var(--pp-polish-line);
  border-radius: 10px;
  background: var(--pp-polish-panel-soft);
  color: var(--pp-polish-muted);
}

.solo-badges > li::before {
  border-color: var(--pp-polish-line-strong);
}

.solo-badges strong {
  color: var(--pp-polish-text);
}

.solo-dialog .solo-badges > li.earned {
  border-color: rgb(120 221 165 / 46%);
  background: rgb(120 221 165 / 11%);
  color: var(--pp-polish-muted);
}

.solo-badges > li.earned::before {
  border-color: var(--pp-polish-success);
  background: var(--pp-polish-success);
  box-shadow: 0 0 0 3px rgb(120 221 165 / 22%);
}

.solo-badges > li.earned strong {
  color: var(--pp-polish-success);
}

.solo-dialog .solo-history {
  border-top-color: var(--pp-polish-line);
}

.solo-dialog .solo-history > li {
  border-bottom-color: var(--pp-polish-line);
  color: var(--pp-polish-muted);
}

.solo-history > li > strong {
  color: var(--pp-polish-text);
  font-variant-numeric: tabular-nums;
}

.solo-history > li > span {
  color: var(--pp-polish-muted);
}

.solo-history summary {
  color: var(--pp-polish-accent);
}

.solo-reward {
  border-color: rgb(120 221 165 / 42%);
  background: rgb(120 221 165 / 12%);
  color: var(--pp-polish-success);
}

/* Clearing progress is destructive, so it stays in the alert family rather than the accent. */
#solo-clear {
  border-color: rgb(255 125 135 / 45%);
  background: transparent;
  color: var(--pp-polish-alert-text);
}

#solo-clear:hover:not(:disabled) {
  border-color: var(--pp-polish-alert);
  background: rgb(255 125 135 / 14%);
  color: #ffc9cf;
}

/* ------------------------------------------------------------------------------------------------
 * Game summary
 * ---------------------------------------------------------------------------------------------- */

.game-summary-intro,
.game-summary-note {
  color: var(--pp-polish-muted);
}

.game-summary-total {
  border-block-color: var(--pp-polish-line);
}

.game-summary-total > span {
  color: var(--pp-polish-muted);
}

#game-total {
  color: var(--pp-polish-success);
  font-variant-numeric: tabular-nums;
}

.game-summary h4 {
  color: var(--pp-polish-text);
}

.game-round-list > li {
  border-bottom-color: var(--pp-polish-line);
}

.game-round-label {
  color: var(--pp-polish-muted);
}

.game-round-place {
  color: var(--pp-polish-text);
}

/* ------------------------------------------------------------------------------------------------
 * Loading state
 * ---------------------------------------------------------------------------------------------- */

.loading-state {
  background: var(--pp-polish-ink);
  color: var(--pp-polish-muted);
}

.loading-inner svg {
  color: var(--pp-polish-line-strong);
}

.loading-inner h1 {
  color: var(--pp-polish-text);
}

/* ------------------------------------------------------------------------------------------------
 * Motion — short, hardware-friendly, and gone under reduced motion. Optional sound cues are managed separately by game-feedback.js.
 * ---------------------------------------------------------------------------------------------- */

.map-panel.revealed,
.map-panel.revealed.expanded {
  animation: polish-panel-in 220ms ease both;
}

@keyframes polish-panel-in {
  from {
    opacity: 0;
    transform: translateY(10px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

/* ------------------------------------------------------------------------------------------------
 * Responsive
 * ---------------------------------------------------------------------------------------------- */

/* Tablet header keeps its two-row layout; the party link drops to its icon there. */
@media (min-width: 681px) and (max-width: 1050px) {
  #topbar .topbar-party-link span {
    display: none;
  }

  #topbar .topbar-party-link {
    width: 44px;
    min-width: 44px;
    padding: 0;
    border-radius: 12px;
  }
}

/* Phones: icon-only and 44px, which lets it sit in the header's control row in normal flow rather
 * than floating over the brand at 320px. The header hides the settings and fullscreen controls at
 * this width, so the row still ends inside the viewport. */
@media (max-width: 680px) {
  #topbar .topbar-party-link {
    width: 44px;
    min-width: 44px;
    height: 44px;
    padding: 0;
    border-radius: 12px;
  }

  #topbar .topbar-party-link span {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  /* Give back the room the icon and the progress row need on a narrow phone. */
  #topbar:has(#solo-menu-button) .nav-controls #exit-button {
    display: none;
  }

  #topbar .brand-lockup {
    /* Narrow phones: the header is 56-94px tall and still carries the progress row, so the lockup
     * shrinks rather than taking the row's room. */
    width: 132px;
  }

  .dialog-actions--exit .subtle-button,
  .dialog-actions--exit .dialog-actions-party {
    flex: 1 1 45%;
  }

  .dialog-actions--exit .primary-button {
    flex: 1 1 100%;
  }

  .map-panel {
    border-radius: var(--pp-polish-radius-lg) var(--pp-polish-radius-lg) 0 0;
  }

  .map-panel.revealed,
  .map-panel.revealed.expanded {
    border-radius: var(--pp-polish-radius-lg) var(--pp-polish-radius-lg) 0 0;
  }

  .result-stats .stat strong {
    font-variant-numeric: tabular-nums;
  }
}

@media (max-width: 400px) {
  #topbar .topbar-party-link {
    width: 40px;
    min-width: 40px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .map-panel.revealed,
  .map-panel.revealed.expanded {
    animation: none;
  }

  .primary-button:hover:not(:disabled),
  .map-panel.revealed,
  .map-panel.revealed.expanded {
    transform: none;
  }

  .street-hotspot,
  .primary-button,
  .subtle-button,
  .viewpoint-retry,
  #topbar .nav-controls .icon-button,
  #topbar .topbar-party-link {
    transition: none;
  }
}

/* The in-game "Reduce motion" setting, alongside the system preference. */
.reduced-motion .map-panel.revealed,
.reduced-motion .map-panel.revealed.expanded {
  animation: none;
}

.reduced-motion .primary-button:hover:not(:disabled) {
  transform: none;
}
