/* ==============================================================
   Geomeister - nautical-chart instrument panel
   ink / paper / magenta (target) / cyan (your fix) / amber (score)
   ============================================================== */

:root {
  --ink:        #0a1620;
  --ink-2:      #12222e;
  --ink-3:      #1b3040;
  --paper:      #e9dfc8;
  --muted:      #8da2ae;
  --magenta:    #e4407f;
  --cyan:       #4fc3d9;
  --amber:      #f0b24b;

  --bar-top:    64px;
  /* The band along the bottom of the embed that belongs to Google: the logo
     bottom-left, the capture date beside it, Terms and Report-a-problem
     bottom-right. Nothing of ours is allowed to sit in it. */
  --pano-chrome: 36px;

  --display: 'IBM Plex Sans Condensed', 'Roboto Condensed', 'Arial Narrow', system-ui, sans-serif;
  --body:    'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono:    'IBM Plex Mono', ui-monospace, 'SFMono-Regular', Consolas, monospace;

  --ease: cubic-bezier(.2, .7, .3, 1);
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--body);
  overscroll-behavior: none;
}

button { font: inherit; color: inherit; }

:focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 2px;
}

.sheet {
  position: relative;
  height: 100%;
  height: 100dvh;      /* tracks mobile browser chrome; 100% is the fallback */
  overflow: hidden;
}

/* -- Panorama ------------------------------------------------ */

.pano { position: absolute; inset: 0; background: var(--ink-2); }

.pano__frame { position: absolute; inset: 0; }

.pano__frame iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

/* Soft blend under the opaque bars. Never intercepts pointer events. */
.pano__vignette {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 5;
  /* Only under the top bar now. A wash along the bottom would dim Google's
     logo and links, which is the thing this page must not do. */
  background:
    linear-gradient(to bottom, rgba(10,22,32,.55) 0, rgba(10,22,32,0) 120px);
}

/* -- Chrome bars (these double as the cover over the embed UI) -- */

.bar {
  position: absolute;
  left: 0;
  right: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 0 18px;
  background: var(--ink);          /* opaque: that is the point */
  color: var(--paper);
}

.bar--top {
  top: 0;
  height: var(--bar-top);
  justify-content: space-between;
  border-bottom: 1px solid rgba(233,223,200,.22);
  box-shadow: 0 10px 26px rgba(0,0,0,.45);
}

.bar__group { display: flex; align-items: center; gap: 12px; min-width: 0; }

.wordmark {
  font-family: var(--display);
  font-weight: 700;
  font-size: 21px;
  letter-spacing: .14em;
  text-transform: uppercase;
}

.rule { width: 22px; height: 1px; background: rgba(233,223,200,.4); }

.coordline {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .09em;
  color: var(--muted);
  text-transform: uppercase;
  white-space: nowrap;
}

.readout__label {
  font-family: var(--display);
  font-size: 11px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
}

.readout__value {
  font-family: var(--mono);
  font-weight: 600;
  font-size: 20px;
  color: var(--amber);
  font-variant-numeric: tabular-nums;
  min-width: 4ch;
  text-align: right;
}

.linkbtn {
  background: none;
  border: 0;
  padding: 6px 2px;
  cursor: pointer;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .07em;
  color: var(--muted);
  text-decoration: underline;
  text-underline-offset: 3px;
  white-space: nowrap;
}
.linkbtn:hover { color: var(--paper); }
a.linkbtn { text-decoration: underline; text-underline-offset: 3px; }

/* -- Signature: the graduated round scale -------------------- */
/* A chart distance-scale. Each cell is one round; the bar rising
   from the neatline is that round's score out of 5,000.        */

.scale {
  display: flex;
  align-items: flex-end;
  height: 38px;
  border-bottom: 1px solid rgba(233,223,200,.45);
}

.station {
  position: relative;
  width: 46px;
  height: 100%;
  border-left: 1px solid rgba(233,223,200,.45);
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.station:last-child { border-right: 1px solid rgba(233,223,200,.45); }

.station__fill {
  width: 100%;
  height: calc(var(--fill, 0) * 30px);
  background: linear-gradient(to top, rgba(240,178,75,.85), rgba(240,178,75,.3));
  transition: height .6s var(--ease);
}

.station__num {
  position: absolute;
  bottom: 3px;
  left: 0;
  right: 0;
  text-align: center;
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: .06em;
  color: rgba(141,162,174,.75);
}

.station.is-current { background: rgba(228,64,127,.1); }
.station.is-current .station__num { color: var(--magenta); }
.station.is-current::before {
  content: '';
  position: absolute;
  top: -1px;
  left: 50%;
  transform: translateX(-50%);
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid var(--magenta);
}

/* -- Guess panel --------------------------------------------- */

/* Anchored bottom-left, not bottom-right, to leave the embed's own compass
   and zoom controls uncovered. The compass is a fair aid - it gives heading,
   never position, and reading the sun against north is the kind of inference
   the game should reward. Freeing the whole corner rather than threading the
   panel around the controls keeps this robust to wherever Google puts
   them. */
.guess {
  position: absolute;
  left: 16px;
  bottom: calc(var(--pano-chrome) + 14px);
  z-index: 30;
  width: 320px;
  background: rgba(10,22,32,.94);
  border: 1px solid rgba(233,223,200,.25);
  box-shadow: 0 18px 44px rgba(0,0,0,.6);
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  transition: width .28s var(--ease);
}

.guess.is-open { width: min(560px, 46vw); }

.guess__map {
  height: 210px;
  background: var(--ink-2);
  transition: height .28s var(--ease);
}
.guess.is-open .guess__map { height: min(420px, 48vh); }

.guess__toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  background: none;
  border: 0;
  padding: 2px 4px;
  cursor: pointer;
  font-family: var(--display);
  font-size: 11px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--muted);
}
.guess__toggle:hover { color: var(--paper); }

.guess__toggle-icon {
  width: 9px;
  height: 9px;
  border: 1px solid currentColor;
  border-right-width: 3px;
  border-bottom-width: 3px;
}
.guess.is-open .guess__toggle-icon { border-width: 3px 1px 1px 3px; }

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

.btn {
  border: 1px solid transparent;
  padding: 11px 16px;
  cursor: pointer;
  font-family: var(--display);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: .16em;
  text-transform: uppercase;
  transition: background .18s var(--ease), color .18s var(--ease), transform .1s var(--ease);
}
.btn:active { transform: translateY(1px); }

.btn--primary { background: var(--magenta); color: #fff; }
.btn--primary:hover { background: #f2588f; }
.btn--primary:disabled {
  background: transparent;
  border-color: rgba(233,223,200,.28);
  color: rgba(141,162,174,.8);
  cursor: default;
  transform: none;
}
.btn--lg { padding: 15px 30px; font-size: 14px; }

/* -- Curtains (start / result / summary) ---------------------- */

.curtain {
  position: absolute;
  inset: 0;
  z-index: 60;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 28px;
  background: radial-gradient(120% 90% at 50% 0%, rgba(27,48,64,.97), rgba(10,22,32,.99));
}
.curtain.is-visible { display: flex; animation: rise .45s var(--ease) both; }

@keyframes rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

.card {
  width: min(520px, 100%);
  border: 1px solid rgba(233,223,200,.24);
  background: rgba(10,22,32,.7);
  padding: 40px;
  text-align: left;
}
.card--wide { width: min(640px, 100%); }

.eyebrow {
  margin: 0 0 14px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--magenta);
}

.display {
  margin: 0 0 18px;
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(44px, 8vw, 76px);
  line-height: .92;
  letter-spacing: .02em;
  text-transform: uppercase;
}

.lede {
  margin: 0 0 28px;
  max-width: 42ch;
  font-size: 15px;
  line-height: 1.6;
  color: rgba(233,223,200,.78);
}

.specs {
  display: flex;
  gap: 34px;
  margin: 0 0 32px;
  padding: 18px 0;
  border-top: 1px solid rgba(233,223,200,.2);
  border-bottom: 1px solid rgba(233,223,200,.2);
}
.specs dt {
  font-family: var(--display);
  font-size: 10px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 5px;
}
.specs dd {
  margin: 0;
  font-family: var(--mono);
  font-size: 19px;
  color: var(--paper);
}

/* -- Result plot ---------------------------------------------- */

.curtain--result { padding: 0; }

.plot {
  display: grid;
  grid-template-columns: 1fr 380px;
  width: 100%;
  height: 100%;
}

.plot__map { min-height: 0; background: var(--ink-2); }

.plot__data {
  padding: 44px 40px;
  border-left: 1px solid rgba(233,223,200,.22);
  background: var(--ink);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}

.scoreline { margin: 0 0 18px; display: flex; align-items: baseline; gap: 10px; }
.scoreline__value {
  font-family: var(--mono);
  font-weight: 600;
  font-size: 62px;
  line-height: 1;
  color: var(--amber);
  font-variant-numeric: tabular-nums;
}
.scoreline__unit {
  font-family: var(--display);
  font-size: 12px;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--muted);
}
.scoreline--hero .scoreline__value { font-size: clamp(64px, 13vw, 108px); }

.meter {
  height: 3px;
  background: rgba(233,223,200,.16);
  margin-bottom: 34px;
}
.meter__fill {
  display: block;
  height: 100%;
  width: 0;
  background: var(--amber);
  transition: width .8s var(--ease);
}

.fields { margin: 0 0 auto; display: grid; grid-template-columns: 1fr 1fr; gap: 24px 20px; }
.field--wide { grid-column: 1 / -1; }
.fields dt {
  font-family: var(--display);
  font-size: 10px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 7px;
}
.fields dd {
  margin: 0;
  font-family: var(--mono);
  font-size: 17px;
  line-height: 1.35;
  color: var(--paper);
}
.fields .field__sub { margin-top: 5px; font-size: 12px; color: var(--muted); }

.plot__data .btn { margin-top: 34px; }

/* -- Final log ------------------------------------------------ */

.verdict {
  margin: 0 0 28px;
  max-width: 40ch;
  font-size: 15px;
  line-height: 1.6;
  color: rgba(233,223,200,.78);
}

.log { list-style: none; margin: 0 0 32px; padding: 0; border-top: 1px solid rgba(233,223,200,.2); }
.log li {
  display: grid;
  grid-template-columns: 44px 1fr 120px 76px;
  align-items: center;
  gap: 14px;
  padding: 13px 0;
  border-bottom: 1px solid rgba(233,223,200,.12);
  font-family: var(--mono);
  font-size: 13px;
}
.log__n { color: var(--magenta); font-size: 11px; letter-spacing: .1em; }
.log__place { color: var(--paper); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.log__dist { color: var(--muted); text-align: right; }
.log__pts { color: var(--amber); text-align: right; font-weight: 600; }

.progress {
  margin: -14px 0 30px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .08em;
  color: var(--muted);
}

/* -- Stats and the trend chart -------------------------------- */

.bar__links { display: flex; align-items: center; gap: 18px; }

.subhead {
  margin: 0 0 22px;
  font-family: var(--display);
  font-weight: 700;
  font-size: 34px;
  line-height: 1;
  letter-spacing: .03em;
  text-transform: uppercase;
}

.disclose {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: none;
  border: 0;
  border-top: 1px solid rgba(233,223,200,.2);
  border-bottom: 1px solid rgba(233,223,200,.2);
  padding: 13px 2px;
  cursor: pointer;
  font-family: var(--display);
  font-size: 11px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
}
.disclose:hover { color: var(--paper); }
.disclose__mark {
  width: 0; height: 0;
  border-left: 5px solid currentColor;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: transform .2s var(--ease);
}
.disclose[aria-expanded="true"] .disclose__mark { transform: rotate(90deg); }

.chart { position: relative; margin: 20px 0 4px; }
.chart[hidden] { display: none; }
.chart__plot svg { width: 100%; height: auto; display: block; overflow: visible; }

.chart__grid { stroke: rgba(233,223,200,.12); stroke-width: 1; }
.chart__tick {
  fill: var(--muted);
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: .06em;
}
.chart__band { fill: rgba(141,162,174,.16); }
.chart__line { fill: none; stroke: var(--amber); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart__dot { fill: var(--amber); stroke: var(--ink); stroke-width: 2; }
.chart__cursor { stroke: rgba(233,223,200,.35); stroke-width: 1; stroke-dasharray: 2 4; }
.chart__hit { fill: var(--paper); stroke: var(--ink); stroke-width: 2; }
#chartSurface { cursor: crosshair; }

.chart__tip {
  position: absolute;
  top: -4px;
  transform: translateX(-50%);
  pointer-events: none;
  opacity: 0;
  transition: opacity .12s var(--ease);
  background: var(--ink-3);
  border: 1px solid rgba(233,223,200,.28);
  padding: 6px 9px;
  white-space: nowrap;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--paper);
}
.chart__tip b { color: var(--amber); font-weight: 600; }
.chart__tip span { display: block; margin-top: 3px; font-size: 10px; color: var(--muted); }

.chart__caption {
  margin-top: 10px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .07em;
  color: var(--muted);
}
.chart__empty { margin: 0; color: var(--muted); font-size: 13px; }

.runs {
  list-style: none;
  margin: 22px 0 26px;
  padding: 0;
  max-height: 232px;
  overflow-y: auto;
}
.runs li {
  display: grid;
  grid-template-columns: 52px 1fr 96px 74px;
  gap: 12px;
  align-items: baseline;
  padding: 9px 0;
  border-bottom: 1px solid rgba(233,223,200,.12);
  font-family: var(--mono);
  font-size: 12px;
}
.runs .run__n { color: var(--magenta); font-size: 10px; letter-spacing: .1em; }
.runs .run__when { color: var(--muted); }
.runs .run__km { color: var(--muted); text-align: right; }
.runs .run__score { color: var(--amber); text-align: right; font-weight: 600; }

.rowbtns { display: flex; align-items: center; justify-content: space-between; gap: 16px; }

/* -- Leaflet overrides ---------------------------------------- */

.leaflet-container {
  background: #0d1c26;
  font-family: var(--mono);
  cursor: crosshair;
}
.leaflet-control-attribution {
  background: rgba(10,22,32,.8) !important;
  color: var(--muted) !important;
  font-size: 9px !important;
}
.leaflet-control-attribution a { color: var(--muted) !important; }
.leaflet-bar a {
  background: var(--ink);
  color: var(--paper);
  border-color: rgba(233,223,200,.25);
}
.leaflet-bar a:hover { background: var(--ink-3); color: var(--paper); }

.pin {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid var(--ink);
  box-shadow: 0 0 0 1px rgba(233,223,200,.6);
}
.pin--guess  { background: var(--cyan); }
.pin--target { background: var(--magenta); }

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

@media (max-width: 900px) {
  .scale { display: none; }

  /* The one bar now carries the round, three controls and the score. The
     wordmark is the only thing in it that is decoration rather than
     information, so on a phone it is what goes. */
  .wordmark { display: none; }
  .rule { display: none; }
  .bar { gap: 10px; padding: 0 12px; }
  .readout__label { display: none; }
  .readout__value { font-size: 17px; }
  .bar__links { gap: 13px; }

  .plot { grid-template-columns: 1fr; grid-template-rows: 42vh 1fr; }
  .plot__data { border-left: 0; border-top: 1px solid rgba(233,223,200,.22); padding: 26px 20px; }
  .scoreline__value { font-size: 46px; }
  .fields { grid-template-columns: 1fr 1fr; gap: 18px 16px; }
  .card { padding: 26px 20px; }
  .subhead { font-size: 27px; }

  /* Four figures will not sit on one line on a phone. */
  .specs { flex-wrap: wrap; gap: 18px 26px; }
  .specs dd { font-size: 17px; }

  /* Still leaves a right-hand gutter clear so the compass survives on a
     phone, where the panel would otherwise span the full width. */
  .guess { left: 12px; right: 92px; width: auto; }
  .guess.is-open { width: auto; }
  .guess__map { height: 168px; }
  .guess.is-open .guess__map { height: min(300px, 38vh); }

  .log li { grid-template-columns: 30px 1fr 84px; }
  .log__dist { display: none; }

  .runs { max-height: 40vh; }
  .runs li { grid-template-columns: 38px 1fr 76px; gap: 10px; }
  .runs .run__km { display: none; }

  .rowbtns { flex-direction: column; align-items: stretch; gap: 14px; }
  .rowbtns .btn { width: 100%; }
  .chart__tip { font-size: 10px; }
}

/* Very narrow. Measured at 320px: round label 62 + three controls 108 +
   score 30 + gaps and padding 46 = 246 of the 320 available. */
@media (max-width: 430px) {
  .bar { gap: 8px; padding: 0 10px; }
  .bar__links { gap: 10px; }
  .coordline { font-size: 10px; }
  .btn--lg { padding: 14px 20px; font-size: 13px; }
  .display { font-size: clamp(38px, 13vw, 54px); }
  .guess { right: 84px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

/* ==============================================================
   Accounts, sessions and modes
   Amber stays reserved for scores, magenta for the target and the
   primary action, cyan for you. Everything added here works in
   paper and muted so those three keep their meaning.
   ============================================================== */

/* A tall card (the lobby) must not be clipped by a centred flex
   container. Auto margins centre it while there is room and let it
   scroll once there is not. The result plot is exempt: it is sized
   to fill rather than to fit. */
.curtain { overflow-y: auto; align-items: flex-start; }
.card { margin: auto; }
.curtain--result { align-items: stretch; overflow: hidden; }

/* -- Transient messages --------------------------------------- */

.toast {
  position: absolute;
  z-index: 80;
  left: 50%;
  bottom: calc(var(--pano-chrome) + 18px);
  transform: translate(-50%, 8px);
  margin: 0;
  max-width: min(440px, calc(100vw - 32px));
  padding: 11px 16px;
  border: 1px solid rgba(228,64,127,.55);
  background: rgba(10,22,32,.96);
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.5;
  letter-spacing: .04em;
  color: var(--paper);
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s var(--ease), transform .2s var(--ease);
}
.toast.is-visible { opacity: 1; transform: translate(-50%, 0); }

/* -- Buttons: a quieter second action ------------------------- */

.btn--ghost {
  background: transparent;
  border-color: rgba(233,223,200,.3);
  color: var(--paper);
}
.btn--ghost:hover { border-color: var(--paper); background: rgba(233,223,200,.06); }
.btn--ghost:disabled {
  color: rgba(141,162,174,.7);
  border-color: rgba(233,223,200,.15);
  cursor: default;
}

.rowbtns--start { justify-content: flex-start; gap: 12px; margin-bottom: 22px; }

/* -- Mode picker ----------------------------------------------- */
/* Each chip carries how many locations it can draw from, because that
   is the thing that actually differs between them. */

.modes {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 28px;
  padding: 0;
  border: 0;
}
.modes legend { padding: 0; margin-bottom: 12px; float: left; width: 100%; }

.mode {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 8px 12px;
  cursor: pointer;
  background: transparent;
  border: 1px solid rgba(233,223,200,.24);
  text-align: left;
  transition: border-color .18s var(--ease), background .18s var(--ease);
}
.mode:hover { border-color: rgba(233,223,200,.5); }
.mode.is-on { border-color: var(--cyan); background: rgba(79,195,217,.09); }

.mode__name {
  font-family: var(--display);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.mode.is-on .mode__name { color: var(--cyan); }
.mode__count { font-family: var(--mono); font-size: 10px; color: var(--muted); }

.modes--tight { margin-bottom: 18px; }
.modes--tight .mode { padding: 6px 10px; }

/* -- Forms ------------------------------------------------------ */

.form { margin: 0 0 20px; }

.input { display: block; margin-bottom: 18px; }
.input__label {
  display: block;
  margin-bottom: 6px;
  font-family: var(--display);
  font-size: 10px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
}
.input input {
  width: 100%;
  padding: 10px 12px;
  background: rgba(10,22,32,.6);
  border: 1px solid rgba(233,223,200,.24);
  color: var(--paper);
  font-family: var(--mono);
  font-size: 14px;
  letter-spacing: .04em;
}
.input input:focus { border-color: var(--cyan); outline: none; }
.input input::placeholder { color: rgba(141,162,174,.55); }

#joinCode { text-transform: uppercase; letter-spacing: .3em; font-size: 18px; }

.formnote {
  margin: 0 0 16px;
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.6;
  color: var(--muted);
}
.formnote:empty { margin: 0; }
#authError:not(:empty), #lobbyError:not(:empty) { color: var(--magenta); }

.whoami {
  margin: 0;
  padding-top: 18px;
  border-top: 1px solid rgba(233,223,200,.15);
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.7;
  color: var(--muted);
}
.whoami b { color: var(--paper); font-weight: 500; }

/* -- The session code ------------------------------------------ */
/* Read aloud and typed in by hand, so it is set like a stamped
   serial: wide tracking, monospaced, nothing else near it. */

.session { margin-bottom: 30px; }

.codebar {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  padding: 16px 18px;
  margin-bottom: 20px;
  border: 1px solid rgba(233,223,200,.24);
  background: rgba(18,34,46,.6);
}
.code {
  margin: 0;
  font-family: var(--mono);
  font-weight: 600;
  font-size: 34px;
  line-height: 1;
  letter-spacing: .22em;
  color: var(--paper);
}
.codebar__side { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.codebar__name {
  margin: 0;
  font-family: var(--display);
  font-size: 12px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
}

/* -- Standings -------------------------------------------------- */

.standings {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--mono);
  font-size: 12px;
  margin-bottom: 18px;
}
.standings td { padding: 7px 8px; border-bottom: 1px solid rgba(233,223,200,.1); }
.standings td:first-child { padding-left: 0; }
.standings td:last-child { padding-right: 0; }
.standings .n { text-align: right; font-variant-numeric: tabular-nums; }
.standings__head td {
  font-family: var(--display);
  font-size: 10px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--muted);
  border-bottom-color: rgba(233,223,200,.24);
}
.standings tr:not(.standings__head) td:nth-child(3) { color: var(--amber); font-weight: 600; }
.standings tr.is-you td { color: var(--paper); }
.standings tr.is-you td:first-child {
  box-shadow: inset 2px 0 0 var(--cyan);
  padding-left: 8px;
}

.tag {
  font-family: var(--display);
  font-size: 9px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--cyan);
}
.delta { color: var(--muted); font-size: 10px; margin-left: 6px; }

/* -- Lobby ------------------------------------------------------ */

.lobby {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 34px;
  padding-top: 24px;
  border-top: 1px solid rgba(233,223,200,.2);
  margin-bottom: 22px;
}
.lobby__col { min-width: 0; }
.lobby__col .btn { width: 100%; margin-top: 4px; }

.subhead2 {
  margin: 0 0 12px;
  font-family: var(--display);
  font-weight: 600;
  font-size: 15px;
  letter-spacing: .14em;
  text-transform: uppercase;
}

.sessions { list-style: none; margin: 20px 0 0; padding: 0; }
.sessions__item {
  display: flex;
  align-items: baseline;
  gap: 12px;
  width: 100%;
  padding: 9px 0;
  background: none;
  border: 0;
  border-top: 1px solid rgba(233,223,200,.12);
  cursor: pointer;
  text-align: left;
}
.sessions__item:hover .sessions__meta { color: var(--paper); }
.sessions__code {
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: .16em;
  color: var(--cyan);
}
.sessions__meta { font-family: var(--mono); font-size: 11px; color: var(--muted); }

/* -- The comparison, on the summary screen ---------------------- */

.compare {
  margin: 0 0 26px;
  padding-top: 22px;
  border-top: 1px solid rgba(233,223,200,.2);
}
.compare .progress { margin: 0 0 16px; }
.compare .standings:empty { display: none; }

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

@media (max-width: 900px) {
  .lobby { grid-template-columns: 1fr; gap: 26px; }
  .codebar { align-items: flex-start; gap: 12px; }
  .code { font-size: 28px; letter-spacing: .18em; }
  .rowbtns--start { flex-direction: column; align-items: stretch; }
  .rowbtns--start .btn { width: 100%; }
  .modes { gap: 6px; }
  .mode { padding: 7px 10px; flex: 1 0 auto; }
  .toast { bottom: calc(var(--pano-chrome) + 12px); font-size: 10px; }

  /* Six columns of standings will not fit a phone. Margin is the one that
     can go: it is derivable from the scores sitting next to it. */
  .standings { font-size: 11px; }
  .standings td { padding: 6px 5px; }
  .standings td:nth-child(4) { display: none; }
}

/* ==============================================================
   The bottom edge belongs to Google
   The embed puts its logo bottom-left, the capture date beside it,
   and Terms / Report-a-problem bottom-right. That is attribution,
   and the game covers none of it: there is no bottom bar, the
   vignette does not wash over it, and the guess panel is lifted
   clear of the whole band. The top bar stays opaque, because the
   address chip it covers names the street and the region, which is
   the answer rather than a credit.
   ============================================================== */

/* A control that is switched off should read as switched off rather
   than as one that does nothing when pressed. */
.linkbtn:disabled {
  color: rgba(141,162,174,.4);
  text-decoration-style: dotted;
  cursor: default;
}
.linkbtn:disabled:hover { color: rgba(141,162,174,.4); }

/* Keeps the three controls together and away from the score, which is
   the one thing in the bar that changes while you are reading it. */
.bar--top .bar__links { gap: 16px; }

/* ==============================================================
   Softening pass
   The chart-instrument character stays - same palette, same
   condensed caps, same monospaced figures. What changes is the
   hand: corners are rounded, the structural strokes go from
   hairlines to a confident 2px, and things you can press get a
   shape of their own instead of being text with a line under it.
   Two radii only, so it reads as one decision rather than as
   whatever each element felt like.
   ============================================================== */

:root {
  --r-sm: 9px;    /* buttons, chips, inputs, anything you press */
  --r-md: 16px;   /* cards, panels, plates */
  --r-pill: 999px;
}

/* -- Surfaces --------------------------------------------------- */

.card {
  border-width: 2px;
  border-radius: var(--r-md);
  box-shadow: 0 22px 60px rgba(0,0,0,.45);
}

.guess {
  border-width: 2px;
  border-radius: var(--r-md);
}
/* The radius has to clip the tiles, or Leaflet paints square corners
   straight over it. */
.guess__map { border-radius: 10px; overflow: hidden; }

.codebar { border-width: 2px; border-radius: var(--r-md); }
.toast { border-width: 2px; border-radius: var(--r-sm); }
.chart__tip { border-radius: var(--r-sm); }

/* -- Things you press -------------------------------------------- */

.btn { border-width: 2px; border-radius: var(--r-sm); }

/* A link-button in a bar of controls reads better as a shape than as
   underlined text. In prose the underline stays, because there it is
   the only thing marking it as a link at all. */
.linkbtn {
  padding: 6px 8px;
  border-radius: var(--r-sm);
  transition: background .16s var(--ease), color .16s var(--ease);
}
.bar__links .linkbtn, .rowbtns .linkbtn, .codebar__side .linkbtn {
  text-decoration: none;
}
.linkbtn:hover { background: rgba(233,223,200,.1); }
.linkbtn:disabled:hover { background: none; }

.mode { border-width: 2px; border-radius: var(--r-sm); }

.input input { border-width: 2px; border-radius: var(--r-sm); }

/* Was two hairlines across the card. A bordered row of its own is
   friendlier and says "this opens" more clearly. */
.disclose {
  border: 2px solid rgba(233,223,200,.2);
  border-radius: var(--r-sm);
  padding-left: 12px;
  padding-right: 12px;
  transition: border-color .16s var(--ease), background .16s var(--ease);
}
.disclose:hover { border-color: rgba(233,223,200,.4); background: rgba(233,223,200,.04); }

.sessions__item { border-radius: var(--r-sm); padding-left: 8px; padding-right: 8px; }
.sessions__item:hover { background: rgba(233,223,200,.06); }

.leaflet-bar a:first-child { border-radius: var(--r-sm) var(--r-sm) 0 0; }
.leaflet-bar a:last-child { border-radius: 0 0 var(--r-sm) var(--r-sm); }
.leaflet-bar { border-radius: var(--r-sm); overflow: hidden; }
.leaflet-control-attribution { border-radius: 6px 0 0 0; }

/* -- Bars and readouts ------------------------------------------- */

/* The top bar itself stays square. Rounding its bottom corners would
   lift it off the address chip underneath, which is the one thing it
   is there to cover. */

.rule { width: 18px; height: 2px; border-radius: var(--r-pill); }

/* Rounded ends anchored to the baseline: the bar still reads from the
   neatline up, it just stops looking cut with a knife. */
.station__fill { border-radius: 4px 4px 0 0; }
.scale { border-bottom-width: 2px; }

.meter { height: 5px; border-radius: var(--r-pill); }
.meter__fill { border-radius: var(--r-pill); }

.tag {
  border-radius: var(--r-pill);
  padding: 2px 8px;
  background: rgba(79,195,217,.14);
}

/* -- Rows --------------------------------------------------------- */

.runs li, .log li { border-radius: var(--r-sm); }
.runs li:hover, .log li:hover { background: rgba(233,223,200,.05); }

.standings tr.is-you td { background: rgba(79,195,217,.07); }
.standings tr.is-you td:first-child {
  border-radius: var(--r-sm) 0 0 var(--r-sm);
}
.standings tr.is-you td:last-child {
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
}

/* -- The chart ---------------------------------------------------- */

.chart__line { stroke-width: 2.5; }
.chart__plot { border-radius: var(--r-sm); }

/* -- Focus -------------------------------------------------------- */
/* The outline already follows each element's own radius, so there is
   nothing to round here - only room to give it. */
.card :focus-visible, .bar :focus-visible { outline-offset: 3px; }

/* The controls carry their own padding now, so the gaps between them
   can come in without them touching. */
@media (max-width: 900px) {
  .bar__links { gap: 6px; }
  .linkbtn { padding: 6px 7px; }
}
@media (max-width: 430px) {
  .bar__links { gap: 3px; }
  .linkbtn { padding: 6px 6px; }
}

/* The round label has a long and a short form; the bar is too busy on a
   phone for "Game 12 · Round 05 / 05". Measured at 320px with the compact
   form: 279 of 320 used. */
.lbl-short { display: none; }
.coordline { min-width: 0; overflow: hidden; text-overflow: ellipsis; }

@media (max-width: 900px) {
  .lbl-long { display: none; }
  .lbl-short { display: inline; }
  .bar__links { flex: none; }
}
@media (max-width: 430px) {
  .bar__links { gap: 2px; }
  .linkbtn { padding: 6px 5px; }
}

/* ==============================================================
   The duel
   A clock on the round, and the other player's pin on the map
   once you have both committed. The clock has three states and
   they escalate: bone while there is time, amber under thirty
   seconds, and magenta the moment the rush lands - magenta being
   the colour this interface already uses for "the target", which
   is what you are suddenly short of time to find.
   ============================================================== */

.clock {
  font-family: var(--mono);
  font-weight: 600;
  font-size: 17px;
  font-variant-numeric: tabular-nums;
  letter-spacing: .04em;
  color: var(--paper);
  padding: 3px 9px;
  border: 2px solid rgba(233,223,200,.28);
  border-radius: var(--r-sm);
  min-width: 5ch;
  text-align: center;
  transition: color .2s var(--ease), background .2s var(--ease),
              border-color .2s var(--ease);
}
.clock[hidden] { display: none; }

.clock.is-warn { color: var(--amber); border-color: rgba(240,178,75,.55); }

.clock.is-rush {
  color: #fff;
  background: var(--magenta);
  border-color: var(--magenta);
  animation: rush 1s var(--ease) infinite;
}
@keyframes rush { 50% { opacity: .6; } }

/* -- The round, settled between players ------------------------- */

.versus {
  margin: 0 0 24px;
  padding-top: 18px;
  border-top: 1px solid rgba(233,223,200,.2);
}
.versus[hidden] { display: none; }

.versus__head {
  margin: 0 0 10px;
  font-family: var(--display);
  font-size: 10px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
}

.versus__list { list-style: none; margin: 0; padding: 0; }
.versus__list li {
  display: grid;
  grid-template-columns: 1fr auto 64px;
  align-items: baseline;
  gap: 10px;
  padding: 7px 8px;
  border-radius: var(--r-sm);
  font-family: var(--mono);
  font-size: 12px;
}
.versus__list li.is-you { background: rgba(79,195,217,.1); }

.versus__who {
  color: var(--paper);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.versus__km { color: var(--muted); text-align: right; }
.versus__pts { color: var(--amber); text-align: right; font-weight: 600; }

/* Bone, so the three roles on the result map stay distinct without a
   legend: cyan is your fix, magenta is the truth, bone is theirs. */
.pin--rival { background: var(--paper); }

@media (max-width: 900px) {
  .clock { font-size: 15px; padding: 2px 7px; min-width: 4.5ch; }
  .versus__list li { grid-template-columns: 1fr auto 54px; gap: 8px; font-size: 11px; }
}
@media (max-width: 430px) {
  .clock { font-size: 14px; padding: 2px 5px; }
}

/* At 320px the bar cannot hold the round, three controls, a clock and the
   score. The score is the one that is also on every result card and readable
   from the filled scale, so while a clock is running it steps aside. If
   :has() is unavailable the round label truncates instead, which is untidy
   but not broken. */
@media (max-width: 430px) {
  .bar--top:has(.clock:not([hidden])) .readout__value { display: none; }
}
