:root {
  --accent: #ffc86e;
  --panel: rgba(10, 11, 28, 0.58);
  --line: rgba(255, 255, 255, 0.09);
  --text: #eceeff;
  --muted: #9ba0cc;
  --ph: #ff6154;                                 /* Product Hunt's brand colour, for the launch link */
  --live: 114, 230, 162;                         /* the live count's green (rgb parts): the pill and the picker's cards */
  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  --top: max(16px, env(safe-area-inset-top));   /* top edge of the title, links and pills */
  --bottom: max(14px, env(safe-area-inset-bottom));   /* bottom edge of the dock */
  --edge: 12px;                                  /* min side gutter of the bottom dock */
  --gutter: max(var(--edge), env(safe-area-inset-left), env(safe-area-inset-right));   /* mirrored: keeps the dock centred between notch insets */
  --btn: 36px;                                  /* icon button size (44px on touch) */
  color-scheme: dark;
}
* { box-sizing: border-box; }
html, body {
  margin: 0; height: 100%; overflow: hidden; background: #05060f; color: var(--text);
  font: 14px/1.4 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;   /* no pull-to-refresh or rubber-banding when swiping the scene */
}
/* one-finger drags on the scene are the app's (look around, swipe to change city, js/app.js); a pinch still zooms */
#screen { position: fixed; inset: 0; display: block; image-rendering: pixelated; touch-action: pinch-zoom; }
button { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* auto-hiding chrome */
.ui { transition: opacity .6s ease, transform .6s ease; }
body.idle, body.idle * { cursor: none; }
body.idle .ui, body.ui-off .ui { opacity: 0; pointer-events: none; }
body.idle .hud-bottom, body.ui-off .hud-bottom { transform: translate(-50%, 8px); }
/* ?obs (OBS / embed mode): the scene only, for good. No interface, pills or toasts. */
.obs .ui, .obs .pill { display: none !important; }

/* city title */
.hud-city {
  position: fixed; top: var(--top); left: max(18px, env(safe-area-inset-left));
  max-width: calc(100vw - 440px - var(--ph-room, 0px));   /* clear of the shop, support and social links */
  text-shadow: 0 1px 14px rgba(0, 0, 0, .7); pointer-events: none;
}
.wordmark { margin: 0; font: 600 11px/1 var(--mono); letter-spacing: .28em; text-transform: uppercase; color: var(--muted); }
#cityName { margin: 8px 0 2px; font-size: 30px; font-weight: 650; letter-spacing: -.01em; line-height: 1.1; }
.sub { margin: 0; color: var(--muted); font-size: 13px; }
.sub time { color: var(--accent); font-family: var(--mono); white-space: nowrap; }
/* live count (js/live.js): a glowing pill with a blinking pixel, "23 here now · 5 in Tokyo · 480 today · 12,345 all
   time". Frosted like the other panels so it reads over any scene. One row; on phones the city and all time go on lines
   of their own (see max-width: 600px). */
.live {
  position: relative; display: grid; grid-auto-flow: column; align-items: center; column-gap: 6px; width: fit-content;
  margin: 10px 0 0; padding: 5px 12px 5px 10px; border-radius: 14px;
  border: 1px solid rgba(var(--live), .32); background: var(--panel);
  -webkit-backdrop-filter: blur(12px) saturate(1.3); backdrop-filter: blur(12px) saturate(1.3);
  box-shadow: 0 0 14px rgba(var(--live), .2), inset 0 0 10px rgba(var(--live), .08);
  color: var(--text); font-size: 12px; line-height: 1.5; text-shadow: none;
}
.live[hidden] { display: none; }
.live::before {
  content: ""; flex: none; width: 6px; height: 6px; margin-right: 2px;
  background: rgb(var(--live)); box-shadow: 0 0 8px rgba(var(--live), .9); animation: live 2.4s ease-in-out infinite;
}
.live::after {   /* the glow breathes with the pixel (opacity only, so it stays off the main thread) */
  content: ""; position: absolute; inset: -1px; border-radius: inherit; pointer-events: none;
  box-shadow: 0 0 22px rgba(var(--live), .35); animation: live 2.4s ease-in-out infinite;
}
.live span { white-space: nowrap; }
.live span + span { color: var(--muted); }
.live span + span::before { content: "·"; margin-right: 6px; }   /* as far from the dot as the gap before it */
@keyframes live { 50% { opacity: .35; } }

/* author links */
#links {
  position: fixed; top: var(--top); right: max(18px, env(safe-area-inset-right));
  display: flex; gap: 2px; padding: 4px; border-radius: 14px; border: 1px solid var(--line); background: var(--panel);
  -webkit-backdrop-filter: blur(12px) saturate(1.3); backdrop-filter: blur(12px) saturate(1.3);
}
#links a { color: var(--muted); transition: color .2s, background .2s; }
#links a:hover, #links a:focus-visible { color: var(--text); }
#phLink, #shopLink, #coffee { height: var(--btn); display: flex; align-items: center; gap: 8px; padding: 0 12px 0 10px; border-radius: 10px; font-size: 13px; text-decoration: none; }
#shopLink:hover, #coffee:hover { background: color-mix(in srgb, var(--accent) 14%, transparent); }
#phLink svg, #shopLink svg, #coffee svg { width: 16px; height: 16px; fill: var(--accent); shape-rendering: crispEdges; }
/* the Product Hunt launch link (js/launch.js): in Product Hunt's colour, lit up so it stands out for the launch week */
#links #phLink {
  position: relative; color: var(--text); background: color-mix(in srgb, var(--ph) 16%, transparent);
  box-shadow: 0 0 12px color-mix(in srgb, var(--ph) 22%, transparent), inset 0 0 0 1px color-mix(in srgb, var(--ph) 30%, transparent);
}
#links #phLink:hover, #links #phLink:focus-visible { background: color-mix(in srgb, var(--ph) 28%, transparent); }
#phLink svg { fill: var(--ph); }
/* a faint steady glow, like the live pill's; when the link appears it breathes three times, done by the time the idle
   controls fade (3.5 s), then holds still: the page stays open for hours (opacity only, so it stays off the main thread) */
#phLink::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; opacity: 0;
  box-shadow: 0 0 22px color-mix(in srgb, var(--ph) 60%, transparent); animation: ph-glow 1.2s ease-in-out 3;
}
@keyframes ph-glow { 50% { opacity: 1; } }
:root:has(#phLink:not([hidden])) { --ph-room: 175px; }   /* the city title keeps clear of it too */

/* bottom dock */
.hud-bottom {
  position: fixed; left: 50%; bottom: var(--bottom); transform: translateX(-50%);
  width: min(958px, calc(100vw - 2 * var(--gutter))); display: grid;   /* the track title keeps 150px beside every button */ grid-template-columns: minmax(0, 1fr); gap: 8px;
}
/* One row of chips (the city picker, the tour, the weather): centred while they fit; when they don't (the narrowest phones)
   it bleeds into the gutters and swipes. No edge-fade mask: it would switch off the chips' backdrop blur. */
#cities {
  display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none;
  margin-inline: calc(-1 * var(--gutter)); padding: 2px calc(var(--gutter) + 2px);
  scroll-snap-type: x proximity; scroll-padding-inline: calc(var(--gutter) + 24px); scroll-behavior: smooth;
}
#cities::-webkit-scrollbar { display: none; }
.chip {
  flex: none; display: inline-flex; align-items: baseline; gap: 8px; padding: 7px 12px; cursor: pointer;
  border-radius: 999px; border: 1px solid var(--line); background: var(--panel);
  -webkit-backdrop-filter: blur(12px) saturate(1.3); backdrop-filter: blur(12px) saturate(1.3);
  transition: border-color .2s, background .2s, box-shadow .2s; scroll-snap-align: start;
}
.chip:first-child { margin-left: auto; }   /* auto margins centre without clipping the start (justify-content would) */
.chip:last-child { margin-right: auto; }
.chip small { font: 11px var(--mono); color: var(--muted); }
.chip:hover { border-color: rgba(255, 255, 255, .22); }
/* the city on screen opens the picker, lit in its colour; the tour and weather chips are lit (without the glow) while a
   tour runs or a weather is picked */
.menu-chip svg { align-self: center; width: 16px; height: 16px; fill: var(--muted); shape-rendering: crispEdges; }
.menu-chip.on { border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.menu-chip.on svg { fill: var(--accent); }
.menu-chip.on small { color: var(--accent); }
.menu-chip[aria-expanded="true"] { background: color-mix(in srgb, #fff 10%, var(--panel)); }
#cityBtn {
  border-color: color-mix(in srgb, var(--accent) 75%, transparent);
  background: color-mix(in srgb, var(--accent) 16%, var(--panel));
  box-shadow: 0 0 22px -8px var(--accent);
}
#cityBtn[aria-expanded="true"] { background: color-mix(in srgb, var(--accent) 28%, var(--panel)); }
#cityBtn { flex: 0 1 auto; min-width: 0; }      /* a long name gives way first (the title shows it whole) */
#cityBtnName { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* its hint (js/city-roll.js): other cities' names roll up through it and back, over its own (kept, see-through) */
#cityBtnName.rolling { position: relative; color: transparent; }
.name-roll { position: absolute; top: 0; left: 0; width: 100%; display: flex; flex-direction: column; color: var(--text); }
.name-roll span { flex: none; overflow: hidden; text-overflow: ellipsis; }
#cityBtnTime { transition: opacity .2s; }
#cityBtnName.rolling + #cityBtnTime { opacity: 0; }   /* the time is the city on screen's, not the names rolling by */
#cityBtn svg, #cityBtn small { fill: var(--accent); color: var(--accent); }
/* a thin rule between the city and those two chips */
#tourBtn { position: relative; margin-left: 9px; }
#tourBtn::before {
  content: ""; position: absolute; left: -9px; top: 5px; bottom: 5px; width: 1px;
  background: rgba(255, 255, 255, .24); pointer-events: none;
}

#player {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px 8px 8px;
  border-radius: 16px; border: 1px solid var(--line); background: var(--panel);
  -webkit-backdrop-filter: blur(14px) saturate(1.3); backdrop-filter: blur(14px) saturate(1.3);
}
.icon-btn {
  flex: none; width: var(--btn); height: var(--btn); display: grid; place-items: center; padding: 0;
  border: 0; border-radius: 10px; background: transparent; cursor: pointer;
}
.icon-btn:hover { background: rgba(255, 255, 255, .08); }
.icon-btn:disabled { opacity: .35; cursor: default; background: transparent; }
.icon-btn svg { width: 16px; height: 16px; fill: currentColor; shape-rendering: crispEdges; }
#play { background: var(--accent); color: #12121c; }
#play:hover { filter: brightness(1.08); }
#play.pulse { animation: pulse 2.2s ease-in-out infinite; }
@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent); }
  50% { box-shadow: 0 0 0 9px transparent; }
}
.track { flex: 1; min-width: 0; }
#trackTitle, #trackMeta { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#trackTitle { font-weight: 560; }
#trackMeta { font: 11px var(--mono); color: var(--muted); }
.vols { flex: none; display: flex; align-items: center; gap: 10px; }
.vol { flex: none; display: flex; align-items: center; gap: 6px; color: var(--muted); }
.vol svg { flex: none; width: 14px; height: 14px; fill: currentColor; shape-rendering: crispEdges; }
.vol input { width: 84px; accent-color: var(--accent); }
#queueBtn[aria-expanded="true"], #timerBtn[aria-expanded="true"], #vibeBtn[aria-expanded="true"], #mixerBtn[aria-expanded="true"], #saveBtn[aria-expanded="true"], #togetherBtn[aria-expanded="true"], #chatBtn[aria-expanded="true"], #pip[aria-pressed="true"] { background: rgba(255, 255, 255, .1); color: var(--accent); }
#timerBtn.on { color: var(--accent); }   /* a timer is running */
#mixerBtn svg, #togetherBtn svg, #chatBtn svg { width: 18px; }   /* the faders, the two people and the bubble are 9 pixels wide */
/* the mini player's source video: kept in the page for Picture-in-Picture, but never seen */
.pip-source { position: fixed; left: 0; top: 0; width: 1px; height: 1px; opacity: 0; pointer-events: none; }

/* popovers: up next, timers, vibe, together, the city sounds mixer and save open over the chips, the cities, tour and weather
   above them */
.dock { position: relative; }
.pop {
  position: absolute; left: 0; bottom: calc(100% + 8px); width: min(360px, 100%);
  display: flex; flex-direction: column; border-radius: 16px; border: 1px solid var(--line);
  background: rgba(10, 11, 28, 0.74);
  -webkit-backdrop-filter: blur(14px) saturate(1.3); backdrop-filter: blur(14px) saturate(1.3);
  box-shadow: 0 18px 40px -20px rgba(0, 0, 0, .8); animation: pop-in .16s ease-out;
}
@keyframes pop-in { from { opacity: 0; transform: translateY(6px); } }
.pop-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 12px 14px 6px; }
.pop-head span { font: 600 11px/1 var(--mono); letter-spacing: .28em; text-transform: uppercase; color: var(--muted); white-space: nowrap; }
.pop-head small { font: 11px var(--mono); color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* up next, the city tour and the weather: lists of row buttons */
#queue, #tour, #weather, #mixer { max-height: min(380px, 55vh); }
#tour, #weather { width: min(320px, 100%); }   /* above their own chips (js/app.js placeOver sets left) */
#mixer { left: auto; right: 0; width: min(320px, 100%); }   /* under its button, on the right of the dock */
/* every city: a search and a grid of previews (img/thumbs), centred over the dock; the grid scrolls on short screens */
#cityPicker {   /* --dock-top (js/app.js measureDock, again as it opens): it may cover the city title, never the top of the screen */
  left: 0; right: 0; margin-inline: auto; width: min(760px, 100%); max-height: min(640px, calc(var(--dock-top, 80vh) - var(--top) - 8px));
}
#cityFind {
  margin: 2px 10px 8px; padding: 8px 12px; border-radius: 10px; border: 1px solid var(--line);
  background: rgba(255, 255, 255, .06); font: 13px var(--mono); color: var(--text);
}
#cityFind::placeholder { color: var(--muted); }
#cityFind:focus-visible { outline: none; border-color: color-mix(in srgb, var(--accent) 60%, transparent); }
#cityList {
  list-style: none; margin: 0; padding: 0 6px 6px; overflow-y: auto; overscroll-behavior: contain;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 4px;
}
.city-card {
  position: relative; width: 100%; display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; gap: 0 8px;
  padding: 4px 4px 6px; border: 1px solid transparent; border-radius: 12px; background: transparent; text-align: left; cursor: pointer;
}
.city-card img {
  grid-column: 1 / -1; display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; margin-bottom: 5px;
  border-radius: 8px; background: rgba(255, 255, 255, .06);
}
.city-card span { padding-left: 3px; font-weight: 560; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.city-card small { padding-right: 3px; font: 11px var(--mono); color: var(--muted); }
.city-card:hover, .city-card:focus-visible { background: rgba(255, 255, 255, .08); }
.city-card[aria-current="true"] {
  border-color: color-mix(in srgb, var(--accent) 75%, transparent);
  background: color-mix(in srgb, var(--accent) 16%, transparent);
}
.city-card[aria-current="true"] small { color: var(--accent); }
/* who's in each city (js/live.js cityLabels): the live pill's pixel and "5 here", dark on the preview's corner */
.card-live {
  position: absolute; top: 9px; left: 9px; display: flex; align-items: center; gap: 5px;
  padding: 0 7px 0 6px; border-radius: 7px; border: 1px solid rgba(var(--live), .32);
  background: rgba(6, 7, 18, .78); box-shadow: 0 0 10px rgba(var(--live), .18);
  font: 500 10.5px/18px var(--mono); color: var(--text); white-space: nowrap; pointer-events: none;
}
.card-live[hidden] { display: none; }
.card-live::before { content: ""; width: 5px; height: 5px; background: rgb(var(--live)); box-shadow: 0 0 6px rgba(var(--live), .9); }
/* the city with the most people right now (js/live.js topCity), across the top of the grid: its preview fills the first
   column (a subgrid, so it lines up with the cards under it) and the rest reads "Most people right now", its name and
   its local time, lit green like the live pill (or in the accent, like any card, when it's the city on screen) */
.featured-item { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; }
.featured-item[hidden] { display: none; }
.city-featured {
  grid-column: 1 / -1; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-columns: subgrid;
  align-items: center; margin-bottom: 2px; border-color: rgba(var(--live), .26);
  background: linear-gradient(90deg, rgba(var(--live), .1), rgba(var(--live), .02) 70%);
}
.city-featured img { grid-column: 1; margin: 0; }
.city-featured .feat-text {   /* not the cards' one-line name: "Most people right now" takes two lines on phones */
  grid-column: 2 / -1; display: flex; flex-direction: column; gap: 5px; min-width: 0; padding: 0 8px 0 6px; font-weight: 400; white-space: normal;
}
.feat-text em {
  display: flex; align-items: flex-start; gap: 7px; font: 600 10.5px/1.3 var(--mono); letter-spacing: .16em; text-transform: uppercase;
  color: rgb(var(--live)); text-wrap: balance;
}
.feat-text em::before {
  content: ""; flex: none; width: 5px; height: 5px; margin-top: calc((1.3em - 5px) / 2);   /* the middle of the first line */
  background: rgb(var(--live)); box-shadow: 0 0 6px rgba(var(--live), .9);
  animation: live 2.4s ease-in-out infinite;
}
.feat-text strong { font-size: 22px; font-weight: 600; line-height: 1.15; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.feat-text small { font: 11px var(--mono); color: var(--muted); }
.city-featured:not([aria-current]):hover, .city-featured:not([aria-current]):focus-visible { background: linear-gradient(90deg, rgba(var(--live), .16), rgba(255, 255, 255, .06) 70%); }
@media (prefers-reduced-motion: reduce) { .feat-text em::before { animation: none; } }
/* the last card: "Request a city" (a link to X), a lit pixel billboard (js/request-board.js) glowing in the city's accent */
a.city-card { color: inherit; text-decoration: none; }
.req-art {
  grid-column: 1 / -1; aspect-ratio: 16 / 9; margin-bottom: 5px; border-radius: 8px; overflow: hidden;
  background: radial-gradient(90% 80% at 50% 35%, color-mix(in srgb, var(--accent) 18%, #0c0e1d), #06070e 75%);
}
.req-art canvas {
  display: block; width: 100%; height: 100%; image-rendering: pixelated;
  --glow: color-mix(in srgb, var(--accent) 55%, #ffd98a);
  filter: drop-shadow(0 0 3px color-mix(in srgb, var(--glow) 70%, transparent));
  animation: req-glow 3.2s ease-in-out infinite;
}
@keyframes req-glow { 50% { filter: drop-shadow(0 0 6px var(--glow)); } }
.city-request:hover .req-art canvas, .city-request:focus-visible .req-art canvas { animation: none; filter: drop-shadow(0 0 7px var(--glow)); }
@media (prefers-reduced-motion: reduce) { .req-art canvas { animation: none; } }
.pop-list { list-style: none; margin: 0; padding: 0 6px 6px; overflow-y: auto; overscroll-behavior: contain; }
.pop-item {
  width: 100%; display: flex; align-items: center; gap: 10px; padding: 8px; text-align: left;
  border: 0; border-radius: 10px; background: transparent; cursor: pointer;
}
.pop-item:hover, .pop-item:focus-visible { background: rgba(255, 255, 255, .08); }
.pop-text { flex: 1; min-width: 0; }
.pop-title, .pop-meta { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pop-title { font-weight: 560; }
.pop-meta { font: 11px var(--mono); color: var(--muted); }
.q-n { flex: none; width: 18px; display: grid; place-items: center; font: 11px var(--mono); color: var(--muted); }
.q-n svg { display: none; width: 10px; height: 10px; fill: var(--accent); shape-rendering: crispEdges; }
.pop-item:hover .q-n b, .pop-item:focus-visible .q-n b { display: none; }
.pop-item:hover .q-n svg, .pop-item:focus-visible .q-n svg { display: block; }
li:first-child .q-n { color: var(--accent); }
.q-dur { flex: none; font: 11px var(--mono); color: var(--muted); }
.q-empty, .mix-empty { padding: 10px 8px 12px; font: 12px var(--mono); color: var(--muted); }
.pick-dot { flex: none; width: 18px; display: grid; place-items: center; }
[aria-checked="true"] > .pick-dot::before { content: ""; width: 6px; height: 6px; background: var(--accent); }

/* timers: focus presets and sleep minutes, with skip / stop / off pushed to the right */
.t-row { display: flex; flex-wrap: wrap; gap: 6px; padding: 2px 14px 12px; }
.t-row + .pop-head { border-top: 1px solid var(--line); }
.t-opt {
  min-width: 44px; min-height: 32px; padding: 0 10px; border-radius: 10px; cursor: pointer;
  border: 1px solid var(--line); background: transparent; font: 12px var(--mono); color: var(--text);
  transition: border-color .2s, background .2s, color .2s;
}
.t-opt:hover { border-color: rgba(255, 255, 255, .22); }
.t-opt[aria-pressed="true"] {
  border-color: color-mix(in srgb, var(--accent) 75%, transparent); color: var(--accent);
  background: color-mix(in srgb, var(--accent) 16%, transparent);
}
.t-act { border-color: transparent; color: var(--muted); }
.t-act:hover { border-color: transparent; background: rgba(255, 255, 255, .08); color: var(--text); }
.t-opt:not(.t-act) + .t-act { margin-left: auto; }

/* running timers: stay on screen when the UI idles (sliding up into the corner #links leaves), hidden by H */
#timerPill { display: flex; gap: 14px; cursor: pointer; transition: opacity .6s ease, border-color .2s; }
#timerPill span { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
#timerPill span::before { content: ""; flex: none; width: 6px; height: 6px; background: var(--accent); }
#timerPill span:empty { display: none; }
#timerPill:hover { border-color: rgba(255, 255, 255, .22); }
body.idle #corner { top: var(--top); }
body.idle #timerPill { opacity: .6; }
body.ui-off #timerPill { opacity: 0; pointer-events: none; }

.mix-empty { margin: 0; padding-inline: 0; }

/* mixer rows: name · slider (0-200 %, 100 % = as the city was designed) · value */
#mixReset {
  margin: -4px -6px; padding: 4px 6px; border: 0; border-radius: 6px; background: transparent; cursor: pointer;
  font: 11px var(--mono); color: var(--muted);
}
#mixReset:hover:not(:disabled) { color: var(--text); background: rgba(255, 255, 255, .08); }
#mixReset:disabled { opacity: .4; cursor: default; }
#mixList { padding: 2px 14px 10px; overflow-y: auto; overscroll-behavior: contain; }
.mix-row { display: grid; grid-template-columns: 78px minmax(0, 1fr) 36px; align-items: center; gap: 10px; min-height: 32px; }
.mix-sep { margin-top: 4px; padding-top: 4px; border-top: 1px solid var(--line); }   /* events after the beds */
.mix-name { font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mix-row input { width: 100%; min-width: 0; margin: 0; accent-color: var(--accent); }
.mix-val { font: 11px var(--mono); color: var(--muted); text-align: right; }
.mix-row.changed .mix-val { color: var(--accent); }

/* vibe: three segmented radio groups (native radios underneath, so arrow keys move within a group) */
/* never taller than the room above the dock (100% is the dock, 8px the gap under the panel): on short screens it scrolls */
#vibe { padding-bottom: 12px; max-height: calc(100dvh - var(--top) - 100% - 8px - var(--bottom)); overflow-y: auto; overscroll-behavior: contain; }
#vibe fieldset { min-width: 0; margin: 0; padding: 6px 14px 4px; border: 0; }
#vibe legend { padding: 0; margin-bottom: 6px; font: 11px var(--mono); color: var(--muted); }
.seg { display: flex; gap: 2px; padding: 3px; border-radius: 12px; border: 1px solid var(--line); background: rgba(255, 255, 255, .05); }
.seg-grid { display: grid; grid-template-columns: repeat(3, 1fr); }   /* the nine styles, three to a row */
.seg label { position: relative; flex: 1; min-width: 0; }
.seg input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
.seg span {
  display: block; padding: 7px 4px; border-radius: 9px; text-align: center; font-size: 13px; white-space: nowrap;
  color: var(--muted); transition: background .15s, color .15s, box-shadow .15s;
}
.seg label:hover span { color: var(--text); }
.seg input:checked + span {
  color: var(--text); background: color-mix(in srgb, var(--accent) 20%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 60%, transparent);
}
.seg input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 1px; }
.vibe-note { margin: 8px 14px 0; font: 11px/1.5 var(--mono); color: var(--muted); }
#vibeSkip { padding: 0; border: 0; background: none; font: inherit; color: var(--accent); cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }

/* save this scene: the S and R keys as buttons, so touch screens can reach them */
#saveMenu { left: auto; right: 0; width: min(300px, 100%); }
#saveMenu svg, #together .pop-item > svg { flex: none; width: 16px; height: 16px; fill: var(--accent); shape-rendering: crispEdges; }
#saveMenu a { color: var(--text); text-decoration: none; }

/* together (README "Together"): who's here, four reactions and a lantern */
#together .pop-head small { color: var(--text); }
.tg-reacts { display: flex; gap: 6px; padding: 4px 14px 8px; }
.tg-react {   /* each in its own colour, the same as its sprite in js/reactions.js */
  flex: 1; min-height: 40px; display: grid; place-items: center; padding: 0; cursor: pointer;
  border: 1px solid var(--line); border-radius: 10px; background: rgba(255, 255, 255, .03);
  transition: border-color .2s, background .2s;
}
.tg-react[data-kind="heart"] { --c: #ff6b8b; }
.tg-react[data-kind="note"] { --c: #8fd3ff; }
.tg-react[data-kind="star"] { --c: #ffd95e; }
.tg-react[data-kind="moon"] { --c: #fff0b3; }
.tg-react:hover { border-color: color-mix(in srgb, var(--c) 55%, transparent); background: color-mix(in srgb, var(--c) 10%, transparent); }
/* the picked one (what a tap on the scene drops): lit in its colour, like a picked timer or vibe */
.tg-react[aria-pressed="true"] {
  border-color: color-mix(in srgb, var(--c) 75%, transparent); background: color-mix(in srgb, var(--c) 16%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c) 40%, transparent);
}
.tg-react:active { background: color-mix(in srgb, var(--c) 22%, transparent); }
.tg-react svg { width: 21px; height: 21px; fill: var(--c); shape-rendering: crispEdges; }   /* 7 px art at 3x */
.tg-hint { margin: -2px 14px 8px; font: 11px/16px var(--mono); color: var(--muted); }
.tg-hint svg { width: 14px; height: 14px; vertical-align: -3px; fill: var(--c); shape-rendering: crispEdges; }   /* 7 px art at 2x */

/* chat (README "Chat"): the city's last hour, oldest first, a line to write in, and why a message wasn't sent */
#chatBtn { position: relative; }
#chatBtn.unread::after {   /* said while the panel was closed */
  content: ""; position: absolute; top: calc(50% - 11px); right: calc(50% - 13px); width: 6px; height: 6px;
  background: var(--accent); box-shadow: 0 0 6px var(--accent);
}
#chat { width: min(380px, 100%); }
#chat .pop-head small { color: var(--text); }
.chat-log {
  list-style: none; margin: 0; padding: 2px 14px 4px; display: flex; flex-direction: column; gap: 6px;
  max-height: min(300px, 38dvh); overflow-y: auto; overscroll-behavior: contain;
}
.chat-log:empty { display: none; }
.chat-msg { font-size: 13px; line-height: 18px; overflow-wrap: anywhere; }
.chat-name { margin-right: 6px; font: 600 11px/18px var(--mono); color: hsl(var(--h, 230) 70% 76%); }
.chat-msg.mine .chat-name { color: var(--accent); }
.chat-msg time { margin-left: 6px; font: 10.5px var(--mono); color: var(--muted); white-space: nowrap; }
.chat-hide {   /* shown on hover and focus with a mouse; always, a little dim, on touch screens */
  margin-left: 4px; padding: 0 5px; border: 0; border-radius: 5px; background: transparent; cursor: pointer;
  font: 10.5px/18px var(--mono); color: var(--muted); opacity: 0;
}
.chat-msg:hover .chat-hide, .chat-hide:focus-visible { opacity: 1; }
.chat-hide:hover { color: var(--text); background: rgba(255, 255, 255, .08); }
@media (hover: none) { .chat-hide { opacity: .75; } }
.chat-empty { margin: 0; padding: 4px 14px 8px; font: 12px/1.5 var(--mono); color: var(--muted); }
.chat-form { position: relative; display: flex; gap: 6px; padding: 6px 8px 0 14px; }
#chatText {
  flex: 1; min-width: 0; padding: 8px 12px; border-radius: 10px; border: 1px solid var(--line);
  background: rgba(255, 255, 255, .06); font: inherit; font-size: 14px; color: var(--text);
}
#chatText::placeholder { color: var(--muted); }
#chatText:focus-visible { outline: none; border-color: color-mix(in srgb, var(--accent) 60%, transparent); }
#chatText:disabled { opacity: .6; }
#chatSend { color: var(--accent); }
#chatSend:disabled { color: var(--muted); }
.chat-foot { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin: 0; padding: 6px 14px 10px; font: 11px/1.45 var(--mono); color: var(--muted); }
#chatNote.warn { color: #ffb3a1; }
#chatUnhide { flex: none; padding: 0; border: 0; background: none; font: inherit; color: var(--muted); cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }
#chatUnhide:hover { color: var(--text); }
/* emoji (js/emoji.js): the smiley's popup between the log and the text box, which gives it some of its room, and the
   shortcode list over them, above the text box; drawn by the system's own emoji font */
#chat { --emoji-font: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif; }
#chatEmojiBtn { color: var(--muted); }
#chatEmojiBtn:hover:not(:disabled) { color: var(--text); }
#chatEmojiBtn[aria-expanded="true"] { background: rgba(255, 255, 255, .1); color: var(--accent); }
#chat.picking .chat-log { max-height: min(140px, 18dvh); }
.chat-emoji { margin-top: 4px; padding: 0 8px 0 10px; border-top: 1px solid var(--line); }
.emoji-scroll { max-height: min(204px, 28dvh); overflow-y: auto; overscroll-behavior: contain; }
.emoji-sec[hidden] { display: none; }
.emoji-label { margin: 9px 4px 3px; font: 600 10px/1 var(--mono); letter-spacing: .24em; text-transform: uppercase; color: var(--muted); }
.emoji-row { display: grid; grid-template-columns: repeat(auto-fill, minmax(36px, 1fr)); }
.emoji {
  height: 36px; padding: 0; border: 0; border-radius: 9px; background: transparent; cursor: pointer;
  font: 21px/1 var(--emoji-font); color: var(--text);
}
.emoji:hover, .emoji:focus-visible { outline: none; background: rgba(255, 255, 255, .1); }
.emoji:focus-visible { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 60%, transparent); }
.emoji-hint { margin: 0; padding: 6px 4px 2px; border-top: 1px solid var(--line); font: 11px/18px var(--mono); color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-suggest {
  position: absolute; left: 14px; bottom: calc(100% + 6px); z-index: 1; width: min(260px, calc(100% - 22px));
  list-style: none; margin: 0; padding: 4px; border-radius: 12px; border: 1px solid var(--line);
  background: rgba(14, 15, 34, .97); box-shadow: 0 12px 30px -12px rgba(0, 0, 0, .8);
}
.chat-suggest li {
  display: flex; align-items: center; gap: 10px; padding: 3px 8px; border-radius: 8px; cursor: pointer;
  font: 12px/26px var(--mono); color: var(--muted); white-space: nowrap;
}
.chat-suggest li span + span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.chat-suggest li:hover { color: var(--text); }
.chat-suggest li[aria-selected="true"] { background: rgba(255, 255, 255, .1); color: var(--text); }
.emoji-e { flex: none; width: 22px; text-align: center; font: 18px/1 var(--emoji-font); }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }


/* status pills */
.pill {
  position: fixed; top: var(--top); padding: 8px 12px; border-radius: 10px;
  border: 1px solid var(--line); background: var(--panel); font: 12px var(--mono); color: var(--text);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
}
/* top right, below #links: the running timers, then "tuning in…" */
#corner {
  position: fixed; top: calc(var(--top) + var(--btn) + 18px); right: max(18px, env(safe-area-inset-right));
  display: flex; flex-direction: column; align-items: flex-end; gap: 8px; transition: top .6s ease;
}
#corner .pill { position: static; }
#loading { color: var(--muted); }
#toast { left: 50%; transform: translateX(-50%); min-width: min(360px, calc(100vw - 32px)); max-width: calc(100vw - 32px); }
#toast .progress { display: flex; align-items: center; gap: 10px; margin-top: 6px; }
#toast .bar { flex: 1; height: 3px; border-radius: 2px; overflow: hidden; background: rgba(255, 255, 255, .12); }
#toast .bar i { display: block; height: 100%; width: 0; background: var(--accent); }
#toastCancel {
  flex: none; padding: 3px 10px; font: 11px var(--mono); cursor: pointer;
  border: 1px solid var(--line); border-radius: 8px; background: rgba(255, 255, 255, .06);
}
#toastCancel:hover { background: rgba(255, 255, 255, .12); }
[hidden] { display: none !important; }

/* the city's billboard: an invisible button over its face (placed by js/app.js), lit up with a label on hover;
   during the Product Hunt launch week, while the face shows the launch, a link to it in its place, lit in Product Hunt's orange */
:is(#pitchSpot, #phSpot) { --spot: var(--accent); position: fixed; padding: 0; border: 0; border-radius: 3px; background: transparent; cursor: pointer; transition: box-shadow .2s; touch-action: pinch-zoom; }
#phSpot { --spot: var(--ph); -webkit-user-drag: none; -webkit-touch-callout: none; }
:is(#pitchSpot, #phSpot) span {
  position: absolute; left: 50%; top: calc(100% + 8px); transform: translateX(-50%); padding: 5px 10px; border-radius: 10px;
  border: 1px solid var(--line); background: rgba(10, 11, 28, .78); font: 11px var(--mono); color: var(--text); white-space: nowrap;
  opacity: 0; pointer-events: none; transition: opacity .2s;
}
@media (hover: hover) {
  :is(#pitchSpot, #phSpot):hover { box-shadow: 0 0 0 2px color-mix(in srgb, var(--spot) 70%, transparent), 0 0 28px -6px var(--spot); }
  :is(#pitchSpot, #phSpot):hover span { opacity: 1; }
}
:is(#pitchSpot, #phSpot):focus-visible span { opacity: 1; }
body.idle :is(#pitchSpot, #phSpot), body.ui-off :is(#pitchSpot, #phSpot) { box-shadow: none; }
body.idle :is(#pitchSpot, #phSpot) span, body.ui-off :is(#pitchSpot, #phSpot) span { opacity: 0; }

/* about panel (the text inside is written by tools/seo.mjs). js/app.js makes it tabbed (.tabbed): a fixed-height panel,
   the tabs and close button on top, one section below that scrolls on its own. Without JS the sections simply stack. */
#about {
  width: min(640px, calc(100vw - 24px)); max-height: min(860px, calc(100dvh - 32px)); padding: 0; overflow: auto;
  overscroll-behavior: contain; border: 1px solid var(--line); border-radius: 16px; color: var(--text);
  background: rgba(10, 11, 28, .86); -webkit-backdrop-filter: blur(18px) saturate(1.3); backdrop-filter: blur(18px) saturate(1.3);
  box-shadow: 0 24px 80px -20px rgba(0, 0, 0, .8); scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, .18) transparent;
}
#about.tabbed { height: min(820px, calc(100dvh - 32px)); overflow: hidden; }   /* same size on every tab, so nothing jumps */
#about::backdrop { background: rgba(3, 4, 12, .5); }
.about-inner { padding: 22px 24px 26px; }
.tabbed .about-inner { height: 100%; padding: 0; display: grid; grid-template: auto minmax(0, 1fr) / minmax(0, 1fr) auto; }
.about-close { color: var(--muted); }
.about-close:hover { color: var(--text); }
.tabbed .about-close { grid-area: 1 / 2; align-self: center; margin: 4px 10px 0 4px; }
.about-tabs { grid-area: 1 / 1; display: flex; padding: 8px 0 0 12px; overflow-x: auto; scrollbar-width: none; }
.about-tabs::-webkit-scrollbar { display: none; }
#about:not(.tabbed) .about-tabs { display: none; }
.about-tabs [role="tab"] {
  flex: none; position: relative; padding: 13px 10px 14px; border: 0; background: none; cursor: pointer;
  font: 600 11px/1 var(--mono); letter-spacing: .2em; text-transform: uppercase; color: var(--muted); transition: color .2s;
}
.about-tabs [role="tab"]:hover, .about-tabs [aria-selected="true"] { color: var(--text); }
.about-tabs [aria-selected="true"]::after { content: ""; position: absolute; left: 10px; right: calc(10px + .2em); bottom: 0; height: 2px; background: var(--accent); }
.about-tabs [role="tab"]:focus-visible { outline-offset: -4px; border-radius: 8px; }   /* the row clips anything outside it */
.tabbed .about-body {
  grid-area: 2 / 1 / 3 / 3; overflow-y: auto; overscroll-behavior: contain; padding: 20px 24px 20px; border-top: 1px solid var(--line);
  scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, .18) transparent;
}
.tabbed .about-panel > h3 { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }   /* the tab says it */
#about h2 { margin: 0 0 8px; font-size: 20px; font-weight: 650; letter-spacing: -.01em; line-height: 1.2; }
#about h3 { margin: 26px 0 10px; font: 600 11px/1 var(--mono); letter-spacing: .28em; text-transform: uppercase; color: var(--muted); }
#about p, #about li, #about dd { color: #cdd0ee; line-height: 1.55; }
#about p { margin: 0 0 10px; }
#about a { color: var(--accent); text-underline-offset: 3px; }
#about b { color: var(--text); font-weight: 600; }
#aboutCity { padding-bottom: 18px; margin-bottom: 22px; border-bottom: 1px solid var(--line); }
/* cities: a card per city in its own accent (--c from the scene); the whole card switches city, the one on screen is lit */
.city-list { margin: 0; padding: 0; list-style: none; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 240px), 1fr)); gap: 8px; }
.city-list li {
  --c-: var(--c, var(--accent)); position: relative; padding: 11px 13px 12px; border-radius: 12px;
  border: 1px solid var(--line); background: rgba(255, 255, 255, .03); transition: border-color .2s, background .2s, box-shadow .2s;
}
.city-list li:hover { border-color: color-mix(in srgb, var(--c-) 45%, transparent); background: color-mix(in srgb, var(--c-) 7%, transparent); }
.city-list li:has([aria-current]) {
  border-color: color-mix(in srgb, var(--c-) 75%, transparent); background: color-mix(in srgb, var(--c-) 13%, transparent);
  box-shadow: 0 0 22px -10px var(--c-);
}
.city-list li:has(a:focus-visible) { outline: 2px solid var(--c-); outline-offset: 2px; }
#about .city-list a { font-weight: 600; text-decoration: none; color: var(--c-); }
.city-list a::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.city-list a:focus-visible { outline: none; }
.city-list span { display: block; margin-top: 1px; font: 11px var(--mono); color: var(--muted); }
#about .city-list p { margin: 6px 0 0; font-size: 13px; line-height: 1.5; }
.keys { margin: 0; display: grid; gap: 6px; }
.keys div { display: grid; grid-template-columns: 120px 1fr; gap: 12px; align-items: baseline; }
.keys dt { white-space: nowrap; }
.keys dd { margin: 0; }
kbd {
  display: inline-block; min-width: 22px; padding: 2px 6px; text-align: center; font: 11px/1.4 var(--mono); color: var(--text);
  border: 1px solid rgba(255, 255, 255, .16); border-bottom-width: 2px; border-radius: 6px; background: rgba(255, 255, 255, .06);
}
/* FAQ: questions fold open, one at a time (<details name>) */
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  display: flex; align-items: baseline; justify-content: space-between; gap: 16px; padding: 11px 2px;
  font-weight: 600; cursor: pointer; list-style: none;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; flex: none; font: 15px/1 var(--mono); color: var(--muted); transition: color .2s; }
.faq summary:hover::after { color: var(--text); }
.faq details[open] summary::after { content: "−"; color: var(--accent); }
.faq summary:focus-visible { outline-offset: -2px; border-radius: 6px; }
#about .faq p { margin: -2px 24px 14px 2px; }
.about-foot { margin-top: 16px !important; }
/* What's new: the latest changes at the end of the About tab (tools/seo.mjs), a day and a line each; whats-new/ has them all */
.news { margin: 0; padding: 0; list-style: none; }
.news li { display: grid; grid-template-columns: 52px 1fr; gap: 10px; align-items: baseline; padding: 8px 0; border-bottom: 1px solid var(--line); }
#about .news li { font-size: 14px; line-height: 1.5; }
.news time { font: 11px var(--mono); color: var(--muted); white-space: nowrap; }

/* billboard card: what the billboard opens (the text is written by tools/seo.mjs), in the city's accent */
#pitchCard {
  width: min(420px, calc(100vw - 24px)); padding: 0; border: 1px solid var(--line); border-radius: 16px; color: var(--text);
  background: rgba(10, 11, 28, .86); -webkit-backdrop-filter: blur(18px) saturate(1.3); backdrop-filter: blur(18px) saturate(1.3);
  box-shadow: 0 24px 80px -20px rgba(0, 0, 0, .8);
}
#pitchCard::backdrop { background: rgba(3, 4, 12, .5); }
.pitch-inner { position: relative; padding: 22px 24px 20px; }
#pitchCard .about-close { position: absolute; top: 10px; right: 10px; }
.pitch-kicker { margin: 0 40px 12px 0; font: 600 11px/1.4 var(--mono); letter-spacing: .2em; text-transform: uppercase; color: var(--accent); }
#pitchCard h2 { margin: 0 0 8px; font-size: 20px; font-weight: 650; letter-spacing: -.01em; line-height: 1.2; }
#pitchCard p:not([class]) { margin: 0 0 18px; color: #cdd0ee; line-height: 1.55; }
.pitch-cta {
  display: inline-flex; align-items: center; gap: 6px; min-height: 40px; padding: 0 16px; border-radius: 10px;
  font-weight: 600; text-decoration: none; color: #12121c; background: var(--accent); transition: filter .2s;
}
.pitch-cta:hover { filter: brightness(1.1); }
.pitch-note { margin: 12px 0 0; font: 11px/1.5 var(--mono); color: var(--muted); }

/* touch: finger-sized targets */
@media (pointer: coarse) {
  :root { --btn: 44px; }
  .chip { padding: 9px 14px; }
  .vol input, .mix-row input { height: 32px; }
  .mix-row { min-height: 40px; }
  .about-tabs [role="tab"] { padding-block: 17px 18px; }
  .t-opt { min-height: 40px; padding-inline: 12px; }
  .seg span { padding-block: 11px; }
  #toastCancel { min-height: 36px; padding-inline: 14px; }
  #saveMenu kbd, #together kbd { display: none; }
  .tg-react { min-height: 48px; }
  #cityFind { font-size: 16px; }                  /* iOS Safari zooms the page into a field with smaller text */
  #chatText { font-size: 16px; }   /* iOS zooms into a text box whose text is smaller */
}
/* mouse and trackpad on wider windows: a mouse needs less room than a thumb, so denser FAQ rows keep every question in
   view in a 720px panel */
@media (pointer: fine) and (min-width: 601px) {
  #about.tabbed { height: min(720px, calc(100dvh - 32px)); }
  .faq summary { padding-block: 7px; }
}
/* tablets and narrow windows (one row would squeeze the track title away): the volume sliders get their own row under
   the track, with the vibe, timer, together, chat and save buttons */
@media (max-width: 940px) {
  #player { flex-wrap: wrap; gap: 2px 6px; }
  .vols { order: 1; flex: 1 0 calc(100% - 5 * (var(--btn) + 6px)); min-width: 0; gap: 18px; padding: 0 6px; }   /* min-width: range inputs have a wide intrinsic minimum */
  #vibeBtn, #timerBtn, #togetherBtn, #chatBtn, #saveBtn { order: 2; }   /* share the volume row, so the track title keeps its room */
  .vol { flex: 1; min-width: 0; }
  .vol input { flex: 1; width: auto; min-width: 0; }
  /* the Product Hunt launch week: the shop and coffee links shrink to icons, so its link keeps its words and the title its room */
  :root:has(#phLink:not([hidden])) { --ph-room: 0px; }
  #links:has(#phLink:not([hidden])) :is(#shopLink, #coffee) { width: var(--btn); padding: 0; justify-content: center; }
  #links:has(#phLink:not([hidden])) :is(#shopLink, #coffee) span { display: none; }
}
/* phones in portrait */
@media (max-width: 600px) {
  :root { --edge: 8px; }
  #cityName { font-size: 24px; }
  .hud-city { max-width: calc(100vw - 4 * var(--btn) - 66px); }   /* clear of #links: four icons */
  /* the pill: dot, "23 here now · 480 today", the city on a line of its own under them and "12,345 all time" under
     that (on the first line when it's all there is) */
  .live { grid-auto-flow: row; grid-template-columns: auto auto; }
  .live:has(.live-now ~ .live-today) { grid-template-columns: auto auto auto; }
  .live::before, .live span { grid-row: 1; }
  .live .live-city { grid-area: 2 / 2 / 3 / -1; }
  .live:has(.live-now, .live-today) .live-all { grid-area: 3 / 2 / 4 / -1; }
  .live .live-city::before, .live:has(.live-now, .live-today) .live-all::before { content: none; }
  #phLink, #shopLink, #coffee { width: var(--btn); padding: 0; justify-content: center; }
  #phLink span, #shopLink span, #coffee span { display: none; }
  #links:has(#phLink:not([hidden])) [data-network="github"] { display: none; }   /* the launch week: still four icons */
  .chip { padding-inline: 12px; gap: 6px; }
  #timerPill { flex-direction: column; gap: 4px; }   /* one timer per line, clear of the city title */
  /* a third row: the sliders get row 2 to themselves, the vibe, timer, together, chat, mixer and save buttons go below them */
  .vols { display: contents; }
  #player::before, #player::after { content: ""; flex-basis: 100%; }   /* line breaks around the sliders */
  #player::before { order: 1; }
  .vol { order: 2; padding-inline: 6px; }
  #player::after { order: 3; }
  #vibeBtn, #timerBtn, #togetherBtn, #chatBtn, #mixerBtn, #saveBtn { order: 4; }
  .pop, #tour, #weather, #mixer, #saveMenu, #cityPicker, #chat { width: 100%; }
  #cityBtnTime { display: none; }               /* the title shows the local time: the three chips fit one row */
  #cityList { grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); }   /* two columns down to 320 px */
  .feat-text strong { font-size: 19px; }
  #vibe fieldset { padding-inline: 10px; }
  .seg span { padding-inline: 2px; }            /* every row's labels fit down to 320 px */
  #queue .pop-head small, #tour .pop-head small, #weather .pop-head small { display: none; }
  .about-inner { padding: 18px 16px 22px; }
  #about.tabbed { height: min(860px, calc(100dvh - 32px)); }   /* phones: nearly full height */
  .tabbed .about-inner { padding: 0; }
  .tabbed .about-body { padding: 16px 16px 18px; }
  .about-tabs { padding-left: 6px; }
  .about-tabs [role="tab"] { padding-inline: 5px; letter-spacing: .08em; }   /* all five tabs fit beside the close button from 360px */
  .about-tabs [aria-selected="true"]::after { left: 5px; right: calc(5px + .08em); }
  .tabbed .about-close { margin-right: 6px; }
  .keys div { grid-template-columns: 96px 1fr; }
  .pitch-inner { padding: 18px 16px; }
}
/* short screens (phones in landscape): tighter title and dock so more of the scene shows */
@media (max-height: 500px) {
  :root { --top: max(10px, env(safe-area-inset-top)); --bottom: max(8px, env(safe-area-inset-bottom)); }
  #cityName { margin: 4px 0 0; font-size: 22px; }
  .sub { font-size: 12px; }
  .live { margin-top: 6px; padding-block: 3px; font-size: 11px; }
  .hud-bottom { gap: 6px; }
  #player { padding-block: 6px; }
}
@media (prefers-reduced-motion: reduce) {
  .ui, #corner, #timerPill { transition: none; }
  #play.pulse, .pop, .live::before, .live::after, #phLink::after { animation: none; }
  .seg span { transition: none; }
  #cities { scroll-behavior: auto; }
}

/* Below 400px the tour and weather chips drop their state (still lit while on; their menus say which), so the three
   chips fit one row. */
@media (max-width: 399px) {
  #tourState, #weatherState { display: none; }
}
/* On the narrowest phones, keep room for city names beside the four links. */
@media (max-width: 360px) {
  #player { column-gap: 4px; }   /* the third row's six buttons fit beside each other down to 320 px */
  #links { display: grid; grid-template-columns: repeat(2, var(--btn)); }
  .hud-city { max-width: calc(100vw - 2 * var(--btn) - 64px); }
  #corner { top: calc(var(--top) + 2 * var(--btn) + 20px); }
}
/* Below 360px (down to 320px) the About tabs tighten again so all five still fit. */
@media (max-width: 359px) {
  .about-tabs [role="tab"] { padding-inline: 3.5px; letter-spacing: 0; }
  .about-tabs [aria-selected="true"]::after { left: 3.5px; right: 3.5px; }
}
