/* ══════════════════════════════════════════════
   LONDON BUSES — v2.5 design
   Tokens → Reset → Shell → Topbar → Sidebar → Map
   → Right panel → Drawer → Footer → Mobile
══════════════════════════════════════════════ */

:root {
  /* ── Typography ── */
  --font-sans: 'Geist', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono: 'Geist Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  /* ── Type scale ── */
  --fs-xs: 11px;
  --fs-sm: 12.5px;
  --fs-md: 13px;
  --fs-lg: 15px;
  --fs-xl: 18px;
  --fs-2xl: 22px;

  /* ── Spacing scale ── */
  --sp-1: 4px;  --sp-2: 6px;  --sp-3: 10px; --sp-4: 12px;
  --sp-5: 16px; --sp-6: 20px; --sp-7: 28px; --sp-8: 40px;

  /* ── Radii ── */
  --r-sm: 4px; --r-md: 6px; --r-lg: 10px; --r-xl: 14px; --r-pill: 999px;

  /* ── Motion ── */
  --t-fast: 150ms cubic-bezier(.4,0,.2,1);

  /* ── Surfaces / palette ── */
  --bg:        #0c0e13;
  --surf:      rgba(14,16,22,0.86);
  --surf-s:    #141820;
  --surf2:     #1b1f2c;
  --surf3:     #20253a;
  --bd:        rgba(255,255,255,0.07);
  --bd2:       rgba(255,255,255,0.13);
  --tx:        #eef0f8;
  --tx2:       #b8bcce;
  --mu:        #6e7492;
  --acc:       #e8344a;
  --acc-bg:    rgba(232,52,74,0.13);
  --acc-bd:    rgba(232,52,74,0.32);
  --green:     #22c55e; --gbg: rgba(34,197,94,0.12);
  --amber:     #f59e0b; --abg: rgba(245,158,11,0.12);
  --blue:      #60a5fa; --bbg: rgba(96,165,250,0.12);
  --pill-bg:   rgba(255,255,255,0.05);
  --pill-bd:   rgba(255,255,255,0.09);
  --pill-hv:   rgba(255,255,255,0.10);
  --pill-a-bg: rgba(232,52,74,0.14);
  --pill-a-bd: rgba(232,52,74,0.34);
  --pill-a-tx: #f87185;
  --map-fallback: #0c0e13;
  --sc-th:  #1e2438;
  --sh:     0 2px 16px rgba(0,0,0,.5);
  --sh-lg:  0 8px 40px rgba(0,0,0,.6);
  --bdr: rgba(245,158,11,.18); --bdt: #fbbf24;
  --bds: rgba(96,165,250,.15); --bdst:#93c5fd;
  --bdg: rgba(34,197,94,.14);  --bdgt:#4ade80;
  --bde: rgba(232,52,74,.16);  --bdet:#f87185;
  --footer-h: 32px;
  --header-h: 50px;
}
[data-theme="light"] {
  --bg:        #f2f0eb;
  --surf:      rgba(255,255,255,0.92);
  --surf-s:    #ffffff;
  --surf2:     #f8f7f4;
  --surf3:     #edeae3;
  --bd:        rgba(0,0,0,0.07);
  --bd2:       rgba(0,0,0,0.13);
  --tx:        #111111;
  --tx2:       #454240;
  --mu:        #888380;
  --acc:       #e0201a;
  --acc-bg:    rgba(224,32,26,0.07);
  --acc-bd:    rgba(224,32,26,0.26);
  --green:     #16a34a; --gbg: rgba(22,163,74,0.09);
  --amber:     #d97706; --abg: rgba(217,119,6,0.09);
  --blue:      #2563eb; --bbg: rgba(37,99,235,0.08);
  --pill-bg:   rgba(0,0,0,0.04);
  --pill-bd:   rgba(0,0,0,0.09);
  --pill-hv:   rgba(0,0,0,0.07);
  --pill-a-bg: rgba(224,32,26,0.08);
  --pill-a-bd: rgba(224,32,26,0.28);
  --pill-a-tx: #bf1616;
  --map-fallback: #e6e2d8;
  --sc-th:  #dbd7cf;
  --sh:     0 2px 16px rgba(0,0,0,.09);
  --sh-lg:  0 8px 40px rgba(0,0,0,.13);
  --bdr: rgba(217,119,6,.12);  --bdt: #b45309;
  --bds: rgba(37,99,235,.10);  --bdst:#1d4ed8;
  --bdg: rgba(22,163,74,.10);  --bdgt:#15803d;
  --bde: rgba(224,32,26,.10);  --bdet:#b91c1c;
}

/* ── Reset ── */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html,body{height:100dvh;overflow:hidden}
body{font-family:var(--font-sans);background:var(--bg);color:var(--tx);-webkit-font-smoothing:antialiased;transition:background .3s,color .3s}
input,button{font-family:inherit;color:inherit}
button{background:none;border:none;cursor:pointer}
a{color:inherit;text-decoration:none}
:focus-visible{outline:2px solid var(--acc);outline-offset:2px;border-radius:4px}

.skip-link{position:fixed;top:-40px;left:8px;z-index:100;background:var(--acc);color:#fff;padding:6px 12px;border-radius:6px;font-size:12px;font-weight:600;transition:top .2s}
.skip-link:focus{top:8px}

.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* ── Shell ── */
.shell{
  position:relative;z-index:10;
  display:grid;
  grid-template-rows:var(--header-h) 1fr var(--footer-h);
  grid-template-columns:296px 1fr 308px;
  height:100dvh;
}

/* ══════════════════════════════════════════════ TOPBAR ══ */
.topbar{
  grid-column:1/-1;grid-row:1;
  display:flex;align-items:center;gap:10px;padding:0 16px;
  background:var(--surf);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);
  border-bottom:1px solid var(--bd);box-shadow:var(--sh);z-index:40;
  transition:background .3s,border-color .3s;
}
.tb-brand{display:flex;align-items:center;gap:8px;flex-shrink:0;margin-right:4px}
.tb-icon{width:28px;height:28px;background:var(--acc);border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:13px;color:#fff}
.tb-name{font-size:15px;font-weight:600;letter-spacing:-.3px;color:var(--tx)}
.tb-ver{font-family:var(--font-mono);font-size:9px;color:var(--mu);background:var(--surf3);padding:2px 7px;border-radius:20px}
.tb-sep{width:1px;height:18px;background:var(--bd2);flex-shrink:0}

/* (Removed .tb-alert / .alert-pip — tender pill retired from the topbar.) */
@keyframes blink{0%,100%{opacity:1}50%{opacity:.35}}

/* Wrap positions the absolute autocomplete under the search field. The
   width/margin constraints live on the wrap so the <ul> inherits the same
   column width via left:0 / right:0 without a manual offset. */
.tb-search-wrap{
  position:relative;
  flex:1;max-width:460px;min-width:180px;margin-left:auto;
}

.tb-search{
  display:flex;align-items:center;gap:8px;
  background:var(--surf2);border:1px solid var(--bd);
  border-radius:20px;padding:5px 10px 5px 15px;
  min-height:32px;
  transition:border-color .2s,box-shadow .2s,background .2s;
  cursor:text;overflow:hidden;
}
.tb-search:focus-within{border-color:var(--acc-bd);box-shadow:0 0 0 3px var(--acc-bg);background:var(--surf-s)}
.tb-search svg{color:var(--mu);flex-shrink:0}
/* min-width:0 lets the input actually shrink when the pills strip grows;
   without it the input's intrinsic size pushes the placeholder into the pills. */
.tb-search input{border:none;outline:none;background:none;font-size:13px;color:var(--tx);flex:1 1 60px;min-width:60px;width:auto}
.tb-search input::placeholder{color:var(--mu)}

.tb-actions{display:flex;align-items:center;gap:6px}
.tb-btn{display:flex;align-items:center;gap:5px;font-size:12px;font-weight:600;color:var(--tx2);padding:6px 12px;border-radius:8px;background:var(--surf2);border:1px solid var(--bd);cursor:pointer;transition:all .15s;white-space:nowrap}
.tb-btn:hover{background:var(--surf3);border-color:var(--bd2);color:var(--tx)}
.tb-btn.pri{background:var(--acc);color:#fff;border-color:transparent;box-shadow:0 2px 10px rgba(232,52,74,.28)}
.tb-btn.pri:hover{filter:brightness(1.08)}
.theme-btn{width:32px;height:32px;border-radius:8px;background:var(--surf2);border:1px solid var(--bd);display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--mu);transition:all .15s}
.theme-btn:hover{color:var(--tx);background:var(--surf3)}
.i-sun{display:block}.i-moon{display:none}
[data-theme="light"] .i-sun{display:none}
[data-theme="light"] .i-moon{display:block}

/* ══════════════════════════════════════════════ SIDEBAR ══ */
.sidebar{
  grid-row:2;grid-column:1;
  display:flex;flex-direction:column;
  background:var(--surf);backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);
  border-right:1px solid var(--bd);overflow:hidden;transition:background .3s,border-color .3s;
}
.sb-tabs{display:flex;gap:3px;padding:10px 14px 0;border-bottom:1px solid var(--bd);flex-shrink:0}
.sb-tab{font-size:12px;font-weight:500;color:var(--mu);padding:6px 12px;border-radius:8px 8px 0 0;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;transition:all .15s}
.sb-tab.on{color:var(--acc);border-bottom-color:var(--acc);background:var(--acc-bg)}

.sb-live{
  display:flex;align-items:center;justify-content:space-between;
  padding:8px 14px;border-bottom:1px solid var(--bd);
  background:var(--surf2);flex-shrink:0;
}
.sb-live-n{font-family:var(--font-mono);font-size:12px;font-weight:700;color:var(--tx)}
.sb-live-l{font-size:11px;color:var(--mu)}
.sb-live-dot{display:flex;align-items:center;gap:5px;font-size:10.5px;color:var(--mu)}
.live-pip{width:5px;height:5px;border-radius:50%;background:var(--green);flex-shrink:0;animation:blink 2.2s ease infinite}

.sb-body{flex:1;overflow-y:auto;padding:10px 14px 20px;scrollbar-width:thin;scrollbar-color:var(--sc-th) transparent}
.sb-body::-webkit-scrollbar{width:3px}
.sb-body::-webkit-scrollbar-thumb{background:var(--sc-th);border-radius:2px}

.sb-sec{border-bottom:1px solid var(--bd);padding:10px 0}
.sb-sec:first-child{padding-top:4px}
.sb-sec:last-child{border-bottom:none}
.sb-sec-hd{display:flex;align-items:center;justify-content:space-between;cursor:pointer;padding-bottom:8px;user-select:none}
.sb-sec-lbl{font-size:9.5px;font-weight:700;letter-spacing:1px;text-transform:uppercase;color:var(--mu)}
.sb-sec-r{display:flex;align-items:center;gap:8px}
.sb-sec-act{font-size:10.5px;font-weight:600;color:var(--acc);text-transform:none;letter-spacing:0;cursor:pointer}
.chev{color:var(--mu);transition:transform .22s;flex-shrink:0}
.chev.open{transform:rotate(180deg)}
.sb-sec-bd{overflow:hidden;transition:max-height .28s cubic-bezier(.22,1,.36,1),opacity .22s}
.sb-sec-bd.shut{max-height:0!important;opacity:0;pointer-events:none}

.colour-seg{display:flex;background:var(--surf2);border:1px solid var(--bd);border-radius:10px;padding:3px;gap:2px;margin-bottom:2px}
.c-btn{flex:1;text-align:center;padding:6px 0;font-size:12px;font-weight:500;color:var(--mu);border-radius:8px;cursor:pointer;transition:all .18s}
.c-btn.on{background:var(--surf3);color:var(--tx);box-shadow:0 1px 4px rgba(0,0,0,.25)}

.pill-grp{display:flex;flex-wrap:wrap;gap:6px}
.pill{font-size:12px;font-weight:500;padding:5px 12px;border-radius:20px;border:1px solid var(--pill-bd);background:var(--pill-bg);color:var(--mu);cursor:pointer;transition:background .15s,color .15s,border-color .15s,transform .1s;white-space:nowrap;user-select:none;display:flex;align-items:center;gap:5px}
.pill:hover{background:var(--pill-hv);color:var(--tx);border-color:var(--bd2)}
.pill.on{background:var(--pill-a-bg);border-color:var(--pill-a-bd);color:var(--pill-a-tx)}
.pill.tap{animation:pulse .22s ease}
@keyframes pulse{0%{transform:scale(1)}50%{transform:scale(.92)}100%{transform:scale(1)}}
.op-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0}

/* Matches the topbar .tb-search pill exactly — same border radius, padding,
   focus ring and input sizing — so the Bus Stop search, the Routes-tab
   search and the global search all read as one component. */
.sb-input{
  display:flex;align-items:center;gap:8px;
  background:var(--surf2);border:1px solid var(--bd);
  border-radius:20px;padding:5px 10px 5px 15px;
  min-height:32px;
  transition:border-color .2s,box-shadow .2s,background .2s;
  cursor:text;
}
.sb-input:focus-within{border-color:var(--acc-bd);box-shadow:0 0 0 3px var(--acc-bg);background:var(--surf-s)}
.sb-input svg{color:var(--mu);flex-shrink:0}
.sb-input input{border:none;outline:none;background:none;font-size:13px;color:var(--tx);flex:1 1 60px;min-width:60px;width:auto}
.sb-input input::placeholder{color:var(--mu)}

/* ══════════════════════════════════════════════ MAP ══ */
.map-area{grid-row:2;grid-column:2;position:relative;overflow:hidden;background:var(--map-fallback)}
#map{position:absolute;inset:0;z-index:1;background:var(--map-fallback)}
.leaflet-container{background:var(--map-fallback);font-family:inherit}

.map-col-bar{position:absolute;top:12px;left:50%;transform:translateX(-50%);z-index:20}
.map-col-toggle{
  display:flex;align-items:center;gap:10px;
  background:var(--surf);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);
  border:1px solid var(--bd2);border-radius:20px;
  padding:5px 5px 5px 14px;box-shadow:var(--sh);
}
.map-col-label{font-size:11px;font-weight:600;color:var(--mu);white-space:nowrap;letter-spacing:.2px}
.map-col-seg{display:flex;background:var(--surf2);border-radius:14px;padding:3px;gap:2px}
.map-col-opt{
  font-size:11.5px;font-weight:500;color:var(--mu);
  padding:5px 13px;border-radius:12px;cursor:pointer;
  transition:all .18s;white-space:nowrap;
}
.map-col-opt:hover{color:var(--tx)}
.map-col-opt.on{background:var(--surf-s);color:var(--tx);box-shadow:0 1px 4px rgba(0,0,0,.2)}

.map-ctl{position:absolute;top:12px;right:12px;display:flex;gap:6px;z-index:20}
.mctl{display:flex;align-items:center;gap:6px;background:var(--surf);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);border:1px solid var(--bd2);border-radius:20px;padding:7px 14px;font-size:12px;font-weight:500;color:var(--tx2);box-shadow:var(--sh);cursor:pointer;transition:all .18s;white-space:nowrap}
.mctl:hover{background:var(--surf2);color:var(--tx)}
.mctl.on{background:var(--surf2);color:var(--tx)}
.mctl.pri{background:var(--acc);color:#fff;border-color:transparent;box-shadow:0 4px 14px rgba(232,52,74,.3)}
.mctl.pri:hover{filter:brightness(1.08)}

.leaflet-control-zoom{border:none!important;box-shadow:var(--sh)!important;border-radius:10px!important;overflow:hidden;background:var(--surf)!important}
.leaflet-control-zoom a{background:transparent!important;color:var(--mu)!important;border:none!important;width:36px!important;height:36px!important;line-height:36px!important;font-size:18px!important;font-weight:400!important}
.leaflet-control-zoom a:hover{background:var(--surf2)!important;color:var(--tx)!important}
.leaflet-control-zoom a+a{border-top:1px solid var(--bd)!important}
.leaflet-control-attribution{background:var(--surf)!important;color:var(--mu)!important;font-size:10px!important;border-radius:4px 0 0 0;padding:2px 6px!important}
.leaflet-control-attribution a{color:var(--tx2)!important}

/* ══════════════════════════════════════════════ RIGHT PANEL ══ */
.rp{
  grid-row:2;grid-column:3;
  display:flex;flex-direction:column;
  background:var(--surf);backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);
  border-left:1px solid var(--bd);overflow:hidden;transition:background .3s,border-color .3s;
  position:relative;
}
.rp-head{padding:20px 20px 0;flex-shrink:0}
.rp-title{font-size:13px;font-weight:600;letter-spacing:-.2px;color:var(--tx)}
.rp-sub{font-size:11px;color:var(--mu);margin-top:2px}
/* Mirror the sidebar's tab strip 1:1 so the two panels share a single
   horizontal band — same top offset, padding, font, radius and gap. */
.rp-tabs{display:flex;gap:3px;padding:10px 14px 0;border-bottom:1px solid var(--bd);flex-shrink:0}
.rp-tab{font-size:12px;font-weight:500;color:var(--mu);padding:6px 12px;border-radius:8px 8px 0 0;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;transition:all .15s}
.rp-tab.on{color:var(--acc);border-bottom-color:var(--acc);background:var(--acc-bg)}
.rp-body{flex:1;overflow-y:auto;padding:20px 20px 16px;scrollbar-width:thin;scrollbar-color:var(--sc-th) transparent}
.rp-body::-webkit-scrollbar{width:3px}
.rp-body::-webkit-scrollbar-thumb{background:var(--sc-th);border-radius:2px}

.hero-stats{display:flex;flex-direction:column;gap:12px;margin-bottom:24px}
.hero-stat{
  display:flex;align-items:center;justify-content:space-between;
  background:var(--surf2);border:1px solid var(--bd);border-radius:14px;
  padding:14px 16px;
}
.hero-stat-n{font-family:var(--font-mono);font-size:26px;font-weight:700;color:var(--tx);line-height:1;letter-spacing:-.5px}
.hero-stat-l{font-size:11px;color:var(--mu);margin-top:4px}
.hero-stat-d{font-size:10px;font-weight:700;padding:3px 9px;border-radius:20px;display:inline-flex;align-items:center;gap:4px;margin-top:6px}
.d-up{background:var(--gbg);color:var(--green)}
.d-dn{background:var(--bde);color:var(--bdet)}
.d-n {background:var(--abg);color:var(--amber)}
/* (Removed .hero-mini-bars / .hmb-* — sparkline superseded by the Fleet Mix block.) */

.callout{
  display:flex;align-items:flex-start;gap:11px;
  background:var(--bdr);border:1px solid rgba(245,158,11,.22);
  border-radius:14px;padding:14px 16px;margin-bottom:24px;
}
.callout-icon{font-size:20px;flex-shrink:0;line-height:1;margin-top:1px}
.callout-title{font-size:13px;font-weight:700;color:var(--bdt);margin-bottom:4px}
.callout-body{font-size:11.5px;color:var(--tx2);line-height:1.6}
.callout-body strong{color:var(--bdt)}

.slbl{font-size:9px;font-weight:700;letter-spacing:1.1px;text-transform:uppercase;color:var(--mu);margin:0 0 12px}

.op-cards{display:flex;flex-direction:column;gap:8px}
.op-card{
  display:flex;align-items:center;gap:12px;
  background:var(--surf2);border:1px solid var(--bd);border-radius:12px;
  padding:12px 14px;cursor:pointer;
  transition:border-color .18s,background .15s,box-shadow .18s;
}
.op-card:hover{border-color:var(--bd2);background:var(--surf3);box-shadow:var(--sh)}
.op-card-swatch{width:4px;border-radius:3px;align-self:stretch;flex-shrink:0;min-height:32px}
.op-card-main{flex:1;min-width:0}
.op-card-name{font-size:12.5px;font-weight:600;color:var(--tx)}
.op-card-sub{font-size:10.5px;color:var(--mu);margin-top:2px}
.op-card-stats{display:flex;gap:10px;flex-shrink:0;align-items:center}
.op-stat{text-align:center}
.op-stat-n{font-family:var(--font-mono);font-size:13px;font-weight:700;color:var(--tx);line-height:1;display:block}
.op-stat-l{font-size:9px;color:var(--mu);margin-top:2px}
.op-card-arrow{color:var(--mu);flex-shrink:0;opacity:.5;transition:opacity .15s,transform .15s}
.op-card:hover .op-card-arrow{opacity:1;transform:translateX(2px)}

.bdg{font-size:9.5px;font-weight:700;padding:2px 7px;border-radius:20px;display:inline-block;white-space:nowrap}
.b-amber{background:var(--bdr);color:var(--bdt)}
.b-blue {background:var(--bds);color:var(--bdst)}
.b-green{background:var(--bdg);color:var(--bdgt)}
.b-red  {background:var(--bde);color:var(--bdet)}

.bar-row{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.bar-lbl{font-size:11.5px;color:var(--tx2);width:84px;flex-shrink:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bar-track{flex:1;height:5px;background:var(--surf3);border-radius:3px;overflow:hidden}
.bar-fill{height:100%;border-radius:3px;transition:width .7s cubic-bezier(.22,1,.36,1)}
.bar-pct{font-family:var(--font-mono);font-size:11px;color:var(--mu);width:28px;text-align:right;flex-shrink:0}

/* Route card — tightened for less visual noise. Reduced type sizes, flatter
   KPI tiles (no border, subtle surface), compact tender rows. The goal is a
   calm "data card" where the route number is the only thing that shouts. */
.route-card{background:var(--surf2);border:1px solid var(--bd);border-radius:12px;padding:14px;margin-bottom:10px;transition:border-color .18s,box-shadow .18s;cursor:pointer}
.route-card:hover{border-color:var(--bd2);box-shadow:var(--sh)}
.rc-top{display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:10px;gap:10px}
.rc-num{font-family:var(--font-mono);font-size:18px;font-weight:700;color:var(--tx);line-height:1;letter-spacing:-.2px}
.rc-name{font-size:11.5px;color:var(--mu);margin-top:3px;line-height:1.35}
.rc-op{
  font-size:9.5px;font-weight:600;padding:2px 8px;border-radius:var(--r-pill);
  color:#fff;white-space:nowrap;flex-shrink:0;align-self:flex-start;
  letter-spacing:.2px;line-height:1.4;
}
/* Route number + type chip on the same line. The chip sits next to the
   route number rather than the operator pill so it visually belongs to the
   route's identity (which it describes), not to the contractor relationship. */
.rc-num-row{display:flex;align-items:center;gap:8px;line-height:1}
.rc-type-chip{
  font-size:9px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;
  color:var(--mu);background:var(--surf-s);border:1px solid var(--bd);
  padding:2px 6px;border-radius:var(--r-pill);line-height:1.2;white-space:nowrap;
}
.rc-type-chip[hidden]{display:none}

/* KPI grid — single row of 4 KPI tiles for the headline route facts
   (PVR · Stops · Freq · EWT/OTP). Lives inside the Route section now,
   so margin-bottom is small — the section already provides bottom spacing.
   .rc-kpis--five extends to 5 columns when the MPS tile is added — same
   tile metrics, just narrower. */
.rc-kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:4px;margin-bottom:5px}
.rc-kpis--five{grid-template-columns:repeat(5,1fr)}
.rc-kpi{background:var(--surf-s);border:none;border-radius:var(--r-md);padding:7px 9px}
.rc-kpi-l{font-size:9px;font-weight:600;letter-spacing:.6px;text-transform:uppercase;color:var(--mu);margin-bottom:2px}
.rc-kpi-v{font-family:var(--font-mono);font-size:12px;font-weight:700;color:var(--tx);line-height:1.2}

/* Section grouping inside the route card — Route / Fleet / Tender.
   Reuses the modal-section "tag" treatment so the visual vocabulary is
   consistent with the About/Roadmap dialogs. */
.rc-section{display:flex;flex-direction:column;gap:5px;margin-bottom:8px}
.rc-section:last-child{margin-bottom:0}
.rc-section-tag{
  font-size:9px;font-weight:700;letter-spacing:.8px;text-transform:uppercase;
  color:var(--mu);padding:0 2px;
}

/* Detail panel: flat surface, tight rows. */
.rc-tender{background:var(--surf-s);border:none;border-radius:var(--r-md);padding:10px 12px;display:flex;flex-direction:column;gap:4px}
.rc-tr{display:flex;justify-content:space-between;align-items:baseline;font-size:11.5px;gap:10px;padding:3px 0}
.rc-tr + .rc-tr{border-top:1px solid var(--bd)}
.rc-tr-l{color:var(--mu)}
.rc-tr-v{font-weight:500;color:var(--tx);display:inline-flex;align-items:center;gap:6px;text-align:right}
/* "(no change)" / "first award" placeholder vocabulary — quieter than the
   real data values, distinct from the bare "—" we use for missing data. */
.rc-tr-v.rc-tr-v--muted{color:var(--mu);font-style:italic;font-weight:400}
/* Small badge next to the Next-contract operator name when the awarded
   operator differs from the current incumbent at the top of the card. */
.rc-op-change{
  display:inline-block; padding:1px 6px; border-radius:8px;
  font-size:9.5px; font-weight:700; letter-spacing:.6px; text-transform:uppercase;
  background:var(--amber-bg, rgba(217,119,6,.18));
  color:var(--amber-tx, #c2810c);
  border:1px solid var(--amber-bd, rgba(217,119,6,.45));
}

/* Tooltip-available labels — a faint dashed underline (standard "more
   info on hover" convention) signals availability without taking up any
   horizontal space the way a glyph would. text-underline-offset keeps
   the dashes off the label baseline so they don't compete with the text.
   The actual popup is rendered by js/tooltip.js (see .app-tooltip below). */
.rc-tr-l[data-tip], .rc-kpi-l[data-tip]{
  cursor:help;
  text-decoration:underline dashed;
  text-decoration-color:color-mix(in srgb, currentColor 35%, transparent);
  text-decoration-thickness:1px;
  text-underline-offset:3px;
}

/* Custom hover tooltip — a single shared element controlled by
   js/tooltip.js. Positioned via inline style by the JS; this rule
   defines look + the open/close transition. position:fixed so the tip
   floats above any overflow:hidden parent. */
.app-tooltip{
  position:fixed;z-index:9999;
  display:none;max-width:280px;
  background:var(--surf2);color:var(--tx);
  border:1px solid var(--bd);
  border-radius:var(--r-md);
  padding:8px 10px;
  font-family:var(--font-sans);font-size:11.5px;line-height:1.45;font-weight:400;
  letter-spacing:0;text-transform:none;
  box-shadow:0 4px 16px rgba(0,0,0,.32);
  pointer-events:none;
  opacity:0;transition:opacity .12s ease-out;
}
.app-tooltip.is-visible{opacity:1}
/* Small triangle pointing at the anchor — sits below the bubble by
   default (because the bubble is above the target) and flips above the
   bubble when --below is applied (target near the top of the viewport). */
.app-tooltip::after{
  content:"";position:absolute;left:50%;transform:translateX(-50%);
  width:0;height:0;border:5px solid transparent;
  border-top-color:var(--bd);
  bottom:-10px;
}
.app-tooltip--below::after{
  border-top-color:transparent;border-bottom-color:var(--bd);
  top:-10px;bottom:auto;
}

.route-search-prompt{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  padding:48px 24px;text-align:center;color:var(--mu);
}
.route-search-prompt svg{margin-bottom:14px;opacity:.3}
.route-search-prompt p{font-size:13px;line-height:1.7}

/* ── Filtered-routes list (Routes tab, when sidebar filters are active) ── */
.rfl-head{
  font-size:11px;font-weight:600;color:var(--mu);margin-bottom:10px;
  padding-bottom:8px;border-bottom:1px solid var(--bd);
}
.rfl-head .rfl-count{font-weight:700;color:var(--tx)}
.rfl-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px}
.rfl-item{
  display:flex;align-items:center;gap:10px;width:100%;
  padding:7px 8px;border-radius:8px;cursor:pointer;text-align:left;
  background:none;border:none;color:var(--tx);transition:background .12s;
}
.rfl-item:hover{background:var(--surf2)}
.rfl-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
.rfl-id{font-family:var(--font-mono);font-weight:700;font-size:13px;min-width:42px}
.rfl-dest{
  color:var(--mu);font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;
}
.rfl-empty{color:var(--mu);font-size:13px;padding:8px;text-align:center;list-style:none}

/* ── Drawer ── */
.drawer{
  position:absolute;inset:0;z-index:30;
  display:flex;flex-direction:column;
  background:var(--surf);backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);
  transform:translateX(100%);
  transition:transform .32s cubic-bezier(.22,1,.36,1);
  overflow:hidden;
}
.drawer.open{transform:translateX(0)}
.drawer-head{display:flex;align-items:center;gap:10px;padding:16px 20px;border-bottom:1px solid var(--bd);flex-shrink:0}
.drawer-back{width:30px;height:30px;border-radius:8px;background:var(--surf2);border:1px solid var(--bd);display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--mu);flex-shrink:0;transition:all .15s}
.drawer-back:hover{background:var(--surf3);color:var(--tx)}
.drawer-head-swatch{width:4px;border-radius:3px;align-self:stretch;flex-shrink:0}
.drawer-head-name{font-size:14px;font-weight:600;color:var(--tx)}
.drawer-head-sub{font-size:11px;color:var(--mu);margin-top:2px}
.drawer-body{flex:1;overflow-y:auto;padding:20px;scrollbar-width:thin;scrollbar-color:var(--sc-th) transparent}
.drawer-body::-webkit-scrollbar{width:3px}
.drawer-body::-webkit-scrollbar-thumb{background:var(--sc-th);border-radius:2px}

.drawer-kpi-pair{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:20px}
.dkpi{background:var(--surf2);border:1px solid var(--bd);border-radius:12px;padding:14px}
.dkpi-n{font-family:var(--font-mono);font-size:22px;font-weight:700;color:var(--tx);line-height:1}
.dkpi-l{font-size:10px;color:var(--mu);margin-top:5px}
.dkpi-d{display:inline-block;font-size:9.5px;font-weight:700;padding:2px 7px;border-radius:20px;margin-top:7px}

.dsec{margin-bottom:20px}
.dsec-lbl{font-size:9px;font-weight:700;letter-spacing:1.1px;text-transform:uppercase;color:var(--mu);margin-bottom:10px}

.garage-list{display:flex;flex-direction:column;gap:6px}
.garage-item{display:flex;align-items:center;justify-content:space-between;background:var(--surf2);border:1px solid var(--bd);border-radius:10px;padding:10px 12px;font-size:12px}
.garage-name{font-weight:500;color:var(--tx)}
.garage-count{font-family:var(--font-mono);font-size:11px;color:var(--mu)}

/* ══════════════════════════════════════════════ FOOTER ══ */
.footer{
  grid-column:1/-1;grid-row:3;
  display:flex;align-items:center;justify-content:space-between;
  padding:0 16px;
  background:var(--surf);border-top:1px solid var(--bd);
  font-size:10.5px;color:var(--mu);
  transition:background .3s,border-color .3s;
  z-index:30;
}
.footer-left{display:flex;align-items:center;gap:10px;min-width:0}
.footer-live{
  display:inline-flex;align-items:center;gap:6px;
  padding:0 8px;border-radius:999px;
  background:var(--surf2);border:1px solid var(--bd);
  font-family:var(--font-mono);font-size:10.5px;color:var(--tx2);
  letter-spacing:.2px;white-space:nowrap;flex-shrink:0;
}
.footer-live .live-pip{width:5px;height:5px;border-radius:50%;background:var(--green);animation:blink 2.2s ease infinite;flex-shrink:0}
.footer-links{display:flex;gap:14px}
.footer-link{color:var(--mu);cursor:pointer;transition:color .15s;background:none;border:none;font-size:inherit;font-family:inherit;padding:0}
.footer-link:hover{color:var(--tx)}

/* ══════════════════════════════════════════════ MOBILE ══ */
.mob-top,.mob-sheet,.mob-nav{display:none}

@media(max-width:900px){
  .rp{display:none}
  .shell{grid-template-columns:280px 1fr}
}
/* Legacy 620px mobile block removed — the consolidated "MOBILE RESPONSIVE
   PASS" block further down the file (max-width:760px) is the single source
   of truth. See its comment header for the layout + HUD reshuffle. */

/* ══════════════════════════════════════════════ LEAFLET POPUPS + MARKERS ══ */

.leaflet-popup-content-wrapper{
  background:var(--surf-s);color:var(--tx);
  border:1px solid var(--bd2);border-radius:12px;
  box-shadow:var(--sh-lg);padding:2px;
}
.leaflet-popup-content{margin:12px 14px;font-size:12.5px;line-height:1.5;min-width:220px;max-width:280px}
.leaflet-popup-tip{background:var(--surf-s);border:1px solid var(--bd2)}
.leaflet-popup-close-button{color:var(--mu)!important}

/* Identify popup — "routes here" chip grid */
.map-id-popup__label{
  font-size:9.5px;font-weight:700;letter-spacing:1px;text-transform:uppercase;
  color:var(--mu);margin-bottom:8px;
}
.map-id-popup__chips,.map-popup__route-chips,.map-popup__routes{
  display:flex;flex-wrap:wrap;gap:4px;margin-top:8px;
  max-height:168px;overflow-y:auto;
  scrollbar-width:thin;scrollbar-color:var(--sc-th) transparent;
  padding-right:2px; /* so hover/focus ring isn't clipped by overflow */
}
.map-id-popup__chips::-webkit-scrollbar,
.map-popup__route-chips::-webkit-scrollbar,
.map-popup__routes::-webkit-scrollbar{width:3px}
.map-id-popup__chips::-webkit-scrollbar-thumb,
.map-popup__route-chips::-webkit-scrollbar-thumb,
.map-popup__routes::-webkit-scrollbar-thumb{background:var(--sc-th);border-radius:2px}

.map-id-popup__chip,.map-popup__route-chip{
  display:inline-block;padding:2px 7px;border-radius:20px;
  font-family:var(--font-mono);font-size:10.5px;font-weight:700;line-height:1.3;
  color:#fff;background:var(--chip-col,#475569);cursor:pointer;
  border:1px solid transparent;transition:filter .12s,transform .08s;
}
.map-id-popup__chip:hover,.map-popup__route-chip:hover{filter:brightness(1.1);transform:translateY(-1px)}

/* Stop popup — name, towards, ID, routes */
.map-popup__name{
  display:block;font-size:13px;font-weight:600;color:var(--tx);
  padding-bottom:8px;border-bottom:1px solid var(--bd);margin-bottom:8px;
}
.map-popup__id{display:block;font-family:var(--font-mono);font-size:11px;color:var(--mu);margin-top:2px}

.map-popup__meta{font-size:12px;padding-bottom:8px;border-bottom:1px solid var(--bd);margin-bottom:8px}
.map-popup__meta div{display:flex;justify-content:space-between;gap:12px;padding:4px 0}
.map-popup__meta div+div{border-top:1px solid var(--bd)}
.map-popup__meta dt{color:var(--mu)}
.map-popup__meta dd{color:var(--tx);font-weight:600}

/* Chip grid sits under a section header inside the garage popup. */
.map-popup__routes-hd{
  display:block;font-size:9.5px;font-weight:700;letter-spacing:1px;
  text-transform:uppercase;color:var(--mu);margin-bottom:4px;
}

/* "View all routes operated here" CTA inside the garage popup — mirrors
   the drawer's #dShowRoutes (.d-cta-full) so the two entry points feel
   identical. Sits below the route chips. */
.map-popup__cta{
  display:flex;align-items:center;justify-content:center;gap:6px;
  width:100%;margin-top:10px;padding:9px 12px;
  font-family:inherit;font-size:12px;font-weight:600;
  color:var(--acc);background:transparent;
  border:1px solid var(--bd);border-radius:8px;
  cursor:pointer;transition:background .15s, border-color .15s;
}
.map-popup__cta:hover{background:var(--acc-bg);border-color:var(--acc)}
.map-popup__cta:active{transform:scale(.98)}
.map-popup__cta svg{opacity:.75;transition:transform .15s}
.map-popup__cta:hover svg{transform:translateX(2px);opacity:1}

/* Garage pin */
.garage-marker{background:none!important;border:none!important}
/* Garage marker — port of the original farhan.app/london-buses design.
   A rounded 32×32 square in the operator's brand colour, 2px white border,
   DM Sans 11 / 700 operator code centred inside. */
.garage-marker-pin{
  position:relative;
  width:32px;height:32px;
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--garage-col,hsl(240 10% 12%));
  color:#fff;
  border:2px solid #fff;
  border-radius:6px;
  box-shadow:0 2px 6px hsl(240 10% 3.9% / .35);
  cursor:pointer;
  transition:transform 150ms cubic-bezier(.4,0,.2,1), box-shadow 150ms cubic-bezier(.4,0,.2,1);
}
.garage-marker-pin:hover{
  transform:scale(1.12);
  box-shadow:0 3px 10px hsl(240 10% 3.9% / .45);
}
.garage-marker-op{
  font-family:var(--font-sans);
  font-size:11px;font-weight:700;letter-spacing:.02em;line-height:1;
}
[data-theme="dark"] .garage-marker-pin{border-color:hsl(240 6% 20%)}

@media (max-width:640px){
  .garage-marker-pin{width:28px;height:28px}
  .garage-marker-op{font-size:10px}
}

/* Multi-route end label */
.route-end-label{
  display:inline-block;padding:2px 7px;border-radius:5px;
  background:var(--label-col,#111);color:#fff;
  font-family:var(--font-mono);font-size:10.5px;font-weight:700;
  box-shadow:0 1px 4px rgba(0,0,0,.4);
  transform:translate(-50%,-50%);white-space:nowrap;
}

.garage-route-tooltip{
  background:var(--surf-s)!important;color:var(--tx)!important;
  border:1px solid var(--bd2)!important;border-radius:6px!important;
  box-shadow:var(--sh)!important;font-size:10.5px;font-weight:600;padding:3px 8px;
}
.garage-route-tooltip::before{border-top-color:var(--bd2)!important}

/* ══════════════════════════════════════════════ SEARCH PILLS + AUTOCOMPLETE ══ */

.search-pills{
  display:flex;gap:4px;align-items:center;
  flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;
  max-width:60%;scrollbar-width:none;
}
.search-pills::-webkit-scrollbar{display:none}
.search-pill{
  display:inline-flex;align-items:center;gap:4px;flex-shrink:0;
  background:var(--pill-a-bg);border:1px solid var(--pill-a-bd);color:var(--pill-a-tx);
  border-radius:14px;padding:1px 3px 1px 8px;
  font-family:var(--font-mono);font-size:10.5px;font-weight:700;line-height:1.4;
}
.search-pill-x{
  width:14px;height:14px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  color:inherit;opacity:.75;transition:opacity .12s,background .12s;
}
.search-pill-x:hover{opacity:1;background:rgba(255,255,255,.1)}

.tb-search-x,.sb-input-x{
  width:18px;height:18px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  color:var(--mu);transition:color .12s,background .12s;flex-shrink:0;
}
.tb-search-x:hover,.sb-input-x:hover{color:var(--tx);background:var(--pill-hv)}

.tb-autocomplete,.sb-autocomplete{
  position:absolute;z-index:45;
  background:var(--surf-s);border:1px solid var(--bd2);border-radius:10px;
  box-shadow:var(--sh-lg);padding:4px;margin:0;list-style:none;
  max-height:260px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--sc-th) transparent;
}
.tb-autocomplete{top:calc(100% + 6px);left:0;right:0;width:auto}
.sb-autocomplete{position:static;margin-top:6px;width:100%;max-height:180px}
.tb-autocomplete li,.sb-autocomplete li{
  display:flex;align-items:center;justify-content:space-between;gap:8px;
  padding:6px 10px;border-radius:7px;cursor:pointer;font-size:12.5px;color:var(--tx);
}
.tb-autocomplete li:hover,.tb-autocomplete li[aria-selected="true"],
.sb-autocomplete li:hover,.sb-autocomplete li[aria-selected="true"]{background:var(--surf2)}
.ac-id{font-family:var(--font-mono);font-weight:700}
.ac-id mark{background:var(--acc-bg);color:var(--acc);padding:0 1px;border-radius:3px}
.ac-dest{color:var(--mu);font-size:11px;text-align:right;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* Garage filter — custom multi-select dropdown (operators as group labels). */
.sb-ms{position:relative}
.sb-ms-btn{
  width:100%;min-height:32px;display:flex;align-items:center;justify-content:space-between;gap:8px;
  background:var(--surf2);border:1px solid var(--bd);border-radius:20px;
  padding:6px 12px 6px 14px;font-size:13px;font-family:inherit;color:var(--tx);cursor:pointer;text-align:left;
  transition:border-color .2s,box-shadow .2s,background .2s;
}
.sb-ms-btn:hover{border-color:var(--bd2)}
.sb-ms-btn[aria-expanded="true"]{border-color:var(--acc-bd);box-shadow:0 0 0 3px var(--acc-bg);background:var(--surf-s)}
.sb-ms-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.sb-ms-label--placeholder{color:var(--mu)}
.sb-ms-chev{flex-shrink:0;color:var(--mu);transition:transform .2s}
.sb-ms-btn[aria-expanded="true"] .sb-ms-chev{transform:rotate(180deg)}

.sb-ms-chips{display:flex;flex-wrap:wrap;gap:5px;margin-top:8px}
.sb-ms-chip{
  display:inline-flex;align-items:center;gap:5px;max-width:100%;
  background:var(--pill-a-bg);border:1px solid var(--pill-a-bd);color:var(--pill-a-tx);
  border-radius:13px;padding:3px 5px 3px 9px;font-size:11px;font-weight:600;
}
.sb-ms-chip .op-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0}

/* Route-type filter pills carry the same colour dots as the operator pills,
   but only show them when the user is colouring routes by type — otherwise
   the dot is meaningless noise. paint-mode.js flips `html.paint-by-type`. */
.pill[data-filter="routetype"] .op-dot{display:none}
html.paint-by-type .pill[data-filter="routetype"] .op-dot{display:inline-block}

.sb-ms-chip-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.sb-ms-chip-x{
  width:15px;height:15px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  color:inherit;opacity:.8;flex-shrink:0;cursor:pointer;
}
.sb-ms-chip-x:hover{opacity:1;background:rgba(255,255,255,.12)}

.sb-ms-panel{
  margin-top:8px;max-height:200px;overflow-y:auto;
  background:var(--surf-s);border:1px solid var(--bd2);border-radius:10px;padding:4px;
  scrollbar-width:thin;scrollbar-color:var(--sc-th) transparent;
}
.sb-ms-panel::-webkit-scrollbar{width:3px}
.sb-ms-panel::-webkit-scrollbar-thumb{background:var(--sc-th);border-radius:2px}
.sb-ms-group{padding:7px 8px 3px;font-size:9.5px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--mu)}
.sb-ms-opt{display:flex;align-items:center;gap:8px;padding:5px 8px;border-radius:7px;cursor:pointer;font-size:12.5px;color:var(--tx)}
.sb-ms-opt:hover{background:var(--surf2)}
.sb-ms-opt input{accent-color:var(--acc);cursor:pointer;flex-shrink:0;margin:0}
.sb-ms-opt-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

.sb-selected-pill{
  display:inline-flex;align-items:center;gap:6px;margin-top:8px;
  background:var(--pill-a-bg);border:1px solid var(--pill-a-bd);color:var(--pill-a-tx);
  border-radius:14px;padding:3px 5px 3px 10px;font-size:11.5px;font-weight:600;max-width:100%;
}
/* `hidden` attribute loses against any explicit display on the element —
   force it back. Belt-and-braces so the whole codebase stays consistent. */
[hidden]{display:none!important}
.sb-selected-pill-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.sb-selected-pill-x{
  width:16px;height:16px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  color:inherit;opacity:.8;flex-shrink:0;
}
.sb-selected-pill-x:hover{opacity:1;background:rgba(255,255,255,.12)}

.sb-clear-btn{
  font-size:10.5px;font-weight:600;color:var(--acc);
  padding:3px 10px;border-radius:10px;background:var(--acc-bg);
  border:1px solid var(--acc-bd);cursor:pointer;transition:filter .12s;
}
.sb-clear-btn:hover{filter:brightness(1.12)}

/* Operator drawer: clickable garage item */
.garage-item{cursor:pointer;transition:border-color .15s,background .15s}
.garage-item:hover{border-color:var(--bd2);background:var(--surf3)}
.garage-item.is-active{border-color:var(--pill-a-bd);background:var(--pill-a-bg)}
.garage-item.is-active .garage-name{color:var(--pill-a-tx)}

/* ══════════════════════════════════════════════ OVERVIEW TAB v2 ══ */

.rp-kicker{
  font-size:9.5px;font-weight:700;letter-spacing:1.2px;text-transform:uppercase;
  color:var(--mu);margin-bottom:4px;
}
.rp-title-lg{font-size:16px;font-weight:600;letter-spacing:-.3px;color:var(--tx)}

/* KPI cards at the top of Overview — 2×2 default, override with .ov-kpis-4 */
.ov-kpis{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;margin-bottom:20px}
.ov-kpis-4{grid-template-columns:repeat(2,1fr)}
.ov-kpi{
  background:var(--surf2);border:1px solid var(--bd);border-radius:12px;
  padding:14px 10px;text-align:center;
}
.ov-kpi-n{font-family:var(--font-mono);font-size:22px;font-weight:700;color:var(--tx);line-height:1;letter-spacing:-.5px}
.ov-kpi-l{font-size:10.5px;color:var(--mu);margin-top:6px}

.ov-sec{margin-bottom:22px}
.ov-sec .slbl{margin-bottom:10px}

/* By-Operator table */
.ov-ops{width:100%;border-collapse:collapse;font-size:11.5px}
.ov-ops thead th{
  font-size:9px;font-weight:700;letter-spacing:.8px;text-transform:uppercase;
  color:var(--mu);text-align:right;padding:4px 0 8px;font-weight:700;
}
.ov-ops thead th:first-child{text-align:left}
.ov-ops tbody tr{
  cursor:pointer;
  transition:background .15s,border-color .15s;
}
.ov-ops tbody tr:hover{background:var(--surf2)}
.ov-ops tbody td{
  padding:11px 0;border-top:1px solid var(--bd);
  font-family:var(--font-mono);font-size:11.5px;color:var(--tx2);text-align:right;
}
.ov-ops tbody td:first-child{text-align:left;font-family:var(--font-sans);font-weight:600;color:var(--tx);padding-left:12px;position:relative}
.ov-ops tbody td:first-child::before{
  content:'';position:absolute;left:0;top:14px;bottom:14px;width:3px;border-radius:2px;
  background:var(--op-col,#64748b);
}

/* EV adoption bar list */
#ov-ev-bars .bar-row{margin-bottom:10px}
#ov-ev-bars .bar-lbl{width:96px}

/* ══════════════════════════════════════════════ FLEET MIX (Overview) ══ */
.slbl-sub{font-weight:500;letter-spacing:.2px;text-transform:none;color:var(--mu);opacity:.85;margin-left:4px}

.fleet-mix{display:flex;flex-direction:column;gap:12px}
.fleet-mix-bar{
  display:flex;width:100%;height:16px;border-radius:8px;overflow:hidden;
  background:var(--surf3);border:1px solid var(--bd);
}
.fleet-mix-seg{
  height:100%;transition:flex-basis .6s cubic-bezier(.22,1,.36,1);
  position:relative;
}
.fleet-mix-seg+.fleet-mix-seg{box-shadow:inset 1px 0 0 rgba(0,0,0,.2)}

.fleet-mix-legend{display:grid;grid-template-columns:repeat(2,1fr);gap:6px 12px}
.fleet-mix-row{display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--tx2);min-width:0}
.fleet-mix-dot{width:8px;height:8px;border-radius:3px;flex-shrink:0}
.fleet-mix-row-lbl{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fleet-mix-row-pct{font-family:var(--font-mono);font-size:11px;font-weight:700;color:var(--tx);flex-shrink:0}

/* Search field + Clear-search share the row. `flex:1 1 0` + `min-width:0`
   on the input lets it truly shrink when the button appears (without it,
   the input's intrinsic min-content keeps the row wider than the panel
   column). The button stays at its natural width via `flex:0 0 auto`. */
.route-search-row{display:flex;align-items:center;gap:8px;margin-bottom:16px;min-width:0}
.route-search-row > .sb-input{flex:1 1 0;min-width:0}
.route-search-row > .sb-clear-btn{flex:0 0 auto;white-space:nowrap}

.d-cta{
  display:inline-flex;align-items:center;gap:5px;
  background:transparent;color:var(--acc);
  border:1px solid var(--acc-bd);border-radius:8px;
  padding:7px 12px;font-size:12px;font-weight:600;cursor:pointer;
  transition:background .15s,border-color .15s,transform .08s;
}
.d-cta:hover{background:var(--acc-bg);border-color:var(--acc)}
.d-cta:active{transform:scale(.98)}
.d-cta svg{opacity:.75;transition:transform .15s}
.d-cta:hover svg{transform:translateX(2px);opacity:1}

/* Full-width variant for in-drawer primary action */
.d-cta-full{display:flex;width:100%;justify-content:center;padding:11px 14px;font-size:12.5px}

/* Topbar global reset — appears only when anything is active */
.tb-btn-reset{
  color:var(--acc);background:var(--acc-bg);border-color:var(--acc-bd);
}
.tb-btn-reset:hover{filter:brightness(1.1);border-color:var(--acc);color:var(--acc)}
.tb-btn-reset svg{color:inherit}

/* ══════════════════════════════════════════════ ABOUT / ROADMAP MODALS ══
   Class names match what about.js / roadmap.js inject, re-pointed at the
   new token system so the modals feel native in the redesigned app. */

.modal{
  position:fixed;inset:0;z-index:200;
  display:flex;align-items:center;justify-content:center;padding:20px;
}
.modal[hidden]{display:none!important}
.modal-backdrop{position:absolute;inset:0;background:rgba(0,0,0,.5);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px)}
.modal-panel{
  position:relative;
  inline-size:100%;max-inline-size:480px;
  max-block-size:min(85dvh,720px);
  overflow-y:auto;
  background:var(--surf-s);
  border:1px solid var(--bd);
  border-radius:12px;
  box-shadow:var(--sh-lg);
  padding:clamp(16px,.6rem + 2vw,20px);
  scrollbar-width:thin;scrollbar-color:var(--sc-th) transparent;
}
.modal-panel::-webkit-scrollbar{width:3px}
.modal-panel::-webkit-scrollbar-thumb{background:var(--sc-th);border-radius:2px}
/* About + Roadmap now share a width so the two dialogs feel like siblings. */
.modal-panel--wide{max-inline-size:560px}
.modal-panel{max-inline-size:560px}

.modal-close{
  position:sticky;top:12px;float:right;
  margin-inline-end:-8px;margin-block-end:-38px;
  width:26px;height:26px;
  display:inline-flex;align-items:center;justify-content:center;
  border:none;background:var(--surf-s);color:var(--tx2);
  border-radius:6px;cursor:pointer;z-index:2;
  transition:background .12s,color .12s;
}
.modal-close:hover{background:var(--surf2);color:var(--tx)}

.modal-header{display:flex;align-items:center;gap:14px;margin-bottom:18px}
.modal-brand{
  width:36px;height:36px;
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--acc);color:#fff;border-radius:8px;flex:none;
}
.modal-title{font-size:18px;font-weight:700;color:var(--tx);margin:0;line-height:1.2}
.modal-subtitle{font-size:11px;color:var(--mu);margin-top:2px}
.modal-heading{display:flex;flex-direction:column;gap:2px}

.modal-lede{color:var(--tx2);font-size:13px;line-height:1.55;margin-bottom:18px}

.modal-disclaimer{
  margin:0 0 22px;padding:14px;
  border:1px solid rgba(245,158,11,.28);background:var(--bdr);color:var(--bdt);
  border-radius:10px;font-size:11.5px;line-height:1.55;
}
.modal-disclaimer strong{color:var(--bdt)}

.modal-section{margin-top:22px}

.modal-support{
  margin-block-start:18px;padding:18px 20px;
  background:var(--surf2);border:1px solid var(--bd);border-radius:10px;
}
.modal-support .modal-section-tag{margin-block-end:10px;color:var(--tx2)}
.modal-support__copy{color:var(--tx);font-size:13px;line-height:1.55;margin-block:0 14px}
.modal-support__link{
  display:inline-flex;align-items:center;gap:6px;
  padding:7px 16px;background:var(--blue);color:#fff;
  border:1px solid var(--blue);border-radius:8px;
  font-size:13px;font-weight:600;text-decoration:none;
  transition:transform .12s,box-shadow .12s,filter .12s;
}
.modal-support__link:hover{transform:translateY(-1px);box-shadow:var(--sh);filter:brightness(1.08)}
.modal-support__link .icon-sm{opacity:.85}

.credits-list{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:2px}
.credits-list li{
  display:flex;flex-direction:column;align-items:flex-start;gap:2px;
  padding:8px 10px;border-radius:6px;font-size:13px;line-height:1.45;color:var(--tx);
}
.credits-list li:hover{background:var(--surf2)}
.credits-list a{color:var(--tx);font-weight:500;text-decoration:underline dashed var(--bd2);text-underline-offset:3px}
.credits-list a:hover{color:var(--blue);text-decoration-color:var(--blue)}
.credits-plain{color:var(--tx);font-family:var(--font-mono);font-size:11.5px}
.credits-note{color:var(--mu);font-size:11.5px;text-align:left}
.credits-list--inline li{flex-direction:row;justify-content:space-between;align-items:baseline;gap:16px}
.credits-list--inline .credits-note{text-align:right}
.modal-note{margin-top:10px;font-size:11.5px;color:var(--tx2);padding:0 10px}

.roadmap{inline-size:100%;margin-block-start:14px;border-collapse:collapse;font-size:13px}
.roadmap thead th{
  text-align:start;padding:8px 12px;border-bottom:1px solid var(--bd);
  color:var(--mu);
}
.roadmap tbody td{padding:12px;border-bottom:1px solid var(--bd);color:var(--tx2);vertical-align:top}
.roadmap tbody tr:last-child td{border-bottom:none}
.roadmap__desc{font-size:11.5px;color:var(--mu);margin-top:4px;line-height:1.5}
.roadmap__desc ul{padding-left:18px;margin:6px 0 0}
.roadmap__link{color:var(--blue);text-decoration:none;border-bottom:1px dashed var(--blue);font-weight:500;font-size:11.5px}
.roadmap__link:hover{filter:brightness(1.1)}

.b{
  display:inline-block;padding:2px 8px;border-radius:20px;
  font-size:10px;font-weight:700;white-space:nowrap;letter-spacing:.3px;
}
.b.shipped{background:var(--bdg);color:var(--bdgt)}
.b.planned{background:var(--bds);color:var(--bdst)}
.b.considering{background:var(--bdr);color:var(--bdt)}
.b.deferred{background:var(--bde);color:var(--bdet)}

/* ══════════════════════════════════════════════ CHANGELOG PAGE ══ */

body.changelog-page{overflow:auto;height:auto}
body.changelog-page html{height:auto}

.changelog-main{
  padding:40px 24px 64px;
  max-width:820px;margin:0 auto;width:100%;
}
.cl-header{margin-bottom:40px}
.cl-eyebrow{font-size:9.5px;font-weight:700;letter-spacing:1px;text-transform:uppercase;color:var(--mu);display:block;margin-bottom:8px}
.cl-title{font-size:clamp(28px,3.5vw,40px);font-weight:700;letter-spacing:-.5px;margin:0 0 16px;color:var(--tx)}
.cl-sub{font-size:15px;color:var(--tx2);line-height:1.6;max-width:640px}

.cl-entry{
  background:var(--surf-s);border:1px solid var(--bd);border-radius:14px;
  padding:24px;margin-bottom:20px;
}
.cl-entry-title{display:flex;align-items:center;gap:10px;margin-bottom:6px;flex-wrap:wrap}
.cl-version{font-family:var(--font-mono);font-size:16px;font-weight:700;color:var(--tx)}
.cl-date{font-size:11px;color:var(--mu);font-family:var(--font-mono)}
.cl-entry-title h2{font-size:18px;font-weight:600;color:var(--tx);margin:0 0 0 6px;flex:1 1 100%}
.cl-body-text{color:var(--tx2);font-size:14px;line-height:1.6}
.cl-body-text p{margin:0 0 10px}
.cl-body-text p:last-child{margin-bottom:0}
.cl-body-text ul,.cl-body-text ol{padding-left:20px;margin:8px 0 12px}
.cl-body-text li{margin-bottom:6px}
.cl-body-text strong{color:var(--tx)}
.cl-body-text code{background:var(--surf2);border:1px solid var(--bd);padding:1px 6px;border-radius:4px;font-family:var(--font-mono);font-size:12px;color:var(--tx)}
.cl-inline-link{color:var(--blue);text-decoration:none;border-bottom:1px dashed var(--blue)}
.cl-inline-link:hover{filter:brightness(1.1)}

.cl-hero{margin:18px 0 20px;padding:20px;border-radius:10px;background:var(--surf2);border:1px solid var(--bd)}
.cl-hero.dark{background:linear-gradient(180deg,var(--surf2),var(--surf3))}

.cl-authors{display:flex;gap:6px;margin-top:12px;padding-top:12px;border-top:1px solid var(--bd)}
.cl-author{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--mu)}
.cl-author-avatar{width:18px;height:18px;border-radius:50%;background:var(--acc);color:#fff;display:inline-flex;align-items:center;justify-content:center;font-size:9px;font-weight:700}

.cl-support{background:var(--surf2);border:1px solid var(--bd);border-radius:12px;padding:18px 20px;margin:24px 0}
.cl-support__title{font-size:14px;font-weight:700;color:var(--tx);margin-bottom:6px}
.cl-support__copy{font-size:12.5px;color:var(--tx2);line-height:1.55;margin-bottom:12px}

.hero-mock{display:flex;gap:12px;align-items:flex-start}
.hm-main,.hm-cards{flex:1}
.hm-card{background:var(--surf-s);border:1px solid var(--bd);border-radius:8px;padding:10px;font-size:11px;color:var(--tx2);margin-bottom:6px}
.hm-card.hl{border-color:var(--acc-bd);background:var(--acc-bg);color:var(--tx)}
.hm-row{display:flex;align-items:center;gap:6px;padding:3px 0;font-size:11px;color:var(--tx2)}
.hm-row.sel{color:var(--tx);font-weight:600}
.hm-dot{width:6px;height:6px;border-radius:50%;background:var(--acc)}
.hm-bar{height:4px;background:var(--surf3);border-radius:2px;overflow:hidden;margin-top:4px}
.hm-body{font-size:11px;color:var(--mu);margin-top:4px}
.d{color:var(--mu);font-size:11px}

.app-footer{
  display:flex;align-items:center;justify-content:center;gap:14px;flex-wrap:wrap;
  padding:14px 20px;border-top:1px solid var(--bd);
  font-size:11px;color:var(--mu);
}
.app-footer a{color:var(--mu);text-decoration:none}
.app-footer a:hover{color:var(--tx)}
.footer-link-btn{background:none;border:none;padding:0;color:inherit;cursor:pointer;font:inherit}
.footer-link-btn:hover{color:var(--tx)}
.footer-sep{color:var(--bd2)}
.footer-sep::before{content:"·"}
.footer-spacer{flex:1}
.footer-disclaimer{color:var(--mu);font-style:italic}

.icon{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;flex-shrink:0}
.icon-sm{width:12px;height:12px}

/* Legacy btn classes used by the changelog shell */
.btn{
  display:inline-flex;align-items:center;gap:6px;
  padding:7px 14px;border-radius:8px;font-size:12.5px;font-weight:600;
  text-decoration:none;cursor:pointer;transition:all .15s;
  border:1px solid var(--bd);background:var(--surf2);color:var(--tx2);
}
.btn:hover{background:var(--surf3);border-color:var(--bd2);color:var(--tx)}
.btn-outline{background:transparent}
.btn-ghost{background:transparent;border-color:transparent}
.btn-ghost:hover{background:var(--surf2);border-color:var(--bd)}
.btn-sm{padding:5px 12px;font-size:12px}
.btn-icon{padding:6px;width:32px;height:32px;justify-content:center}

/* ══════════════════════════════════════════════ TYPOGRAPHY HARMONY ══
   A single treatment for every "small uppercase label" across the app —
   sidebar filter headers, overview section labels, drawer section labels,
   popup headings, roadmap/credits section tags. */
.sb-sec-lbl,
.slbl,
.dsec-lbl,
.rp-kicker,
.modal-section-tag,
.map-popup__routes-hd,
.roadmap thead th,
.ov-ops thead th{
  font-size:9.5px!important;
  font-weight:700!important;
  letter-spacing:1px!important;
  text-transform:uppercase!important;
  color:var(--mu)!important;
  line-height:1.2!important;
}
.ov-ops thead th:not(:first-child){text-align:right!important}

/* .rp-tabs-top is a no-op — left in place as a stable selector on the
   markup in case we ever want to shift the right-panel tabs independently. */
.rp-tabs-top{}

/* Roadmap stage pills — four states, same visual language as the route-card
   contract badges so "amber = attention", "blue = upcoming", "green = done". */
.roadmap__stage-cell{white-space:nowrap;vertical-align:middle!important}
.roadmap__stage{
  display:inline-block;padding:3px 10px;border-radius:20px;
  font-size:10px;font-weight:700;letter-spacing:.3px;
  white-space:nowrap;line-height:1.3;
}
.roadmap__stage--idea    {background:var(--surf3);color:var(--tx2);border:1px solid var(--bd2)}
.roadmap__stage--planned {background:var(--bds);color:var(--bdst)}
.roadmap__stage--building{background:var(--bdr);color:var(--bdt)}
.roadmap__stage--shipped {background:var(--bdg);color:var(--bdgt)}

/* Roadmap title column — give it presence so the stage pill doesn't dominate. */
.roadmap__title{font-weight:600;color:var(--tx);font-size:13px;white-space:nowrap;padding-right:12px!important}
.roadmap__notes{margin:6px 0 0;padding-left:18px;font-size:11.5px;color:var(--mu);line-height:1.5}
.roadmap__notes li{margin-bottom:3px}

/* Drop the "bus icon" block from About/Roadmap headers — the title + subtitle
   already identify the dialog, and removing the mark makes the two modals
   feel lighter and more typographic. */
.modal-brand{display:none!important}
.modal-header{gap:0}

/* ══════════════════════════════════════════════ CHANGELOG PAGE OVERRIDES ══
   The main app locks html/body at 100dvh so Leaflet fills the viewport. The
   changelog is a scrollable long-read — undo that on this page only. */
html.changelog-page,
html.changelog-page body{
  height:auto;overflow:auto;
}
html.changelog-page body{
  display:flex;flex-direction:column;min-height:100dvh;
}
html.changelog-page .topbar{
  position:sticky;top:0;z-index:40;flex-shrink:0;
}
html.changelog-page .changelog-main{
  flex:1;
}
html.changelog-page .app-footer{flex-shrink:0}

/* ══════════════════════════════════════════════ CHANGELOG PAGE v2 ══
   Port of the original Vercel-style article list — wide reading column,
   clean borders between entries, inline version pill, bold accent support
   card at the end. Overrides the lightweight v1 rules earlier in the file. */

html.changelog-page,
html.changelog-page body{height:auto;overflow:auto;display:block}
html.changelog-page body{background:var(--bg);display:flex;flex-direction:column;min-height:100dvh}
html.changelog-page .topbar{position:sticky;top:0;z-index:40;flex-shrink:0}

.changelog-main{
  flex:1;
  padding:72px 32px 120px;
  background:var(--bg);
}
.changelog-area{display:contents}
.changelog{
  max-width:720px;margin:0 auto;
  display:flex;flex-direction:column;
}

.cl-header{
  display:flex;flex-direction:column;gap:10px;
  margin-bottom:64px;
}
.cl-eyebrow{
  font-size:11px;font-weight:500;color:var(--mu);
  letter-spacing:.4px;text-transform:uppercase;
  padding:0;margin:0;
}
.cl-title{
  font-size:clamp(1.625rem,1rem + 2.5vw,2.75rem);
  font-weight:600;color:var(--tx);
  letter-spacing:-.035em;line-height:1.05;margin:0;
}
.cl-sub{
  font-size:15px;color:var(--tx2);line-height:1.6;
  max-width:560px;margin-top:6px;
}

/* Entry: flat, separated by a single border-bottom rather than a card. */
.cl-entry{
  background:transparent;border:none;border-radius:0;
  padding:0 0 64px;margin:0 0 64px;
  border-bottom:1px solid var(--bd);
}
.cl-entry:last-of-type{border-bottom:none;margin-bottom:0;padding-bottom:8px}

.cl-date{
  font-size:13px;color:var(--mu);font-family:var(--font-mono);
  margin:0 0 12px;letter-spacing:-.01em;
  display:inline-flex;align-items:center;gap:10px;flex-wrap:wrap;
}
.cl-version{
  display:inline-flex;align-items:center;
  padding:2px 10px;margin:0;
  font-family:var(--font-mono);
  font-size:11px;font-weight:600;color:var(--tx2);
  background:var(--surf2);border:1px solid var(--bd);
  border-radius:999px;letter-spacing:.02em;
}

.cl-entry-title{
  font-size:clamp(1.125rem,.9rem + 1.5vw,1.75rem);
  font-weight:600;color:var(--tx);letter-spacing:-.025em;
  line-height:1.2;margin:0 0 24px;
  text-decoration:none;display:block;
  transition:color .15s;
}
.cl-entry-title:hover{color:var(--blue)}

.cl-inline-link{
  padding:0;background:none;border:none;
  color:var(--blue);border-bottom:1px dashed rgba(96,165,250,.4);
  font:inherit;cursor:pointer;
}
.cl-inline-link:hover{border-bottom-style:solid}

/* Bullet-list layout for entries — tightened from the old paragraph form so
   each release reads as a scannable list of changes. */
.cl-list{
  list-style:none;margin:0;padding:0;
  display:flex;flex-direction:column;gap:10px;
}
.cl-list li{
  position:relative;padding-left:0;
  font-size:14px;line-height:1.55;color:var(--tx);
}

/* Small coloured tag chips — NEW / FIX / DATA / UX / PERF — shown inline at
   the start of each list item so the type of change is readable at a glance. */
.cl-tag{
  display:inline-block;
  font-family:var(--font-mono);font-size:9.5px;font-weight:700;
  letter-spacing:.06em;text-transform:uppercase;
  padding:2px 6px;border-radius:4px;
  margin-right:6px;vertical-align:1px;
  white-space:nowrap;
}
.cl-tag--new {background:rgba( 34,197, 94,.12);color:#22c55e;border:1px solid rgba( 34,197, 94,.25)}
.cl-tag--fix {background:rgba(239, 68, 68,.12);color:#ef4444;border:1px solid rgba(239, 68, 68,.25)}
.cl-tag--data{background:rgba( 59,130,246,.12);color:#60a5fa;border:1px solid rgba( 59,130,246,.25)}
.cl-tag--ux  {background:rgba(168, 85,247,.12);color:#a855f7;border:1px solid rgba(168, 85,247,.25)}
.cl-tag--perf{background:rgba(245,158, 11,.12);color:#f59e0b;border:1px solid rgba(245,158, 11,.25)}

/* Tag legend at the top of the changelog — tiny single-line key.
   The legend sits between .cl-header and the first .cl-entry. We pull it
   close to the subheading (lighter top spacing) and push the first article
   further away (heavier bottom spacing) so the legend reads as part of the
   header block rather than as an awkward middle section. */
.cl-header:has(+ .cl-tag-legend){margin-bottom:18px}
.cl-tag-legend{
  font-size:12px;color:var(--mu);margin:0 0 64px;
  display:flex;flex-wrap:wrap;align-items:center;gap:6px;line-height:1.8;
}
.cl-tag-legend strong{color:var(--tx);margin-right:4px}

/* Bold primary support card at the end of the log — matches the original. */
.cl-support{
  margin-block-start:64px;padding:28px;
  background:var(--acc);color:#fff;
  border:1px solid var(--acc);border-radius:14px;text-align:center;
}
.cl-support__title{
  margin:0 0 6px;
  font-size:clamp(1.125rem,.9rem + .8vw,1.375rem);
  font-weight:600;color:#fff;letter-spacing:-.02em;
}
.cl-support__copy{
  margin:0 0 16px;color:rgba(255,255,255,.78);
  font-size:13px;line-height:1.55;
}
.cl-support .modal-support__link{
  background:#fff;color:var(--acc);border-color:#fff;
}
.cl-support .modal-support__link:hover{filter:brightness(.95)}

/* Hero preview card with a miniature mock inside */
.cl-hero{
  width:100%;aspect-ratio:16 / 9;
  border:1px solid var(--bd);border-radius:10px;
  background:var(--surf2);
  background-image:radial-gradient(circle,var(--bd2) 1px,transparent 1px);
  background-size:18px 18px;
  display:flex;align-items:center;justify-content:center;
  padding:28px;margin-bottom:28px;overflow:hidden;position:relative;
  box-shadow:var(--sh);
}
.cl-hero.dark{background:#141820;background-image:radial-gradient(circle,#2a2f40 1px,transparent 1px);border-color:#24293a}

.hero-mock{
  width:100%;max-width:520px;
  background:var(--surf-s);border:1px solid var(--bd);
  border-radius:6px;box-shadow:var(--sh);
  overflow:hidden;display:flex;flex-direction:column;
}
.hm-bar{
  height:22px;display:flex;align-items:center;gap:5px;padding:0 10px;
  border-bottom:1px solid var(--bd);
}
.hm-dot{width:7px;height:7px;border-radius:50%;background:var(--bd2)}
.hm-body{display:flex;min-height:120px}
.hm-side{
  width:90px;border-right:1px solid var(--bd);
  padding:8px 6px;display:flex;flex-direction:column;gap:4px;
  background:var(--surf2);
}
.hm-si{height:14px;border-radius:3px;padding:0 6px;display:flex;align-items:center;gap:5px}
.hm-si.sel{background:var(--acc-bg)}
.hm-si .d{width:5px;height:5px;border-radius:1.5px;background:var(--bd2)}
.hm-si .l{flex:1;height:3px;border-radius:2px;background:var(--bd)}
.hm-si.sel .d,.hm-si.sel .l{background:var(--acc)}
.hm-main{flex:1;padding:12px;display:flex;flex-direction:column;gap:8px}
.hm-title{height:6px;width:40%;border-radius:2px;background:var(--bd2)}
.hm-cards{display:flex;gap:6px}
.hm-card{
  flex:1;height:30px;border:1px solid var(--bd);border-radius:4px;
  padding:5px 6px;display:flex;flex-direction:column;gap:3px;justify-content:space-between;
  background:var(--surf-s);
}
.hm-card.hl{background:var(--acc);border-color:var(--acc)}
.hm-card .t{height:3px;width:50%;border-radius:2px;background:var(--bd2)}
.hm-card .b{height:5px;width:35%;border-radius:2px;background:var(--bd)}
.hm-card.hl .t,.hm-card.hl .b{background:rgba(255,255,255,.6)}
.hm-table{display:flex;flex-direction:column;gap:3px;margin-top:2px}
.hm-row{height:11px;border:1px solid var(--bd);border-radius:3px;background:var(--surf-s)}
.hm-row.sel{background:var(--acc-bg);border-color:var(--acc-bd)}

/* Body text: wider type, comfortable leading */
.cl-body-text{
  font-size:15px;color:var(--tx2);line-height:1.7;margin:0 0 16px;
}
.cl-body-text + .cl-body-text{margin-top:-4px}
.cl-body-text strong{color:var(--tx);font-weight:600}
.cl-body-text a{
  color:var(--blue);text-decoration:none;font-weight:500;
  border-bottom:1px solid rgba(96,165,250,.3);
  transition:border-color .15s;
}
.cl-body-text a:hover{border-bottom-color:var(--blue)}
.cl-body-text code{
  font-family:var(--font-mono);font-size:.88em;
  background:var(--surf2);border:1px solid var(--bd);
  border-radius:4px;padding:1px 6px;color:var(--tx);
}

/* Authors */
.cl-authors{display:flex;align-items:center;gap:12px;margin-top:28px;flex-wrap:wrap;padding:0;border:none}
.cl-author{
  display:inline-flex;align-items:center;gap:8px;
  font-size:13px;color:var(--tx2);font-weight:500;text-decoration:none;
  transition:color .15s;
}
.cl-author:hover{color:var(--tx)}
.cl-author-avatar{
  width:22px;height:22px;border-radius:50%;background:var(--acc);color:#fff;
  display:inline-flex;align-items:center;justify-content:center;
  font-size:10px;font-weight:700;
}

@media (max-width:640px){
  .changelog-main{padding:56px 20px 80px}
  .cl-entry{padding-bottom:48px;margin-bottom:48px}
  .cl-header{margin-bottom:48px}
  .cl-body-text{font-size:14.5px}
}

/* ══════════════════════════════════════════════════════════════════════════
   ORIGINAL-SITE PARITY — ported verbatim from github.com/farhanmunim/london-buses
   @ HEAD and re-pointed at the v2.5 token palette via the bridge below. This
   block overrides any earlier footer / modal / changelog declarations so the
   About dialog, Roadmap dialog, Changelog page, and app footer all match the
   live site at london-buses.farhan.app. ══════════════════════════════════ */

/* ── Legacy token bridge ────────────────────────────────────────────────── */
:root{
  --text-1: var(--tx);
  --text-2: var(--tx2);
  --text-3: var(--mu);
  --border-c: var(--bd);
  --border-2: var(--bd2);
  --muted-bg: var(--surf2);
  --muted-fg: var(--tx2);
  --surface: var(--bg);
  --accent-lt: var(--acc-bg);
  --green-tx: var(--green);
  --amber-tx: var(--bdt);
  --amber-bg: var(--bdr);
  --amber-bd: rgba(245,158,11,.28);
  /* font-sans and font-mono are defined at the top :root — do not re-declare
     here or the cascade self-references to empty. */
  --fs-xs: 11px;
  --fs-sm: 12.5px;
  --fs-md: 13px;
  --fs-lg: 15px;
  --fs-xl: 18px;
  --sp-1: 4px; --sp-2: 6px; --sp-3: 10px; --sp-4: 12px;
  --sp-5: 16px; --sp-6: 20px; --sp-7: 28px;
  --r-sm: 4px; --r-md: 6px; --r-lg: 10px; --r-xl: 14px; --r-pill: 999px;
  --shadow-sm: 0 1px 3px rgba(0,0,0,.18);
  --shadow-md: 0 4px 12px rgba(0,0,0,.28);
  --shadow-lg: var(--sh-lg);
  --t-fast: 150ms cubic-bezier(.4,0,.2,1);
  --z-topbar: 40; --z-modal: 200; --z-overlay: 150;
  --overlay: rgba(0,0,0,.55);
  /* hsl-based legacy colours (the original used `hsl(var(--card))` etc.) */
  --card: 230 22% 11%;
  --popover: 230 22% 11%;
  --primary: 349 82% 56%;
  --primary-foreground: 0 0% 100%;
  --info: 214 89% 62%;
  --muted: 230 10% 40%;
}
[data-theme="light"]{
  --card: 0 0% 100%;
  --popover: 0 0% 100%;
  --primary: 3 78% 49%;
  --primary-foreground: 0 0% 100%;
  --info: 214 84% 47%;
  --muted: 40 6% 96%;
}

/* ── APP FOOTER (original) ──────────────────────────────────────────────── */
.app-footer{
  grid-column:1/-1;grid-row:3;
  height:32px;flex-shrink:0;
  background:var(--surf);border-top:1px solid var(--border-c);
  display:flex;align-items:center;padding:0 var(--sp-6);gap:var(--sp-5);
  font-size:var(--fs-xs);color:var(--text-3);
  z-index:var(--z-topbar);
}
.app-footer a{
  color:var(--text-2);text-decoration:none;font-weight:500;
  transition:color var(--t-fast);
  display:inline-flex;align-items:center;gap:5px;
}
.app-footer a:hover{color:var(--text-1)}
.app-footer .footer-sep{width:1px;height:12px;background:var(--border-c)}
.app-footer .footer-spacer{flex:1}
.app-footer .footer-meta{
  font-family:var(--font-mono);font-size:10.5px;color:var(--text-3);
  display:inline-flex;align-items:center;gap:6px;
}
.app-footer .footer-meta::before{
  content:"";width:6px;height:6px;border-radius:var(--r-pill);
  background:var(--green-tx);
}

.footer-data{
  display:inline-flex;align-items:center;gap:6px;
  padding:2px 10px;border-radius:var(--r-pill);
  background:var(--muted-bg);border:1px solid var(--border-c);
}
.footer-data-dot{
  width:6px;height:6px;border-radius:var(--r-pill);background:var(--green-tx);
  flex-shrink:0;
}
.footer-data .footer-meta{color:var(--text-2)}
.footer-data .footer-meta::before{display:none}
.footer-data .footer-meta #footer-date,
.footer-data .footer-meta #footer-next-date{color:var(--text-1);font-weight:500}
.footer-data-next{color:var(--text-3)!important}

.footer-link-btn{
  background:none;border:none;padding:0;color:inherit;cursor:pointer;font:inherit;
  transition:color var(--t-fast);
}
.footer-link-btn:hover{color:var(--text-1)}
.footer-disclaimer{color:var(--text-3);font-style:italic}

@media (max-width:900px){
  .app-footer{padding:0 var(--sp-4);gap:var(--sp-3);font-size:10.5px}
}
@media (max-width:640px){
  .app-footer{display:none!important}
  .footer-data{flex-wrap:wrap}
  .footer-data-next{display:none}
}

/* ── MODAL SHELL (original) ─────────────────────────────────────────────── */
.modal{
  position:fixed;inset:0;z-index:var(--z-modal);
  display:flex;align-items:center;justify-content:center;padding:var(--sp-5);
}
.modal[hidden]{display:none!important}
.modal-backdrop{position:absolute;inset:0;background:var(--overlay);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px)}
.modal-panel{
  position:relative;
  inline-size:100%;max-inline-size:480px;
  max-block-size:min(85dvh,720px);
  overflow-y:auto;
  background:hsl(var(--card));
  border:1px solid var(--border-c);
  border-radius:var(--r-xl);
  box-shadow:var(--shadow-lg);
  padding:clamp(1rem,.6rem + 2vw,1.25rem);
  scrollbar-width:thin;scrollbar-color:var(--sc-th) transparent;
}
.modal-panel::-webkit-scrollbar{width:3px}
.modal-panel::-webkit-scrollbar-thumb{background:var(--sc-th);border-radius:2px}
.modal-panel--wide{max-inline-size:640px}
.modal-close{
  position:sticky;top:var(--sp-3);float:right;
  margin-inline-end:calc(-1 * var(--sp-2));
  margin-block-end:calc(-26px - var(--sp-3));
  width:26px;height:26px;
  display:inline-flex;align-items:center;justify-content:center;
  border:none;background:hsl(var(--card) / .85);backdrop-filter:blur(4px);
  color:var(--text-2);border-radius:var(--r-sm);cursor:pointer;z-index:2;
  transition:background var(--t-fast),color var(--t-fast);
}
.modal-close:hover{background:var(--muted-bg);color:var(--text-1)}

.modal-header{display:flex;align-items:center;gap:var(--sp-4);margin-bottom:var(--sp-5)}
.modal-brand{
  width:36px;height:36px;
  display:inline-flex;align-items:center;justify-content:center;
  background:hsl(var(--primary));color:hsl(var(--primary-foreground));
  border-radius:var(--r-md);flex:none;
}
.modal-heading{display:flex;flex-direction:column;gap:2px}
.modal-title{font-size:var(--fs-xl);font-weight:700;color:var(--text-1);margin:0;line-height:1.2}
.modal-subtitle{font-size:var(--fs-xs);color:var(--text-3)}
.modal-lede{color:var(--text-2);font-size:var(--fs-sm);line-height:1.55;margin-bottom:var(--sp-5)}

.modal-disclaimer{
  margin:0 0 var(--sp-6);padding:var(--sp-4);
  border:1px solid var(--amber-bd);background:var(--amber-bg);color:var(--amber-tx);
  border-radius:var(--r-md);font-size:var(--fs-xs);line-height:1.55;
}
.modal-disclaimer strong{color:var(--amber-tx)}

.modal-section{margin-top:var(--sp-6)}
.modal-section-tag{
  display:inline-block;margin-bottom:var(--sp-3);
  font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.08em;
  color:var(--text-3);
}

.modal-support{
  margin-block-start:var(--sp-5);padding:var(--sp-5) var(--sp-6);
  background:var(--muted-bg);border:1px solid var(--border-c);border-radius:var(--r-md);
}
.modal-support .modal-section-tag{margin-block-end:var(--sp-3);color:var(--text-2)}
.modal-support__copy{color:var(--text-1);font-size:var(--fs-sm);line-height:1.55;margin-block:0 var(--sp-4)}
.modal-support__link{
  display:inline-flex;align-items:center;gap:var(--sp-2);
  padding:var(--sp-2) var(--sp-5);
  background:hsl(var(--info));color:#fff;
  border:1px solid hsl(var(--info));border-radius:var(--r-md);
  font-size:var(--fs-sm);font-weight:600;text-decoration:none;
  transition:transform var(--t-fast),box-shadow var(--t-fast),filter var(--t-fast);
}
.modal-support__link:hover{transform:translateY(-1px);box-shadow:var(--shadow-sm);filter:brightness(1.05)}
.modal-support__link .icon-sm{opacity:.85}

.modal-note{margin-top:var(--sp-3);font-size:var(--fs-xs);color:var(--text-2);padding:0 var(--sp-3)}

.credits-list{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:var(--sp-1)}
.credits-list li{
  display:flex;flex-direction:column;align-items:flex-start;gap:2px;
  padding:var(--sp-2) var(--sp-3);border-radius:var(--r-sm);
  font-size:var(--fs-sm);line-height:1.45;color:var(--text-1);
}
.credits-list li:hover{background:var(--muted-bg)}
.credits-list a{color:var(--text-1);font-weight:500;text-decoration:underline dashed var(--border-2);text-underline-offset:3px}
.credits-list a:hover{color:hsl(var(--info));text-decoration-color:hsl(var(--info))}
.credits-plain{color:var(--text-1);font-family:var(--font-mono);font-size:var(--fs-xs)}
.credits-note{color:var(--text-3);font-size:var(--fs-xs);text-align:left}
.credits-list--inline li{flex-direction:row;justify-content:space-between;align-items:baseline;gap:var(--sp-4)}
.credits-list--inline .credits-note{text-align:right}

/* Roadmap table + stage pills */
.roadmap{inline-size:100%;margin-block-start:var(--sp-5);border-collapse:collapse;font-size:var(--fs-sm)}
.roadmap thead th{
  text-align:start;padding:var(--sp-2) var(--sp-3);
  border-bottom:1px solid var(--border-c);
  font-size:10.5px;font-weight:600;color:var(--text-3);
  text-transform:uppercase;letter-spacing:.06em;
}
.roadmap tbody td{padding:var(--sp-3);border-bottom:1px solid var(--border-c);vertical-align:top;color:var(--text-2)}
.roadmap tbody tr:last-child td{border-bottom:none}
.roadmap__title{font-weight:600;color:var(--text-1);white-space:nowrap;padding-right:var(--sp-4)!important}
.roadmap__desc{font-size:var(--fs-xs);color:var(--text-3);line-height:1.55;margin-top:4px}
.roadmap__notes{margin:var(--sp-2) 0 0;padding-left:var(--sp-5);font-size:var(--fs-xs);color:var(--text-3);line-height:1.5}
.roadmap__notes li{margin-bottom:3px}
.roadmap__link{color:hsl(var(--info));text-decoration:none;border-bottom:1px dashed hsl(var(--info) / .4);font-weight:500;font-size:var(--fs-xs)}
.roadmap__link:hover{border-bottom-style:solid}
.roadmap__stage-cell{white-space:nowrap;vertical-align:middle!important}
.roadmap__stage{
  display:inline-block;padding:3px 10px;border-radius:var(--r-pill);
  font-size:10px;font-weight:700;letter-spacing:.3px;white-space:nowrap;line-height:1.3;
}
.roadmap__stage--idea    {background:var(--surf3);color:var(--text-2);border:1px solid var(--border-2)}
.roadmap__stage--planned {background:var(--bds);color:var(--bdst)}
.roadmap__stage--building{background:var(--bdr);color:var(--bdt)}
.roadmap__stage--shipped {background:var(--bdg);color:var(--bdgt)}

/* ── CHANGELOG PAGE SHELL (original) ────────────────────────────────────── */
html.changelog-page,
html.changelog-page body{height:auto;overflow:auto}
html.changelog-page body{
  background:var(--surface);color:var(--text-1);
  font-family:var(--font-sans);
  display:flex;flex-direction:column;min-height:100dvh;
}
/* Match the main app shell exactly so the changelog header reads as the
   same component — same height, padding, gap, background, border. */
html.changelog-page .topbar{
  position:sticky;top:0;z-index:var(--z-topbar);flex-shrink:0;
  height:var(--header-h);padding:0 16px;gap:10px;
  background:var(--surf);border-bottom:1px solid var(--bd);
  display:flex;align-items:center;box-shadow:var(--sh);
}

/* Changelog-page logo + brand */
.topbar-logo{
  display:inline-flex;align-items:center;gap:var(--sp-3);
  font-size:var(--fs-md);font-weight:700;color:var(--text-1);text-decoration:none;
}
.logo-mark{
  width:28px;height:28px;border-radius:var(--r-md);
  background:hsl(var(--primary));color:hsl(var(--primary-foreground));
  display:inline-flex;align-items:center;justify-content:center;
}
.version-pill{
  display:inline-flex;align-items:center;padding:2px 8px;
  font-family:var(--font-mono);font-size:10.5px;font-weight:600;
  color:var(--text-2);background:var(--muted-bg);
  border:1px solid var(--border-c);border-radius:var(--r-pill);
  text-decoration:none;
}
.topbar-spacer{flex:1}

/* Icon helpers used in changelog + modals */
.icon{
  width:16px;height:16px;stroke:currentColor;fill:none;
  stroke-width:2;stroke-linecap:round;stroke-linejoin:round;flex-shrink:0;
}
.icon-sm{width:14px;height:14px}

/* Theme toggle SVG swap: icons inline into the button, one shows per theme */
.theme-toggle .theme-icon-dark{display:none}
.theme-toggle .theme-icon-light{display:block}
[data-theme="dark"] .theme-toggle .theme-icon-dark{display:block}
[data-theme="dark"] .theme-toggle .theme-icon-light{display:none}

/* Legacy btn primitives */
.btn{
  display:inline-flex;align-items:center;gap:var(--sp-2);
  padding:7px 14px;border-radius:var(--r-md);
  font-size:var(--fs-sm);font-weight:600;text-decoration:none;cursor:pointer;
  border:1px solid var(--border-c);background:var(--surf-s);color:var(--text-1);
  transition:background var(--t-fast),border-color var(--t-fast),color var(--t-fast);
  font-family:var(--font-sans);
}
.btn:hover{background:var(--muted-bg);border-color:var(--border-2)}
.btn-outline{background:transparent}
.btn-ghost{background:transparent;border-color:transparent}
.btn-ghost:hover{background:var(--muted-bg);border-color:var(--border-c)}
.btn-sm{padding:5px 12px;font-size:var(--fs-xs)}
.btn-icon{padding:6px;width:32px;height:32px;justify-content:center}

/* Changelog content column */
/* The body is the scroll container on the changelog page — don't make main
   its own scroller or the sticky topbar (a body child) won't catch on
   scroll. Let main simply flex-grow to fill between topbar and footer. */
.changelog-main{flex:1;display:flex;flex-direction:column}
.changelog-area{flex:1;padding:72px 32px 120px;background:var(--surface)}

/* Light mode changelog: flat white page surface. `data-theme` sits on the
   html element itself, so both selectors must combine on html — not use a
   descendant combinator. */
html.changelog-page[data-theme="light"],
html.changelog-page[data-theme="light"] body{
  --bg:#ffffff;
  --surface:#ffffff;
  --surf:#ffffff;
  background:#ffffff!important;
}
html.changelog-page[data-theme="light"] .changelog-main,
html.changelog-page[data-theme="light"] .changelog-area{background:#ffffff!important}
html.changelog-page[data-theme="light"] .topbar,
html.changelog-page[data-theme="light"] .app-footer{background:#ffffff!important;border-color:var(--bd)}

/* Pin the footer to the viewport on the changelog page so it's always
   visible while scrolling — matches the main app where the grid keeps the
   footer on screen at all times. sticky-bottom doesn't work here because a
   footer at the end of the document never "passes" the viewport bottom, so
   we fix-position it and reserve space with padding-bottom on body. */
html.changelog-page .app-footer{
  position:fixed;bottom:0;left:0;right:0;
  z-index:var(--z-topbar);
}
html.changelog-page body{padding-bottom:32px}
.changelog{max-width:720px;margin:0 auto;display:flex;flex-direction:column}

.cl-header{display:flex;flex-direction:column;gap:var(--sp-3);margin-bottom:72px}
.cl-eyebrow{font-size:var(--fs-xs);font-weight:500;color:var(--text-3);letter-spacing:.04em;text-transform:uppercase}
.cl-title{
  font-size:clamp(1.625rem,1rem + 2.5vw,2.75rem);
  font-weight:600;color:var(--text-1);letter-spacing:-.035em;line-height:1.05;margin:0;
}
.cl-sub{font-size:var(--fs-lg);color:var(--text-2);line-height:1.6;max-width:560px;margin-top:var(--sp-2)}

.cl-entry{
  background:transparent;border:none;border-radius:0;
  padding-bottom:72px;margin:0 0 72px;
  border-bottom:1px solid var(--border-c);
}
.cl-entry:last-of-type{border-bottom:none;margin-bottom:0;padding-bottom:8px}

.cl-date{
  font-size:var(--fs-md);color:var(--text-3);margin-bottom:var(--sp-4);
  font-family:var(--font-mono);letter-spacing:-.01em;
  display:inline-flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap;
}
.cl-version{
  display:inline-flex;align-items:center;padding:2px 8px;margin:0;
  font-family:var(--font-mono);font-size:var(--fs-xs);font-weight:600;
  color:var(--text-2);background:var(--muted-bg);
  border:1px solid var(--border-c);border-radius:var(--r-pill);letter-spacing:.01em;
}

.cl-entry-title{
  font-size:clamp(1.125rem,.9rem + 1.5vw,1.75rem);
  font-weight:600;color:var(--text-1);letter-spacing:-.025em;
  line-height:1.2;margin-bottom:24px;
  text-decoration:none;display:block;transition:color var(--t-fast);
}
.cl-entry-title:hover{color:hsl(var(--info))}

.cl-inline-link{
  padding:0;background:none;border:none;color:hsl(var(--info));
  border-bottom:1px dashed hsl(var(--info) / .4);font:inherit;cursor:pointer;
}
.cl-inline-link:hover{border-bottom-style:solid}

.cl-support{
  margin-block-start:72px;padding:var(--sp-7);
  background:hsl(var(--primary));color:hsl(var(--primary-foreground));
  border:1px solid hsl(var(--primary));border-radius:var(--r-lg);text-align:center;
}
.cl-support__title{
  margin:0 0 var(--sp-2);
  font-size:clamp(1.125rem,.9rem + .8vw,1.375rem);
  font-weight:600;color:hsl(var(--primary-foreground));letter-spacing:-.02em;
}
.cl-support__copy{
  margin:0 0 var(--sp-5);
  color:hsl(var(--primary-foreground) / .78);
  font-size:var(--fs-sm);line-height:1.55;
}
.cl-support .modal-support__link{
  background:hsl(var(--primary-foreground));color:hsl(var(--primary));
  border-color:hsl(var(--primary-foreground));
}
.cl-support .modal-support__link:hover{filter:brightness(.95)}

/* Hero preview card + miniature mock */
.cl-hero{
  width:100%;aspect-ratio:16 / 9;
  border:1px solid var(--border-c);border-radius:var(--r-lg);
  background:hsl(240 5% 98%);
  background-image:radial-gradient(circle,hsl(240 5% 88%) 1px,transparent 1px);
  background-size:18px 18px;
  display:flex;align-items:center;justify-content:center;
  padding:28px;margin-bottom:28px;overflow:hidden;position:relative;
  box-shadow:var(--shadow-sm);
}
.cl-hero.dark{
  background:hsl(240 10% 10%);
  background-image:radial-gradient(circle,hsl(240 5% 22%) 1px,transparent 1px);
  border-color:hsl(240 8% 18%);
}
[data-theme="dark"] .cl-hero:not(.dark){
  background:hsl(240 10% 10%);
  background-image:radial-gradient(circle,hsl(240 5% 22%) 1px,transparent 1px);
  border-color:hsl(240 8% 18%);
}
.hero-mock{
  width:100%;max-width:520px;
  background:var(--surf-s);border:1px solid var(--border-c);
  border-radius:var(--r-md);box-shadow:var(--shadow-md);
  overflow:hidden;display:flex;flex-direction:column;
}
.cl-hero.dark .hero-mock{background:hsl(240 6% 14%);border-color:hsl(240 8% 22%)}
.hm-bar{height:22px;display:flex;align-items:center;gap:5px;padding:0 10px;border-bottom:1px solid var(--border-c)}
.cl-hero.dark .hm-bar{border-color:hsl(240 8% 22%)}
.hm-dot{width:7px;height:7px;border-radius:var(--r-pill);background:var(--border-2)}
.cl-hero.dark .hm-dot{background:hsl(240 5% 28%)}
.hm-body{display:flex;min-height:120px}
.hm-side{
  width:90px;border-right:1px solid var(--border-c);
  padding:8px 6px;display:flex;flex-direction:column;gap:4px;
  background:hsl(240 5% 99%);
}
.cl-hero.dark .hm-side{background:hsl(240 8% 12%);border-color:hsl(240 8% 22%)}
.hm-si{height:14px;border-radius:3px;padding:0 6px;display:flex;align-items:center;gap:5px}
.hm-si.sel{background:var(--accent-lt)}
.cl-hero.dark .hm-si.sel{background:hsl(240 8% 22%)}
.hm-si .d{width:5px;height:5px;border-radius:1.5px;background:var(--border-2)}
.cl-hero.dark .hm-si .d{background:hsl(240 5% 40%)}
.hm-si .l{flex:1;height:3px;border-radius:2px;background:var(--border-c)}
.cl-hero.dark .hm-si .l{background:hsl(240 5% 30%)}
.hm-si.sel .d,.hm-si.sel .l{background:hsl(var(--primary) / .6)}
.cl-hero.dark .hm-si.sel .d,.cl-hero.dark .hm-si.sel .l{background:hsl(0 0% 95%)}
.hm-main{flex:1;padding:12px;display:flex;flex-direction:column;gap:8px}
.hm-title{height:6px;width:40%;border-radius:2px;background:var(--border-2)}
.cl-hero.dark .hm-title{background:hsl(240 5% 40%)}
.hm-cards{display:flex;gap:6px}
.hm-card{
  flex:1;height:30px;border:1px solid var(--border-c);border-radius:4px;
  padding:5px 6px;display:flex;flex-direction:column;gap:3px;justify-content:space-between;
  background:var(--surf-s);
}
.cl-hero.dark .hm-card{background:hsl(240 8% 16%);border-color:hsl(240 8% 24%)}
.hm-card.hl{background:hsl(var(--primary));border-color:hsl(var(--primary))}
.hm-card .t{height:3px;width:50%;border-radius:2px;background:var(--border-2)}
.hm-card .b{height:5px;width:35%;border-radius:2px;background:var(--border-c)}
.cl-hero.dark .hm-card .t{background:hsl(240 5% 35%)}
.cl-hero.dark .hm-card .b{background:hsl(240 5% 45%)}
.hm-card.hl .t,.hm-card.hl .b{background:hsl(var(--primary-foreground) / .6)}
.hm-table{display:flex;flex-direction:column;gap:3px;margin-top:2px}
.hm-row{height:11px;border:1px solid var(--border-c);border-radius:3px;background:var(--surf-s)}
.cl-hero.dark .hm-row{background:hsl(240 8% 16%);border-color:hsl(240 8% 24%)}
.hm-row.sel{background:var(--accent-lt);border-color:var(--accent-lt)}
.cl-hero.dark .hm-row.sel{background:hsl(240 8% 24%);border-color:hsl(240 8% 30%)}

.cl-body-text{font-size:var(--fs-lg);color:var(--text-2);line-height:1.7;margin:0 0 var(--sp-5)}
.cl-body-text + .cl-body-text{margin-top:-4px}
.cl-body-text strong{color:var(--text-1);font-weight:600}
.cl-body-text a{
  color:hsl(var(--info));text-decoration:none;font-weight:500;
  border-bottom:1px solid hsl(var(--info) / .3);
  transition:border-color var(--t-fast);
}
.cl-body-text a:hover{border-bottom-color:hsl(var(--info))}
.cl-body-text code{
  font-family:var(--font-mono);font-size:.88em;
  background:var(--muted-bg);border:1px solid var(--border-c);
  border-radius:var(--r-sm);padding:1px 6px;color:var(--text-1);
}

.cl-authors{display:flex;align-items:center;gap:var(--sp-4);margin-top:28px;flex-wrap:wrap;padding:0;border:none}
.cl-author{
  display:inline-flex;align-items:center;gap:var(--sp-3);
  font-size:var(--fs-md);color:var(--text-2);font-weight:500;text-decoration:none;
  transition:color var(--t-fast);
}
.cl-author:hover{color:var(--text-1)}
.cl-author-avatar{
  width:22px;height:22px;border-radius:var(--r-pill);
  color:#fff;display:inline-flex;align-items:center;justify-content:center;
  font-size:10px;font-weight:700;
}

@media (max-width:640px){
  .changelog-area{padding:56px 20px 96px}
  .cl-entry{padding-bottom:48px;margin-bottom:48px}
  .cl-header{margin-bottom:48px}
}

/* Non-interactive "+N more" pill shown when >3 pills are committed. Slightly
   muted so it reads as a counter rather than another selectable chip. */
.search-pill-more{
  background:var(--pill-bg)!important;border-color:var(--pill-bd)!important;
  color:var(--mu)!important;cursor:default;padding:1px 8px!important;
}

/* Roadmap stage pills need a hairline border to match the other badges in
   the app (route-card contract bdg, filter pills) so they read as a set. */
.roadmap__stage{border:1px solid transparent}
.roadmap__stage--idea    {border-color:var(--bd2)}
.roadmap__stage--planned {border-color:var(--bdst)}
.roadmap__stage--building{border-color:var(--bdt)}
.roadmap__stage--shipped {border-color:var(--bdgt)}

/* Version pill links to the changelog — subtle hover to cue interactivity. */
a.tb-ver{text-decoration:none;transition:background .15s,color .15s}
a.tb-ver:hover{background:var(--surf2);color:var(--tx2)}

/* ══════════════════════════════════════════════ MOBILE RESPONSIVE PASS ══
   Everything below only takes effect on narrow viewports — the desktop
   shell above is untouched. Uses modern CSS (clamp/min/dvh/logical props)
   so type and spacing scale smoothly from phone → tablet. */

/* 1) Desktop topbar/sidebar/panel/footer hide cleanly; mobile chrome takes
   over. Break a bit higher than before (760px) so shrunken laptops also
   get the single-column layout before the HUD starts to crowd. */
@media (max-width: 760px){
  .shell{display:block;height:100dvh}
  .topbar,.sidebar,.rp,.app-footer{display:none!important}
  .mob-top,.mob-sheet,.mob-nav{display:flex}

  /* The map fills everything between the mobile top bar and bottom nav. */
  .map-area{
    position:fixed;top:52px;bottom:calc(58px + env(safe-area-inset-bottom));
    left:0;right:0;z-index:0;
  }

  /* Map HUD reshuffle: Colour-by pill is in the Filters sheet already, no
     need to duplicate it as a floating pill. Map-layer controls become a
     compact vertical stack on the right so they don't fight for horizontal
     real estate with anything else. */
  .map-col-bar{display:none}
  .map-ctl{
    top:12px;right:12px;left:auto;
    flex-direction:column;align-items:flex-end;gap:6px;
    z-index:20;
  }
  .mctl{padding:6px 10px;font-size:11px;gap:4px;border-radius:10px}

  /* Leaflet zoom tucked into the bottom-left so it doesn't collide with the
     stacked layer toggles on the right. */
  .leaflet-bottom.leaflet-right{right:auto;left:8px;bottom:calc(8px + env(safe-area-inset-bottom));}
}

/* 2) Mobile topbar ---------------------------------------------------------
   Brand (icon + name) left, version pill centre-right, theme toggle far
   right. Height locked to 52px so the .map-area offset stays predictable. */
.mob-top{
  position:fixed;top:0;left:0;right:0;z-index:50;
  align-items:center;gap:8px;
  padding:0 clamp(10px, 3vw, 16px);
  height:52px;
  background:var(--surf);
  backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);
  border-bottom:1px solid var(--bd);
}
.mob-brand{display:inline-flex;align-items:center;gap:8px;flex-shrink:0;text-decoration:none}
.mob-brand .mob-icon{
  width:28px;height:28px;background:var(--acc);border-radius:var(--r-md);
  display:inline-flex;align-items:center;justify-content:center;color:#fff;flex-shrink:0;
}
.mob-title{
  font-size:15px;font-weight:600;letter-spacing:-.3px;color:var(--tx);
  white-space:nowrap;
}

/* 3) Pull-up sheet -------------------------------------------------------- */
.mob-sheet{
  flex-direction:column;
  position:fixed;left:0;right:0;
  bottom:calc(58px + env(safe-area-inset-bottom));
  z-index:40;
  background:var(--surf);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);
  border-top:1px solid var(--bd);border-radius:16px 16px 0 0;
  box-shadow:0 -8px 24px rgba(0,0,0,.18);
  transform:translateY(calc(100% - 122px));
  transition:transform .36s cubic-bezier(.22,1,.36,1);
  max-height:calc(100dvh - 52px - 58px - env(safe-area-inset-bottom));
}
.mob-sheet.up{transform:translateY(0)}
.mob-pull{
  display:flex;align-items:center;justify-content:center;
  padding:10px 0 4px;cursor:grab;
  background:none;border:none;width:100%;
}
.mob-handle{width:40px;height:4px;background:var(--bd2);border-radius:999px}

.mob-peek{
  display:grid;grid-template-columns:repeat(3,1fr);
  padding:clamp(8px,2vw,12px) clamp(12px,4vw,16px) 14px;
  border-bottom:1px solid var(--bd);
}
.mob-kpi{text-align:center;padding:0 6px;min-width:0}
.mob-kpi + .mob-kpi{border-inline-start:1px solid var(--bd)}
.mob-kpi-n{
  font-family:var(--font-mono);font-size:clamp(16px,4.5vw,20px);font-weight:700;
  color:var(--tx);line-height:1;
}
.mob-kpi-n.amber{color:var(--bdt)}
.mob-kpi-l{font-size:10.5px;color:var(--mu);margin-top:4px}

.mob-stabs{
  display:flex;gap:2px;
  padding:10px clamp(12px,4vw,16px) 0;border-bottom:1px solid var(--bd);
}
.mob-stab{
  font-size:12.5px;font-weight:500;color:var(--mu);
  padding:7px 12px;border-radius:var(--r-md) var(--r-md) 0 0;
  cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;
  transition:color .12s,background .12s,border-color .12s;
}
.mob-stab.on{color:var(--acc);border-bottom-color:var(--acc);background:var(--acc-bg)}
.mob-sbody{
  overflow-y:auto;padding:clamp(10px,3vw,14px) clamp(12px,4vw,16px) clamp(14px,4vw,18px);
  flex:1;min-height:0;scrollbar-width:none;
}
.mob-sbody::-webkit-scrollbar{display:none}

/* 4) Bottom nav ----------------------------------------------------------- */
.mob-nav{
  position:fixed;left:0;right:0;bottom:0;z-index:50;
  background:var(--surf);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);
  border-top:1px solid var(--bd);
  padding:6px 0 max(8px, env(safe-area-inset-bottom));
}
.mob-nav-items{display:flex;width:100%}
.mob-ni{
  flex:1;min-width:0;
  display:flex;flex-direction:column;align-items:center;gap:3px;
  background:none;border:none;padding:6px 4px;
  font-size:10.5px;font-weight:500;color:var(--mu);
  cursor:pointer;transition:color .12s;
}
.mob-ni svg{width:20px;height:20px;stroke-width:2}
.mob-ni.on{color:var(--acc)}
.mob-ni.on svg{stroke-width:2.25}
.mob-fab{display:none}   /* FAB removed from the design — 4 equal taps */
/* (.mob-alert removed — mobAlert retired site-wide.) */

/* 5) Filters sheet body uses a clone of the desktop filter section. At very
   narrow widths, operator pills wrap into two nice rows instead of spilling. */
@media (max-width:760px){
  #ms-filters .pill-grp{gap:6px}
  #ms-filters .pill{padding:6px 12px;font-size:12px}
}

/* Hide the Leaflet attribution block — attribution is still honoured via the
   data-source notes in the About modal. */
.leaflet-control-attribution{display:none!important}

/* ── Mobile simplification ─────────────────────────────────────────────────
   The bottom nav is the single tab switcher; we don't need a duplicated
   tab strip or a KPI peek sitting between the handle and the content. */
@media (max-width: 760px){
  .mob-peek,.mob-stabs{display:none!important}
  /* With peek + stabs gone, the sheet collapses to: drag-handle → body.
     Bump the "peek" offset down to show just the handle when closed. */
  .mob-sheet{transform:translateY(calc(100% - 24px))}
  .mob-sheet.up{transform:translateY(0)}
  .mob-pull{padding:8px 0 4px}
}

/* Mobile overrides for relocated desktop controls --------------------------
   The Clear-all button and the live-count / Clear-filters strip move into
   the mobile chrome on phones — give each a fit-the-bar treatment. */
@media (max-width: 760px){
  /* Reset-all pill compresses inside the mobile topbar. */
  #mob-top #resetAll{padding:4px 10px;font-size:11px}
  #mob-top #resetAll svg{width:11px;height:11px}

  /* Sheet live strip: transparent bg, small vertical padding, no bottom
     border (section separators handle it). */
  #ms-filters #sb-live{
    background:transparent;border-bottom:none;
    padding:4px 0 10px;margin-bottom:6px;border-bottom:1px solid var(--bd);
  }
}

/* Prevent horizontal overflow in the right panel + mobile sheet. The grid
   tracks on .shell were letting route cards and the Clear-search row push
   the panel past its 308px column because default `min-width: auto` on grid
   / flex children makes them grow to fit intrinsic content. */
.shell > *{min-width:0}
.rp-body,.mob-sbody{overflow-x:hidden}
.route-search-row,.route-card{min-width:0;max-width:100%}
.rc-kpis,.rc-kpi,.rc-tender{min-width:0}
.rc-kpi-v,.rc-tr-v{overflow-wrap:anywhere}

/* Route-card direction swap — compact icon button next to the destination
   name. Click spins the icon 180° (one-shot) while the name text flips
   between outbound / inbound origin→destination. */
.rc-ident{min-width:0;flex:1}
.rc-name-row{display:flex;align-items:center;gap:8px;min-width:0}
.rc-name-row .rc-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rc-dir-btn{
  flex-shrink:0;
  width:22px;height:22px;border-radius:var(--r-sm);
  display:inline-flex;align-items:center;justify-content:center;
  background:transparent;border:1px solid var(--bd);color:var(--mu);
  cursor:pointer;transition:border-color .12s,background .12s,color .12s;
}
.rc-dir-btn:hover{border-color:var(--acc-bd);background:var(--acc-bg);color:var(--acc)}
.rc-dir-btn.is-spinning svg{animation:rc-dir-spin .4s cubic-bezier(.22,1,.36,1)}
@keyframes rc-dir-spin{
  from{transform:rotate(0)}
  to  {transform:rotate(180deg)}
}

/* ══════════════════════════════════════ REDUCED MOTION ══ */
/* Honour the OS "reduce motion" setting (WCAG 2.3.3): collapse every
   transition/animation to near-instant and stop the looping live-pip blink,
   without removing the end state. */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;
    animation-iteration-count:1!important;
    transition-duration:.01ms!important;
    scroll-behavior:auto!important;
  }
}
