/* Barlow Semi Condensed (SIL OFL), self-hosted so no third-party request.
   Drawn from highway and signage lettering, which is the point: it belongs on
   a transport tool. Used only for headings, numerals and signage chips — body
   text stays on the system stack so the payload stays ~31KB. */
@font-face { font-family:"Barlow SC"; src:url("/fonts/barlow-semi-condensed-600.woff2") format("woff2"); font-weight:600; font-style:normal; font-display:swap; }
@font-face { font-family:"Barlow SC"; src:url("/fonts/barlow-semi-condensed-700.woff2") format("woff2"); font-weight:700; font-style:normal; font-display:swap; }
:root { --font-display:"Barlow SC", "Arial Narrow", -apple-system, sans-serif; }

/* Sydney Metro M1 teal (#168388, TfNSW Open Data Hub) as the fill colour, and
   a darkened #14666a wherever it is text: the official teal is only 4.53:1 on
   white and fails outright on tinted backgrounds. Same hue, AA everywhere.
   These are wayfinding colours used to signal transport mode — this app is
   not affiliated with TfNSW and must not carry their identity. */
:root {
  color-scheme:light;
  --bg:#f6f6f0; --surface:#fff;
  --text:#223c3d; --muted:#626e65;
  --accent:#14666a; --accent-fill:#168388; --accent-tint:#e6f2f2;
  /* Two border tiers and nothing else: a hairline for dividers and card
     outlines, a slightly stronger edge for things you can click. */
  --line:#dbe5e5; --line-strong:#c9d8d8;
  /* Occupancy ramp. These are the LIGHTEST values of each hue that still
     clear 3:1 against the meter track — going brighter stops the fill being
     reliably distinguishable from the track it sits in, and the fill is the
     whole point of the meter. */
  --meter-free:#299958; --meter-tight:#be780e; --meter-full:#e25950;
  --meter-track:#e6f1f1; --meter-ring:#c9dcdc;
  --shadow-hover:0 6px 20px #223c3d14;
  /* Radius scale: pill, small (controls), medium (panels), large (cards). */
  --accessible:#2f6fed;
  /* Input outlines: 3:1 against the page and the field (WCAG 1.4.11),
     which the decorative --line-strong is not. */
  --field-border:#7a8e8c;
  --surface-2:#f3f7f7; --tint:#e2f0f0; --ink-teal:#275455; --hover-surface:#f4f9f9;
  --pill-good-bg:#e3f5e9; --pill-good-fg:#1f7a45;
  --pill-warn-bg:#fdf0dc; --pill-warn-fg:#8a5408;
  --pill-bad-bg:#fdeceb;  --pill-bad-fg:#b3261e;
  --pill-none-bg:#eef2f2; --pill-none-fg:#55666a;
  --r-pill:999px; --r-sm:6px; --r-md:10px; --r-lg:14px; }
* { box-sizing:border-box; }
body { margin:0; background:var(--surface); color:var(--text); font:15px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif; -webkit-font-smoothing:antialiased; }
a { color:var(--accent); text-decoration:none; }
@media(hover:hover) and (pointer:fine) { a:hover { text-decoration:underline; } }
button,input,select { font:inherit; color:inherit; }
button,a,summary,input,select { -webkit-tap-highlight-color:transparent; }
:focus-visible { outline:3px solid var(--accent-fill); outline-offset:4px; }
[hidden] { display:none!important; }
h1,h2,p { margin:0; }
h1 { font-size:30px; letter-spacing:-1px; font-weight:650; }
h2 { font-size:18px; font-weight:600; }
.topbar { padding:18px max(20px,calc((100vw - 1040px)/2)); border-bottom:1px solid var(--line); display:flex; align-items:center; justify-content:space-between; gap:16px; }
.brand { display:flex; align-items:center; gap:10px; color:var(--text); }
.brand-badge { display:grid; place-items:center; width:30px; height:30px; background:var(--accent-fill); color:white; border-radius:var(--r-sm); font-weight:700; }
.brand-name { font-weight:650; }
.brand-sub { display:none; }
.topbar-right { display:flex; align-items:center; gap:8px; font-size:12px; color:var(--muted); }
.live-dot { width:7px; height:7px; border-radius:50%; background:#929a95; }
.live-dot.on { background:#299451; }
.live-dot.err { background:#b65a23; }
.demo-badge,.demo-banner { color:#834814; background:#fff6e8; }
.demo-banner { padding:12px 20px; font-size:12px; }
main { max-width:1080px; padding:32px 20px 48px; margin:auto; }
.station-heading { margin-bottom:24px; }
.toolbar { display:flex; align-items:center; gap:16px; flex-wrap:wrap; margin-bottom:20px; }
.search-field { flex:1 1 240px; }
.search-field > span { position:absolute; width:1px; height:1px; clip-path:inset(50%); overflow:hidden; }
.search-field input { width:100%; min-height:44px; padding:10px 12px; border:1px solid var(--line-strong); border-radius:var(--r-sm); background:var(--surface); }
.segmented { display:flex; gap:3px; }
.seg-btn { min-height:40px; padding:8px 10px; border:0; background:transparent; border-radius:var(--r-sm); cursor:pointer; color:var(--muted); font-size:13px; }
.seg-btn.active { color:var(--accent); background:var(--accent-tint); font-weight:600; }
.sort-field { display:flex; gap:8px; align-items:center; color:var(--muted); font-size:12px; }
.sort-field select { min-height:40px; max-width:145px; border:1px solid var(--line); border-radius:var(--r-sm); padding:6px; background:var(--surface); }
.counts-note { font-size:12px; color:var(--muted); margin:14px 0; }
.station-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr)); gap:24px; }
.station-card { border:1px solid var(--line); border-radius:var(--r-md); padding:20px; }
.card-head,.lot-card-head { display:flex; justify-content:space-between; align-items:center; gap:12px; }
.card-head { margin-bottom:12px; }
.card-head h2 a { color:var(--text); }
.station-open { font-size:12px; }
.lot-rows { display:grid; }
.lot-row { display:block; padding:15px 0; color:var(--text); border-top:1px solid var(--line); }
.lot-row:last-child { padding-bottom:0; }
@media(hover:hover) and (pointer:fine) {
 .lot-row:hover { text-decoration:none; }
 .lot-row:hover .row-values > strong { color:var(--accent); text-decoration:underline; }
}
/* Status you can read before any numbers, then the count with a label that
   says what it counts, then the supporting figure underneath. */
.row-values { display:flex; justify-content:space-between; align-items:center; gap:16px; margin-bottom:12px; }
.lot-ident { display:flex; align-items:center; gap:9px; flex-wrap:wrap; min-width:0; }
.status-pill { display:inline-block; padding:4px 11px; border-radius:var(--r-pill); font-size:12.5px; font-weight:600; white-space:nowrap; }
.s-good { background:var(--pill-good-bg); color:var(--pill-good-fg); }
.s-warn { background:var(--pill-warn-bg); color:var(--pill-warn-fg); }
.s-bad { background:var(--pill-bad-bg); color:var(--pill-bad-fg); }
.s-unknown { background:var(--pill-none-bg); color:var(--pill-none-fg); }
.lot-count { text-align:right; flex:0 0 auto; line-height:1.1; }
.lot-count b { display:block; font-variant-numeric:tabular-nums; }
.lot-count span { display:block; font-size:11px; color:var(--muted); margin-top:3px; }
.lot-meta { margin-top:9px; font-size:12px; color:var(--muted); }
.lot-meta span { font-variant-numeric:tabular-nums; font-weight:600; color:var(--text); }
.row-values > strong { font-weight:600; font-size:15px; }
.row-values > span { color:var(--muted); font-size:12px; }
.row-values b { font-size:24px; font-weight:600; color:var(--text); font-variant-numeric:tabular-nums; margin-right:3px; }
.occupancy { display:flex; align-items:center; gap:12px; }
.bar { flex:1; height:14px; border-radius:var(--r-pill); background:var(--meter-track); overflow:hidden; box-shadow:inset 0 0 0 1px var(--meter-ring); }
.bar > span {
  display:block; height:100%; border-radius:inherit;
  /* --pct is how FULL the car park is, so the width and the colour come from
     the same number. The gradient is scaled to the track (10000%/--pct), not
     to the fill, so a bar at 40% shows the colour that 40% means — otherwise
     every bar would compress the whole green-to-red ramp into itself and they
     would all look identical. Stops follow the bands the labels already use:
     green while there is real room, amber past ~85% full, red at "Almost
     full" (under 10% free) through "Full". */
  width:calc(var(--pct, 0) * 1%);
  background-image:linear-gradient(90deg, var(--meter-free) 0%, var(--meter-free) 62%, var(--meter-tight) 85%, var(--meter-full) 96%, var(--meter-full) 100%);
  background-size:calc(10000% / var(--pct, 100)) 100%;
  background-position:left center; background-repeat:no-repeat;
}
.back-link { display:inline-block; font-size:13px; margin-bottom:22px; }
.lot-cards { display:grid; grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr)); gap:16px; }
.lot-card { padding:22px; border:1px solid var(--line); border-radius:var(--r-md); }
.lot-card-head h2 { font-size:20px; }
.lot-card-number { display:flex; align-items:baseline; gap:9px; margin:20px 0 22px; }
.lot-card-number strong { font-size:48px; line-height:1.1; letter-spacing:-1.5px; font-weight:600; font-variant-numeric:tabular-nums; }
.lot-card-number > span { font-size:13px; color:var(--muted); }
.lot-card-foot { display:flex; justify-content:space-between; gap:12px; margin-top:18px; font-size:12px; color:var(--muted); }
.stale-tag,.full-label { font-size:12px; color:#96430d; }
.source-panel,.map-details { border-top:1px solid var(--line); margin-top:24px; }
summary { cursor:pointer; padding:16px 0; font-size:13px; color:var(--muted); }
.source-table { display:grid; gap:18px; margin:16px 0; }
.source-row { display:flex; gap:20px; flex-wrap:wrap; border-top:1px solid var(--line); padding-top:12px; font-size:12px; }
.source-name { flex:1 1 230px; }
.source-name span,.source-cell span { display:block; color:var(--muted); }
.updated-line { margin-top:20px; font-size:12px; color:var(--muted); }
.precinct-header { display:flex; justify-content:space-between; align-items:center; gap:12px; padding:10px 0 18px; }
.map-layers { display:flex; gap:4px; }
.map-layers button { border:1px solid var(--line); border-radius:var(--r-sm); padding:8px 12px; background:var(--surface); cursor:pointer; font-size:12px; }
.map-layers button.active { background:var(--accent-tint); color:var(--accent); }
.precinct-layout { display:grid; grid-template-columns:280px minmax(0,1fr); border:1px solid var(--line); border-radius:var(--r-sm); overflow:hidden; }
.map-sidebar { padding:16px; }
.map-lot { display:flex; width:100%; align-items:center; gap:10px; text-align:left; padding:12px 8px; border:0; border-radius:var(--r-sm); background:var(--surface); cursor:pointer; }
.map-lot.selected { background:var(--accent-tint); }
.map-lot strong { font-size:12px; }
.map-lot small { display:block; font-size:11px; color:var(--muted); }
.lot-symbol { font-size:13px; font-weight:600; width:28px; flex-shrink:0; }
.map-count { margin-left:auto; font-weight:600; }
.walking-note { margin-top:20px; font-size:12px; color:var(--muted); }
.walking-note p { margin-bottom:10px; }
.map-surface iframe { display:block; border:0; width:100%; height:440px; }
.map-caption { display:flex; justify-content:space-between; gap:12px; padding:12px 0; color:var(--muted); font-size:11px; }
.footer { max-width:1040px; margin:20px auto; padding:20px; font-size:11px; color:var(--muted); border-top:1px solid var(--line); }
.footer-fine { margin-top:8px; }
.loading,.empty-state { padding:40px 0; color:var(--muted); }
/* Present for screen readers and search engines, invisible on screen. */
.visually-hidden { position:absolute; width:1px; height:1px; margin:-1px; padding:0; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0; }
.skip-link { position:fixed; top:-100px; left:16px; padding:10px; background:var(--surface); z-index:20; }
.skip-link:focus { top:12px; }
@media(max-width:640px) {
 main { padding-top:24px; }
 .lot-cards { grid-template-columns:1fr; gap:12px; }
 .lot-card { padding:18px; }
 .lot-card-number { margin:12px 0 16px; }
 .lot-card-number strong { font-size:40px; }
 .toolbar { gap:10px; }
 .search-field { flex-basis:100%; }
 .segmented { flex:1; }
 .sort-field > span { display:none; }
 .precinct-layout { grid-template-columns:1fr; }
 .precinct-header { flex-wrap:wrap; }
 .map-surface iframe { height:360px; }
}
#viz3d { display:block; width:100%; height:440px; border-radius:var(--r-sm); background:var(--surface-2); touch-action:none; user-select:none; -webkit-user-select:none; -webkit-touch-callout:none; }
.three-controls { display:flex; align-items:center; justify-content:space-between; gap:12px; color:var(--muted); font-size:12px; margin:12px 0; }
.three-controls button { background:var(--surface); border:1px solid var(--line); border-radius:var(--r-sm); padding:8px 12px; cursor:pointer; }
@media(max-width:640px) { #viz3d { height:320px; } }
/* Stamped over the 3D map itself, not in the caption, so a screenshot of the
   map carries it too. It is a beta: bay positions are traced from photos. */
.viz-wrap { position:relative; }
/* Appears once the map is turned off north; tap to turn it back. */
.viz-compass { position:absolute; top:8px; right:8px; display:grid; place-items:center; width:40px; height:40px; padding:0; border:1px solid var(--line-strong); border-radius:50%; background:var(--surface); color:var(--text); box-shadow:0 2px 8px #0002; cursor:pointer; opacity:0; pointer-events:none; transition:opacity .2s; }
.viz-compass.shown { opacity:1; pointer-events:auto; }
.viz-compass svg { width:22px; height:22px; }
@media (prefers-reduced-motion: reduce) { .viz-compass { transition:none; } }
.viz-watermark { position:absolute; top:10px; left:10px; padding:3px 8px; border-radius:var(--r-sm); background:var(--surface); color:var(--muted); font:600 .72rem/1.3 var(--font-display); letter-spacing:.06em; text-transform:uppercase; pointer-events:none; opacity:.92; }

/* A quieter palette with clear, distinct areas for choosing and comparing. */
body { background:var(--bg); }
.topbar { background:var(--surface); padding-block:20px; }
.brand-badge { width:36px; height:36px; border-radius:var(--r-md); background:var(--ink-teal); }
.brand-name { font-size:17px; letter-spacing:-.4px; }
.topbar-right { padding:6px 10px; background:var(--surface-2); border-radius:var(--r-pill); }
main { padding-top:38px; }
.station-heading { display:flex; justify-content:space-between; align-items:center; gap:20px; margin-bottom:26px; }
.page-kicker { display:block; margin-bottom:7px; font-size:11px; font-weight:650; letter-spacing:1.3px; text-transform:uppercase; color:var(--accent); }
h1 { font-size:38px; line-height:1.15; letter-spacing:-1.5px; }
.toolbar { background:var(--surface); padding:12px; border:1px solid var(--line); border-radius:var(--r-lg); gap:12px; margin-bottom:16px; }
/* The search box is the first thing on the home page and stands on its
   own: one input, no panel around it. */
.search-field { display:block; margin-bottom:16px; }
.search-field input { background:var(--surface); border:1px solid var(--field-border); border-radius:var(--r-lg); padding-left:14px; min-height:48px; font-size:16px; }
.segmented { background:var(--surface-2); padding:3px; border-radius:var(--r-md); }
.seg-btn { min-height:36px; border-radius:var(--r-sm); }
.seg-btn.active { background:var(--ink-teal); color:white; }
.sort-field select { border:0; background:var(--surface); }
.list-heading { display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:16px; }
.list-heading > span { font-size:11px; color:var(--muted); }
/* One continuous list instead of a card grid. Rows are content-height, so a
   station with one car park takes exactly the room it needs and leaves no
   hole beside a taller neighbour — and busiest-first order still reads top
   to bottom, which column-packing would have broken. */
.station-grid { grid-template-columns:1fr; gap:12px; background:transparent; border:0; border-radius:0; overflow:visible; }
.station-card { background:var(--surface); padding:0; border:1px solid var(--line); border-radius:var(--r-lg); overflow:hidden; display:grid; grid-template-columns:minmax(220px,270px) 1fr auto; align-items:center; }
.card-head { display:contents; }
.station-title { grid-column:1; grid-row:1; padding:22px 14px 22px 22px; }
.station-open { grid-column:3; grid-row:1; justify-self:end; padding:0 18px 0 10px; }
.station-title { display:flex; align-items:center; gap:10px; min-width:0; }
.station-meta { display:flex; align-items:center; flex-wrap:wrap; gap:6px 10px; margin-top:6px; }
.line-badge { display:inline-block; padding:2px 8px; border-radius:var(--r-sm); font-size:11.5px; font-weight:600; letter-spacing:.4px; }
.station-title h2 { font-size:20px; line-height:1.2; font-weight:650; letter-spacing:-.25px; }
.station-marker { display:grid; place-items:center; flex:0 0 38px; height:38px; background:var(--accent); color:var(--surface); border-radius:50%; font-size:14px; font-weight:700; letter-spacing:.3px; }
.station-open { white-space:nowrap; }
.lot-rows { grid-column:2; grid-row:1; padding:16px 0; flex:none; }
.lot-row,.lot-row:last-child { padding:14px 0; display:flex; flex-direction:column; justify-content:center; }
.lot-row:first-child { border-top:0; }
.row-values > strong { background:var(--accent-tint); border:1px solid var(--line-strong); border-radius:var(--r-sm); padding:4px 10px; font-size:13px; font-weight:650; color:var(--accent); }
.row-values b { font-size:28px; color:var(--ink-teal); }
.bar { height:14px; background:var(--meter-track); border-radius:var(--r-pill); box-shadow:inset 0 0 0 1px var(--meter-ring); }
.lot-cards { gap:20px; }
.lot-card { padding:0; background:var(--surface); border-radius:var(--r-lg); overflow:hidden;  }
.lot-card-head { background:var(--tint); padding:17px 22px; border-bottom:1px solid var(--line-strong); }
.lot-card-head h2 { margin-right:auto; display:grid; place-items:center; min-width:43px; min-height:38px; padding:3px 9px; background:var(--surface); border:1px solid var(--line-strong); border-radius:var(--r-md); font-size:19px; }
.lot-card-number { padding:0 22px; margin:25px 0; }
.lot-card-number strong { font-size:58px; font-weight:600; color:var(--ink-teal); letter-spacing:-2px; }
.lot-card .occupancy { margin:0 22px 22px; }
.lot-card-foot { padding:15px 22px; margin:0; background:var(--surface-2); border-top:1px solid var(--line); align-items:center; }
.lot-card-foot a { background:var(--tint); border-radius:var(--r-sm); padding:7px 10px; font-weight:550; }
.map-details { padding:0 20px; border:1px solid var(--line); border-radius:var(--r-md); background:var(--surface); margin-top:12px; }
.map-details > summary { padding:20px 0; font-size:14px; font-weight:600; color:var(--text); }
.source-panel { margin-top:24px; }
.back-link { margin-bottom:26px; }
.footer { border-color:var(--line); }
@media(max-width:700px) {
 .station-card { grid-template-columns:1fr auto; align-items:center; }
 .station-title { padding:14px 8px 4px 16px; }
 /* The second column exists here; column 3 would be made up on the fly,
    and the car park rows (spanning 1 / -1) would stop short of it. */
 .station-open { grid-column:2; padding-right:16px; }
 .lot-rows { grid-column:1 / -1; grid-row:2; padding:0 16px 10px; }
}
@media(max-width:640px) {
 main { padding-top:26px; }
 h1 { font-size:31px; }
 .station-heading { gap:10px; margin-bottom:22px; }
 .toolbar { gap:8px; padding:10px; }
 .seg-btn { padding-inline:9px; }
 .lot-cards { gap:14px; }
 .lot-card-head { padding:12px 18px; }
 .lot-card-number { padding:0 18px; margin:16px 0; }
 .lot-card-number strong { font-size:44px; }
 .lot-card .occupancy { margin:0 18px 16px; }
 .lot-card-foot { padding:10px 18px; }
}
.three-heading { display:flex; justify-content:space-between; align-items:center; gap:12px; padding:20px 0 0; }
.three-heading > span { color:var(--muted); font-size:12px; }
.three-panel #viz3d { height:520px; }
@media(max-width:640px) { .three-heading { align-items:flex-start; flex-direction:column; gap:4px; } .three-panel #viz3d { height:360px; } }
.favourites-area { margin-bottom:26px; padding:20px; background:var(--tint); border:1px solid var(--line-strong); border-radius:var(--r-lg); }
.favourites-area .list-heading { margin-bottom:12px; }
.favourites-hint { display:flex; align-items:center; gap:6px; margin:-4px 0 18px; color:var(--muted); font-size:13px; }
.favourites-hint .icon { width:15px; height:15px; }
/* Favourites pack like a wall of tiles: each station card keeps its own
   height instead of stretching to match its neighbour, and columns fill in
   as more are saved (one on a phone, two or three on wider screens). */
.favourites-grid { columns:var(--fav-cols, 1); column-gap:12px; margin-bottom:-12px; }
@media (max-width:900px) { .favourites-grid { columns:var(--fav-cols-mid, 1); } }
@media (max-width:640px) { .favourites-grid { columns:1; } }
/* A card with room to spare lays its car parks side by side instead of
   stretching one row across the whole width. */
.favourite-card { container-type:inline-size; }
@container (min-width:560px) {
  .fav-rows { display:grid; grid-template-columns:repeat(auto-fit, minmax(240px, 1fr)); column-gap:28px; }
  .favourite-card .fav-rows .lot-row + .lot-row { border-top:0; margin-top:0; padding-top:10px; }
}
.favourite-card { break-inside:avoid; margin-bottom:12px; background:var(--surface); padding:12px 14px; border:1px solid var(--line-strong); border-radius:var(--r-md); }

/* A compact saved car park: code, status, count and star on one line. */
/* Two classes, so it outranks the generic ".lot-row:last-child" column layout. */
.favourite-card .fav-row { display:grid; grid-template-columns:minmax(0,1fr) auto; column-gap:10px; align-items:center; padding:10px 0 0; border-top:0; }
.fav-row > .favourite-button { grid-column:2; grid-row:1; align-self:start; min-width:36px; min-height:36px; flex-basis:36px; font-size:20px; }
.fav-row > .alt-line { grid-column:1 / -1; padding-top:6px; }
.fav-line { display:flex; align-items:center; gap:8px; margin-bottom:8px; min-width:0; }
.fav-line strong { font-size:14px; font-weight:650; }
.fav-count { margin-left:auto; white-space:nowrap; line-height:1; }
.fav-count b { font-size:20px; margin-right:4px; color:var(--text); font-variant-numeric:tabular-nums; }
.fav-count span { font-size:11px; color:var(--muted); }
.fav-row .soon, .fav-row .usual { margin-top:6px; }
.favourite-station { font-weight:600; font-size:14px; }
.favourite-card .lot-row { padding-bottom:0; }
.lot-row-main { display:flex; gap:12px; align-items:center; }
.lot-row-link { flex:1; min-width:0; color:var(--text); }
@media(hover:hover) and (pointer:fine) { .lot-row-link:hover { text-decoration:none; } }
.favourite-button { display:grid; place-items:center; flex:0 0 40px; min-width:40px; min-height:40px; padding:0; border:1px solid var(--line-strong); border-radius:var(--r-md); color:#597071; background:var(--surface); font-size:24px; cursor:pointer; }
@media(hover:hover) and (pointer:fine) { .favourite-button:hover { background:var(--accent-tint); } }
.favourite-button.saved { color:#795e0d; background:#fff4cc; border-color:#ecda9c; }
.nearby-controls { display:flex; flex-wrap:wrap; gap:10px; align-items:center; margin:12px 0; }
.nearby-controls button { border:1px solid var(--line-strong); background:var(--tint); color:var(--ink-teal); padding:10px 16px; border-radius:var(--r-md); cursor:pointer; font-size:13px; font-weight:600; }
.nearby-controls button:disabled { opacity:.65; cursor:wait; }
.nearby-controls > span,.distance-label { color:var(--muted); font-size:11px; }
.preference-message { font-size:12px; color:#765315; margin:12px 0; }
.preference-message:empty { display:none; }
@media(max-width:640px) {
  .favourites-area { padding:12px; margin-bottom:18px; }
  .favourites-area .list-heading { margin-bottom:8px; }
  .favourites-area .list-heading h2 { font-size:16px; }
  .favourite-card { padding:10px 12px; }
  .favourites-grid { gap:8px; }
}
/* Rows after the first in a station's card, divided like the station list. */
.favourite-card .lot-row + .lot-row { border-top:1px solid var(--line); padding-top:8px; margin-top:8px; }
/* Motion stays attached to a user action or a changing value. */
.icon { display:inline-block; width:20px; height:20px; flex-shrink:0; vertical-align:middle; }
.brand-badge { padding:0; background:transparent; }
.search-field { position:relative; }
.search-field > .icon { position:absolute; left:13px; top:13px; width:19px; height:19px; color:var(--muted); pointer-events:none; }
.search-field input { padding-left:40px; }
.favourite-button .icon { width:22px; height:22px; }
.favourite-button.saved .icon-star { fill:currentColor; }
.list-heading h2,.three-heading h2 { display:flex; align-items:center; gap:8px; }
.back-link,.three-controls button,.nearby-controls button,.lot-card-foot a,.station-open { display:inline-flex; align-items:center; gap:6px; }
.station-open .icon,.lot-card-foot .icon { width:15px; height:15px; }
summary .icon { margin-right:7px; }
button,.lot-card-foot a,.station-open,.back-link { transition:transform 180ms cubic-bezier(.2,.8,.2,1),background-color 180ms ease,box-shadow 180ms ease; }
button:active,.lot-card-foot a:active { transform:scale(.95); }
.station-card { transition:background-color 160ms ease; }
@media(hover:hover) and (pointer:fine) { .station-card:hover { background:var(--hover-surface); } }
details[open] > .precinct-panel,details[open] > .source-table { animation:disclosure-in 240ms cubic-bezier(.16,1,.3,1); }
@keyframes disclosure-in { from { opacity:0; transform:translateY(-5px); } to { opacity:1; transform:translateY(0); } }
.favourite-button { min-width:44px; min-height:44px; flex-basis:44px; }
.seg-btn,.map-layers button,.three-controls button { min-height:44px; }
@media(max-width:640px) {
 .search-field input { font-size:16px; }
 .toolbar .segmented { flex:1 1 100%; }
 .toolbar .seg-btn { flex:1; }
 .toolbar .sort-field { width:100%; justify-content:space-between; }
 .toolbar .sort-field > span { display:block; }
 .sort-field select { min-height:44px; max-width:none; }
 .topbar { padding:14px 16px; gap:8px; }
 main { padding-inline:16px; }
 .station-title h2 { overflow-wrap:anywhere; }
 .list-heading { align-items:flex-start; }
 .list-heading > span { text-align:right; }
 .lot-card-head { flex-wrap:wrap; }
 .three-controls { align-items:flex-start; }
 .three-controls > span { max-width:55%; }
 .three-controls button { white-space:nowrap; }
}
@media(prefers-reduced-motion:reduce) {
 *,*::before,*::after { animation:none!important; transition:none!important; scroll-behavior:auto!important; }
}

/* Signage type: names, numerals and chips in the condensed face. */
h1, .station-title h2, .lot-count b, .lot-card-number strong, .brand-name,
.line-badge, .status-pill, .row-values b, .fav-count b, .map-count, .lot-symbol {
  font-family:var(--font-display);
}
h1 { letter-spacing:-.5px; }
.station-title h2 { letter-spacing:0; font-weight:700; font-size:21px; }
.lot-count b, .row-values b, .fav-count b { letter-spacing:-.5px; font-weight:700; }
.line-badge { letter-spacing:.6px; text-transform:uppercase; }

/* Night mode. This revisits the earlier light-only decision deliberately:
   the app's peak use is the 6am and evening commute, which is exactly when a
   white screen in a dark car is worst. Every pair below was measured, not
   eyeballed — dark themes fail differently from light ones, because pure
   white text on near-black is harsher than the light theme's equivalent. */
@media (prefers-color-scheme: dark) {
  :root {
    color-scheme:dark;
    --bg:#101819; --surface:#182224; --surface-2:#1e2a2c; --hover-surface:#222f31;
    --text:#e6eeed; --muted:#9db0ae; --ink-teal:#bfe4e2;
    --accent:#6fc9c5; --accent-fill:#2aa5a8; --accent-tint:#1b3336; --tint:#1b3336;
    --line:#2b3a3c; --line-strong:#3d5153; --field-border:#5f7577;
    --meter-track:#243133; --meter-ring:#35484a;
    --meter-free:#3fb977; --meter-tight:#e0a13c; --meter-full:#f0736a;
    --pill-good-bg:#16341f; --pill-good-fg:#7fd8a1;
    --pill-warn-bg:#3a2a10; --pill-warn-fg:#f0bd72;
    --pill-bad-bg:#3b1b19; --pill-bad-fg:#f5a49d;
    --pill-none-bg:#232f31; --pill-none-fg:#a9bcba;
    --shadow-hover:0 6px 20px #0008;
  }
  body { background:var(--bg); }
  .demo-badge,.demo-banner { color:#f2c88a; background:#33260f; }
  .stale-tag,.full-label { color:#f0a878; }
  .live-dot { background:#6b7a78; }
  .live-dot.on { background:#4cc47c; }
  .live-dot.err { background:#e08a52; }
  .favourite-button.saved { color:#f0d07a; background:#332c0e; border-color:#5a4d1c; }
  /* Light-mode ink colours that would sit dark-on-dark here. The active
     segment's fill turns pale in this theme, so its text must turn dark. */
  .seg-btn.active, .install-app { color:var(--bg); }
  .favourite-button { color:var(--muted); }
  .preference-message { color:#f0bd72; }
  img.brand-badge { filter:brightness(1.1); }
}

/* "Usually almost full by 7:05am on Wednesdays". Empty until the history loads,
   and for car parks without enough history, so it takes no space then. */
.usual { margin:6px 0 0; font-size:12px; color:var(--muted); }
.usual:empty, .soon:empty { display:none; }
/* Only shown when it is about to matter, in the "Almost full" pill's amber. */
.soon { margin:6px 0 0; font-size:12px; font-weight:650; color:var(--pill-warn-fg); }
.lot-card-number + .soon, .lot-card-number + .soon + .usual, .lot-card-number + .usual { margin:-16px 22px 16px; }
.lot-card-number + .soon + .usual { margin-top:-12px; }
.lot-card-number + .soon:empty + .usual { margin-top:-16px; }
@media(max-width:640px) { .lot-card-number + .soon, .lot-card-number + .soon + .usual, .lot-card-number + .usual { margin-left:18px; margin-right:18px; } }

/* "Try Kellyville North · 212 spots · 3 km", only under a car park that is
   full or almost full. */
.alt-line:empty { display:none; }
.alt { display:inline-flex; align-items:center; gap:4px; font-size:13px; font-weight:650; color:var(--accent); text-decoration:none; }
.alt:hover { text-decoration:underline; }
.alt .icon { width:14px; height:14px; }
.lot-row > .alt-line { padding:0 0 10px; }
.lot-card .alt-line { padding:0 22px 16px; margin-top:-6px; }
@media(max-width:640px) { .lot-card .alt-line { padding:0 18px 14px; } }

/* Shown only where the browser offers installing. */
.install-app { border:0; padding:4px 10px; border-radius:var(--r-pill); background:var(--accent-fill); color:#fff; font:inherit; font-weight:650; cursor:pointer; }

/* The accessible-parking sign: white on blue, as on the ground. One blue for
   both themes: 4.55:1 for the white symbol, and at least 3.57:1 against every
   card surface, light or dark. Same blue as the 3D map's accessible bays. */
.accessible-badge { display:inline-grid; place-items:center; width:20px; height:20px; margin-left:4px; border-radius:4px; background:var(--accessible); color:#fff; vertical-align:-5px; }
.accessible-badge .icon { width:15px; height:15px; stroke-width:2.3; }
.accessible-badge .icon circle { fill:currentColor; }

/* ---- Spacing rhythm -------------------------------------------------------
   One scale for the vertical rhythm of every page. The margins it replaces
   had drifted apart across older rules: 26, 22, 14, 12, 24 and 20 px between
   the sections of the station page alone.
     --gap-section  between page sections
     --gap-sibling  between cards or panels in a group, and heading to content
     --gap-caption  a small note under the thing it describes
   Declared last so it wins over the older per-element margins at every width. */
:root { --gap-section:24px; --gap-sibling:12px; --gap-caption:8px; }
@media (max-width:640px) { :root { --gap-section:16px; } }

.preference-message:empty { display:none; }

/* Home */
.search-field { margin-bottom:var(--gap-section); }
.favourites-hint { margin:calc(var(--gap-caption) - var(--gap-section)) 0 var(--gap-section); }
.favourites-area { margin-bottom:var(--gap-section); }
.favourites-area .list-heading { margin-bottom:var(--gap-sibling); }
.toolbar { margin-bottom:var(--gap-sibling); }
.nearby-controls { margin:0 0 var(--gap-section); }
.list-heading { margin-bottom:var(--gap-sibling); }
.station-grid { gap:var(--gap-sibling); }

/* Station page */
.back-link { margin-bottom:var(--gap-section); }
.station-heading { margin-bottom:var(--gap-section); }
.lot-cards { gap:var(--gap-sibling); }
.counts-note { margin:var(--gap-caption) 0 var(--gap-section); }
.map-details, .source-panel { margin-top:var(--gap-sibling); }
.updated-line { margin-top:var(--gap-section); }

/* The sort menu is a 44 px touch target; with no outline that height read
   as empty space inside the filter box. A visible field makes it a control. */
.sort-field select { min-height:40px; padding:0 10px; border:1px solid var(--field-border); border-radius:var(--r-md); background:var(--surface); color:var(--text); }
