/* Colours sampled straight out of the original scan. */
:root {
  --paper: #fafbe3;   /* the map's own edge colour, so margins look intentional */
  --ink:   #393939;
  --bar:   #4d4d4d;
  --rule:  #bebebe;
  --green: #389401;
  --star:  #fda213;
  --water: #00a1d2;

  --ok:   #43d17a;
  --warn: #e8b33a;
  --bad:  #e8624a;

  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
}

/* Standalone does not include the status bar in the viewport, so the top inset
   it reports has already been applied — padding by it again double-counts.
   This is the documented pattern, not a workaround:
   https://gist.github.com/cvan/6c022ff9b14cf8840e9d28730f75fc14
   The home indicator IS a real overlap, so --safe-b stays. */
@media (display-mode: standalone) {
  :root { --safe-t: 0px; }
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  /* NOT height:100% — in iOS standalone that resolves against an initial
     containing block which excludes the status bar, giving 812pt on a 874pt
     screen while env(safe-area-inset-top) still reports 62px. vh units are
     measured against the full screen, so the page finally covers it. */
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  overscroll-behavior: none;
  touch-action: none;            /* no pinch, no double-tap zoom, no rubber-banding */
  background: var(--paper);
  color: var(--ink);
  font: 15px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  -webkit-text-size-adjust: 100%;
  -webkit-user-select: none;
  user-select: none;
}

/* The map sheet: full screen width, taller than the viewport, centred and
   clipped. Real SVG in the DOM — the browser rasterises it at native DPR. */
#stage {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  touch-action: none;
}
#stage.pannable { cursor: grab; }
#stage.pannable.dragging { cursor: grabbing; }

#backdrop {
  position: absolute;
  inset: 0;
  overflow: hidden;
}
#backdrop img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.35);          /* overscan so the blur has no soft edge */
  filter: blur(38px) saturate(1.15) brightness(1.02);
}

/* Mobile first: on a phone the sheet fills the width and overflows top and
   bottom. On a wide window that would make the map absurdly large, so it is
   also capped at the width that makes it exactly viewport-tall — i.e. it
   switches from fill-width to fit-window without a breakpoint. */
#sheet {
  position: absolute;
  left: 0;
  top: 0;
  width: min(100%, calc(100dvh * var(--sheet-aspect, 0.5554)));
  aspect-ratio: var(--sheet-aspect, 0.449);
  transform-origin: 0 0;          /* JS drives translate+scale from here */
  will-change: transform;
}
#art { position: absolute; inset: 0; }
#art svg, #art img, #art picture { display: block; width: 100%; height: 100%; }
#art img {
  -webkit-user-drag: none;      /* belt and braces with draggable="false" */
  user-select: none;
  pointer-events: none;         /* gestures belong to #stage, not the image */
}

/* position marker, placed as a percentage of the sheet */
#me { position: absolute; left: 0; top: 0; transform: translate(-50%, -50%); }
#me[hidden] { display: none; }

#dot {
  width: 18px; height: 18px;
  border-radius: 50%;
  background: #1a73e8;
  border: 2.5px solid #fff;
  box-shadow: 0 1px 5px rgba(0,0,0,.4);
}

/* Translucent accuracy halo, clamped so a good fix is still visible */
#accuracy {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  min-width: 54px; min-height: 54px;
  border-radius: 50%;
  background: rgba(26,115,232,.16);
  border: 1px solid rgba(26,115,232,.28);
  pointer-events: none;
}

/* ---------- status bar ---------- */
#status[hidden] { display: none; }

#status {
  position: fixed;
  z-index: 10;
  top: 0; left: 0; right: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: calc(var(--safe-t) + 9px) calc(var(--safe-r) + 14px) 9px calc(var(--safe-l) + 14px);
  background: rgba(24, 28, 20, .88);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  color: #f3f4ee;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

#statusText { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.dot {
  flex: none;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: #8d99a6;
  transition: background .3s;
}
.dot.ok   { background: var(--ok); box-shadow: 0 0 0 4px rgba(67, 209, 122, .18); }
.dot.warn { background: var(--warn); }
.dot.bad  { background: var(--bad); }

/* ---------- bottom bar: standing rule + legend ---------- */
/* Three columns: an empty gutter the width of the button, the pill, then the
   button. The pill is centred on the screen rather than merely left of it. */
#footbar {
  position: fixed;
  z-index: 10;
  left: calc(var(--safe-l) + 16px);
  right: calc(var(--safe-r) + 16px);
  bottom: calc(var(--safe-b) + 16px);
  display: grid;
  grid-template-columns: 40px 1fr 40px;
  gap: 8px;
  align-items: stretch;      /* one height, set once, shared by both */
  height: 40px;
}

/* One material — frosted glass — in two themes.
 *
 *   light  : things you read   (the standing rule, place tooltips)
 *   dark   : things you press  (the legend button)
 *
 * Same blur, same saturation, so they belong to one system; inverted so the
 * control never reads as a label. */
.rule, #tip, #legendBtn, #drawer {
  -webkit-backdrop-filter: blur(16px) saturate(1.5);
  backdrop-filter: blur(16px) saturate(1.5);
}

.rule, #tip, #drawer {
  background: rgba(252, 252, 246, .62);
  color: #2b3028;
}

.rule, #tip {
  border: 1px solid rgba(24, 28, 20, .10);
  box-shadow: 0 1px 10px rgba(40, 40, 25, .13);
}

.rule {
  grid-column: 2;
  justify-self: center;      /* shrink to the text, centred in the gap */
  max-width: 100%;
  min-width: 0;
  margin: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 13px;
  border-radius: 20px;
  overflow: hidden;
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: .01em;
}
.rule .nobike { stroke: #c30008; }

/* The text must be its own flex child with min-width:0, otherwise it
   overflows into the pill's padding-right and eats it. */
.rule span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

#legendBtn {
  grid-column: 3;
  aspect-ratio: 1;           /* square from the shared height, so a true circle */
  display: grid; place-items: center;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, .16);
  border-radius: 50%;
  background: rgba(22, 26, 18, .70);
  box-shadow: 0 1px 10px rgba(40, 40, 25, .22);
  color: #f6f7f1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
#legendBtn:active { background: rgba(22, 26, 18, .88); }
#footbar[hidden] { display: none; }
#legendBtn svg {
  width: 20px; height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
}
#legendBtn svg .fill { fill: currentColor; stroke: none; }

/* ---------- drawer ---------- */
#scrim {
  position: fixed;
  inset: 0;
  z-index: 20;
  background: rgba(24, 28, 20, .22);
}
#scrim[hidden] { display: none; }

#drawer {
  position: fixed;
  z-index: 30;
  left: 0; right: 0; bottom: 0;
  margin: 0 auto;
  max-width: 560px;
  max-height: 82svh;
  display: flex;
  flex-direction: column;
  border-radius: 28px 28px 0 0;   /* = close button inset (12) + its radius (16) */
  border-top: 1px solid rgba(255, 255, 255, .55);
  /* Hangs 80px below the screen edge. Rubber-banding upward would otherwise
     lift the sheet off the bottom and expose bare page behind it. */
  padding-bottom: calc(var(--safe-b) + 80px);
  margin-bottom: -80px;
  touch-action: none;             /* the sheet itself drags; the list opts back in */
  will-change: transform;
}
#drawer[hidden] { display: none; }

@media (prefers-reduced-motion: reduce) {
  #drawer, #scrim { transition: none !important; }
}

.grabber {
  width: 38px; height: 4px;
  margin: 8px auto 0;
  border-radius: 2px;
  background: rgba(24, 28, 20, .20);
  position: relative;
}
.grabber::after {                 /* invisible, but a real finger target */
  content: "";
  position: absolute;
  left: -40px; right: -40px; top: -14px; bottom: -14px;
}

.drawer-head {
  display: flex;
  align-items: center;
  padding: 4px calc(var(--safe-r) + 56px) 14px calc(var(--safe-l) + 18px);
                                /* right clears the button; bottom keeps the list
                                   off it, top centres the title on it */
}
.drawer-head h2 {
  flex: 1;
  margin: 0;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
}
/* Concentric with the drawer's corner: centre sits 28px from the top and
   right edges, which is exactly the corner radius, so the gap to the arc and
   the gap to the straight edges are both 12px. */
#drawerClose {
  position: absolute;
  top: 11px;                    /* +1px border-top = 12 from the outer edge */
  right: 12px;
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border: 0; border-radius: 50%;
  background: rgba(24, 28, 20, .07);
  color: var(--ink);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
#drawerClose:active { background: rgba(24, 28, 20, .14); }
#drawerClose svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }

.drawer-body {
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  touch-action: pan-y;           /* the one place scrolling is allowed */
  padding: 0 calc(var(--safe-r) + 14px) 18px calc(var(--safe-l) + 14px);
}

.note {
  margin: 0 0 12px;
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 11.5px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: #5c6157;
}
.nobike { width: 16px; height: 16px; flex: none; fill: none; stroke: #c30008; stroke-width: 1.6; }
.nobike .ring { stroke-width: 1.9; }

/* ---------- legend content ---------- */

.col { margin: 0; padding: 0; list-style: none; border: 1px solid rgba(24, 28, 20, .13); }

.col li {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  min-height: 32px;
  font-size: 13px;
}
.col li + li { border-top: 1px solid rgba(24, 28, 20, .10); }

.sym { flex: none; width: 60px; display: flex; align-items: center; justify-content: center; gap: 3px; }
.label { flex: 1; min-width: 0; }

.heads i { width: 8px; height: 8px; display: block; }

.line { width: 44px; height: 2.5px; display: block; }
.line.dashed { height: 0; background: none; border-top: 3px dashed var(--green); }

.dots i { width: 7px; height: 7px; border-radius: 50%; background: var(--green); display: block; }
.tris i {
  width: 0; height: 0; display: block;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-bottom: 9px solid var(--green);
}

.stars { flex: none; color: var(--star); letter-spacing: -.04em; white-space: nowrap; }
.stars::before { content: "★"; }
.stars[data-n="2"]::before { content: "★★"; }
.stars[data-n="3"]::before { content: "★★★"; }
.stars[data-n="4"]::before { content: "★★★★"; }
.stars[data-n="5"]::before { content: "★★★★★"; }

.mk { font-weight: 700; letter-spacing: .04em; }

.badge {
  position: relative;
  display: grid;
  place-items: center;
  width: 19px; height: 19px;
  border: 1.4px solid var(--ink);
  font-size: 11.5px;
  font-weight: 500;
}
.badge.round { border-radius: 50%; }
.badge.dotted::before {
  content: "";
  position: absolute;
  top: -2px; left: -1px;
  width: 4px; height: 4px;
  border-radius: 50%;
  background: var(--ink);
}

.gate {
  display: block;
  padding-bottom: 4px;
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  border-bottom: 4px double var(--ink);
}
.gate.locked { width: 20px; border-bottom-width: 5px; }

.drop { width: 15px; height: 15px; fill: var(--water); }



/* ---------- tappable places on the map ---------- */
/* No hit-box elements: taps are matched to the nearest place in JS, so
   badges that sit almost on top of each other cannot fight over the tap. */
#sheet { touch-action: none; }

#tip {
  position: absolute;
  transform-origin: 50% 100%;
  margin-top: -12px;            /* sit just above the badge */
  padding: 6px 11px;
  border-radius: 14px;
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
  pointer-events: none;
}
#tip[hidden] { display: none; }
#tip::after {                    /* little pointer down to the badge */
  content: "";
  position: absolute;
  left: 50%; bottom: -5px;
  width: 9px; height: 9px;
  margin-left: -5px;
  background: inherit;
  border-right: 1px solid rgba(24, 28, 20, .10);
  border-bottom: 1px solid rgba(24, 28, 20, .10);
  transform: rotate(45deg);
}


/* the difficulty key sits with the stars it explains, as the last row —
   laid out like the printed legend: a star in the symbol column, two lines */
.col li.key { font-size: 11px; color: #5c6157; line-height: 1.45; }
.col li.key .sym .stars { font-size: 15px; }

.hint-foot {
  margin: 12px 0 0;
  font-size: 12px;
  color: #5c6157;
}
