/* Race weekend hub. A night look and a day look.
   Colours are set as variables on <html data-mode>. The brand colour
   (--ac) and the text colour used on it (--on) are written by theme.js.

   The brand colour is for the organiser's mark, the main button and what
   is selected. It never carries meaning. Meaning has its own colours,
   which do not change with the brand:
     --ok  good to go      --wn  take care      --dg  a clash, a problem
   Type sizes: 13 14 15 17 20 24 34 44. Corners: 8 14 20 and fully round. */

/* The three typefaces are kept on this site, so nothing is fetched from
   anyone else and the app looks right with no connection.
   All three are under the SIL Open Font License (see /fonts). */
@font-face {
  font-family: 'Bricolage Grotesque';
  src: url('/fonts/bricolage-grotesque.woff') format('woff');
  font-weight: 500 700;
  font-display: swap;
}

@font-face {
  font-family: 'Hanken Grotesk';
  src: url('/fonts/hanken-grotesk.woff') format('woff');
  font-weight: 100 900;
  font-display: swap;
}

@font-face {
  font-family: 'JetBrains Mono';
  src: url('/fonts/jetbrains-mono.woff') format('woff');
  font-weight: 100 800;
  font-display: swap;
}

:root {
  --font: 'Hanken Grotesk', 'Helvetica Neue', Arial, sans-serif;
  --display: 'Bricolage Grotesque', 'Helvetica Neue', Arial, sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  --ac: #A3C2B9;
  --on: #0E0F11;
  --gutter: 58px;
  --pad: 20px;
}

/* A 12-hour time ("10:44 AM") needs more room than "10:44". */
:root[data-clock='12h'] {
  --gutter: 78px;
}

:root[data-mode='night'] {
  color-scheme: dark;
  --bg: #0E0F11;
  --s1: #17191C;
  --s2: #1F2226;
  --ln: #2A2D31;
  --l2: #3A3E44;
  --tx: #F3F4F1;
  --sc: #A4A9AE;
  --wn: #F0B56A;
  --ok: #8FD4A8;
  --dg: #FF8A7A;
  --fb: #7D838A; /* edges of text boxes: must be visible, not just decorative */
  --gl: rgba(23, 25, 28, 0.94);
  --gb: rgba(255, 255, 255, 0.14);
  --gh: rgba(255, 255, 255, 0.1);
  --sh: rgba(0, 0, 0, 0.55);
}

:root[data-mode='day'] {
  color-scheme: light;
  --bg: #F5F6F7;
  --s1: #FFFFFF;
  --s2: #ECEEF0;
  --ln: #DFE2E5;
  --l2: #C5CAD0;
  --tx: #0E0F11;
  --sc: #565C63;
  --wn: #8A4300;
  --ok: #1B6B3A;
  --dg: #B3261E;
  --fb: #767C84;
  --gl: rgba(255, 255, 255, 0.95);
  --gb: rgba(255, 255, 255, 0.95);
  --gh: rgba(255, 255, 255, 0.9);
  --sh: rgba(14, 15, 17, 0.16);
}

* {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  touch-action: manipulation; /* no double-tap zoom delay; pinch zoom still works */
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--tx);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.35;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}

a {
  color: inherit;
  text-decoration: none;
}

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

button {
  cursor: pointer;
}

h1,
h2,
h3,
p {
  margin: 0;
}

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

main:focus {
  outline: none;
}

[hidden] {
  display: none !important;
}

.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 50;
  min-height: 44px;
  padding: 12px 16px;
  border: 0;
  background: var(--ac);
  color: var(--on);
  font-weight: 600;
}

.skip:focus {
  left: 8px;
  top: 8px;
}

#app {
  position: relative;
  max-width: 430px;
  min-height: 100vh;
  min-height: 100dvh;
  margin: 0 auto;
}

.screen {
  padding: calc(env(safe-area-inset-top, 0px) + 14px) var(--pad) calc(env(safe-area-inset-bottom, 0px) + 116px);
  display: flex;
  flex-direction: column;
}

.screen--bare {
  padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 32px);
}

/* ---------- Type ---------- */

/* The day or screen name. Deliberately smaller than the "next up" card
   below it: the next thing to do is what should catch the eye. */
.h1 {
  margin-top: 6px;
  font-family: var(--display);
  font-size: 34px;
  font-weight: 700;
  line-height: 38px;
  letter-spacing: -0.9px;
  overflow-wrap: anywhere;
}

.h1--sm {
  font-size: 38px;
  line-height: 40px;
  letter-spacing: -1.1px;
}

.sub {
  margin-top: 4px;
  color: var(--sc);
  font-size: 16px;
  line-height: 22px;
}

.h2 {
  margin-top: 22px;
  font-size: 17px;
  font-weight: 600;
  line-height: 22px;
}

.mono {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

.small {
  font-size: 14px;
  line-height: 19px;
}

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

.brand-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 44px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  font-size: 15px;
  font-weight: 600;
}

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

.brand-who {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The organiser's name is never cut short: on a narrow phone it takes a second line. */
.brand-name {
  line-height: 18px;
  overflow-wrap: anywhere;
}

.brand-who {
  color: var(--sc);
  font-size: 13px;
  font-weight: 500;
  line-height: 17px;
}

.brand-mark {
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: var(--ac);
  color: var(--on);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--display);
  font-size: 15px;
  font-weight: 700;
}

.brand-actions {
  flex: none;
  display: flex;
  gap: 8px;
}

/* A small labelled button in the header. */
.chip {
  height: 44px;
  padding: 0 14px 0 10px;
  border: 1px solid var(--ln);
  border-radius: 22px;
  background: var(--s1);
  color: var(--tx);
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 15px;
  font-weight: 600;
}

.icon-btn {
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--ln);
  border-radius: 22px;
  background: var(--s1);
  color: var(--tx);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 600;
}

.back {
  align-self: flex-start;
  min-height: 44px;
  margin-left: -6px;
  padding-right: 10px;
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 15px;
  font-weight: 600;
}

/* ---------- Tabs (days, filters) ---------- */

.tabs {
  margin: 10px calc(var(--pad) * -1) 0;
  padding: 0 var(--pad);
  display: flex;
  gap: 22px;
  border-bottom: 1px solid var(--ln);
  overflow-x: auto;
  scrollbar-width: none;
}

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

.tab {
  flex: none;
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  justify-content: center;
  border: 0;
  border-bottom: 2px solid transparent;
  background: transparent;
  color: var(--sc);
  display: flex;
  align-items: center;
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
}

.tab[aria-current='page'],
.tab[aria-pressed='true'] {
  border-bottom-color: var(--ac);
  color: var(--tx);
  font-weight: 700;
}

/* ---------- Pass card ---------- */

.pass {
  margin-top: 14px;
  border: 1px solid var(--ln);
  border-radius: 20px;
  background: var(--s1);
  display: flex;
  flex-direction: column;
}

.pass-body {
  padding: 16px 16px 14px;
  display: flex;
  flex-direction: column;
}

.pass-kicker {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  color: var(--sc);
  font-size: 15px;
  font-weight: 600;
  line-height: 20px;
}

/* Under a quarter of an hour to go: the countdown becomes the loudest thing on the card. */
.pass-soon {
  margin: -3px 0 -3px -2px;
  padding: 4px 12px;
  border-radius: 14px;
  background: var(--wn);
  color: var(--bg);
  font-size: 17px;
  font-weight: 700;
  line-height: 22px;
}

.pass-kicker .mono {
  color: var(--sc);
  font-weight: 500;
}

.pass-route {
  margin-top: 6px;
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--display);
  font-size: 32px;
  font-weight: 700;
  line-height: 34px;
  letter-spacing: -0.8px;
}

.pass-route i {
  flex: 1;
  min-width: 16px;
  height: 0;
  border-top: 2px dotted var(--sc);
}

.pass-title {
  margin-top: 6px;
  font-family: var(--display);
  font-size: 30px;
  font-weight: 700;
  line-height: 32px;
  letter-spacing: -0.7px;
  overflow-wrap: anywhere;
}

.pass-facts {
  margin-top: 12px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px 22px;
}

.pass-facts--spread {
  justify-content: space-between;
}

.fact {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.fact-label {
  color: var(--sc);
  font-size: 14px;
  line-height: 18px;
}

.fact-value {
  font-size: 16px;
  font-weight: 600;
  line-height: 24px;
}

.fact-value.mono {
  font-size: 20px;
  font-weight: 700;
}

.fact-value--big.mono {
  font-size: 24px;
  line-height: 28px;
}

.pass-foot {
  border-top: 1px dashed var(--l2);
  padding: 4px 6px 4px 16px;
  min-height: 52px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  color: var(--sc);
  font-size: 14px;
  line-height: 19px;
}

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

.rows,
.events {
  margin: 8px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
}

.events {
  margin-top: 0;
}

.rows--plain {
  gap: 8px;
}

.row {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 56px;
  padding: 8px 0;
  border-bottom: 1px solid var(--ln);
}

.rows > .row:last-child {
  border-bottom: 0;
}

.row-time {
  flex: none;
  width: var(--gutter);
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 15px;
  font-weight: 700;
  line-height: 20px;
}

.row-time small {
  display: block;
  color: var(--sc);
  font-family: var(--font);
  font-size: 13px;
  font-weight: 500;
  line-height: 16px;
}

.row-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.row-title {
  font-size: 16px;
  font-weight: 600;
  line-height: 21px;
  overflow-wrap: anywhere;
}

.row-sub {
  color: var(--sc);
  font-size: 14px;
  line-height: 19px;
  overflow-wrap: anywhere;
}

.row-sub a {
  text-decoration: underline;
  text-decoration-color: var(--l2);
  text-underline-offset: 3px;
}

/* A place name inside a line of text: the padding makes it easy to tap,
   the matching negative margin keeps the line where it was. */
.row-sub a.place {
  display: inline-block;
  max-width: 100%;
  padding: 14px 0;
  margin: -14px 0;
}

.row-aside {
  flex: none;
  color: var(--sc);
  font-size: 14px;
  font-weight: 500;
}

.row--done .row-time,
.row--done .row-title {
  color: var(--sc);
  font-weight: 500;
}

.row--key .row-time {
  color: var(--ac);
}

.row-num {
  flex: none;
  width: 26px;
  height: 26px;
  border: 1.5px solid var(--l2);
  border-radius: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--sc);
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 700;
}

.row--current .row-num {
  border-color: var(--ac);
  background: var(--ac);
  color: var(--on);
}

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

.btn {
  flex: none;
  min-height: 44px;
  padding: 0 18px;
  border: 1px solid var(--l2);
  border-radius: 22px;
  background: transparent;
  color: var(--tx);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
}

.btn--primary {
  border-color: var(--ac);
  background: var(--ac);
  color: var(--on);
}

.btn--text {
  padding: 0 14px;
  border-color: transparent;
  color: var(--ac);
}

.btn--wide {
  flex: 1 1 auto;
  min-height: 46px;
}

.btn--close {
  width: 44px;
  padding: 0;
  border-color: transparent;
  color: var(--sc);
}

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

.btn-row {
  margin-top: 12px;
  display: flex;
  flex-wrap: wrap; /* two long labels stack on a narrow phone rather than pushing off the side */
  gap: 8px;
}

/* ---------- Segmented control ---------- */

.seg {
  align-self: flex-start;
  min-height: 52px;
  padding: 3px;
  border: 1px solid var(--ln);
  border-radius: 26px;
  background: var(--s1);
  display: inline-flex;
  align-items: center;
}

.seg > * {
  min-width: 44px;
  min-height: 44px;
  padding: 0 16px;
  border: 0;
  border-radius: 22px;
  justify-content: center;
  background: transparent;
  color: var(--sc);
  display: flex;
  align-items: center;
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
}

/* Selected is plain dark-on-light (or light-on-dark), so the brand colour
   is left for the one main button on a screen. */
.seg > [aria-current='page'],
.seg > [aria-pressed='true'] {
  background: var(--tx);
  color: var(--bg);
}

.head-split {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 44px;
}

/* ---------- Cards and notices ---------- */

.card {
  margin-top: 12px;
  padding: 14px 16px;
  border: 1px solid var(--ln);
  border-radius: 20px;
  background: var(--s1);
}

.card--row {
  padding: 10px 10px 10px 16px;
  display: flex;
  align-items: center;
  gap: 12px;
}

.notice {
  margin-top: 6px;
  display: flex;
  align-items: flex-start;
  gap: 8px;
  color: var(--wn);
  font-size: 14px;
  font-weight: 500;
  line-height: 19px;
}

.notice svg {
  flex: none;
  margin-top: 1px;
}

.empty {
  margin-top: 18px;
  color: var(--sc);
  font-size: 15px;
  line-height: 21px;
}

.big-time {
  margin-top: 2px;
  font-family: var(--display);
  font-size: 42px;
  font-weight: 700;
  line-height: 44px;
  letter-spacing: -1.2px;
}

.big-time small {
  color: var(--sc);
  font-family: var(--font);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0;
}

.kicker {
  margin-top: 14px;
  color: var(--ac);
  font-size: 15px;
  font-weight: 600;
  line-height: 20px;
}

.stop-title {
  margin-top: 2px;
  font-size: 20px;
  font-weight: 600;
  line-height: 26px;
}

.stop-note {
  margin-top: 2px;
  color: var(--sc);
  font-size: 14px;
  line-height: 19px;
}

.row-aside--strong {
  color: var(--tx);
  font-weight: 700;
}

/* ---------- Explore ---------- */

.day-head {
  margin-top: 20px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--ln);
  color: var(--sc);
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 500;
}

.event {
  border-bottom: 1px solid var(--ln);
}

.event--over .row-title,
.event--over .row-time {
  color: var(--sc);
}

.event-main {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 0;
}

.event-toggle {
  flex: 1;
  min-width: 0;
  min-height: 44px;
  padding: 0;
  border: 0;
  background: transparent;
  text-align: left;
  display: flex;
  align-items: center;
  gap: 14px;
}

.event-more {
  padding: 0 0 14px calc(var(--gutter) + 14px);
  display: flex;
  flex-direction: column;
  gap: 6px;
  color: var(--sc);
  font-size: 14px;
  line-height: 19px;
}

.event-more p + p {
  margin-top: 0;
}

.event-links {
  margin-top: 4px;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* A long site name wraps inside its button instead of pushing the page sideways. */
.event-links .btn {
  max-width: 100%;
  min-width: 0;
  padding-top: 8px;
  padding-bottom: 8px;
  flex-wrap: wrap;
  row-gap: 0;
  white-space: normal;
  overflow-wrap: anywhere;
}

/* On a narrow phone the details use the full width, not just the part beside the time. */
@media (max-width: 379px) {
  .event-more {
    padding-left: 0;
  }
}

.search {
  margin-top: 12px;
  width: 100%;
  height: 48px;
  padding: 0 16px;
  border: 1px solid var(--fb);
  border-radius: 24px;
  background: var(--s1);
  color: var(--tx);
  font-size: 16px;
}

.search::placeholder {
  color: var(--sc);
}

/* ---------- Eat ---------- */

.times {
  margin-top: 12px;
  display: flex;
  gap: 8px;
  font-family: var(--mono);
}

.times button {
  flex: 1;
  min-width: 0;
  height: 44px;
  padding: 0;
  border: 1px solid var(--l2);
  border-radius: 14px;
  background: transparent;
  color: var(--tx);
  font-size: 15px;
  font-weight: 500;
}

.times button[aria-pressed='true'] {
  border-color: var(--tx);
  background: var(--tx);
  color: var(--bg);
  font-weight: 700;
}

.own {
  margin-top: 10px;
  display: flex;
  gap: 8px;
}

.own input {
  flex: 1;
  min-width: 0;
  height: 48px;
  padding: 0 16px;
  border: 1px solid var(--fb);
  border-radius: 24px;
  background: var(--s1);
  font-size: 16px;
}

.own input::placeholder {
  color: var(--sc);
}

.label {
  margin-top: 22px;
  font-size: 17px;
  font-weight: 600;
  line-height: 22px;
}

/* ---------- Join and More ---------- */

.choice {
  width: 100%;
  min-height: 64px;
  padding: 10px 0;
  border: 0;
  border-bottom: 1px solid var(--ln);
  background: transparent;
  text-align: left;
  display: flex;
  align-items: center;
  gap: 14px;
}

.avatar {
  flex: none;
  width: 44px;
  height: 44px;
  border: 1px solid var(--ln);
  border-radius: 22px;
  background: var(--s1);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  font-weight: 600;
}

.stack {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.presets {
  margin-top: 10px;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.fine {
  margin-top: 10px;
  color: var(--sc);
  font-size: 14px;
  line-height: 20px;
}

/* ---------- Preview bar ---------- */

#preview-bar {
  position: sticky;
  top: 0;
  z-index: 30;
  padding: calc(env(safe-area-inset-top, 0px) + 6px) var(--pad) 6px;
  background: var(--wn);
  color: var(--bg);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-size: 14px;
  font-weight: 600;
}

/* No connection: calm, not alarming. A newer plan waiting: the brand colour. */
#preview-bar[data-kind='offline'] {
  background: var(--s2);
  color: var(--tx);
  min-height: 40px;
}

#preview-bar[data-kind='update'] {
  background: var(--ac);
  color: var(--on);
}

#preview-bar button {
  flex: none;
  min-height: 44px;
  padding: 0 14px;
  border: 1.5px solid currentColor;
  border-radius: 22px;
  background: transparent;
  color: inherit;
  font-size: 14px;
  font-weight: 600;
}

/* ---------- Map ---------- */

#map-layer {
  position: relative;
  isolation: isolate; /* the map's own layers never rise above the screen content */
  height: 30vh;
  height: 30dvh;
  min-height: 190px;
  max-height: 300px;
  background: var(--s2);
  overflow: hidden;
}

#map-canvas {
  position: absolute;
  inset: 0;
}

#map-message {
  position: absolute;
  inset: 0;
  padding: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  color: var(--sc);
  font-size: 15px;
  line-height: 21px;
}

/* ---------- Full-screen map (the Map tab) ----------
   The map fills the screen. The screen's own content floats over it: the
   filter at the top, the card about the selected place at the bottom. */

#app.app--map {
  height: 100vh;
  height: 100dvh;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  grid-template-columns: minmax(0, 1fr);
  overflow: hidden;
}

#app.app--map > #preview-bar {
  grid-row: 1;
}

#app.app--map > #map-layer,
#app.app--map > #screen {
  grid-row: 2;
  grid-column: 1;
  min-height: 0;
}

#map-layer.map-layer--full {
  height: auto;
  min-height: 0;
  max-height: none;
}

/* The map's credit line. Written by this app, in fixed words, so the map
   service cannot put anything of its own on the screen. */
#map-credit {
  position: absolute;
  right: 6px;
  bottom: 6px;
  z-index: 2;
  max-width: calc(100% - 12px);
  margin: 0;
  padding: 2px 8px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.86);
  color: #2b2f33;
  font-size: 11px;
  line-height: 16px;
}

#map-credit a {
  color: inherit;
  text-decoration: underline;
}

#map-canvas[hidden] ~ #map-credit {
  display: none;
}

/* Full screen: the credit sits at the top, where the pop-up card never covers it. */
.map-layer--full #map-credit {
  top: calc(env(safe-area-inset-top, 0px) + 70px);
  right: auto;
  bottom: auto;
  left: var(--pad);
  max-width: calc(100% - 96px);
}

/* Clear of the filter bar. */
.map-layer--full .maplibregl-ctrl-top-left,
.map-layer--full .maplibregl-ctrl-top-right {
  top: calc(env(safe-area-inset-top, 0px) + 70px);
}

/* The credit line stops short of the zoom buttons. */
.map-layer--full .maplibregl-ctrl-top-left {
  max-width: calc(100% - 56px);
}

/* On a touch screen you pinch to zoom, as in any maps app. The buttons stay for mouse and keyboard. */
@media (pointer: coarse) {
  .maplibregl-ctrl-top-right {
    display: none;
  }
  .map-layer--full .maplibregl-ctrl-top-left {
    max-width: 100%;
  }
}

/* Nothing behind the full-screen map to scroll or bounce. */
.map-open,
.map-open body {
  overflow: hidden;
  overscroll-behavior: none;
}

.screen--over-map {
  position: relative;
  z-index: 1;
  padding: calc(env(safe-area-inset-top, 0px) + 12px) var(--pad) calc(env(safe-area-inset-bottom, 0px) + 92px);
  justify-content: space-between;
  gap: 12px;
  pointer-events: none; /* touches fall through to the map, except on the controls themselves */
}

.screen--over-map > * {
  pointer-events: auto;
}

.screen--map-list {
  position: relative;
  z-index: 1;
  padding-top: calc(env(safe-area-inset-top, 0px) + 12px);
  background: var(--bg);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.map-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.map-top .seg {
  box-shadow: 0 2px 10px var(--sh);
}

.map-top .seg > * {
  padding: 0 13px;
}

.btn--solid {
  background: var(--s1);
  box-shadow: 0 2px 10px var(--sh);
}

.screen--map-list .map-top .seg,
.screen--map-list .btn--solid {
  box-shadow: none;
}

.map-card {
  min-height: 0; /* on a short screen the card shrinks and scrolls rather than running off it */
  max-height: 46vh; /* and never hides the pin it is about */
  max-height: 46dvh;
  margin-top: 0;
  overflow-y: auto;
  box-shadow: 0 12px 32px var(--sh);
}

/* When the card has to scroll, its buttons stay in view at the bottom of it. */
.map-card-actions {
  position: sticky;
  bottom: 0;
  margin-bottom: -12px;
  padding-bottom: 12px;
  background: var(--s1);
}

.map-card:focus {
  outline: none;
}

.map-card:focus-visible {
  outline: 2px solid var(--ac);
  outline-offset: 2px;
}

.map-card-head {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.map-card-head .btn--text {
  margin: -8px -10px 0 0;
}

.map-card .row-sub.warn {
  margin-top: 6px;
}

.map-card-more {
  margin: 4px -8px -6px 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.map-hint {
  align-self: center;
  padding: 9px 16px;
  border: 1px solid var(--ln);
  border-radius: 20px;
  background: var(--s1);
  color: var(--sc);
  font-size: 14px;
  box-shadow: 0 2px 10px var(--sh);
}

.screen--under-map {
  padding-top: 14px;
}

.pin {
  width: 26px;
  height: 26px;
  padding: 0;
  border: 2.5px solid var(--tx);
  border-radius: 13px;
  background: var(--s1);
  color: var(--tx);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 700;
  box-shadow: 0 2px 8px var(--sh);
  cursor: pointer;
}

.pin--still {
  cursor: default;
}

.pin--group {
  border-color: var(--s1);
  background: var(--ac);
  color: var(--on);
}

.pin--selected {
  width: 34px;
  height: 34px;
  border-radius: 17px;
  outline: 3px solid var(--ac);
  outline-offset: 1px;
  z-index: 2;
}

.maplibregl-ctrl-attrib {
  font-family: var(--font);
}

/* ---------- Menu ----------
   Four tabs, each with its icon and its word, each always in the same
   place. The bar is solid enough that nothing reads through it, and the
   page fades out underneath so no row is half hidden behind it. */

.tabbar {
  position: fixed;
  left: 50%;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 12px);
  z-index: 20;
  width: min(406px, calc(100vw - 24px));
  transform: translateX(-50%);
}

#tabbar:not(:empty)::before {
  content: '';
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 19;
  height: calc(env(safe-area-inset-bottom, 0px) + 104px);
  background: linear-gradient(to top, var(--bg) 42%, transparent);
  pointer-events: none;
}

/* Over the full-screen map there is no page to fade. */
.app--map #tabbar::before {
  display: none;
}

.tabbar nav {
  height: 64px;
  padding: 4px;
  border: 1px solid var(--ln);
  border-radius: 22px;
  background: var(--gl);
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
  box-shadow: 0 10px 28px var(--sh);
  display: flex;
  align-items: stretch;
}

/* Blur over a moving map is costly on cheap phones, and the bar is nearly solid anyway. */
.app--map .tabbar nav {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  background: var(--s1);
}

.tabbar nav a {
  flex: 1 1 0;
  min-width: 0;
  border-radius: 18px;
  color: var(--sc);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  font-size: 12px;
  font-weight: 600;
  line-height: 15px;
}

.tabbar nav a[aria-current='page'] {
  background: var(--ac);
  color: var(--on);
}

@media (prefers-reduced-motion: no-preference) {
  .btn,
  .chip,
  .tabbar nav a {
    transition: transform 120ms ease-out, background-color 160ms ease-out, color 160ms ease-out;
  }
}

/* Something should move under your thumb, whatever you press. */
.tabbar nav a:active,
.tab:active,
.chip:active,
.choice:active,
.event-toggle:active,
.times button:active,
.seg > *:active {
  opacity: 0.7;
}

@media (max-width: 359px) {
  :root {
    --pad: 16px;
  }
  .h1 {
    font-size: 30px;
    line-height: 34px;
  }
}

/* ---------- Notices, stamps and folds ---------- */

/* The organiser's latest message. */
.banner {
  margin-top: 10px;
  padding: 12px 14px;
  border: 1.5px solid var(--wn);
  border-radius: 14px;
  background: var(--s1);
}

.banner-head {
  color: var(--wn);
  font-size: 14px;
  font-weight: 700;
  line-height: 19px;
}

.banner-head + .banner-text {
  margin-top: 2px;
}

.banner-text {
  font-size: 17px;
  font-weight: 600;
  line-height: 23px;
}

.banner-text + .banner-head {
  margin-top: 10px;
}

.notice--info {
  color: var(--sc);
  font-weight: 400;
}

.stamp {
  margin-top: 22px;
  color: var(--sc);
  font-size: 14px;
  line-height: 20px;
}

/* Things already done, or advice to open when needed. */
.fold {
  margin-top: 10px;
  border-bottom: 1px solid var(--ln);
}

.fold > summary {
  min-height: 44px;
  display: flex;
  align-items: center;
  color: var(--sc);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}

.fold--card {
  padding: 0 14px;
  border: 1px solid var(--ln);
  border-radius: 14px;
  background: var(--s1);
}

.fold--card > summary {
  min-height: 52px;
  color: var(--tx);
  font-size: 17px;
}

.fold--card > p {
  padding-bottom: 14px;
  color: var(--sc);
  font-size: 15px;
  line-height: 21px;
}

.address {
  color: var(--tx);
  font-size: 17px;
  line-height: 23px;
}

/* Where a button leads, written small beside its label. */
.btn-host {
  color: var(--sc);
  font-size: 13px;
  font-weight: 500;
}

.btn--primary .btn-host {
  color: inherit;
}

/* ---------- Supporter's current stop ---------- */

.big-label {
  margin-top: 8px;
  color: var(--sc);
  font-size: 15px;
  font-weight: 600;
  line-height: 20px;
}

.big-label + .big-time {
  margin-top: 0;
}

.stop-lead {
  margin-top: 4px;
  font-size: 17px;
  font-weight: 600;
  line-height: 23px;
}

.stop-leave {
  margin-top: 6px;
  font-size: 15px;
  font-weight: 600;
  line-height: 21px;
}

.stop-next {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--ln);
  color: var(--sc);
  font-size: 15px;
  line-height: 21px;
}

.late .times {
  flex-wrap: wrap;
  font-family: var(--font);
}

.late .times button {
  flex: 1 0 28%;
}

/* ---------- Toast: what just happened, and a way to take it back ---------- */

#toast {
  position: fixed;
  left: 50%;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 88px);
  z-index: 40;
  width: min(398px, calc(100vw - 32px));
  transform: translateX(-50%);
  padding: 6px 6px 6px 16px;
  min-height: 52px;
  border-radius: 14px;
  background: var(--tx);
  color: var(--bg);
  box-shadow: 0 10px 28px var(--sh);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-size: 15px;
  font-weight: 600;
  line-height: 20px;
}

#toast button {
  flex: none;
  min-width: 44px;
  min-height: 44px;
  padding: 0 14px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: inherit;
  font-size: 15px;
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.undo-line {
  margin-top: 4px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 6px;
}

/* On the map the card sits at the bottom, so the message goes to the top, under the filters. */
.map-open #toast {
  top: calc(env(safe-area-inset-top, 0px) + 128px);
  bottom: auto;
}

.noscript {
  padding: 24px;
  font-family: sans-serif;
}

/* ---------- Forms: setting up your own plan ---------- */

.form {
  display: flex;
  flex-direction: column;
}

.field {
  margin-top: 14px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.field label,
.pick legend {
  font-size: 14px;
  font-weight: 600;
  line-height: 19px;
}

.optional {
  color: var(--sc);
  font-weight: 500;
}

.field input,
.field select,
.link-box {
  width: 100%;
  min-width: 0;
  height: 50px;
  padding: 0 14px;
  border: 1px solid var(--fb);
  border-radius: 14px;
  background: var(--s1);
  color: var(--tx);
  font: inherit;
  font-size: 16px; /* smaller than this and iPhones zoom the page when the box is tapped */
  appearance: none;
  -webkit-appearance: none;
}

.field select {
  padding-right: 34px;
  background-image: linear-gradient(45deg, transparent 50%, var(--sc) 50%), linear-gradient(135deg, var(--sc) 50%, transparent 50%);
  background-position: calc(100% - 19px) 22px, calc(100% - 14px) 22px;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

.field input::placeholder {
  color: var(--sc);
}

.field input[aria-invalid='true'] {
  border-color: var(--dg);
}

.field-pair {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 12px;
}

.hint {
  margin-top: 6px;
  color: var(--sc);
  font-size: 13px;
  line-height: 18px;
}

.hint:empty {
  display: none;
}

.form-error {
  margin-top: 16px;
  padding: 12px 14px;
  border: 1px solid var(--dg);
  border-radius: 14px;
  color: var(--dg);
  font-size: 15px;
  font-weight: 600;
  line-height: 20px;
}

/* Two or three choices as one control: radio buttons drawn as a row of pills. */
.pick {
  margin: 14px 0 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

.pick legend {
  padding: 0;
  margin-bottom: 6px;
}

.pick-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.pick-row label {
  position: relative;
  flex: 1 1 0;
  min-width: 120px;
}

.pick-row input,
.swatches input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.pick-row span {
  min-height: 48px;
  padding: 0 14px;
  border: 1px solid var(--fb);
  border-radius: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  font-weight: 600;
  text-align: center;
}

.pick-row input:checked + span {
  border-color: var(--tx);
  background: var(--tx);
  color: var(--bg);
}

.pick-row input:focus-visible + span,
.swatches input:focus-visible + .swatch {
  outline: 2px solid var(--ac);
  outline-offset: 2px;
}

/* A set of quick choices inside a form: as many per line as fit, each as wide as its words. */
.pick .times {
  margin-top: 0;
  flex-wrap: wrap;
  font-family: var(--font);
}

.pick .times button {
  flex: 0 1 auto;
  min-width: 64px;
  height: auto;
  min-height: 44px;
  padding: 6px 14px;
}

/* Boxes that only apply to a runner, or only to a supporter, follow the choice above them. */
.form:has(input[name='role'][value='supporter']:checked) .only-runner,
.form:has(input[name='role'][value='runner']:checked) .only-supporter {
  display: none;
}

.swatches {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.swatches label {
  position: relative;
  width: 44px;
  height: 44px;
}

.swatch {
  width: 44px;
  height: 44px;
  border: 3px solid var(--bg);
  border-radius: 22px;
  display: block;
  box-shadow: 0 0 0 1px var(--fb);
}

.swatches input:checked + .swatch {
  box-shadow: 0 0 0 2px var(--tx);
}

.swatch--0 { background: #0B5D46; }
.swatch--1 { background: #1D4ED8; }
.swatch--2 { background: #B91C1C; }
.swatch--3 { background: #7C3AED; }
.swatch--4 { background: #C2410C; }
.swatch--5 { background: #0F766E; }
.swatch--6 { background: #BE185D; }
.swatch--7 { background: #374151; }

.btn--danger {
  border-color: var(--dg);
  color: var(--dg);
}

.tick {
  margin-top: 16px;
  min-height: 44px;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-size: 15px;
  line-height: 21px;
}

.tick input {
  flex: none;
  width: 24px;
  height: 24px;
  margin: 0;
  accent-color: var(--ac);
}

.finder {
  display: flex;
  gap: 8px;
}

.finder input {
  flex: 1;
}

.finder .btn {
  height: 50px;
}

.finder-results {
  color: var(--sc);
  font-size: 14px;
  line-height: 19px;
}

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

.finder-results .choice {
  min-height: 56px;
}

.link-box {
  margin-top: 10px;
  font-size: 13px;
  text-overflow: ellipsis;
}

a.choice {
  color: inherit;
}

.kinds {
  margin-top: 8px;
}

.splits {
  margin: 0;
  padding: 0 0 4px;
  list-style: none;
}

.splits li {
  min-height: 36px;
  border-top: 1px solid var(--ln);
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto 64px;
  align-items: center;
  gap: 12px;
  font-size: 15px;
}

.splits li span:last-child {
  text-align: right;
  font-size: 13px;
}

.facts {
  margin: 0;
  padding: 0 0 0 18px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 15px;
  line-height: 21px;
}

.fact-value small {
  font-family: var(--font);
  font-size: 12px;
  font-weight: 500;
  color: var(--sc);
}

.pass-foot + .pass-foot {
  border-top: 0;
  padding-top: 0;
}

/* ---------- Colour helpers. Last in the file so they win over component colours. ---------- */

.muted {
  color: var(--sc);
}

.warn {
  color: var(--wn);
}

.accent {
  color: var(--ac);
}

.ok {
  color: var(--ok);
}

.danger {
  color: var(--dg);
}
