/* All of the World - look and UI layer.
   Sections: tokens, page, avatar, speech bubble, HUD, touch controls,
   start screen, loading, toasts, map attribution, motion preferences. */

/* ------------------------------------------------------------- tokens -- */

:root {
  --font: ui-rounded, "SF Pro Rounded", "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system,
    "Helvetica Neue", Roboto, "Noto Sans", Arial, sans-serif;

  --ink: #06242c;
  --abyss: #041b22;
  --teal: #06323b;
  --aqua: #2fd6c8;
  --mint: #93f2a4;
  --ice: #d9fffa;

  --text: #f1fffc;
  --text-dim: rgba(231, 255, 251, 0.72);
  --text-faint: rgba(231, 255, 251, 0.52);

  --glass: rgba(5, 34, 42, 0.72);
  --glass-solid: rgba(5, 34, 42, 0.9);
  --line: rgba(255, 255, 255, 0.17);
  --sheen: linear-gradient(180deg, rgba(255, 255, 255, 0.13), rgba(255, 255, 255, 0) 52%);
  --lift: 0 8px 26px rgba(0, 14, 20, 0.38);
  --focus: 0 0 0 2px rgba(4, 27, 34, 0.9), 0 0 0 4px var(--aqua);

  --warn: #ffc857;
  --error: #ff7a7a;

  --sat: env(safe-area-inset-top, 0px);
  --sar: env(safe-area-inset-right, 0px);
  --sab: env(safe-area-inset-bottom, 0px);
  --sal: env(safe-area-inset-left, 0px);

  --edge: 12px;
  /* Height kept clear along the bottom for the imagery attribution line.
     hud.js replaces this with the measured height once the world has drawn it
     (it wraps to two or three lines on a phone). */
  --attrib: calc(24px + var(--sab));
  /* Set by hud.js while an on-screen keyboard covers the bottom of the page. */
  --kb: 0px;
}

/* --------------------------------------------------------------- page -- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

[hidden] {
  display: none !important;
}

html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
  overflow: hidden;
  overscroll-behavior: none;
}

body {
  position: fixed;
  inset: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
  background: var(--abyss);
}

body {
  font: 500 14px/1.35 var(--font);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  touch-action: none;
  /* Shown before the map has anything to draw. */
  background:
    radial-gradient(120% 70% at 78% -8%, rgba(126, 255, 214, 0.26), transparent 62%),
    radial-gradient(90% 60% at 8% 4%, rgba(64, 186, 255, 0.24), transparent 60%),
    linear-gradient(168deg, #0a4853 0%, #06323b 46%, #041b22 100%);
}

input,
button {
  font: inherit;
  color: inherit;
  margin: 0;
}

input {
  user-select: text;
  -webkit-user-select: text;
  touch-action: manipulation;
}

button {
  cursor: pointer;
  touch-action: manipulation;
  -webkit-appearance: none;
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
}

:focus {
  outline: none;
}

::selection {
  color: #fff;
  background: rgba(47, 214, 200, 0.42);
}

:focus-visible {
  box-shadow: var(--focus);
}

#map {
  position: absolute;
  inset: 0;
  z-index: 0;
}

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

.ico {
  width: 18px;
  height: 18px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.ico .ico-fill {
  fill: currentColor;
  stroke: none;
}

.glass {
  color: var(--text);
  background: var(--sheen), var(--glass);
  border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), var(--lift);
  -webkit-backdrop-filter: blur(14px) saturate(1.5);
  backdrop-filter: blur(14px) saturate(1.5);
}

/* Blurring a live WebGL canvas every frame is expensive (measured on desktop at
   ~110 ms/s of GPU-process time while walking): keep the blur only on large
   screens with a mouse, and trade it for a denser tint everywhere else. */
@media (pointer: coarse), (hover: none), (max-width: 999px) {
  .glass {
    background: var(--sheen), rgba(5, 34, 42, 0.84);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

.noscript {
  position: fixed;
  inset: 0;
  z-index: 99;
  display: grid;
  place-items: center;
  margin: 0;
  padding: 24px;
  text-align: center;
  font-size: 16px;
  background: var(--teal);
}

/* ------------------------------------------------------------- avatar -- */

.aotw-avatar {
  /* Classic aqua, in case setColor has not run. */
  --av-base: #2fd6c8;
  --av-mid: #3fe0ae;
  --av-warm: #7df08f;
  --av-glow: #cdfcc6;
  --av-deep: #0f7a84;
  --av-hbase: #33cfe0;
  --av-hlight: #b4f6ff;
  --av-hdeep: #1486a0;
  --av-ink: #128f86;

  position: relative;
  width: 56px;
  height: 64px;
  flex: none;
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
  font-family: var(--font, system-ui, sans-serif);
}

.aotw-s-base { stop-color: var(--av-base); }
.aotw-s-mid { stop-color: var(--av-mid); }
.aotw-s-warm { stop-color: var(--av-warm); }
.aotw-s-glow { stop-color: var(--av-glow); }
.aotw-s-deep { stop-color: var(--av-deep); }
.aotw-s-hbase { stop-color: var(--av-hbase); }
.aotw-s-hlight { stop-color: var(--av-hlight); }
.aotw-s-hdeep { stop-color: var(--av-hdeep); }

.aotw-avatar__shadow {
  position: absolute;
  left: 50%;
  bottom: -7px;
  width: 52px;
  height: 16px;
  margin-left: -26px;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(0, 12, 16, 0.62), rgba(0, 12, 16, 0.3) 58%, rgba(0, 12, 16, 0));
}

/* isSelf: a quiet halo on the ground under your own feet. */
.aotw-avatar__ring {
  position: absolute;
  left: 50%;
  bottom: -11px;
  width: 66px;
  height: 23px;
  margin-left: -33px;
  border-radius: 50%;
  border: 1.5px solid rgba(255, 255, 255, 0.92);
  box-shadow: 0 0 9px 1px var(--av-base), inset 0 0 7px var(--av-base);
  animation: aotw-ring 2.6s ease-in-out infinite;
}

.aotw-avatar__fig {
  position: absolute;
  inset: 0;
  transform-origin: 50% 100%;
}

.aotw-avatar__svg {
  display: block;
  width: 56px;
  height: 64px;
  overflow: visible;
}

/* A thin dark rim keeps the glass readable on pale ground (snow, sand, roofs). */
.aotw-halo {
  fill: rgba(2, 24, 30, 0.34);
  stroke: rgba(2, 24, 30, 0.34);
  stroke-width: 1.7;
}

/* Like the bubble, the name tag shrinks less than the figure does with
   distance, so far-off people can still be told apart. */
.aotw-avatar__name {
  position: absolute;
  left: 50%;
  top: calc(100% + 11px);
  transform: translateX(-50%) scale(calc(clamp(0.74, var(--world-scale, 1), 1.1) / var(--world-scale, 1)));
  transform-origin: 50% 0;
  max-width: 150px;
  padding: 3px 8px 4px;
  border-radius: 999px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 11.5px;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: 0.01em;
  color: #fff;
  background: rgba(4, 27, 34, 0.74);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.16), 0 2px 6px rgba(0, 12, 16, 0.35);
}

.aotw-avatar.is-self .aotw-avatar__name {
  color: var(--ink);
  background: rgba(255, 255, 255, 0.94);
  box-shadow: 0 0 0 1px rgba(4, 27, 34, 0.25), 0 2px 8px rgba(0, 12, 16, 0.4);
}

.aotw-avatar.is-npc .aotw-avatar__name {
  font-weight: 600;
  color: rgba(255, 255, 255, 0.86);
  background: rgba(4, 27, 34, 0.56);
  box-shadow: 0 2px 6px rgba(0, 12, 16, 0.25);
}

/* Muted: the figure steps back and a small crossed-speaker joins the name. */
.aotw-avatar__mute {
  display: none;
  width: 11px;
  height: 11px;
  margin: 0 4px -1.5px 0;
  fill: currentColor;
  stroke: currentColor;
  stroke-width: 1.3;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.aotw-avatar.is-muted .aotw-avatar__mute {
  display: inline-block;
}

.aotw-avatar.is-muted .aotw-avatar__fig {
  opacity: 0.58;
  filter: grayscale(0.85);
}

.aotw-avatar.is-muted .aotw-avatar__shadow {
  opacity: 0.6;
}

.aotw-avatar.is-muted .aotw-avatar__name {
  color: rgba(255, 255, 255, 0.8);
  background: rgba(4, 27, 34, 0.62);
}

/* Tap target, present only after avatar.onTap(). It covers the figure and
   grows as the world scale shrinks, so it never drops under ~44px on screen. */
.aotw-avatar__hit {
  --hit: calc(44px / max(var(--world-scale, 1), 0.1));
  position: absolute;
  left: 50%;
  bottom: 0;
  width: max(56px, var(--hit));
  height: max(64px, var(--hit));
  transform: translateX(-50%);
  border-radius: 28px;
  pointer-events: auto;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

@media (hover: hover) {
  .aotw-avatar:has(.aotw-avatar__hit:hover) .aotw-avatar__fig {
    filter: brightness(1.12);
  }

  .aotw-avatar.is-muted:has(.aotw-avatar__hit:hover) .aotw-avatar__fig {
    opacity: 0.7;
    filter: grayscale(0.85);
  }
}

/* Walking: a little waddle. The fig and shadow animations run on the compositor; an
   animation on the SVG <g class="aotw-head"> inside did not, and repainted every walking
   figure on every frame (measured: a quarter to a third of all rendering work with people
   about), so the head rides with the body. */
.aotw-avatar.is-moving .aotw-avatar__fig {
  animation: aotw-walk 0.62s linear infinite;
}

.aotw-avatar.is-moving .aotw-avatar__shadow {
  animation: aotw-shadow 0.31s ease-in-out infinite alternate;
}

@keyframes aotw-walk {
  0% { transform: translateY(0) rotate(-3.2deg); animation-timing-function: ease-out; }
  25% { transform: translateY(-3.6px) rotate(0deg); animation-timing-function: ease-in; }
  50% { transform: translateY(0) rotate(3.2deg); animation-timing-function: ease-out; }
  75% { transform: translateY(-3.6px) rotate(0deg); animation-timing-function: ease-in; }
  100% { transform: translateY(0) rotate(-3.2deg); }
}

@keyframes aotw-shadow {
  from { transform: scale(1); opacity: 1; }
  to { transform: scale(0.84); opacity: 0.75; }
}

@keyframes aotw-ring {
  0%, 100% { opacity: 0.55; transform: scale(0.96); }
  50% { opacity: 1; transform: scale(1.03); }
}

/* ------------------------------------------------------ speech bubble -- */

.aotw-avatar__bubbles {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 11px);
  width: 0;
  height: 0;
}

.aotw-bubble {
  /* On-screen size stays between 0.86x and 1.15x whatever the world scale. */
  --bubble-k: calc(clamp(0.86, var(--world-scale, 1), 1.15) / var(--world-scale, 1));
  position: absolute;
  left: 0;
  bottom: 0;
  width: max-content;
  max-width: 228px;
  transform: translateX(-50%) scale(var(--bubble-k));
  transform-origin: 50% calc(100% + 11px);
  isolation: isolate;
}

.aotw-bubble__pop {
  transform-origin: 50% calc(100% + 6px);
  /* Keyline and shadow are filters so they wrap body and tail as one shape. Two, not
     three: every filter pass is re-run whenever the figure repaints, and a crowd with
     bubbles up measured 13% faster with one keyline pass. */
  filter:
    drop-shadow(0 0 0.7px rgba(4, 27, 34, 0.95))
    drop-shadow(0 6px 8px rgba(0, 14, 20, 0.4));
  animation:
    aotw-pop 0.3s cubic-bezier(0.2, 1.5, 0.4, 1) both,
    aotw-fade 0.32s ease-in var(--out-delay, 4680ms) forwards;
}

/* Solid white, dark keyline, deep shadow: legible on dark forest, bright sand
   and noisy rooftops alike. */
.aotw-bubble__body {
  position: relative;
  min-width: 40px;
  padding: 8px 13px 11px;
  border-radius: 16px;
  overflow: hidden;
  background: linear-gradient(180deg, #ffffff 30%, #eafaf8);
  color: var(--ink, #06242c);
  font-size: 14px;
  font-weight: 650;
  line-height: 1.3;
  letter-spacing: 0.003em;
  text-align: center;
  text-wrap: balance;
  overflow-wrap: anywhere;
  white-space: normal;
}

.aotw-bubble__body.is-tiny {
  font-size: 19px;
  line-height: 1.15;
}

.aotw-bubble__body.is-long {
  font-size: 13px;
  text-wrap: pretty;
}

.aotw-bubble__text {
  display: block;
}

.aotw-bubble__tail {
  position: absolute;
  left: 50%;
  bottom: -5px;
  z-index: -1;
  width: 13px;
  height: 13px;
  margin-left: -6.5px;
  border-radius: 0 0 3px 0;
  background: #eafaf8;
  transform: rotate(45deg);
}

/* The five seconds, running out along the bottom edge. */
.aotw-bubble__timer {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3.5px;
  background: rgba(6, 36, 44, 0.1);
}

.aotw-bubble__timer::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--av-ink, #128f86);
  transform-origin: 0 50%;
  animation: aotw-drain var(--ttl, 5000ms) linear forwards;
}

@keyframes aotw-pop {
  from { opacity: 0; transform: scale(0.5) translateY(6px); }
  60% { opacity: 1; }
  to { opacity: 1; transform: none; }
}

@keyframes aotw-fade {
  to { opacity: 0; transform: translateY(-7px) scale(0.96); }
}

@keyframes aotw-drain {
  to { transform: scaleX(0); }
}

/* Whoever is talking draws over their neighbours. The world module depth-sorts
   its `.aotw-entity` wrappers with inline z-index; this lifts the ones that
   currently hold a bubble above the rest. */
.aotw-entity:has(.aotw-avatar.is-speaking) {
  z-index: 2000000 !important;
}

/* ---------------------------------------------------------------- HUD -- */

.hud {
  position: absolute;
  inset: 0;
  z-index: 10;
  pointer-events: none;
}

.hud-top {
  position: absolute;
  top: calc(var(--edge) + var(--sat));
  left: calc(var(--edge) + var(--sal));
  right: calc(var(--edge) + var(--sar));
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
}

.hud-top > * {
  pointer-events: auto;
}

/* Where am I + go to place. */

.loc {
  position: relative;
  min-width: 0;
  flex: 0 1 auto;
}

.loc-chip {
  display: flex;
  align-items: center;
  gap: 9px;
  max-width: 100%;
  min-height: 46px;
  padding: 6px 6px 6px 12px;
  border-radius: 23px;
  text-align: left;
  transition: border-color 0.15s, background-color 0.15s;
}

.loc-chip > .ico {
  color: var(--aqua);
  width: 20px;
  height: 20px;
}

.loc-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.loc-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 300px;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: 0.005em;
}

.loc-coords {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 11px;
  font-weight: 500;
  line-height: 1.3;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}

.loc-go {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: none;
  height: 32px;
  margin-left: 4px;
  padding: 0 12px 0 9px;
  border-radius: 16px;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--ice);
  background: rgba(255, 255, 255, 0.1);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12);
  transition: background-color 0.15s, color 0.15s;
}

.loc-go .ico {
  width: 16px;
  height: 16px;
}

.loc-chip:hover .loc-go,
.loc-chip[aria-expanded="true"] .loc-go {
  color: var(--ink);
  background: linear-gradient(180deg, #a8fbe6, var(--aqua));
}

.goto {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  width: 340px;
  max-width: calc(100vw - 2 * var(--edge) - var(--sal) - var(--sar));
  padding: 8px;
  border-radius: 20px;
  background: var(--sheen), var(--glass-solid);
  animation: drop-in 0.18s ease-out;
}

.goto-input {
  display: block;
  width: 100%;
  height: 42px;
  padding: 0 14px;
  border-radius: 13px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.08);
  font-size: 16px;
  font-weight: 600;
  color: #fff;
}

.goto-input::placeholder {
  color: var(--text-faint);
  font-weight: 500;
}

.goto-input:focus {
  border-color: var(--aqua);
  background: rgba(255, 255, 255, 0.12);
  box-shadow: none;
}

.goto-status {
  margin: 8px 8px 2px;
  font-size: 12px;
  color: var(--text-dim);
}

.goto-results {
  list-style: none;
  margin: 6px 0 0;
  padding: 0;
  max-height: min(46vh, 320px);
  overflow-y: auto;
  overscroll-behavior: contain;
  touch-action: pan-y;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.25) transparent;
}

.goto-results:empty {
  display: none;
}

.goto-results .goto-head {
  padding: 6px 10px 4px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.goto-item {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  min-height: 38px;
  padding: 7px 10px;
  border-radius: 11px;
  text-align: left;
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.25;
}

.goto-item .ico {
  width: 15px;
  height: 15px;
  color: var(--aqua);
}

.goto-item span {
  min-width: 0;
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
}

.goto-item:hover,
.goto-item:focus-visible {
  background: rgba(255, 255, 255, 0.12);
  box-shadow: none;
}

/* Nearby people + connection state. */

.people {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
  min-height: 46px;
  padding: 0 15px 0 13px;
  border-radius: 23px;
  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.people-dot {
  position: relative;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #8aa3a8;
}

.people[data-state="online"] .people-dot {
  background: #7df08f;
  box-shadow: 0 0 0 3px rgba(125, 240, 143, 0.22), 0 0 10px #7df08f;
}

.people[data-state="connecting"] .people-dot {
  background: var(--warn);
  animation: blink 1s ease-in-out infinite;
}

.people[data-state="offline"] {
  color: var(--text-dim);
}

@keyframes blink {
  50% { opacity: 0.3; }
}

@keyframes drop-in {
  from { opacity: 0; transform: translateY(-6px); }
}

/* Controls hint (desktop only). */

.hint {
  position: absolute;
  left: calc(var(--edge) + var(--sal));
  bottom: calc(var(--edge) + var(--sab));
  pointer-events: auto;
  display: grid;
  gap: 5px;
  margin: 0;
  padding: 9px 12px 9px 9px;
  border-radius: 14px;
  list-style: none;
  font-size: 11.5px;
  font-weight: 600;
  color: #fff;
  background: rgba(5, 34, 42, 0.6);
  transition: opacity 1.2s;
}

/* After a while the hint steps back; it returns on hover. */
.hint.is-quiet {
  opacity: 0.45;
}

.hint.is-quiet:hover {
  opacity: 1;
  transition-duration: 0.2s;
}

.hint li {
  display: flex;
  align-items: center;
  gap: 7px;
}

.keys {
  display: inline-flex;
  gap: 2px;
  min-width: 78px;
}

kbd {
  display: inline-grid;
  place-items: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 5px;
  font: 700 10px/1 var(--font);
  letter-spacing: 0.02em;
  color: var(--ice);
  background: rgba(255, 255, 255, 0.1);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.2), inset 0 -2px 0 rgba(255, 255, 255, 0.08);
}

/* Chat. */

.hud-bottom {
  position: absolute;
  left: 50%;
  bottom: calc(var(--attrib) + 6px);
  width: min(540px, 100vw - 2 * 196px);
  transform: translateX(-50%);
}

.chat {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  height: 48px;
  padding: 0 6px 0 18px;
  border-radius: 24px;
  pointer-events: auto;
  transition: border-color 0.15s, box-shadow 0.15s;
}

.chat:focus-within {
  border-color: var(--aqua);
  background: var(--sheen), var(--glass-solid);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 0 0 3px rgba(47, 214, 200, 0.28), var(--lift);
}

.chat-input {
  flex: 1 1 auto;
  min-width: 0;
  height: 100%;
  padding: 0;
  border: 0;
  background: none;
  font-size: 16px;
  font-weight: 600;
  color: #fff;
}

.chat-input:focus-visible {
  box-shadow: none;
}

.chat-input::placeholder {
  color: var(--text-dim);
  font-weight: 500;
}

.chat-rule {
  flex: none;
  padding: 3px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  color: var(--text-dim);
  background: rgba(255, 255, 255, 0.08);
}

.rule-long {
  display: none;
}

/* Room to spare and nobody typing: spell the rule out. */
@media (min-width: 1000px) {
  .chat:not(:focus-within) .rule-long {
    display: inline;
  }

  .chat:not(:focus-within) .rule-short {
    display: none;
  }
}

.chat-count {
  flex: none;
  min-width: 28px;
  padding: 3px 7px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 800;
  text-align: center;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  background: var(--warn);
}

.chat-send {
  display: grid;
  place-items: center;
  flex: none;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  color: var(--ink);
  background: linear-gradient(180deg, #b6fde9, var(--aqua) 55%, #57e59a);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7), 0 2px 8px rgba(0, 14, 20, 0.35);
  transition: transform 0.12s, filter 0.12s, opacity 0.15s;
}

.chat-send .ico {
  stroke-width: 2.2;
}

.chat-send:hover {
  filter: brightness(1.08);
}

.chat-send:active {
  transform: scale(0.92);
}

.chat.is-empty .chat-send {
  opacity: 0.55;
}

/* ----------------------------------------------------- touch controls -- */

.touch {
  display: none;
}

html.is-touch .touch {
  display: block;
}

html.is-touch .hint {
  display: none;
}

.joystick {
  position: absolute;
  left: calc(16px + var(--sal));
  bottom: calc(var(--attrib) + 68px);
  width: 124px;
  height: 124px;
  border-radius: 50%;
  pointer-events: auto;
  touch-action: none;
  background:
    radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0) 38%, rgba(255, 255, 255, 0.1) 39%, rgba(255, 255, 255, 0.03) 70%),
    rgba(5, 34, 42, 0.42);
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.34), 0 6px 20px rgba(0, 14, 20, 0.3);
}

.joystick-knob {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 56px;
  height: 56px;
  margin: -28px 0 0 -28px;
  border-radius: 50%;
  background:
    radial-gradient(60% 46% at 42% 24%, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0) 70%),
    radial-gradient(circle at 50% 78%, #9af4b0, var(--aqua) 55%, #14929c);
  box-shadow: 0 0 0 1.5px rgba(4, 27, 34, 0.45), 0 5px 12px rgba(0, 14, 20, 0.45);
  transition: transform 0.14s ease-out;
  will-change: transform;
}

.joystick.is-active .joystick-knob {
  transition: none;
}

.run-btn {
  position: absolute;
  right: calc(16px + var(--sar));
  bottom: calc(var(--attrib) + 84px);
  display: grid;
  place-items: center;
  align-content: center;
  gap: 1px;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  pointer-events: auto;
  touch-action: none;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #fff;
  background: var(--sheen), rgba(5, 34, 42, 0.5);
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.34), 0 6px 20px rgba(0, 14, 20, 0.3);
  transition: transform 0.1s, background-color 0.12s;
}

.run-btn .ico {
  width: 22px;
  height: 22px;
  stroke-width: 2.2;
}

.run-btn[aria-pressed="true"] {
  color: var(--ink);
  background: linear-gradient(180deg, #b6fde9, var(--aqua) 55%, #57e59a);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7), 0 0 0 1.5px rgba(4, 27, 34, 0.4), 0 0 22px rgba(47, 214, 200, 0.6);
  transform: scale(0.96);
}

/* Phone and narrow windows: chat runs edge to edge above the attribution line. */
@media (max-width: 760px) {
  :root {
    --edge: 10px;
  }

  .hud-bottom {
    left: calc(var(--edge) + var(--sal));
    right: calc(var(--edge) + var(--sar));
    width: auto;
    transform: none;
  }

  .hint {
    display: none;
  }

  .loc-chip {
    min-height: 44px;
    gap: 7px;
    padding-left: 10px;
  }

  .people {
    min-height: 44px;
    padding: 0 13px 0 11px;
  }

  .loc-label {
    max-width: 46vw;
    font-size: 13.5px;
  }

  .loc-go {
    width: 32px;
    padding: 0;
    justify-content: center;
    margin-left: 2px;
  }

  .loc-go-text {
    display: none;
  }

  .goto {
    position: fixed;
    top: calc(var(--edge) + var(--sat) + 52px);
    left: calc(var(--edge) + var(--sal));
    right: calc(var(--edge) + var(--sar));
    width: auto;
    max-width: none;
  }
}

/* With the keyboard up the thumbs are busy typing: put the sticks away and
   sit the chat bar right on top of the keys. */
html.is-keyboard .touch {
  display: none;
}

html.is-keyboard .hud-bottom {
  bottom: calc(8px + var(--kb));
}

/* ------------------------------------------------------- start screen -- */

.start {
  position: fixed;
  inset: 0;
  z-index: 50;
  overflow: hidden auto;
  overscroll-behavior: contain;
  touch-action: pan-y;
  scrollbar-width: none;
  background:
    radial-gradient(110% 60% at 82% -6%, rgba(140, 255, 214, 0.34), transparent 62%),
    radial-gradient(90% 56% at 6% 2%, rgba(64, 186, 255, 0.3), transparent 60%),
    linear-gradient(170deg, #0b4d58 0%, #073842 40%, #041b22 100%);
}

.start::-webkit-scrollbar {
  display: none;
}

/* Leaving: the sky lifts away and you are standing on the ground. */
.start.is-leaving {
  transition: opacity 0.5s ease, transform 0.6s cubic-bezier(0.3, 0, 0.2, 1), visibility 0s 0.6s;
  opacity: 0;
  transform: scale(1.12);
  visibility: hidden;
  pointer-events: none;
}

.start-inner {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  min-height: 100%;
  padding: calc(18px + var(--sat)) calc(18px + var(--sar)) calc(14px + var(--sab)) calc(18px + var(--sal));
  overflow: hidden;
}

.start-inner::before,
.start-inner::after {
  content: "";
  flex: 1 1 0;
}

.start-inner::after {
  flex-grow: 1.4;
}

/* Aurora: three slow ribbons of light behind the title. */
.sky {
  position: absolute;
  inset: 0 0 auto;
  height: 460px;
  pointer-events: none;
}

.sky i {
  position: absolute;
  left: 50%;
  border-radius: 50%;
  border-top: 1.5px solid rgba(214, 255, 248, 0.5);
  -webkit-mask-image: linear-gradient(90deg, transparent 8%, #000 38%, #000 62%, transparent 92%);
  mask-image: linear-gradient(90deg, transparent 8%, #000 38%, #000 62%, transparent 92%);
  animation: sway 14s ease-in-out infinite alternate;
}

.sky i:nth-child(1) {
  top: 34px;
  width: 1500px;
  height: 900px;
  margin-left: -900px;
  box-shadow: inset 0 26px 46px -22px rgba(120, 255, 220, 0.5);
  transform: rotate(-9deg);
}

.sky i:nth-child(2) {
  top: 92px;
  width: 1700px;
  height: 1000px;
  margin-left: -700px;
  border-top-color: rgba(190, 240, 255, 0.34);
  box-shadow: inset 0 34px 60px -30px rgba(90, 200, 255, 0.5);
  transform: rotate(7deg);
  animation-duration: 19s;
  animation-direction: alternate-reverse;
}

.sky i:nth-child(3) {
  top: 6px;
  width: 2200px;
  height: 1300px;
  margin-left: -1250px;
  border-top-color: rgba(200, 255, 220, 0.22);
  box-shadow: inset 0 40px 70px -36px rgba(150, 255, 170, 0.36);
  transform: rotate(-3deg);
  animation-duration: 23s;
}

@keyframes sway {
  from { translate: -26px 0; }
  to { translate: 26px 8px; }
}

.start-head {
  position: relative;
  text-align: center;
}

.wordmark {
  margin: 0;
  font-size: clamp(36px, 9.6vw, 58px);
  font-weight: 800;
  line-height: 1.02;
  letter-spacing: -0.035em;
  color: #fff;
  background: linear-gradient(180deg, #ffffff 34%, #a9f7ea 96%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 2px 14px rgba(47, 214, 200, 0.45));
}

.wordmark span {
  font-weight: 300;
  letter-spacing: -0.02em;
}

.tagline {
  margin: 8px 0 0;
  font-size: 15px;
  font-weight: 500;
  color: var(--text-dim);
}

/* The buddy standing on the curve of the Earth. */
.stage {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: flex-end;
  flex: none;
  width: 100%;
  height: 216px;
  padding-bottom: 18px;
}

.stage-globe {
  position: absolute;
  left: 50%;
  top: calc(100% - 40px);
  width: 2400px;
  height: 2400px;
  margin-left: -1200px;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 0%, #11707a 0, #0a4a55 190px, #06323b 420px, #052a33 700px);
  box-shadow:
    inset 0 1.5px 0 rgba(214, 255, 248, 0.85),
    inset 0 18px 34px -14px rgba(120, 255, 226, 0.6),
    0 -14px 60px -4px rgba(47, 214, 200, 0.5),
    0 -2px 14px rgba(160, 255, 236, 0.5);
}

.stage-avatar {
  --world-scale: 2.1;
  position: relative;
  transform: scale(var(--world-scale));
  transform-origin: 50% 100%;
}

.stage-avatar .aotw-avatar__name {
  display: none;
}

.start-form {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  max-width: 780px;
  margin-top: 14px;
}

/* The name field is the buddy's name tag, not a form row. */
.start-name {
  width: min(250px, 100%);
  height: 44px;
  padding: 0 18px;
  border-radius: 22px;
  border: 1px solid rgba(255, 255, 255, 0.3);
  background: var(--sheen), rgba(3, 26, 33, 0.5);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18), 0 6px 20px rgba(0, 14, 20, 0.25);
  text-align: center;
  font-size: 17px;
  font-weight: 700;
  color: #fff;
  transition: border-color 0.15s, box-shadow 0.15s;
}

.start-name::placeholder {
  color: var(--text-faint);
  font-weight: 500;
}

.start-name:focus {
  border-color: var(--aqua);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18), 0 0 0 3px rgba(47, 214, 200, 0.3);
}

.swatches {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-top: 14px;
}

.swatch {
  position: relative;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background:
    radial-gradient(62% 44% at 42% 22%, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0) 72%),
    radial-gradient(circle at 50% 84%, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 52%),
    radial-gradient(circle at 50% 50%, rgba(0, 0, 0, 0) 52%, rgba(0, 20, 26, 0.35)),
    var(--swatch);
  box-shadow: 0 2px 6px rgba(0, 14, 20, 0.4);
  transition: transform 0.14s cubic-bezier(0.2, 1.4, 0.4, 1);
}

.swatch:hover {
  transform: scale(1.1);
}

.swatch[aria-checked="true"] {
  transform: scale(1.12);
  box-shadow: 0 0 0 2px #06323b, 0 0 0 4px #fff, 0 2px 10px rgba(0, 14, 20, 0.4);
}

.start-q {
  margin: 18px 0 11px;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.005em;
  color: #fff;
}

.start-go {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  width: 100%;
}

.btn-go {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  flex: 1 1 260px;
  max-width: 320px;
  min-width: 0;
  padding: 0 18px;
  height: 50px;
  border-radius: 25px;
  font-size: 16px;
  font-weight: 800;
  letter-spacing: -0.005em;
  color: var(--ink);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.65), rgba(255, 255, 255, 0) 50%),
    linear-gradient(100deg, #5fe6dc, #7df0a6);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.8), 0 0 0 1px rgba(4, 27, 34, 0.25), 0 8px 26px rgba(47, 214, 200, 0.38);
  transition: transform 0.14s cubic-bezier(0.2, 1.4, 0.4, 1), filter 0.14s;
}

.btn-go .ico {
  width: 20px;
  height: 20px;
  stroke-width: 1.9;
}

.btn-go:hover {
  filter: brightness(1.06);
  transform: translateY(-1px);
}

.btn-go:active {
  transform: scale(0.97);
}

.btn-go:focus-visible {
  box-shadow: var(--focus);
}

.btn-go span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* "Where you left off": same weight of choice, quieter voice. */
.btn-go--quiet {
  font-size: 14.5px;
  font-weight: 700;
  color: #fff;
  background: var(--sheen), rgba(3, 26, 33, 0.5);
  box-shadow: inset 0 0 0 1.5px rgba(141, 242, 224, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.16), 0 8px 22px rgba(0, 14, 20, 0.25);
}

.btn-go--quiet .ico {
  color: var(--aqua);
}

.btn-go-stack {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.15;
}

.btn-go-stack small {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 11.5px;
  font-weight: 650;
  opacity: 0.74;
}

.btn-go--quiet .btn-go-stack small {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
  opacity: 1;
}

.btn-go-stack span:empty {
  display: none;
}

.btn-go-stack span {
  max-width: 100%;
}

.start-or {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  margin: 13px 0 10px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.start-or::before,
.start-or::after {
  content: "";
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2));
}

.start-or::after {
  transform: scaleX(-1);
}

.start:not(.has-places) .start-or {
  display: none;
}

.places {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 7px;
  width: 100%;
}

.place {
  min-width: 0;
  height: 36px;
  padding: 0 12px;
  border-radius: 19px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12.5px;
  font-weight: 650;
  color: var(--text);
  background: var(--sheen), rgba(3, 26, 33, 0.46);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.17), inset 0 1px 0 rgba(255, 255, 255, 0.14);
  transition: background-color 0.14s, color 0.14s, transform 0.14s cubic-bezier(0.2, 1.4, 0.4, 1);
}

.place:hover {
  color: var(--ink);
  background: linear-gradient(180deg, #d4fff5, #8cf0de);
  transform: translateY(-1px);
}

.place:active {
  transform: scale(0.97);
}

.start-fine {
  margin: 11px 0 0;
  font-size: 12px;
  text-align: center;
  color: var(--text-faint);
}

.start-fine .text-link {
  margin-left: 6px;
  white-space: nowrap;
}

@media (max-width: 760px) {
  .places {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (max-width: 560px) {
  .places {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .tagline {
    font-size: 14px;
  }

  .stage {
    height: 204px;
  }

  .stage-avatar {
    --world-scale: 1.85;
  }

  .start-q {
    margin: 20px 0 10px;
  }

  .start-or {
    margin: 13px 0 10px;
  }

  .place {
    height: 36px;
    padding: 0 10px;
    font-size: 12.5px;
  }

  .start-fine {
    margin-top: 14px;
  }
}

@media (max-height: 700px) and (min-width: 561px) {
  .stage {
    height: 194px;
  }

  .stage-avatar {
    --world-scale: 1.7;
  }
}

/* ------------------------------------------------------------ loading -- */

.loading {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: grid;
  place-items: center;
  padding: 24px;
  background: radial-gradient(80% 60% at 50% 46%, rgba(10, 74, 85, 0.7), rgba(4, 27, 34, 0.86));
  -webkit-backdrop-filter: blur(10px) saturate(1.2);
  backdrop-filter: blur(10px) saturate(1.2);
  animation: fade-in 0.25s ease-out;
}

.loading-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 26px;
  max-width: 380px;
  text-align: center;
}

.loading-avatar {
  --world-scale: 1.4;
  transform: scale(var(--world-scale));
  transform-origin: 50% 100%;
}

.loading-avatar .aotw-avatar__name {
  display: none;
}

.loading-text {
  margin: 0;
  font-size: 15px;
  font-weight: 650;
  color: #fff;
  text-wrap: balance;
}

@keyframes fade-in {
  from { opacity: 0; }
}

/* ------------------------------------------------------------- toasts -- */

.toasts {
  position: absolute;
  top: calc(var(--edge) + var(--sat) + 58px);
  left: 50%;
  z-index: 30;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  width: min(420px, 100vw - 24px);
  transform: translateX(-50%);
}

.toast {
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: 100%;
  padding: 9px 16px 10px 13px;
  border-radius: 20px;
  font-size: 13.5px;
  font-weight: 650;
  line-height: 1.3;
  color: #fff;
  background: var(--sheen), var(--glass-solid);
  border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), var(--lift);
  animation: toast-in 0.26s cubic-bezier(0.2, 1.3, 0.4, 1);
  transition: opacity 0.3s, transform 0.3s;
}

.toast::before {
  content: "";
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--aqua);
  box-shadow: 0 0 8px var(--aqua);
}

.toast[data-kind="warn"]::before {
  background: var(--warn);
  box-shadow: 0 0 8px var(--warn);
}

.toast[data-kind="error"] {
  border-color: rgba(255, 122, 122, 0.55);
}

.toast[data-kind="error"]::before {
  background: var(--error);
  box-shadow: 0 0 8px var(--error);
}

.toast.is-out {
  opacity: 0;
  transform: translateY(-6px);
}

@keyframes toast-in {
  from { opacity: 0; transform: translateY(-10px) scale(0.96); }
}

/* ----------------------------------------------------- shared controls -- */

.text-link {
  color: var(--ice);
  font-weight: 650;
  text-decoration: underline;
  text-decoration-color: rgba(217, 255, 250, 0.45);
  text-underline-offset: 2px;
  touch-action: manipulation;
}

.text-link:hover {
  color: #fff;
  text-decoration-color: currentColor;
}

.text-link:focus-visible {
  border-radius: 4px;
}

/* Checkbox: the real input stays in place (invisible) so it keeps focus and
   keyboard behaviour; the box beside it is the picture. */
.check {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 32px;
  font-size: 14.5px;
  font-weight: 700;
  color: #fff;
  cursor: pointer;
  touch-action: manipulation;
}

.check input {
  position: absolute;
  left: 0;
  top: 50%;
  width: 24px;
  height: 24px;
  margin: -12px 0 0;
  opacity: 0;
  cursor: pointer;
}

.check-box {
  position: relative;
  flex: none;
  width: 24px;
  height: 24px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.08);
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.6);
  transition: background-color 0.12s, box-shadow 0.12s;
}

.check-box::after {
  content: "";
  position: absolute;
  left: 8px;
  top: 3.5px;
  width: 6px;
  height: 12px;
  border: solid var(--ink);
  border-width: 0 2.6px 2.6px 0;
  transform: rotate(42deg) scale(0);
  transition: transform 0.14s cubic-bezier(0.2, 1.6, 0.4, 1);
}

.check input:checked + .check-box {
  background: linear-gradient(180deg, #b6fde9, var(--aqua) 60%, #57e59a);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7);
}

.check input:checked + .check-box::after {
  transform: rotate(42deg) scale(1);
}

/* A smaller option that sits under a big button, e.g. "Use my exact spot". */
.check--quiet {
  flex-basis: 100%;
  justify-content: center;
  min-height: 28px;
  font-size: 13px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.86);
}

.check--quiet small {
  display: block;
  font-size: 11.5px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.62);
}

.check--quiet .check-box {
  width: 20px;
  height: 20px;
  border-radius: 7px;
}

.check--quiet .check-box::after {
  left: 6.5px;
  top: 2.5px;
  width: 5px;
  height: 10px;
}

.check input:focus-visible + .check-box {
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.6), var(--focus);
}

/* The four plain facts shown wherever online is chosen. */
.notice-list {
  display: grid;
  gap: 6px;
  margin: 0 0 8px;
  padding: 0;
  list-style: none;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.4;
  color: var(--text);
  user-select: text;
  -webkit-user-select: text;
}

.notice-list li {
  position: relative;
  padding-left: 16px;
}

.notice-list li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 0.52em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--aqua);
}

.btn-solid,
.btn-plain {
  height: 42px;
  padding: 0 20px;
  border-radius: 21px;
  font-size: 14.5px;
  font-weight: 800;
  transition: transform 0.12s, filter 0.12s, opacity 0.15s;
}

.btn-solid {
  color: var(--ink);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.65), rgba(255, 255, 255, 0) 50%),
    linear-gradient(100deg, #5fe6dc, #7df0a6);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.8), 0 4px 16px rgba(47, 214, 200, 0.3);
}

.btn-solid:disabled {
  opacity: 0.4;
  cursor: default;
  box-shadow: none;
}

.btn-solid:not(:disabled):hover {
  filter: brightness(1.07);
}

.btn-plain {
  color: #fff;
  background: rgba(255, 255, 255, 0.1);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.18);
}

.btn-plain:hover {
  background: rgba(255, 255, 255, 0.17);
}

.btn-solid:not(:disabled):active,
.btn-plain:active {
  transform: scale(0.96);
}

/* ------------------------------------------------------- people panel -- */

.who {
  position: relative;
  flex: none;
}

.people {
  transition: border-color 0.15s;
}

.people:hover,
.people[aria-expanded="true"] {
  border-color: rgba(255, 255, 255, 0.4);
}

/* Solo is a choice, not a fault: a calm open ring instead of the grey dot. */
.people[data-state="solo"] .people-dot {
  background: none;
  box-shadow: inset 0 0 0 2px var(--ice);
}

.people-panel {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  width: 310px;
  max-width: calc(100vw - 2 * var(--edge) - var(--sal) - var(--sar));
  padding: 14px 16px 15px;
  border-radius: 20px;
  background: var(--sheen), var(--glass-solid);
  animation: drop-in 0.18s ease-out;
}

.people-about {
  margin: 0 0 4px;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--text-dim);
}

.switch-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 11px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.people-about + .switch-row {
  margin-top: 10px;
}

.switch-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.switch-text strong {
  font-size: 14.5px;
  font-weight: 700;
}

.switch-text small {
  font-size: 12px;
  color: var(--text-dim);
}

.switch {
  position: relative;
  flex: none;
  width: 48px;
  height: 28px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.14);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.24);
  transition: background-color 0.16s;
}

.switch i {
  position: absolute;
  left: 3px;
  top: 3px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 4px rgba(0, 14, 20, 0.5);
  transition: transform 0.18s cubic-bezier(0.3, 1.4, 0.5, 1);
}

.switch[aria-checked="true"] {
  background: linear-gradient(180deg, #7cecd9, var(--aqua) 60%, #4fdc98);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5);
}

.switch[aria-checked="true"] i {
  transform: translateX(20px);
}

.people-tip {
  margin: 0 0 8px;
  padding-top: 11px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  font-size: 12.5px;
  color: var(--text-dim);
}

.people-panel .text-link {
  font-size: 12.5px;
}

/* -------------------------------------------------------- player card -- */

.pcard {
  position: absolute;
  top: calc(var(--edge) + var(--sat) + 54px);
  left: 50%;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 10px;
  width: max-content;
  max-width: min(380px, 100vw - 2 * var(--edge) - var(--sal) - var(--sar));
  min-height: 56px;
  padding: 6px 6px 6px 12px;
  border-radius: 28px;
  transform: translateX(-50%);
  pointer-events: auto;
  background: var(--sheen), var(--glass-solid);
  animation: pcard-in 0.2s cubic-bezier(0.2, 1.3, 0.4, 1);
}

@keyframes pcard-in {
  from { opacity: 0; transform: translateX(-50%) translateY(-8px) scale(0.96); }
}

.pcard-avatar {
  --world-scale: 0.6;
  flex: none;
  width: 34px;
  height: 39px;
}

.pcard-avatar .aotw-avatar {
  transform: scale(var(--world-scale));
  transform-origin: 0 0;
}

.pcard-avatar .aotw-avatar__name,
.pcard-avatar .aotw-avatar__shadow {
  display: none;
}

.pcard-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
  margin-right: 4px;
}

.pcard-text strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 14.5px;
  font-weight: 700;
  line-height: 1.2;
}

.pcard-text small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 11.5px;
  color: var(--text-dim);
}

.pcard-mute {
  flex: none;
  min-width: 84px;
  height: 40px;
  padding: 0 16px;
  border-radius: 20px;
  font-size: 13.5px;
  font-weight: 800;
  color: #fff;
  background: rgba(255, 255, 255, 0.12);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.22);
  transition: background-color 0.12s, transform 0.12s;
}

.pcard-mute:hover {
  background: rgba(255, 255, 255, 0.2);
}

.pcard-mute:active {
  transform: scale(0.95);
}

.pcard-mute[aria-pressed="true"] {
  color: var(--ink);
  background: var(--warn);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5);
}

.pcard-close {
  display: grid;
  place-items: center;
  flex: none;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  color: var(--text-dim);
}

.pcard-close:hover {
  color: #fff;
  background: rgba(255, 255, 255, 0.1);
}

/* Toasts step down while the card is up so the two never stack. */
.hud.has-card .toasts {
  top: calc(var(--edge) + var(--sat) + 122px);
}

/* Wide screens have room between the two top chips: the card sits up there. */
@media (min-width: 1100px) {
  .pcard {
    top: calc(var(--edge) + var(--sat) - 5px);
  }

  .hud.has-card .toasts {
    top: calc(var(--edge) + var(--sat) + 64px);
  }
}

/* ------------------------------------------------------ consent dialog -- */

.consent {
  position: fixed;
  inset: 0;
  z-index: 35;
  display: grid;
  place-items: center;
  padding: calc(16px + var(--sat)) calc(12px + var(--sar)) calc(16px + var(--sab)) calc(12px + var(--sal));
  overflow-y: auto;
  touch-action: pan-y;
  background: rgba(4, 27, 34, 0.6);
  animation: fade-in 0.18s ease-out;
}

.consent-card {
  width: min(430px, 100%);
  padding: 20px 20px 18px;
  border-radius: 24px;
  background: var(--sheen), var(--glass-solid);
  animation: toast-in 0.24s cubic-bezier(0.2, 1.3, 0.4, 1);
}

.consent-card h2 {
  margin: 0 0 12px;
  font-size: 20px;
  font-weight: 800;
  letter-spacing: -0.01em;
}

.consent-card .text-link {
  font-size: 13px;
}

.consent-card .check {
  display: flex;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}

.consent-card .check input {
  margin-top: -5px;
}

.consent-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 16px;
}

/* --------------------------------------------- start: solo or online -- */

.mode {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
  width: min(430px, 100%);
  margin-top: 15px;
  padding: 4px;
  border-radius: 30px;
  background: rgba(3, 26, 33, 0.5);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.18);
}

.mode-opt {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  min-height: 50px;
  padding: 6px 14px;
  border-radius: 26px;
  text-align: left;
  color: var(--text-dim);
  transition: background-color 0.15s, color 0.15s;
}

.mode-opt .ico {
  width: 22px;
  height: 22px;
}

.mode-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
  line-height: 1.2;
}

.mode-text strong {
  font-size: 15px;
  font-weight: 800;
  color: #fff;
}

.mode-text small {
  font-size: 11.5px;
  font-weight: 600;
}

.mode-opt:hover {
  background: rgba(255, 255, 255, 0.08);
}

.mode-opt[aria-checked="true"] {
  color: rgba(6, 36, 44, 0.78);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0) 55%),
    linear-gradient(100deg, #5fe6dc, #7df0a6);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.8), 0 3px 12px rgba(0, 14, 20, 0.3);
}

.mode-opt[aria-checked="true"] strong {
  color: var(--ink);
}

.notice {
  width: min(560px, 100%);
  margin-top: 10px;
  padding: 13px 16px 11px;
  border-radius: 18px;
  text-align: left;
  background: var(--sheen), rgba(3, 26, 33, 0.62);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.16);
  animation: drop-in 0.2s ease-out;
}

.notice .text-link {
  font-size: 12.5px;
}

.notice .check {
  display: flex;
  margin-top: 10px;
  padding-top: 9px;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}

.notice .check input {
  margin-top: -7.5px;
}

.notice-nudge {
  margin: 4px 0 2px;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--warn);
}

/* With room to spare the four facts sit two by two, and the tick box shares
   a line with the link, so the destinations stay in view below. */
@media (min-width: 761px) {
  .notice {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    column-gap: 16px;
    width: min(720px, 100%);
    padding: 13px 18px 9px;
  }

  #start-notice-body {
    display: contents;
  }

  .notice .notice-list {
    grid-column: 1 / -1;
    grid-template-columns: 1fr 1fr;
    gap: 7px 22px;
    margin-bottom: 10px;
  }

  .notice .check {
    grid-area: 2 / 1;
    margin-top: 0;
    padding-top: 7px;
  }

  .notice .check input {
    margin-top: -8.5px;
  }

  .notice .text-link {
    grid-area: 2 / 2;
    padding-top: 7px;
  }

  .notice::before {
    content: "";
    grid-area: 2 / 1 / 3 / -1;
    align-self: start;
    border-top: 1px solid rgba(255, 255, 255, 0.12);
  }

  .notice .check {
    border-top: 0;
  }

  .notice-nudge {
    grid-column: 1 / -1;
  }
}

.check.is-nudge {
  animation: nudge 0.4s ease-in-out;
}

.check.is-nudge .check-box {
  box-shadow: inset 0 0 0 2px var(--warn), 0 0 0 4px rgba(255, 200, 87, 0.25);
}

@keyframes nudge {
  20%, 60% { transform: translateX(-5px); }
  40%, 80% { transform: translateX(5px); }
}

@media (max-width: 560px) {
  .mode-opt {
    gap: 0;
    padding: 6px 12px;
    justify-content: center;
    text-align: center;
  }

  .mode-opt .ico {
    display: none;
  }

  .mode-text small {
    font-size: 11px;
  }

  .notice-list {
    font-size: 12.5px;
  }
}

@media (max-width: 760px) {
  .people-panel {
    position: fixed;
    top: calc(var(--edge) + var(--sat) + 52px);
    left: calc(var(--edge) + var(--sal));
    right: calc(var(--edge) + var(--sar));
    width: auto;
    max-width: none;
  }
}

/* -------------------------------------------------- privacy.html page -- */
/* A plain reading page in the same clothes as the game. `doc` on <html>
   undoes the game shell's no-scroll, no-select rules. */

html.doc,
html.doc body {
  position: static;
  width: auto;
  height: auto;
  overflow: visible;
  overscroll-behavior: auto;
  touch-action: auto;
}

html.doc body {
  min-height: 100vh;
  user-select: text;
  -webkit-user-select: text;
  -webkit-touch-callout: default;
  font-size: 16px;
  line-height: 1.6;
  background:
    radial-gradient(110% 520px at 82% -60px, rgba(140, 255, 214, 0.26), transparent 62%),
    radial-gradient(90% 460px at 6% -20px, rgba(64, 186, 255, 0.22), transparent 60%),
    linear-gradient(170deg, #0b4d58 0, #073842 420px, #052a33 900px);
  background-color: #052a33;
}

.doc-page {
  max-width: 680px;
  margin: 0 auto;
  padding: calc(34px + var(--sat)) calc(22px + var(--sar)) calc(56px + var(--sab)) calc(22px + var(--sal));
}

.doc-brand {
  display: inline-block;
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: #fff;
  text-decoration: none;
}

.doc-brand span {
  font-weight: 300;
}

.doc-page h1 {
  margin: 26px 0 8px;
  font-size: clamp(30px, 7vw, 40px);
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -0.03em;
  text-wrap: balance;
}

.doc-lede {
  margin: 0 0 26px;
  font-size: 17px;
  color: var(--text-dim);
}

.doc-page section {
  margin-top: 14px;
  padding: 18px 22px 20px;
  border-radius: 20px;
  background: var(--sheen), rgba(3, 26, 33, 0.5);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.13);
}

.doc-page h2 {
  margin: 0 0 8px;
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--ice);
}

.doc-page p,
.doc-page ul {
  margin: 0 0 10px;
}

.doc-page ul {
  padding-left: 20px;
}

.doc-page li {
  margin-bottom: 6px;
}

.doc-page li::marker {
  color: var(--aqua);
}

.doc-page section > :last-child {
  margin-bottom: 0;
}

.doc-page strong {
  font-weight: 700;
  color: #fff;
}

.doc-page a:not(.doc-brand):not(.btn-solid) {
  color: var(--ice);
  text-underline-offset: 2px;
}

.doc-placeholder {
  padding: 2px 8px;
  border-radius: 6px;
  font: 600 14px/1.4 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  color: var(--ink);
  background: var(--warn);
}

.doc-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 26px;
  font-size: 13px;
  color: var(--text-faint);
}

.doc-foot .btn-solid {
  display: inline-grid;
  place-items: center;
  text-decoration: none;
}

/* ---------------------------------------------------- map attribution -- */
/* The world module renders the imagery credit into #map, bottom-right, with
   its own inline styles. The HUD keeps that strip clear (see --attrib); this
   only lifts the credit out from under a phone's home indicator. */

#map .aotw-attribution {
  margin: 0 var(--sar) var(--sab) 0;
}

/* ---------------------------------------------------------- motion ---- */

@media (prefers-reduced-motion: reduce) {
  .aotw-avatar.is-moving .aotw-avatar__fig,
  .aotw-avatar.is-moving .aotw-avatar__shadow,
  .aotw-avatar__ring,
  .sky i,
  .people[data-state="connecting"] .people-dot {
    animation: none;
  }

  .aotw-bubble__pop {
    animation:
      fade-in 0.15s ease-out both,
      aotw-fade 0.32s ease-in var(--out-delay, 4680ms) forwards;
  }

  .start.is-leaving {
    transition: opacity 0.3s, visibility 0s 0.3s;
    transform: none;
  }
}
