/* The replay is its own dark room: a map you watch rather than read, so the
   chrome steps back and the only bright things are the tracks and the photo. */
:root {
  --ink: #eef2ec;
  --dim: #9daba3;
  --faint: #6b7a73;
  --panel: rgba(16, 22, 20, 0.9);
  --line: rgba(238, 242, 236, 0.16);
  --forest: #55b083;
  --sun: #d9a251;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  background: #101614;
  color: var(--ink);
  font-family: "Avenir Next", "Trebuchet MS", Verdana, sans-serif;
}

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

/* The trail is drawn here rather than as a Leaflet polyline: three thousand
   points redrawn sixty times a second is a canvas job, and Leaflet would rebuild
   its SVG path on every frame. Pointer events pass straight through to the map. */
#trail {
  position: absolute;
  inset: 0;
  z-index: 400;
  pointer-events: none;
}

/* --------------------------------------------------------------------- bar */
.bar {
  position: absolute;
  top: max(10px, env(safe-area-inset-top));
  left: 10px;
  right: 10px;
  z-index: 600;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 12px;
  border-radius: 999px;
  background: var(--panel);
  border: 1px solid var(--line);
  backdrop-filter: blur(6px);
}

.back {
  text-decoration: none;
  font-size: 1.15rem;
  line-height: 1;
  padding: 5px 10px;
  border-radius: 999px;
  border: 1px solid var(--line);
  color: inherit;
}

.bar-title { display: flex; flex-direction: column; line-height: 1.2; margin-right: auto; min-width: 0; }
.bar-title strong { font-size: 0.92rem; white-space: nowrap; }
.bar-title small { color: var(--dim); font-size: 0.78rem; }

.ghost {
  font: inherit;
  font-size: 0.8rem;
  font-weight: 800;
  padding: 7px 13px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--dim);
  cursor: pointer;
  white-space: nowrap;
}

.ghost[aria-pressed="true"] { background: var(--forest); border-color: var(--forest); color: #0d1512; }

/* For screen readers and crawlers: the page's one heading, painted nowhere. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --------------------------------------------------------------- lap count */
.lapcount {
  position: absolute;
  top: 74px;
  left: 12px;
  z-index: 600;
  display: grid;
  gap: 2px;
  padding: 11px 16px 12px;
  border-radius: 14px;
  background: var(--panel);
  border: 1px solid var(--line);
  backdrop-filter: blur(6px);
  text-align: center;
}

.lapcount-label {
  font-size: 0.6rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--faint);
}

.lapcount-n {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 5px;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.lapcount-n b {
  font-size: 2.3rem;
  font-weight: 700;
  /* The number changes size as it goes 1 → 10, so it gets a fixed box; a dial
     that shifts under your eye is a dial you stop trusting. */
  min-width: 1.4em;
  transition: color 0.3s ease-out;
}

.lapcount-n small { font-size: 0.85rem; color: var(--faint); }

/* One pip per lap, filling up. The count says where you are, the pips say how
   much day is left — which is the question at lap six. */
.lapcount-dots {
  display: flex;
  gap: 3px;
  justify-content: center;
  margin-top: 4px;
}

.lapcount-dots i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: rgba(238, 242, 236, 0.22);
  transition: background 0.4s ease-out;
}

.lapcount-dots i.done { background: var(--forest); }

/* The tick over: a short pulse rather than a long one, because it happens
   eleven times and the eleventh should still feel like something. */
.lapcount.is-new .lapcount-n b { color: var(--sun); animation: lap-pop 0.9s ease-out; }
.lapcount.is-new { animation: lap-glow 0.9s ease-out; }

@keyframes lap-pop {
  0% { transform: scale(1); }
  22% { transform: scale(1.35); }
  100% { transform: scale(1); }
}

@keyframes lap-glow {
  0% { border-color: var(--sun); box-shadow: 0 0 0 0 rgba(217, 162, 81, 0.45); }
  100% { border-color: var(--line); box-shadow: 0 0 0 18px rgba(217, 162, 81, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .lapcount.is-new .lapcount-n b,
  .lapcount.is-new { animation: none; }
}

/* ------------------------------------------------------------------- photo */
.shot {
  position: absolute;
  top: 74px;
  right: 12px;
  z-index: 600;
  width: min(290px, calc(100vw - 24px));
  margin: 0;
  border-radius: 12px;
  overflow: hidden;
  background: var(--panel);
  border: 1px solid var(--line);
  backdrop-filter: blur(6px);
  animation: shot-in 0.45s ease-out;
}

@keyframes shot-in {
  from { opacity: 0; transform: translateY(-8px) scale(0.98); }
  to { opacity: 1; transform: none; }
}

/* Most of the day's photos are portrait, and a 4:3 crop threw away the top and
   bottom of every one of them. The card gives the picture a generous box and
   lets it keep its own shape inside it. */
.shot img {
  display: block;
  width: 100%;
  max-height: 42vh;
  object-fit: contain;
  background: #0d1512;
}

.shot figcaption { display: grid; gap: 3px; padding: 10px 12px 12px; }
.shot strong { font-size: 0.88rem; }
.shot span { font-size: 0.76rem; color: var(--dim); font-variant-numeric: tabular-nums; }
.shot p { margin: 4px 0 0; font-size: 0.85rem; line-height: 1.4; }

/* --------------------------------------------------------------------- hud */
.hud {
  position: absolute;
  left: 10px;
  right: 10px;
  bottom: max(10px, env(safe-area-inset-bottom));
  z-index: 600;
  padding: 12px 14px 10px;
  border-radius: 14px;
  background: var(--panel);
  border: 1px solid var(--line);
  backdrop-filter: blur(6px);
  display: grid;
  gap: 10px;
}

.map-panel-toggle { display: none; }

.readouts {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}

.readouts dt {
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: 2px;
}

.readouts dd {
  margin: 0;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-variant-numeric: tabular-nums;
  font-size: 1.05rem;
  font-weight: 600;
}

#profile { display: block; width: 100%; height: 46px; }

.controls { display: flex; align-items: center; gap: 10px; }

.play {
  font: inherit;
  font-size: 1rem;
  width: 42px;
  height: 42px;
  flex: none;
  border-radius: 50%;
  border: 0;
  background: var(--forest);
  color: #0d1512;
  cursor: pointer;
}

/* Under the scrubber, one lane per rider who was there for part of the day.
   The bar already says where you are in the day; the lanes say who was out on
   the trail at that moment, which is the question the legend cannot answer.
   The lanes are inset by the thumb's radius so a rider's band starts under the
   same pixel the thumb reaches at that time. */
.timeline { flex: 1; min-width: 0; display: grid; gap: 5px; }

.presence { display: grid; gap: 3px; margin: 0 9px; }

.presence-lane { position: relative; height: 3px; border-radius: 999px; background: rgba(238, 242, 236, 0.07); }

.presence-lane span {
  position: absolute;
  top: 0;
  bottom: 0;
  border-radius: 999px;
  /* Narrow bands still have to be visible, so a stretch shorter than a couple
     of pixels is widened rather than rounded away to nothing. */
  min-width: 3px;
}

/* The scrubber is the one control people reach for, so it gets a real target
   rather than the browser's hairline default. */
#scrub {
  width: 100%;
  min-width: 0;
  appearance: none;
  -webkit-appearance: none;
  height: 5px;
  border-radius: 999px;
  background: rgba(238, 242, 236, 0.18);
  cursor: pointer;
}

#scrub::-webkit-slider-thumb {
  appearance: none;
  -webkit-appearance: none;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: var(--ink);
  border: 0;
  cursor: grab;
}

#scrub::-moz-range-thumb {
  width: 17px; height: 17px; border-radius: 50%;
  background: var(--ink); border: 0; cursor: grab;
}

#scrub:focus-visible, .play:focus-visible, .ghost:focus-visible, .back:focus-visible {
  outline: 2px solid var(--sun);
  outline-offset: 2px;
}

.legend {
  margin: 0;
  font-size: 0.72rem;
  color: var(--faint);
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  align-items: center;
}

.legend b { font-weight: 700; color: var(--dim); }

/* A name that has a page of its own says so quietly: same ink, dotted line. */
.legend .rider-link { color: inherit; text-decoration: none; }
.legend .rider-link b { border-bottom: 1px dotted var(--faint); }
.legend .rider-link:hover b { color: var(--ink); border-bottom-color: var(--ink); }

.caveats { margin-left: auto; }
.caveats summary { cursor: pointer; color: var(--faint); }
.caveats ul {
  position: absolute;
  right: 14px;
  bottom: 34px;
  max-width: min(420px, calc(100vw - 40px));
  margin: 0;
  padding: 10px 14px 10px 28px;
  border-radius: 10px;
  background: #101614;
  border: 1px solid var(--line);
  line-height: 1.5;
}
.caveats li + li { margin-top: 6px; }
.legend i { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 5px; }
.legend em { font-style: normal; color: var(--faint); }

.loading {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 550;
  width: min(360px, calc(100vw - 32px));
  transform: translate(-50%, -50%);
  padding: 24px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--panel);
  color: var(--dim);
  font-size: 0.9rem;
  text-align: center;
  box-shadow: 0 18px 50px rgba(0, 0, 0, .35);
}
.loading h2 { margin: 0 0 8px; color: var(--ink); font-size: 1.1rem; }
.loading p { margin: 0; line-height: 1.5; }
.loading-progress { height: 3px; margin: 16px 0 0; overflow: hidden; border-radius: 99px; background: var(--line); }
.loading-progress::after { content: ""; display: block; width: 45%; height: 100%; background: var(--sun); animation: loading-slide 1.2s ease-in-out infinite alternate; }
.loading-actions { display: flex; justify-content: center; gap: 8px; margin-top: 16px; }
.loading-actions button, .loading-actions a { min-height: 44px; display: inline-flex; align-items: center; padding: 0 14px; border: 1px solid var(--line); border-radius: 999px; background: transparent; color: var(--ink); font: inherit; font-weight: 800; text-decoration: none; cursor: pointer; }
@keyframes loading-slide { to { transform: translateX(120%); } }
@media (prefers-reduced-motion: reduce) { .loading-progress::after { animation: none; width: 100%; } }

/* Markers -------------------------------------------------------------- */

/* The rider sits on the trail rather than floating over it, so the shadow is
   under the wheels and the sprite itself gets no box of its own. The sprite
   never captures the pointer — the map underneath does. */
.rider-icon { background: none; border: 0; pointer-events: none; }

.rider-sprite {
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.55));
}

.rider-svg {
  display: block;
  overflow: visible;
  transform-origin: 50% 50%;
}

/* Relative for the count badge's absolute anchor; the marker element itself
   is positioned by MapLibre with a transform. Explicit size replaces the old
   Leaflet iconSize. */
.photo-pin { position: relative; width: 34px; height: 34px; }

.photo-pin img {
  display: block;
  width: 34px;
  height: 34px;
  object-fit: cover;
  border-radius: 5px;
  border: 2px solid var(--ink);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
  cursor: pointer;
}

/* How many photos are hiding under this one. Without it the pin lies: it looks
   like one photo and it is four. */
.photo-pin b {
  position: absolute;
  top: -6px;
  right: -6px;
  min-width: 17px;
  height: 17px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--sun);
  color: #17110a;
  font-size: 0.66rem;
  font-weight: 800;
  line-height: 17px;
  text-align: center;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
  pointer-events: none;
}

.shot-nav {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
}

.shot-nav button {
  font: inherit;
  font-size: 1rem;
  line-height: 1;
  width: 30px;
  height: 30px;
  flex: none;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: rgba(238, 242, 236, 0.06);
  color: var(--ink);
  cursor: pointer;
}

.shot-nav button:hover { background: rgba(238, 242, 236, 0.16); }

.shot-nav span {
  font-size: 0.74rem;
  color: var(--dim);
  font-variant-numeric: tabular-nums;
}

.hub-pin {
  display: grid;
  place-items: center;
  width: 42px;
  height: 22px;
  font-size: 0.62rem;
  font-weight: 800;
  border-radius: 999px;
  background: var(--ink);
  color: #101614;
  pointer-events: none;
}

/* The base map dimming now lives in map-style/saaksi-mtb-dim.json, not CSS. */
.maplibregl-ctrl-attrib { background: rgba(16, 22, 20, 0.75) !important; color: var(--faint) !important; }
.maplibregl-ctrl-attrib a { color: var(--dim) !important; }

@media (prefers-reduced-motion: reduce) {
  .shot { animation: none; }
}

/* ---------------------------------------------------------------- phone --
   On a 390 px screen the desktop layout spent 66% of the window on chrome: a
   66 px bar, an 88 px lap badge, a 404 px photo card and a 267 px panel, with
   the photo card sitting on top of the panel. What was left of the map was an
   L-shaped strip.

   So on a phone the photo stops being a card floating over the map and becomes
   a strip docked above the panel — a thumbnail and two lines, the same
   information in a fifth of the height. Tapping it opens the full picture,
   which is the one moment a photo is worth the whole screen.

   The panel loses the fat rather than the content: the readouts go from a 2×2
   block to one row, the elevation profile keeps its shape at two thirds the
   height, and the legend stays on one scrollable line. */
@media (max-width: 620px) {
  .bar { gap: 8px; padding: 7px 10px; }
  .bar-title strong { font-size: 0.84rem; }
  .bar-title small { font-size: 0.7rem; }
  .ghost { padding: 6px 10px; font-size: 0.72rem; }
  .back { padding: 4px 9px; }

  .lapcount { top: 66px; padding: 7px 12px 8px; }
  .lapcount-n b { font-size: 1.6rem; }
  .lapcount-label { font-size: 0.52rem; }
  .lapcount-dots i { width: 4px; height: 4px; }

  /* Docked to the panel rather than floating: --hud-h is measured from the
     panel itself, because its height changes with the legend's wrapping. */
  .shot {
    top: auto;
    bottom: calc(var(--hud-h, 200px) + 18px);
    left: 10px;
    right: 10px;
    width: auto;
    display: flex;
    align-items: stretch;
    gap: 0;
  }

  .shot img {
    width: 76px;
    height: 76px;
    flex: none;
    max-height: none;
    object-fit: cover;
  }

  .shot figcaption {
    flex: 1;
    min-width: 0;
    padding: 8px 10px;
    align-content: center;
  }

  .shot strong, .shot span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .shot span { font-size: 0.72rem; }

  .shot p {
    margin: 2px 0 0;
    font-size: 0.78rem;
    line-height: 1.3;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }

  /* Tapped open: the picture gets the room it needs, and the strip layout
     unwinds back into a card. */
  .shot.is-open { display: block; }
  .shot.is-open img { width: 100%; height: auto; max-height: 46vh; }
  .shot.is-open p { -webkit-line-clamp: 4; }

  .hud { padding: 9px 11px 8px; gap: 7px; }
  .map-panel-toggle {
    position: absolute;
    top: 7px;
    right: 7px;
    z-index: 2;
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: rgba(13, 21, 18, 0.92);
    color: var(--ink);
    font: 900 1rem/1 system-ui, sans-serif;
    cursor: pointer;
  }
  .map-panel-toggle:focus-visible { outline: 2px solid var(--sun); outline-offset: 2px; }
  .readouts { grid-template-columns: repeat(4, 1fr); gap: 6px; min-height: 36px; padding-right: 48px; align-items: center; }
  .readouts dt { font-size: 0.52rem; letter-spacing: 0.06em; }
  .readouts dd { font-size: 0.86rem; }

  #profile { height: 30px; }

  .legend {
    flex-wrap: nowrap;
    overflow-x: auto;
    gap: 10px;
    font-size: 0.66rem;
    padding-bottom: 2px;
  }
  .legend span { white-space: nowrap; }
  .caveats { position: static; margin-left: 4px; }
  .caveats ul { right: 10px; bottom: 44px; }

  .hud.is-collapsed {
    padding: 8px 58px 8px 10px;
    gap: 0;
  }
  .hud.is-collapsed .readouts,
  .hud.is-collapsed #profile,
  .hud.is-collapsed .legend,
  .hud.is-collapsed .ai-note { display: none; }
  .hud.is-collapsed .controls { min-height: 42px; }
  .hud.is-collapsed .map-panel-toggle { top: 7px; }
}

@media (max-width: 420px) {
  #fence, #share, .bar .ghost[href="/kiekko"] { display: none; }
}

@media (max-width: 360px) {
  .bar-title { display: none; }
  .bar { justify-content: space-between; }
}

/* --------------------------------------------------------------- the fence */
.fence-view {
  position: fixed;
  inset: 0;
  z-index: 1500;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  place-items: center;
  gap: 10px;
  padding: 46px 12px max(14px, env(safe-area-inset-bottom));
  background: rgba(12, 20, 18, 0.985);
}

.fence-view video {
  max-width: 100%;
  max-height: 100%;
  border-radius: 8px;
  background: #101614;
}

.fence-view p {
  margin: 0;
  max-width: 44ch;
  text-align: center;
  font-size: 0.82rem;
  color: var(--dim);
}

.fence-close {
  position: absolute;
  top: max(10px, env(safe-area-inset-top));
  right: 12px;
  z-index: 2;
  font: inherit;
  font-size: 1.1rem;
  width: 38px;
  height: 38px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: rgba(238, 242, 236, 0.08);
  color: var(--ink);
  cursor: pointer;
}

/* The one-line AI disclaimer under the legend: present, not loud. */
.ai-note {
  margin: 2px 0 0;
  font-size: 0.62rem;
  color: var(--dim);
  opacity: 0.7;
}
