/* Chainage — TekSwipe Traffic. Mobile-first, light/dark. */
:root {
  color-scheme: light;
  --bg: #f1f5f9;
  --surface: #ffffff;
  --surface-2: #f8fafc;
  --surface-glass: rgba(255, 255, 255, 0.92);
  --text: #0f172a;
  --text-muted: #64748b;
  --border: #e2e8f0;
  --brand: #1d4ed8;
  --brand-2: #13b5c9;
  --accent: #f59e0b;
  --on-road: #16a34a;
  --near: #f59e0b;
  --far: #ef4444;
  --none: #64748b;
  --shadow: 0 10px 30px rgba(15, 23, 42, 0.12);
  --shadow-sm: 0 2px 8px rgba(15, 23, 42, 0.08);
  --radius: 16px;
  --radius-sm: 10px;
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-top: env(safe-area-inset-top, 0px);
}
[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0b1220;
  --surface: #111a2e;
  --surface-2: #0e1626;
  --surface-glass: rgba(17, 26, 46, 0.92);
  --text: #e8eef9;
  --text-muted: #94a3b8;
  --border: #24314d;
  --brand: #5b8def;
  --brand-2: #2dd4ef;
  --accent: #fbbf24;
  --shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
  --shadow-sm: 0 2px 10px rgba(0, 0, 0, 0.4);
}

* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
}
button { font-family: inherit; cursor: pointer; }
a { color: var(--brand); }

/* ---------- App shell ---------- */
#app { position: fixed; inset: 0; display: flex; flex-direction: column; }

header.topbar {
  display: flex; align-items: center; gap: 10px;
  padding: calc(8px + var(--safe-top)) 14px 8px;
  background: var(--surface-glass);
  backdrop-filter: saturate(160%) blur(12px);
  border-bottom: 1px solid var(--border);
  z-index: 30;
}
.brand { display: flex; align-items: center; gap: 10px; min-width: 0; color: var(--text); }
.brand-logo { display: inline-flex; flex: none; }
.brand img { width: 34px; height: 34px; border-radius: 9px; box-shadow: var(--shadow-sm); display: block; }
.brand .titles { display: flex; flex-direction: column; line-height: 1.08; min-width: 0; }
.brand .app-name { font-weight: 800; font-size: 1.12rem; letter-spacing: -0.02em; text-decoration: none; color: var(--text); }
.brand .by { font-size: 0.68rem; color: var(--text-muted); white-space: nowrap; }
.brand .by a { color: var(--brand-2); text-decoration: none; font-weight: 700; white-space: nowrap; }
.spacer { flex: 1; }
.iconbtn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 11px;
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text); box-shadow: var(--shadow-sm);
}
.iconbtn:active { transform: scale(0.95); }
.iconbtn svg { width: 20px; height: 20px; }

/* ---------- Map ---------- */
.map-wrap { position: relative; flex: 1; }
#map { position: absolute; inset: 0; background: var(--surface-2); }
/* OpenFreeMap has no dark style, so emulate a night map by inverting luminance
   (invert) then restoring hues (hue-rotate 180). Only the tile canvas is
   affected — DOM markers, controls and attribution stay upright/legible. */
[data-theme="dark"] #map canvas { filter: invert(1) hue-rotate(180deg) brightness(0.95) contrast(0.9) saturate(0.85); }
.maplibregl-ctrl-attrib { font-size: 10px; }

/* Google base map underlay: sits beneath the MapLibre canvas, which turns
   transparent (its basemap layers hidden) so only the chainage overlays and
   markers draw above Google's tiles. Display-only — all input goes to MapLibre. */
#gbase { position: absolute; inset: 0; display: none; }
body.gbase-on #gbase { display: block; }
body.gbase-on #map { background: transparent; }
/* Google draws its own (light) map — don't invert the transparent overlay canvas. */
body.gbase-on #map canvas { filter: none !important; }
/* Google's own logo/terms sit bottom-left; hide the (now wrong) OSM attribution
   and keep the zoom controls clear of Google's "Terms" strip. */
body.gbase-on .maplibregl-ctrl-bottom-left { display: none; }

/* Share-modal QR */
.share-qr { display: flex; flex-direction: column; align-items: center; gap: 6px; margin-top: 14px; }
.share-qr img {
  width: 210px; height: 210px; display: block;
  background: #fff; border: 1px solid var(--border); border-radius: 18px;
  box-shadow: var(--shadow-sm);
}
.share-qr-hint { font-size: 0.72rem; color: var(--text-muted); }

/* Base-map picker menu */
.base-menu {
  position: fixed; top: 62px; right: 10px; z-index: 60;
  display: flex; flex-direction: column; min-width: 200px; overflow: hidden;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 12px; box-shadow: var(--shadow-lg, 0 12px 30px rgba(0,0,0,.18));
}
.base-menu[hidden] { display: none; }
.bm-item {
  display: flex; align-items: baseline; gap: 8px; text-align: left;
  padding: 11px 14px; font-size: 14px; font-weight: 600; color: var(--text);
  background: none; border: 0; border-bottom: 1px solid var(--border); cursor: pointer;
}
.bm-item:last-child { border-bottom: 0; }
.bm-item .bm-sub { font-size: 11px; font-weight: 500; color: var(--muted, #6b7280); }
.bm-item.active { color: var(--brand); }
.bm-item.active::after { content: "✓"; margin-left: auto; font-weight: 700; }
.bm-item:hover { background: var(--surface-2); }

/* status pill that floats over the map after locating */
.float-status {
  position: absolute; top: 12px; left: 50%; transform: translateX(-50%);
  max-width: calc(100% - 24px);
  display: none; align-items: center; gap: 8px;
  padding: 8px 14px; border-radius: 999px;
  background: var(--surface-glass); backdrop-filter: blur(10px);
  box-shadow: var(--shadow); border: 1px solid var(--border);
  font-size: 0.86rem; font-weight: 600; z-index: 18; white-space: nowrap;
}
.float-status.show { display: inline-flex; }
.float-status.live { cursor: pointer; }
.dot { width: 10px; height: 10px; border-radius: 50%; flex: none; }
.float-status.live .dot { background: var(--on-road) !important; animation: pulse 1.6s infinite; }
@keyframes pulse {
  0% { box-shadow: 0 0 0 0 rgba(22,163,74,0.55); }
  70% { box-shadow: 0 0 0 9px rgba(22,163,74,0); }
  100% { box-shadow: 0 0 0 0 rgba(22,163,74,0); }
}

/* Big locate button */
.locate-fab {
  position: absolute; left: 50%; transform: translateX(-50%);
  bottom: calc(20px + var(--safe-bottom));
  display: inline-flex; align-items: center; gap: 10px;
  padding: 14px 22px; border: none; border-radius: 999px;
  background: linear-gradient(135deg, var(--brand-2), var(--brand));
  color: #fff; font-weight: 800; font-size: 1rem;
  box-shadow: 0 8px 24px rgba(29, 78, 216, 0.45); z-index: 20;
}
.locate-fab:active { transform: translateX(-50%) scale(0.97); }
.locate-fab svg { width: 20px; height: 20px; }
.locate-fab[disabled] { opacity: 0.7; }
/* Live tracking → green button + pulsing GPS dot before the label */
.locate-fab.tracking { background: linear-gradient(135deg, #22c55e, #059669); box-shadow: 0 8px 24px rgba(5,150,105,0.45); }
.locate-fab.tracking::before { content: ""; width: 9px; height: 9px; border-radius: 50%; background: #fff; animation: pulse-w 1.6s infinite; }
@keyframes pulse-w {
  0% { box-shadow: 0 0 0 0 rgba(255,255,255,0.7); }
  70% { box-shadow: 0 0 0 8px rgba(255,255,255,0); }
  100% { box-shadow: 0 0 0 0 rgba(255,255,255,0); }
}

.mini-fab {
  position: absolute; right: 14px; z-index: 20;
  width: 46px; height: 46px; border-radius: 14px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); box-shadow: var(--shadow);
}
.mini-fab svg { width: 22px; height: 22px; }
/* Sit above the map zoom controls (bottom-right) so they're not covered. */
.mini-fab.search { bottom: calc(108px + var(--safe-bottom)); }
body.sheet-open .locate-fab, body.sheet-open .mini-fab.search { opacity: 0; pointer-events: none; transition: opacity 0.2s; }

/* ---------- Bottom sheet (result) ---------- */
.sheet {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 25;
  background: var(--surface);
  border-radius: 22px 22px 0 0;
  box-shadow: var(--shadow);
  border-top: 1px solid var(--border);
  transform: translateY(110%);
  transition: transform 0.32s cubic-bezier(0.22, 1, 0.36, 1);
  max-height: 78%; display: flex; flex-direction: column;
  padding-bottom: var(--safe-bottom);
}
.sheet.open { transform: translateY(0); }
.sheet .grabber { width: 42px; height: 5px; border-radius: 3px; background: var(--border); margin: 10px auto 4px; flex: none; }
.sheet .sheet-body { overflow-y: auto; padding: 6px 18px 18px; }

/* Badge stacked ABOVE the title so the road name + distance never get squished. */
.result-head { position: relative; padding-right: 42px; }
.result-head #sheetClose { position: absolute; top: 0; right: 0; flex: none; }
.status-badge {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 12px; border-radius: 999px; color: #fff; font-weight: 800; font-size: 0.82rem;
  margin-bottom: 8px;
}
.result-title { font-size: 1.18rem; font-weight: 800; letter-spacing: -0.01em; margin: 0; }
.result-msg { color: var(--text-muted); font-size: 0.92rem; margin: 6px 0 0; line-height: 1.4; }

.chainage-hero {
  margin: 14px 0; padding: 16px; border-radius: var(--radius);
  background: linear-gradient(135deg, rgba(19,181,201,0.12), rgba(29,78,216,0.12));
  border: 1px solid var(--border); text-align: center;
}
.chainage-hero .label { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted); font-weight: 700; }
.chainage-hero .value-row { display: flex; align-items: center; justify-content: center; gap: 10px; margin-top: 2px; }
.chainage-hero .value { font-size: 2.2rem; font-weight: 900; letter-spacing: -0.02em; }
.chainage-hero .sub { font-size: 0.84rem; color: var(--text-muted); margin-top: 2px; }
.copy-chip {
  flex: none; width: 34px; height: 34px; border-radius: 9px; display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); background: var(--surface); color: var(--text-muted); box-shadow: var(--shadow-sm);
}
.copy-chip svg { width: 17px; height: 17px; }
.copy-chip:active { transform: scale(0.92); }
.share-url { width: 100%; padding: 11px 12px; border-radius: 10px; border: 1px solid var(--border); background: var(--surface-2); color: var(--text); font-size: 0.9rem; margin-top: 10px; }

.facts { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.fact { background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 10px 12px; }
.fact .k { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); font-weight: 700; }
.fact .v { font-size: 0.98rem; font-weight: 700; margin-top: 3px; word-break: break-word; }
.fact.wide { grid-column: 1 / -1; }
/* a fact whose value has a locatable source — tap to drop a pin there */
.fact-src { cursor: pointer; }
.fact-src:hover { border-color: #7c3aed; }
.fact-src .v { display: flex; align-items: center; gap: 6px; }
.fact-src .src-ico { color: #7c3aed; display: inline-flex; margin-left: auto; }
.fact-src .src-ico svg { width: 16px; height: 16px; }

.actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 14px; }
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 12px 14px; border-radius: 12px; font-weight: 700; font-size: 0.9rem;
  border: 1px solid var(--border); background: var(--surface-2); color: var(--text); text-decoration: none;
}
.btn.primary { background: linear-gradient(135deg, var(--brand-2), var(--brand)); color: #fff; border: none; }
.btn.wide { grid-column: 1 / -1; }
.btn svg { width: 18px; height: 18px; }
.btn:active { transform: scale(0.98); }

/* ---------- Search panel ---------- */
.panel {
  position: absolute; inset: 0; z-index: 40; display: none; flex-direction: column;
  background: var(--bg);
}
.panel.open { display: flex; }
.panel-head { display: flex; align-items: center; gap: 10px; padding: calc(10px + var(--safe-top)) 14px 10px; border-bottom: 1px solid var(--border); background: var(--surface); }
.panel-head h2 { font-size: 1.05rem; margin: 0; flex: 1; }
.search-input-wrap { display: flex; gap: 8px; padding: 12px 14px; }
.search-input-wrap input {
  flex: 1; padding: 13px 14px; border-radius: 12px; border: 1px solid var(--border);
  background: var(--surface); color: var(--text); font-size: 1rem;
}
.search-input-wrap input:focus { outline: 2px solid var(--brand); border-color: var(--brand); }
.results { overflow-y: auto; padding: 0 14px 20px; flex: 1; }
.road-item {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  padding: 14px 12px; border-radius: 12px; border: 1px solid var(--border);
  background: var(--surface); color: var(--text); margin-bottom: 8px;
}
.road-item:active { background: var(--surface-2); }
.road-item .ri-name { font-weight: 700; }
.road-item .ri-meta { font-size: 0.78rem; color: var(--text-muted); margin-top: 2px; }
.road-item .ri-go { margin-left: auto; color: var(--brand); flex: none; }
.chainage-ask { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px; margin-bottom: 12px; }
.chainage-ask label { font-size: 0.8rem; color: var(--text-muted); font-weight: 700; }
.chainage-ask .row { display: flex; gap: 8px; margin-top: 8px; }
.chainage-ask input { flex: 1; min-width: 0; padding: 12px; border-radius: 10px; border: 1px solid var(--border); background: var(--surface-2); color: var(--text); font-size: 1rem; }

/* km / m unit switch beside the chainage inputs */
.unit-toggle { display: flex; flex: none; align-self: stretch; border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }
.unit-toggle button {
  border: 0; padding: 0 12px; background: var(--surface); color: var(--text-muted);
  font-weight: 800; font-size: 0.85rem; cursor: pointer;
}
.unit-toggle button + button { border-left: 1px solid var(--border); }
.unit-toggle button.active { background: var(--brand); color: #fff; }
.hint { color: var(--text-muted); font-size: 0.78rem; padding: 8px 2px; }
.empty { text-align: center; color: var(--text-muted); padding: 40px 20px; }

/* Recent searches / pin drops (shown when the search box is empty) */
.recent-group { margin-top: 10px; }
.recent-head { display: flex; align-items: center; justify-content: space-between; padding: 6px 4px; }
.recent-head span { font-size: 0.72rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--text-muted); }
.recent-clear { background: none; border: 0; color: var(--brand); font-size: 0.78rem; font-weight: 700; cursor: pointer; padding: 4px 6px; border-radius: 8px; }
.recent-clear:active { background: var(--surface-2); }
.road-item .ri-ico { flex: none; color: var(--brand); display: inline-flex; }
.road-item .ri-ico svg { width: 20px; height: 20px; }

/* ---------- Modal (help / google embed) ---------- */
.modal-backdrop {
  position: absolute; inset: 0; z-index: 50; display: none;
  align-items: center; justify-content: center; padding: 16px;
  background: rgba(2, 6, 23, 0.55); backdrop-filter: blur(3px);
}
.modal-backdrop.open { display: flex; }
.modal {
  width: 100%; max-width: 460px; max-height: 86%; overflow-y: auto;
  background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow);
  border: 1px solid var(--border); padding: 20px;
}
.modal h3 { margin: 0 0 6px; font-size: 1.15rem; }
.modal p { color: var(--text-muted); font-size: 0.92rem; line-height: 1.5; }
.modal ol { padding-left: 20px; line-height: 1.6; font-size: 0.92rem; }
.modal .tabs { display: flex; gap: 8px; margin: 12px 0; }
.modal .tab { flex: 1; padding: 9px; border-radius: 10px; border: 1px solid var(--border); background: var(--surface-2); font-weight: 700; font-size: 0.85rem; color: var(--text); }
.modal .tab.active { background: var(--brand); color: #fff; border-color: var(--brand); }
.modal .embed-frame { width: 100%; aspect-ratio: 4 / 3; border: 0; border-radius: 12px; margin-top: 8px; background: var(--surface-2); }
.modal-close { float: right; }

/* Full-screen mode (Street View): the modal expands to the whole viewport and
   the embed stretches to fill it. Pure CSS, so it also works on iOS where the
   browser Fullscreen API is unavailable for iframes. */
.modal-backdrop.fs { padding: 0; }
.modal-backdrop.fs .modal {
  width: 100%; max-width: none; height: 100%; max-height: none;
  border-radius: 0; border: 0; display: flex; flex-direction: column; overflow: hidden;
  padding: calc(12px + var(--safe-top, 0px)) 16px 12px;
}
.modal-backdrop.fs .embed-frame { flex: 1; aspect-ratio: auto; min-height: 0; }
/* Floats don't apply to flex items — pin the close/collapse buttons top-right. */
.modal-backdrop.fs .modal { position: relative; }
.modal-backdrop.fs .modal-close { position: absolute; top: calc(10px + var(--safe-top, 0px)); right: 12px; float: none; z-index: 2; }
.modal-backdrop.fs #svFs { right: 56px; }

/* ---------- Toast ---------- */
.toast {
  position: absolute; bottom: calc(90px + var(--safe-bottom)); left: 50%; transform: translateX(-50%) translateY(20px);
  background: #0f172a; color: #fff; padding: 11px 18px; border-radius: 999px; font-size: 0.86rem; font-weight: 600;
  z-index: 60; opacity: 0; transition: all 0.25s; pointer-events: none; max-width: calc(100% - 32px); text-align: center;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ---------- speed limits ---------- */
.speed-box { margin: 4px 0 14px; }
.speed-label { font-size: 0.72rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--text-muted); margin-bottom: 8px; }
.speed-row { display: flex; gap: 16px; }
.speed-item { display: flex; flex-direction: column; align-items: center; gap: 6px; flex: 1; }
/* Australian speed-limit sign: white disc, thick red ring, bold number. */
.speed-sign {
  width: 64px; height: 64px; border-radius: 50%; background: #fff; border: 5px solid #d81e1e;
  display: flex; align-items: center; justify-content: center; box-shadow: 0 1px 3px rgba(0,0,0,.18);
}
.speed-sign .speed-num { color: #111; font-weight: 800; font-size: 1.5rem; line-height: 1; font-variant-numeric: tabular-nums; }
.speed-sign .speed-na { color: #94a3b8; font-weight: 700; font-size: 0.9rem; }
.speed-cap { font-size: 0.72rem; color: var(--text-muted); text-align: center; font-weight: 600; }
.speed-sign.clickable { cursor: pointer; transition: transform .1s; }
.speed-sign.clickable:hover { transform: scale(1.06); }
.speed-label .tap-hint { font-weight: 600; text-transform: none; letter-spacing: 0; color: #7c3aed; margin-left: 6px; }

/* ---------- spinner ---------- */
.spinner { width: 18px; height: 18px; border: 2.5px solid rgba(255,255,255,0.4); border-top-color: #fff; border-radius: 50%; animation: spin 0.7s linear infinite; }
.spinner.dark { border-color: rgba(0,0,0,0.18); border-top-color: #d81e1e; }
@keyframes spin { to { transform: rotate(360deg); } }

/* user location dot (blue) */
.user-marker { width: 18px; height: 18px; border-radius: 50%; background: #2563eb; border: 3px solid #fff; box-shadow: 0 0 0 2px rgba(37,99,235,0.4), 0 2px 6px rgba(0,0,0,0.4); }

/* chainage pin: a labelled teardrop whose tip marks the snapped road point */
.chainage-pin { display: flex; flex-direction: column; align-items: center; filter: drop-shadow(0 3px 5px rgba(0,0,0,0.45)); }
.chainage-pin .cp-label {
  background: var(--accent); color: #1f2937; font-weight: 800; font-size: 0.78rem; line-height: 1;
  padding: 6px 10px; border-radius: 999px; white-space: nowrap; border: 2px solid #fff;
}
.chainage-pin .cp-stem { width: 0; height: 0; border-left: 7px solid transparent; border-right: 7px solid transparent; border-top: 10px solid var(--accent); margin-top: -1px; }

/* marker dropped exactly where the user tapped/clicked (off-road) */
.tap-marker { width: 14px; height: 14px; border-radius: 50%; background: #475569; border: 3px solid #fff; box-shadow: 0 2px 5px rgba(0,0,0,0.45); }

/* marker for the source of a data value (speed sign / AADT point / HV segment) */
.source-marker { display: flex; flex-direction: column; align-items: center; filter: drop-shadow(0 3px 5px rgba(0,0,0,0.45)); }
.source-marker .sm-label {
  background: #7c3aed; color: #fff; font-weight: 800; font-size: 0.74rem; line-height: 1;
  padding: 6px 10px; border-radius: 999px; white-space: nowrap; border: 2px solid #fff; margin-bottom: 4px;
}
.source-marker .sm-dot { width: 14px; height: 14px; border-radius: 50%; background: #7c3aed; border: 3px solid #fff; }

/* active state for header toggle buttons (e.g. road overlay on) */
.iconbtn.active { background: var(--brand); color: #fff; border-color: var(--brand); }

/* "jump to a chainage on this road" control inside the result card */
.chainage-jump { margin-top: 14px; padding: 12px 14px; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-sm); }
.chainage-jump .cj-label { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); font-weight: 700; }
.chainage-jump .cj-row { display: flex; gap: 8px; margin-top: 8px; }
.chainage-jump input { flex: 1; min-width: 0; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--border); background: var(--surface); color: var(--text); font-size: 1rem; }
.cj-ends { display: flex; gap: 8px; margin-top: 8px; }
.cj-ends .btn { flex: 1; padding: 9px; }

.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

@media (min-width: 720px) {
  /* Result card sits as a LEFT panel so the map pin (centre/right) stays visible. */
  .sheet {
    left: 16px; right: auto; top: 76px; bottom: 16px;
    width: 380px; max-width: 40vw; max-height: none;
    border-radius: 18px; border: 1px solid var(--border);
    transform: translateX(-120%);
  }
  .sheet.open { transform: translateX(0); }
  .sheet .grabber { display: none; }
  .panel { left: auto; right: 16px; top: 70px; bottom: 16px; width: 420px; border-radius: var(--radius); border: 1px solid var(--border); overflow: hidden; }
}
