/* A2B hero map: a live shortcut finder on the real Melbourne CBD map. Contract: STYLE.md "Hero map component".
   Owned by the hero-map builder. The landing page sizes .hero-map (full width, a fixed height); everything inside is ours.
   Framing: the poster and the live map use the same formula, so the swap is invisible. The poster is the 1600 x 1000 m
   frame R (1 m per poster px) centred on the default trip; the scale s (px per metre) is
     s = max(cover R, min(fit the default trip with --hm-pad around it, --hm-cap))
   and hero-map.js computes exactly the same numbers for the vector map. Change one, change both. */

.hero-map {
  /* FRAME:START (tools/hero-data.mjs) */
  --hm-fw: 114; --hm-fh: 462; /* default trip box, metres */
/* FRAME:END */
  --hm-pad: 26px;          /* screen space kept clear around the default trip */
  --hm-cap: 1.6px;         /* closest zoom, px per metre */
  --hm-panel-h: 0px;       /* height of the readout strip under the map (narrow boxes only) */
  position: relative;
  overflow: hidden;
  min-height: 440px;
  container: a2b-hero / size;
  background: var(--white);
  -webkit-tap-highlight-color: transparent;
}

/* ---------- poster: shown until the live map is ready ---------- */
/* With scripting on and motion allowed, the poster starts hidden: hero-map.js ripples the map in from A if its base map
   arrives within ~300 ms of first paint, and otherwise fades the poster in (data-hm-intro="poster"). If the script never
   runs, the poster fades in by itself after 600 ms. Once shown, it is never hidden again. */
@media (scripting: enabled) and (prefers-reduced-motion: no-preference) {
  .hero-map:not([data-hm-intro]) .hero-map-poster { opacity: 0; animation: hm-poster-in var(--t-ui) var(--ease-out) 600ms forwards; }
  .hero-map[data-hm-intro="wait"] .hero-map-poster,
  .hero-map[data-hm-intro="ripple"] .hero-map-poster { opacity: 0; }
  .hero-map[data-hm-intro="poster"] .hero-map-poster { animation: hm-poster-in var(--t-ui) var(--ease-out) both; }
}
@keyframes hm-poster-in { from { opacity: 0; } to { opacity: 1; } }
.hero-map-poster {
  position: absolute; left: 0; top: 0; z-index: 0;
  width: 100%; height: 100%; max-width: none;
  object-fit: cover;
  user-select: none; -webkit-user-select: none; pointer-events: none;
}
@supports (width: 1cqw) {
  .hero-map-poster {
    --hm-mw: 100cqw;
    --hm-mh: calc(100cqh - var(--hm-panel-h));
    --hm-s: max(calc(var(--hm-mw) / 1600), calc(var(--hm-mh) / 1000),
                min(calc((var(--hm-mw) - 2 * var(--hm-pad)) / var(--hm-fw)), calc((var(--hm-mh) - 2 * var(--hm-pad)) / var(--hm-fh)), var(--hm-cap)));
    width: calc(var(--hm-s) * 1600);
    height: calc(var(--hm-s) * 1000);
    left: calc(var(--hm-mw) / 2 - var(--hm-s) * 800);
    top: calc(var(--hm-mh) / 2 - var(--hm-s) * 500);
    object-fit: fill;
  }
}

/* ---------- the live map ---------- */
.hm-stage {
  position: absolute; left: 0; top: 0; right: 0; bottom: var(--hm-panel-h); z-index: 1;
  overflow: hidden;
  touch-action: manipulation;   /* the page still scrolls and zooms over the map; a tap sets B */
  cursor: crosshair;
  user-select: none; -webkit-user-select: none;
}
.hm-base {
  position: absolute; left: 0; top: 0; max-width: none;
  pointer-events: none; user-select: none; -webkit-user-select: none;
}
.hm-svg {
  position: absolute; left: 0; top: 0; width: 100%; height: 100%; max-width: none;
  overflow: visible; pointer-events: none;
  will-change: transform;        /* its own layer: the route drawing and passages lighting up never repaint the building map */
  --u: 1;                        /* 1 / scale, set by hero-map.js, turns screen px into map units */
}

/* passages: gold when open; the hatched copy underneath shows when the gold fades out */
.hm-pass-open path { stroke: var(--gold); transition: opacity 250ms ease; }
.hm-pass-open path.is-shut { opacity: 0; }
.hm-pass-shut path { stroke: url(#hm-hatch); }
.hm-pass-open path, .hm-pass-shut path, .hm-hl path { fill: none; stroke-linecap: round; stroke-linejoin: round; }
/* the passages on the route: a wider gold band that fades in as the drawing line reaches it (Web Animations) */
.hm-hl path { stroke: var(--gold); stroke-width: calc(var(--u) * 15px); }

/* street names: map lettering */
.hm-labels text {
  font-family: var(--sans); font-size: calc(var(--u) * 11px); font-weight: 600; font-stretch: 75%;
  letter-spacing: 0.08em; fill: var(--bluestone-2);
  text-anchor: middle; dominant-baseline: central;
}
.hm-labels text.is-off { display: none; }

/* routes */
.hm-street-line { fill: none; stroke: var(--bluestone-2); stroke-width: calc(var(--u) * 2.25px); stroke-linecap: round; stroke-linejoin: round; transition: opacity var(--t-ui) var(--ease-out); }
.hm-street-line.is-off { opacity: 0; }
.hm-route-line { fill: none; stroke: var(--route); stroke-width: calc(var(--u) * 4.5px); stroke-linecap: round; stroke-linejoin: round; }
.hm-route-old { pointer-events: none; }
.hm-nudge { fill: none; stroke: var(--bluestone); stroke-width: calc(var(--u) * 2px); transition: opacity 400ms var(--ease-out); }
.hm-nudge.is-gone { opacity: 0; }

/* pins: round markers, 44px hit area, dragged with pointer capture */
.hm-pin {
  position: absolute; left: 0; top: 0; z-index: 2;
  width: 44px; height: 44px; margin: -22px 0 0 -22px;
  touch-action: none; cursor: grab;
}
.hm-pin::after {
  content: attr(data-letter);
  position: absolute; left: 9px; top: 9px; width: 26px; height: 26px; border-radius: 50%;
  background: var(--bluestone); color: var(--white); box-shadow: 0 0 0 2.5px var(--white);
  font: 800 13px/26px var(--sans); font-stretch: 112%; text-align: center;
}
.hm-pin.is-dragging { cursor: grabbing; }
/* load sequence: the pins drop in (A first, B as the ripple reaches it) */
.hm-pin.is-pre::after { opacity: 0; }
.hm-pin.is-drop::after { animation: hm-pin-drop var(--hm-pin-t, 320ms) var(--ease-spring) var(--hm-delay, 0ms) both; }
@keyframes hm-pin-drop { from { opacity: 0; transform: translateY(-14px); } to { opacity: 1; transform: none; } }

/* ---------- the race, the ghost route (motion layer over the map, under the pins) ---------- */
.hm-fx {
  position: absolute; left: 0; top: 0; width: 100%; height: 100%; max-width: none;
  overflow: visible; pointer-events: none;
  will-change: transform;          /* its own layer: trails and the ghost repaint without the big map */
  --u: 1;
}
.hm-trails { transition: opacity var(--t-ui) var(--ease-out); }
.hm-trails.is-off { opacity: 0; }
.hm-trail { fill: none; stroke-linecap: round; stroke-linejoin: round; }
/* six nested dashes ending at the walker: the overlap is strongest at the walker and fades towards the tail. The
   shortcut's trail is wider than the gold passage band (15 px) so it reads as a halo through the arcades too. */
.hm-trail-a { stroke: var(--route); stroke-width: calc(var(--u) * 22px); stroke-opacity: 0.07; }
.hm-trail-b { stroke: var(--bluestone); stroke-width: calc(var(--u) * 12px); stroke-opacity: 0.05; }
.hm-walker {
  position: absolute; left: 0; top: 0; z-index: 1;
  width: 14px; height: 14px; margin: -7px 0 0 -7px; border-radius: 50%;
  box-shadow: 0 0 0 2.5px var(--white);
  opacity: 0; pointer-events: none; will-change: transform;
  transition: opacity 150ms var(--ease-out);
}
.hm-walker.is-on { opacity: 1; }
.hm-walker-a { background: var(--route); }
.hm-walker-b { background: var(--bluestone); }
/* arrival at B: one ring per walker, scale 1 to 1.6 and fade (Web Animations, 600 ms ease-out) */
.hm-ring { position: absolute; left: 0; top: 0; z-index: 1; width: 0; height: 0; pointer-events: none; }
.hm-ring i { position: absolute; left: -16px; top: -16px; width: 32px; height: 32px; border-radius: 50%; border: 2.5px solid; opacity: 0; box-sizing: border-box; }
.hm-ring-a i { border-color: var(--route); }
.hm-ring-b i { border-color: var(--bluestone); }
/* the pointer's preview: a faint route from A to the street under the cursor (fine pointers only) */
.hm-ghost { opacity: 0; transition: opacity 120ms ease-out; }
.hm-ghost.is-on { opacity: 1; transition-duration: 80ms; }
.hm-ghost path { fill: none; stroke: var(--route); stroke-opacity: 0.45; stroke-width: calc(var(--u) * 3.5px); stroke-linecap: round; stroke-linejoin: round; }
.hm-ghost circle { fill: var(--white); stroke: var(--route); stroke-opacity: 0.8; stroke-width: calc(var(--u) * 2.5px); }
.hm-mask-line { fill: none; stroke: #FFF; stroke-width: calc(var(--u) * 14px); stroke-linecap: round; stroke-linejoin: round; }

/* ---------- readout and controls ---------- */
.hm-panel {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 3;
  display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 12px;
  grid-template-areas: "lead time" "lines lines" "try try";
  grid-template-rows: auto 1fr auto; align-items: center;
  background: var(--white); color: var(--bluestone);
  font-variant-numeric: tabular-nums;
}
.hm-lead {
  grid-area: lead; margin: 0;
  font-size: var(--fs-28); line-height: 1.1; font-weight: 750; font-stretch: var(--w-wide); letter-spacing: -0.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hm-lines { grid-area: lines; align-self: start; align-content: start; margin: 10px 0 0; padding: 0; list-style: none; display: grid; gap: 4px; }
.hm-line { display: grid; grid-template-columns: 22px minmax(0, 1fr); column-gap: 10px; align-items: start; font-size: var(--fs-16); line-height: 1.4; }
.hm-line[hidden] { display: none; }
.hm-sw { width: 22px; height: 22px; display: block; overflow: visible; }
.hm-line.is-note { grid-template-columns: minmax(0, 1fr); color: var(--bluestone-2); }
.hm-line.is-note .hm-sw { display: none; }
/* walking times are per-digit odometers: a hidden 0 holds the (tabular) width, a strip of digits rolls behind a clip */
.hm-dg { position: relative; display: inline-block; clip-path: inset(0); }
.hm-dg-0 { visibility: hidden; }
.hm-dg-s { position: absolute; left: 0; top: 0; width: 100%; display: flex; flex-direction: column; }
.hm-dg-s > span { display: block; text-align: center; }
/* the readout enters last in the intro */
.hm-panel.is-waiting .hm-lead, .hm-panel.is-waiting .hm-lines { opacity: 0; transform: translateY(6px); }
.hm-panel.is-entering .hm-lead, .hm-panel.is-entering .hm-lines { transition: opacity var(--t-panel) var(--ease-out), transform var(--t-panel) var(--ease-out); }
.hm-panel.is-entering .hm-lines { transition-delay: 70ms; }
.hm-live { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

.hm-try { grid-area: try; display: flex; min-width: 0; }
.hm-try-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.hm-select {
  appearance: none; -webkit-appearance: none;
  flex: 1 1 auto; min-width: 0; width: 100%; height: 44px; padding: 0 34px 0 12px;
  border: 1.5px solid var(--stone-line); border-radius: var(--r-control);
  background: var(--white) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%232B3038' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right 13px center;
  color: var(--bluestone); font: 600 var(--fs-16)/1 var(--sans); font-stretch: var(--w-semi);
  text-overflow: ellipsis; white-space: nowrap; cursor: pointer;
  transition: border-color var(--t-press) ease;
}
.hm-select:focus-visible { outline: none; border-color: var(--bluestone); box-shadow: 0 0 0 3px rgba(255, 79, 26, 0.28); }

.hm-time { grid-area: time; display: inline-flex; gap: 2px; padding: 3px; border-radius: var(--r-control); background: var(--stone); }
.hm-time button {
  appearance: none; -webkit-appearance: none; border: 0; margin: 0;
  min-width: 58px; height: 38px; padding: 0 11px; border-radius: 8px;
  background: transparent; color: var(--bluestone);
  font: 600 var(--fs-16)/1 var(--sans); font-stretch: var(--w-semi); font-variant-numeric: tabular-nums;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: background-color var(--t-press) ease, transform var(--t-press) var(--ease-out);
}
.hm-time button[aria-pressed="true"] { background: var(--gold); }
.hm-time button:active { transform: scale(0.97); }
.hm-time button:focus-visible { outline-offset: 1px; }

.hm-hint { grid-area: hint; margin: 12px 0 0; font-size: var(--fs-14); font-weight: 600; font-stretch: var(--w-semi); line-height: 1.35; color: var(--bluestone-2); min-height: 1.35em; }

@media (hover: hover) and (pointer: fine) {
  .hm-time button[aria-pressed="false"]:hover { background: var(--gold-wash); }
  .hm-select:hover { border-color: var(--bluestone-2); }
}

/* ---------- narrow boxes (phones, small tablets): the readout is a strip under the map ---------- */
@container a2b-hero (max-width: 1023.98px) {
  .hero-map-poster, .hm-stage, .hm-panel { --hm-panel-h: 204px; }
  .hm-panel { height: var(--hm-panel-h); padding: 12px var(--gutter) 14px; }
  .hm-lead { font-size: 20px; }
  .hm-time button { height: 34px; min-width: 54px; padding: 0 10px; font-size: 15px; }
  .hm-lines { margin-top: 8px; gap: 2px; min-height: calc(4 * 1.35 * 15px + 2px); }
  .hm-line { font-size: 15px; line-height: 1.35; column-gap: 8px; grid-template-columns: 20px minmax(0, 1fr); }
  .hm-sw { width: 20px; height: 20px; }
  .hm-hint { display: none; }
}
@container a2b-hero (max-width: 559.98px) and (max-height: 540px) {
  .hero-map-poster, .hm-stage, .hm-panel { --hm-panel-h: 196px; }
  .hm-panel { padding-top: 10px; padding-bottom: 10px; }
  .hm-lines { margin-top: 6px; }
}
@container a2b-hero (min-width: 560px) and (max-width: 1023.98px) {
  .hero-map-poster, .hm-stage, .hm-panel { --hm-panel-h: 184px; }
  .hm-try { max-width: 440px; }
  .hm-lines { min-height: calc(3 * 1.35 * 15px + 2px); }
}

/* ---------- wide boxes: the readout is a white plot cut out of the map's bottom-left corner, aligned with the page's
   left edge; the trip is centred in the map to its right (hero-map.js mirrors this with the panel's measured width) ---------- */
@container a2b-hero (min-width: 1024px) {
  .hero-map-poster, .hm-stage, .hm-panel {
    --hm-inset: max(var(--gutter), calc((100cqw - var(--max)) / 2 + var(--gutter)));
    --hm-panel-w: calc(var(--hm-inset) + 464px);
  }
  .hero-map-poster { left: min(0px, calc(var(--hm-mw) / 2 + var(--hm-panel-w) / 2 - var(--hm-s) * 800)); }
  .hm-panel {
    right: auto; width: var(--hm-panel-w);
    grid-template-areas: "lead lead" "lines lines" "try time" "hint hint";
    grid-template-rows: auto auto auto auto;
    padding: 24px 32px 20px var(--hm-inset);
  }
  .hm-lines { min-height: calc(4 * 1.4 * 16px + 4px); align-content: start; }
  .hm-try, .hm-time { margin-top: 16px; }
}

/* ---------- reduced motion: final states, no transitions ---------- */
@media (prefers-reduced-motion: reduce) {
  .hm-pass-open path { transition: none; }
  .hm-route-line { transition: none; }
  .hm-street-line { transition: none; }
  .hm-nudge { transition: none; }
  .hm-panel.is-entering .hm-lead, .hm-panel.is-entering .hm-lines { transition: none; }
  .hm-pin.is-drop::after { animation: none; }
  .hm-pin.is-pre::after { opacity: 1; }
  .hm-walker, .hm-ring, .hm-trails { display: none; }
  .hm-ghost, .hm-ghost.is-on { transition: none; }
  .hm-trails { transition: none; }
  .hm-time button { transition: none; }
  .hm-time button:active { transform: none; }
  .hm-select { transition: none; }
}
/* keyboard-initiated changes are not animated either */
.hm-instant .hm-pass-open path, .hm-instant .hm-street-line { transition: none; }

/* ---------- the opening reveal: a white "fog of war" lifting from A (one canvas; the map underneath stays still) ---------- */
.hm-fog {
  position: absolute; left: 0; top: 0; width: 100%; height: 100%;
  pointer-events: none;
  will-change: contents;
}
@media (prefers-reduced-motion: reduce) {
  .hm-fog { display: none; }
}
