/* ---------- palette ------------------------------------------------------
   Colour is written as roles rather than names, which is how one stylesheet serves
   two themes: --ink is whatever the page sits on and --plaster is whatever is written
   on it, so swapping the two ramps swaps the theme and every rule below still says
   what it meant. Dark is the default and light overrides it under [data-theme].

   Two things do not simply invert:
   - Amber is a fine fill on any background and an unreadable *text* colour on paper,
     so --sun stays the brand fill and --sun-ink is amber-as-text, darkened for light.
   - --on-sun is whatever is drawn on top of amber. It is dark in both themes, because
     amber is light in both.

   theme.js stamps data-theme on <html> from <head>, before first paint, so the
   attribute is always present by the time this file is applied. */
:root{
  color-scheme:dark;
  /* surfaces, page outward */
  --ink:#0B111C; --ink-1:#121A2A; --ink-2:#1A2438; --ink-3:#25314A;
  /* text, loudest first */
  --plaster:#F3EDE3; --plaster-dim:#BFB6A8; --muted:#7C8AA5;
  --line:rgba(243,237,227,.10); --line-2:rgba(243,237,227,.18);
  --wash:rgba(243,237,227,.07);
  /* brand */
  --sun:#FFB020; --sun-hot:#FF7A2F; --shade:#5D7FE0; --shade-deep:#3A4E9B;
  --sun-ink:#FFB020; --on-sun:#0B111C; --leaf:#5FBF7A;
  --sun-soft:rgba(255,176,32,.09); --sun-wash:rgba(255,176,32,.13);
  --sun-tint:rgba(255,176,32,.30);
  /* panels floating over the map, and the modal backdrop */
  --glass:rgba(11,17,28,.82); --glass-2:rgba(11,17,28,.90); --glass-3:rgba(11,17,28,.95);
  --glass-fade:rgba(11,17,28,0); --scrim:rgba(6,10,17,.72);
  /* rail decoration and the night mask on the day curve */
  --ray-1:rgba(255,176,32,.16); --ray-2:rgba(255,122,47,.10); --ray-3:rgba(255,176,32,.08);
  --grain-opacity:.32; --grain-blend:overlay;
  --night:rgba(11,17,28,.62);
  --picker-filter:invert(.7);
  --shadow-rail:0 0 60px -30px rgba(0,0,0,.9);
  --shadow-pop:0 18px 44px -14px rgba(0,0,0,.85);
  --shadow-pin:0 5px 16px rgba(0,0,0,.6);
  --shadow-panel:0 24px 60px rgba(0,0,0,.55);
  --shadow-float:0 12px 34px rgba(0,0,0,.45);
  --sans:"Archivo",system-ui,sans-serif; --mono:"IBM Plex Mono",ui-monospace,monospace;
  --serif:"Instrument Serif",Georgia,serif;
  --rail:404px;
}
/* Paper, not white: the plaster of the dark theme is warm, and a pure #FFF page next
   to that amber reads clinical. The surfaces run light-to-dark in the same order the
   dark ones run dark-to-light, so depth still means the same thing. */
:root[data-theme="light"]{
  color-scheme:light;
  --ink:#F6F1E8; --ink-1:#FFFDF9; --ink-2:#EDE6D9; --ink-3:#D8CFBF;
  --plaster:#16202F; --plaster-dim:#414D63; --muted:#6B7690;
  --line:rgba(22,32,47,.12); --line-2:rgba(22,32,47,.20);
  --wash:rgba(22,32,47,.06);
  --sun-ink:#B4630B; --leaf:#1C8B4B;
  --sun-soft:rgba(255,176,32,.18); --sun-wash:rgba(255,176,32,.26);
  --sun-tint:rgba(255,176,32,.45);
  --glass:rgba(255,253,249,.86); --glass-2:rgba(255,253,249,.92); --glass-3:rgba(255,253,249,.96);
  --glass-fade:rgba(255,253,249,0); --scrim:rgba(22,32,47,.34);
  --ray-1:rgba(255,176,32,.34); --ray-2:rgba(255,122,47,.22); --ray-3:rgba(255,176,32,.18);
  --grain-opacity:.13; --grain-blend:multiply;
  --night:rgba(22,32,47,.14);
  --picker-filter:none;
  --shadow-rail:0 0 60px -34px rgba(22,32,47,.55);
  --shadow-pop:0 18px 40px -18px rgba(22,32,47,.30);
  --shadow-pin:0 4px 13px rgba(22,32,47,.30);
  --shadow-panel:0 24px 60px rgba(22,32,47,.22);
  --shadow-float:0 12px 30px rgba(22,32,47,.20);
}
*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
body{
  font-family:var(--sans); background:var(--ink); color:var(--plaster);
  overflow:hidden; -webkit-font-smoothing:antialiased;
}
button,input,select{font:inherit;color:inherit}
button{cursor:pointer;background:none;border:none}

/* ---------- shell ---------- */
#app{display:grid;grid-template-columns:var(--rail) 1fr;height:100dvh}
#map{position:relative;height:100dvh;background:var(--ink-1);grid-column:2;grid-row:1}
#rail{grid-column:1;grid-row:1}
#rail{
  position:relative;overflow-y:auto;overflow-x:hidden;
  background:linear-gradient(178deg,var(--ink-1) 0%,var(--ink) 62%);
  border-inline-end:1px solid var(--line-2);
  box-shadow:var(--shadow-rail);
}
/* Bauhaus-poster sunburst bleeding out of the header, plus a fine grain */
/* The sunburst ends on a rule, not at an arbitrary fraction of the rail.
   --rays-h is measured in app.js as the distance from the top of the rail content
   down to the divider under the Sun block. It is deliberately content-relative
   rather than a percentage: a percentage resolves against the rail's *visible*
   height, so the cut landed wherever the viewport happened to end and sliced through
   the middle of a section. The mask fades the last stretch so the light falls off
   into the rule instead of stopping at a hard edge. */
#rail::before{
  content:"";position:absolute;top:0;right:-60%;left:-20%;bottom:auto;
  height:var(--rays-h,42%);pointer-events:none;
  background:
    conic-gradient(from 200deg at 62% 90%,
      transparent 0deg, var(--ray-1) 12deg, transparent 24deg,
      transparent 36deg, var(--ray-2) 48deg, transparent 60deg,
      transparent 74deg, var(--ray-3) 86deg, transparent 100deg);
  filter:blur(.3px);
  -webkit-mask-image:linear-gradient(to bottom,#000 0%,#000 88%,transparent 100%);
  mask-image:linear-gradient(to bottom,#000 0%,#000 88%,transparent 100%);
}
#rail::after{
  content:"";position:absolute;inset:0;pointer-events:none;opacity:var(--grain-opacity);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.5'/%3E%3C/svg%3E");
  mix-blend-mode:var(--grain-blend);
}
.rail-inner{position:relative;z-index:2;padding:26px 24px 40px;display:flex;flex-direction:column;gap:22px}

/* ---------- staggered entrance ---------- */
@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
/* fill-mode is "backwards", not "both": "both" leaves the animation's final transform
   applied forever, and a computed transform of matrix(1,0,0,1,0,0) still creates a
   stacking context. Every section became one, so the search dropdown was painted
   underneath the sections that follow it in the DOM no matter its z-index.
   "backwards" still applies the from-state during the stagger delay, which is the
   only part we actually wanted. */
.sec{animation:rise .62s cubic-bezier(.2,.7,.25,1) backwards}
.sec:nth-child(1){animation-delay:.02s}.sec:nth-child(2){animation-delay:.09s}
.sec:nth-child(3){animation-delay:.16s}.sec:nth-child(4){animation-delay:.23s}
.sec:nth-child(5){animation-delay:.30s}.sec:nth-child(6){animation-delay:.37s}
.sec:nth-child(7){animation-delay:.44s}.sec:nth-child(8){animation-delay:.51s}
@media (prefers-reduced-motion:reduce){.sec{animation:none}}

/* ---------- masthead ---------- */
/* The rail is 404px on a desktop too, so the masthead is never on a wide canvas: the
   wordmark, the subtitle and four controls do not fit on one line in any language.
   Left to share a row they did not shrink — the controls are fixed-size icons — so
   the wordmark simply overflowed under them and the subtitle broke into three lines.
   The group wraps as a whole instead, at every width. See the narrow-width block. */
.mast{display:flex;flex-wrap:wrap;align-items:flex-start;gap:12px;row-gap:10px}
.mast-text{flex:1 1 140px;min-width:0}
.mark{flex:0 0 auto;width:46px;height:46px;position:relative}
.mark svg{display:block}
h1{font-family:var(--serif);font-weight:400;font-size:33px;line-height:.92;letter-spacing:-.015em;direction:ltr}
h1 em{font-style:italic;color:var(--sun-ink)}
.mast p{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--muted);margin-top:7px
}

/* ---------- generic block ---------- */
.block{border-top:1px solid var(--line);padding-top:17px}
.label{
  font-family:var(--mono);font-size:10px;letter-spacing:.19em;text-transform:uppercase;
  color:var(--muted);display:flex;justify-content:space-between;align-items:center;margin-bottom:11px
}
.label b{color:var(--plaster-dim);font-weight:500}

/* ---------- weather ---------- */
.wx{display:flex;gap:13px;align-items:flex-start}
.wx-temp{font-family:var(--mono);font-size:30px;font-weight:600;line-height:1;letter-spacing:-.03em}
.wx-temp span{font-size:14px;color:var(--muted);font-weight:400}
.wx-msg{font-size:12.5px;line-height:1.42;color:var(--plaster-dim);padding-top:3px}
.heatbar{height:3px;margin-top:11px;border-radius:2px;background:var(--ink-3);overflow:hidden}
.heatbar i{display:block;height:100%;width:100%;transform-origin:left center;transform:scaleX(0);
  background:linear-gradient(90deg,var(--shade),var(--sun),var(--sun-hot));
  transition:transform .5s cubic-bezier(.2,.7,.25,1)}

/* ---------- sun dial ---------- */
.dial-wrap{display:flex;gap:16px;align-items:center}
#dial{flex:0 0 auto}
.readout{display:flex;flex-direction:column;gap:9px;min-width:0}
.ro{display:flex;justify-content:space-between;gap:12px;align-items:baseline}
.ro span{font-family:var(--mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--muted)}
.ro b{font-family:var(--mono);font-size:15px;font-weight:500;letter-spacing:-.02em}
.ro b.sun{color:var(--sun-ink)}

/* ---------- day scrubber ---------- */
.day{position:relative;margin-top:2px}
#daycurve{display:block;width:100%;height:62px;border-radius:6px;background:var(--ink-2);cursor:crosshair;touch-action:none}
.day-axis{display:flex;justify-content:space-between;font-family:var(--mono);font-size:9px;
  letter-spacing:.1em;color:var(--muted);margin-top:5px}
.timerow{display:flex;gap:8px;align-items:center;margin-top:11px}
.timerow input[type=date]{
  flex:1;background:var(--ink-2);border:1px solid var(--line-2);border-radius:6px;
  padding:7px 9px;font-family:var(--mono);font-size:12px
}
.clock{font-family:var(--mono);font-size:19px;font-weight:600;letter-spacing:-.02em;min-width:62px;text-align:right}
.nowbtn{font-family:var(--mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;
  border:1px solid var(--line-2);border-radius:6px;padding:7px 10px;color:var(--plaster-dim);transition:.18s}
.nowbtn:hover{border-color:var(--sun-ink);color:var(--sun-ink)}

/* ---------- endpoints ---------- */
.pt{display:flex;align-items:center;gap:11px;padding:9px 11px;border-radius:8px;
  background:var(--ink-2);border:1px solid transparent;transition:.2s;margin-bottom:7px}
.pt.armed{border-color:var(--sun);background:var(--sun-soft)}
.pt .pin{flex:0 0 auto;width:22px;height:22px;border-radius:50%;display:grid;place-items:center;
  font-family:var(--mono);font-size:11px;font-weight:600;color:var(--on-sun)}
/* A and the stops sit on --plaster, which is the text colour: their letter takes the
   page colour back. Only B is on amber, and amber is light in both themes. */
.pt.a .pin,.pt.s .pin{color:var(--ink)}
.pt.a .pin{background:var(--plaster)}
.pt.b .pin{background:var(--sun)}
.pt .txt{flex:1;min-width:0;font-size:12.5px;color:var(--plaster-dim);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pt .txt.empty{color:var(--muted);font-style:italic}
.pt button{font-family:var(--mono);font-size:10px;color:var(--muted);padding:3px 5px;transition:.15s}
.pt button:hover{color:var(--sun-ink)}
.swap{width:100%;font-family:var(--mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;
  color:var(--muted);padding:5px;transition:.15s}
.swap:hover{color:var(--plaster)}

/* ---------- preference ---------- */
.chips{display:grid;grid-template-columns:repeat(4,1fr);gap:5px;background:var(--ink-2);
  padding:4px;border-radius:9px}
.chip{padding:9px 3px;border-radius:6px;font-family:var(--mono);font-size:9.5px;letter-spacing:.07em;
  text-transform:uppercase;color:var(--muted);transition:.2s;text-align:center;line-height:1.3}
.chip:hover{color:var(--plaster)}
.chip.on{background:var(--plaster);color:var(--ink);font-weight:600}
.chip.on.auto{background:var(--sun);color:var(--on-sun)}

/* ---------- routes ---------- */
.routes{display:flex;flex-direction:column;gap:9px}
.card{
  position:relative;border:1px solid var(--line-2);border-radius:11px;padding:13px 14px;
  background:linear-gradient(160deg,var(--ink-2),var(--ink-1));cursor:pointer;
  transition:border-color .22s,transform .22s,box-shadow .22s;overflow:hidden
}
.card:hover{transform:translateX(3px);border-color:var(--line-2)}
.card.sel{border-color:var(--sun);box-shadow:0 0 0 1px rgba(255,176,32,.28),0 14px 34px -18px rgba(255,176,32,.5)}
.card .bar{position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--ink-3)}
.card.sel .bar{background:var(--sun)}
.card h3{font-size:13px;font-weight:600;letter-spacing:.01em;display:flex;align-items:center;gap:8px}
.tag{font-family:var(--mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);border:1px solid var(--line-2);border-radius:3px;padding:1px 5px}
.shadenum{font-family:var(--mono);font-size:27px;font-weight:600;letter-spacing:-.04em;line-height:1;margin:9px 0 3px}
.shadenum s{text-decoration:none;font-size:13px;color:var(--muted)}
.metrics{display:flex;gap:14px;font-family:var(--mono);font-size:11px;color:var(--plaster-dim);margin-top:7px}
.metrics em{font-style:normal;color:var(--muted)}
.detour{font-family:var(--mono);font-size:10.5px;margin-top:8px;padding-top:8px;border-top:1px solid var(--line)}
.detour.free{color:var(--leaf)}.detour.cost{color:var(--sun-ink)}
.sunstrip{display:flex;height:5px;border-radius:3px;overflow:hidden;margin-top:10px;gap:1px}
.sunstrip i{display:block;height:100%}

/* ---------- advice ---------- */
.advice{display:flex;flex-direction:column;gap:0}
.adv{display:flex;gap:11px;align-items:baseline;padding:8px 0;border-bottom:1px solid var(--line)}
.adv:last-child{border-bottom:none}
.adv .side{font-family:var(--mono);font-size:10px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--on-sun);background:var(--sun);border-radius:3px;padding:2px 6px;flex:0 0 auto}
.adv .st{flex:1;font-size:12.5px;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.adv .pc{font-family:var(--mono);font-size:11px;color:var(--muted);flex:0 0 auto}

/* ---------- layers ---------- */
.toggles{display:flex;flex-direction:column;gap:2px}
.tg{display:flex;align-items:center;gap:10px;padding:7px 0;font-size:12.5px;color:var(--plaster-dim);cursor:pointer}
.tg .sw{width:30px;height:17px;border-radius:9px;background:var(--ink-3);position:relative;transition:.24s;flex:0 0 auto}
.tg .sw::after{content:"";position:absolute;top:2.5px;left:2.5px;width:12px;height:12px;border-radius:50%;
  background:var(--muted);transition:.24s}
.tg.on .sw{background:var(--sun-tint)}
.tg.on .sw::after{transform:translateX(13px);background:var(--sun)}
.tg small{margin-left:auto;font-family:var(--mono);font-size:9.5px;color:var(--muted)}

/* ---------- legend + footer ---------- */
.legend{display:flex;align-items:center;gap:9px;font-family:var(--mono);font-size:9.5px;color:var(--muted)}
.ramp{flex:1;height:6px;border-radius:3px;
  background:linear-gradient(90deg,var(--sun-hot),var(--sun) 32%,#8E93B5 55%,var(--shade) 78%,var(--shade-deep))}
footer{font-family:var(--mono);font-size:9.5px;line-height:1.7;color:var(--muted);
  border-top:1px solid var(--line);padding-top:15px}
footer a{color:var(--plaster-dim);text-decoration:none;border-bottom:1px solid var(--line-2)}
footer a:hover{color:var(--sun-ink);border-color:var(--sun-ink)}
footer .warn{color:var(--sun-ink);opacity:.85}

/* ---------- map furniture ---------- */
.maptop{position:absolute;top:14px;left:14px;right:14px;z-index:5;display:flex;gap:9px;
  justify-content:space-between;pointer-events:none}
.pill{pointer-events:auto;background:var(--glass);backdrop-filter:blur(14px);
  border:1px solid var(--line-2);border-radius:99px;padding:8px 14px;
  font-family:var(--mono);font-size:10.5px;letter-spacing:.08em;color:var(--plaster-dim);
  display:flex;align-items:center;gap:9px}
.pill b{color:var(--sun-ink);font-weight:500}
.dot{width:6px;height:6px;border-radius:50%;background:var(--sun);box-shadow:0 0 0 3px rgba(255,176,32,.2)}
.maplibregl-ctrl-attrib{font-size:9px!important;background:var(--glass)!important;color:var(--muted)!important}
.maplibregl-ctrl-attrib a{color:var(--plaster-dim)!important}
.mk{width:26px;height:26px;border-radius:50%;display:grid;place-items:center;
  font-family:var(--mono);font-size:12px;font-weight:600;color:var(--on-sun);
  border:2px solid var(--ink);box-shadow:var(--shadow-pin);cursor:grab}
.mk.a{background:var(--plaster);color:var(--ink)} .mk.b{background:var(--sun)}

.spinner{display:inline-block;width:11px;height:11px;border:2px solid var(--line-2);
  border-top-color:var(--sun-ink);border-radius:50%;animation:spin .7s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.empty-note{font-size:12px;color:var(--muted);line-height:1.55;font-style:italic}

/* ---------- responsive ---------- */
@media (max-width:900px){
  /* A little more rail and a little less map than before. The rail now carries the
     whole question -- from, to and when -- above the fold, and the couple of
     percentage points come back the moment anything is scrolled. */
  #app{grid-template-columns:1fr;grid-template-rows:44dvh 56dvh}
  #map{height:44dvh;grid-column:1;grid-row:1}
  #rail{height:56dvh;grid-column:1;grid-row:2;border-right:none;border-top:1px solid var(--line-2)}
  .rail-inner{padding:16px 16px 30px;gap:15px}
  h1{font-size:31px}
}

/* ---------- search inputs and results ---------- */
/* Owns the autocomplete dropdowns, so it has to out-stack the sections below it —
   including while the entrance animation is still running. */
.sec-route{position:relative;z-index:20}
.ptwrap{position:relative}
.pt-input{
  flex:1;min-width:0;background:none;border:none;outline:none;
  font-size:12.5px;color:var(--plaster);padding:2px 0
}
.pt-input::placeholder{color:var(--muted);font-style:italic}
.pt-input::-webkit-search-cancel-button{display:none}
.pt.filled .pt-input{color:var(--plaster)}
.iconbtn{
  flex:0 0 auto;font-family:var(--mono);font-size:11px;color:var(--muted);
  padding:3px 5px;border-radius:4px;transition:.15s;line-height:1
}
.iconbtn:hover{color:var(--sun-ink);background:var(--sun-soft)}
#geo-a{font-size:13px}
#geo-a.locating{color:var(--sun-ink);animation:pulse 1.1s ease-in-out infinite}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.35}}

.results{
  position:absolute;z-index:30;left:0;right:0;top:calc(100% - 4px);
  background:var(--ink-2);border:1px solid var(--line-2);border-radius:9px;
  box-shadow:var(--shadow-pop);overflow:hidden;max-height:290px;overflow-y:auto;
  /* Opaque by construction: this sits over body copy, so no alpha anywhere. Both
     themes give --ink-2 a flat hex for exactly this. */
  background-color:var(--ink-2)
}
.res{
  display:flex;align-items:baseline;gap:9px;padding:8px 11px;cursor:pointer;
  border-bottom:1px solid var(--line);transition:background .12s
}
.res:last-child{border-bottom:none}
.res:hover,.res.active{background:var(--sun-wash)}
.res .ic{flex:0 0 auto;width:13px;text-align:center;color:var(--sun-ink);font-size:11px}
.res .tx{flex:1;min-width:0}
.res .t1{font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.res .t2{font-family:var(--mono);font-size:9.5px;color:var(--muted);margin-top:2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.res-empty{padding:10px 11px;font-size:12px;color:var(--muted);font-style:italic}

/* iOS Safari zooms the viewport whenever a focused input has a font smaller than
   16px. Targeting coarse pointers rather than a width breakpoint catches tablets in
   landscape too, and avoids the usual fix of maximum-scale=1, which would disable
   pinch-zoom for everyone. */
@media (pointer: coarse){
  .pt-input,.timerow input[type=date],.res .t1{font-size:16px}
  .pt{padding:11px 11px}
  .iconbtn{font-size:15px;padding:6px 8px}
  #geo-a{font-size:17px}
  .res{padding:11px 11px}
}
.tag.auto{border-color:var(--sun-tint);color:var(--sun-ink)}

/* ---------- masthead language switch ---------- */
.langbtn{
  flex:0 0 auto;font-family:var(--mono);font-size:10px;letter-spacing:.12em;
  border:1px solid var(--line-2);border-radius:99px;padding:6px 11px;
  color:var(--plaster-dim);transition:.18s;margin-top:3px
}
.langbtn:hover{border-color:var(--sun-ink);color:var(--sun-ink)}

/* ---------- from / to fields ---------- */
/* The label sits on the same line as the input rather than stacked above it. Stacked,
   the pin and the buttons centre against a two-line block, so they read as misaligned
   with the text itself, which is the only part the eye tracks. */
.ptfield{flex:1;min-width:0;display:flex;align-items:center;gap:9px}
.ptlabel{
  flex:0 0 auto;min-width:2.9em;font-family:var(--mono);font-size:9px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--muted);cursor:pointer;line-height:1
}
.pt{align-items:center;min-height:44px}
.pt-input{line-height:1.2}
.swap{
  width:28px;height:28px;border-radius:50%;border:1px solid var(--line-2);
  background:var(--ink-2);color:var(--muted);font-size:13px;line-height:1;
  margin:-11px auto -11px;position:relative;z-index:3;display:grid;place-items:center;
  transition:.18s;padding:0
}
.swap:hover{color:var(--sun-ink);border-color:var(--sun-ink);transform:rotate(180deg)}

/* ---------- segmented control ---------- */
.seg{display:grid;grid-auto-flow:column;gap:4px;background:var(--ink-2);padding:4px;
  border-radius:9px;margin-bottom:12px}
.segbtn{
  padding:8px 4px;border-radius:6px;font-family:var(--mono);font-size:9.5px;
  letter-spacing:.07em;text-transform:uppercase;color:var(--muted);transition:.2s;text-align:center
}
.segbtn:hover{color:var(--plaster)}
.segbtn.on{background:var(--plaster);color:var(--ink);font-weight:600}

/* ---------- bidirectional text ----------
   Place names are Hebrew inside an English UI and Latin inside a Hebrew one, often in
   the same list. plaintext lets each string pick its own direction from its first
   strong character, which is the only way a mixed list reads correctly either way. */
.res .t1,.res .t2,.adv .st,.pt-input,.card h3,.wx-msg,.empty-note,#build-note{
  unicode-bidi:plaintext
}
/* Numbers and units stay LTR whatever the UI language. */
.shadenum,.metrics,.detour,.clock,.ro b,.pill,.day-axis,.adv .pc,.tag{
  direction:ltr;unicode-bidi:isolate
}

/* ---------- RTL ---------- */
[dir="rtl"] .label,[dir="rtl"] .ptlabel,[dir="rtl"] .segbtn,[dir="rtl"] .chip,
[dir="rtl"] .ro span,[dir="rtl"] .mast p{letter-spacing:.04em}
[dir="rtl"] .mast p{font-size:10px}
[dir="rtl"] .adv .side{font-family:var(--sans);letter-spacing:0}
/* IBM Plex Mono has no Hebrew, so the mono labels fall back mid-string. Use the sans
   stack in RTL, where the system font covers Hebrew properly. */
[dir="rtl"] .ptlabel,[dir="rtl"] .label,[dir="rtl"] .chip,[dir="rtl"] .segbtn,
[dir="rtl"] .ro span,[dir="rtl"] .nowbtn,[dir="rtl"] .res .t2{font-family:var(--sans)}
[dir="rtl"] .swap:hover{transform:rotate(-180deg)}
[dir="rtl"] #dial{transform:none}
[dir="rtl"] .metrics{flex-direction:row}

/* ---------- Lucide icons ---------- */
.ic{width:15px;height:15px;display:block;stroke-width:2}
.res .ic{flex:0 0 auto;width:15px;height:15px;color:var(--sun-ink);margin-top:1px}
.iconbtn .ic,.swap .ic{width:15px;height:15px;margin:0 auto}
.iconbtn{display:grid;place-items:center}
.swap{display:grid;place-items:center}
.res{align-items:flex-start}
@media (pointer: coarse){
  .res .ic,.iconbtn .ic,.swap .ic{width:17px;height:17px}
}

.mastbtn{margin-top:3px;border:1px solid var(--line-2);border-radius:99px;padding:7px}
.mastbtn:hover{border-color:var(--sun-ink)}
.mastbtn.done{border-color:var(--leaf);color:var(--leaf)}
.toast{
  position:fixed;left:50%;bottom:26px;transform:translateX(-50%);z-index:50;
  background:var(--glass-3);border:1px solid var(--line-2);border-radius:99px;
  padding:9px 18px;font-family:var(--mono);font-size:11px;color:var(--plaster);
  opacity:0;transition:opacity .25s;pointer-events:none;
  max-width:min(420px,calc(100vw - 32px));text-align:center;line-height:1.45;
  border-radius:14px;box-shadow:var(--shadow-float)
}
.toast.show{opacity:1}

/* ---------- map layers control, over the map at bottom left ----------
   Wide: a row of base maps on the map, as before. Narrow: one button, and the same
   markup as a popover above it -- three labelled buttons across the bottom of a 375px
   map was most of the width of the map, and the shade layer could only be reached by
   scrolling the rail. */
.mapmenu{position:absolute;left:14px;bottom:14px;z-index:6}
/* Physically bottom-left in both directions: it sits against the map, not the text. */
[dir="rtl"] .mapmenu{left:14px;right:auto}
.mapmenu-btn{display:none}
.maptg{display:none}
.mapseg{
  display:flex;gap:2px;padding:3px;margin:0;
  background:var(--glass);backdrop-filter:blur(14px);
  border:1px solid var(--line-2);border-radius:99px
}
.mapseg .segbtn{
  padding:6px 11px;border-radius:99px;font-size:9px;letter-spacing:.09em;
  text-transform:uppercase;color:var(--plaster-dim);white-space:nowrap
}
.mapseg .segbtn:hover{color:var(--plaster);background:var(--wash)}
.mapseg .segbtn.on{background:var(--plaster);color:var(--ink);font-weight:600}
@media (max-width:900px){
  .mapmenu{left:10px;bottom:10px}
  .mapmenu-btn{
    display:grid;place-items:center;width:40px;height:40px;border-radius:50%;
    background:var(--glass);backdrop-filter:blur(14px);
    border:1px solid var(--line-2);color:var(--plaster-dim)
  }
  .mapmenu-btn .ic{width:18px;height:18px}
  .mapmenu.open .mapmenu-btn{color:var(--sun-ink);border-color:var(--sun-ink)}
  .mapmenu-panel{
    position:absolute;left:0;bottom:calc(100% + 8px);display:none;min-width:172px;
    padding:5px;border-radius:13px;background:var(--glass-3);backdrop-filter:blur(14px);
    border:1px solid var(--line-2);box-shadow:var(--shadow-float)
  }
  .mapmenu.open .mapmenu-panel{display:block}
  /* Stacked and left-aligned inside the popover: a list reads as a choice, a row of
     pills reads as a toolbar. */
  .mapseg{flex-direction:column;gap:1px;padding:0;background:none;border:0;
    border-radius:0;backdrop-filter:none}
  .mapseg .segbtn{text-align:start;padding:10px 11px;border-radius:9px;font-size:10px}
  .maptg{display:flex;margin-top:4px;padding:10px 11px 4px;font-size:12px;
    border-top:1px solid var(--line-2)}
}

/* ---- stops --------------------------------------------------------------
   Rows are generated, so anything positional has to work for two rows and ten. */
.ptwrap + .ptwrap{margin-top:6px}
.pt.s .pin{background:var(--plaster-dim);color:var(--ink)}
.mk.s{background:var(--plaster-dim);color:var(--ink);width:22px;height:22px;font-size:10px}

.drag{flex:0 0 auto;width:13px;padding:0;border:0;background:none;color:var(--muted);
  cursor:grab;display:grid;place-items:center;touch-action:none}
.drag:active{cursor:grabbing}
.drag .ic{width:13px;height:13px}
.ptwrap.dragging{opacity:.6}
.ptwrap.dragging .pt{border-color:var(--sun)}

.ptactions{display:flex;align-items:center;gap:6px;margin-top:9px}
.ghostbtn{display:inline-flex;align-items:center;gap:6px;
  font-family:var(--mono);font-size:9.5px;letter-spacing:.11em;text-transform:uppercase;
  color:var(--muted);background:none;border:1px solid var(--line-2);border-radius:99px;
  padding:6px 11px;transition:.15s;cursor:pointer;white-space:nowrap}
.ghostbtn:hover:not(:disabled){color:var(--sun-ink);border-color:var(--sun-ink)}
.ghostbtn:disabled{opacity:.35;cursor:default}
.ghostbtn.busy{color:var(--sun-ink);border-color:var(--sun-ink)}
.ghostbtn .ic{width:14px;height:14px}
.ghostbtn.icon-only{margin-inline-start:auto;padding:0;width:29px;height:29px;
  display:grid;place-items:center;flex:0 0 auto}
@media (pointer: coarse){
  .ghostbtn{padding:8px 12px;font-size:10px}
  .ghostbtn.icon-only{width:34px;height:34px;padding:0}
  .drag{width:18px}
}

/* ---- live navigation ----------------------------------------------------
   Sits over the map, top-anchored: walking, you glance down at the phone, and the
   instruction should be the first thing under your thumb-shadow, not the last. */
/* Solid to the bottom edge, with the fade moved to a strip below it. The gradient used
   to reach transparent inside the panel, which left the stats row as grey text sitting
   directly on a near-white 3D basemap. */
#nav{position:absolute;top:0;left:0;right:0;z-index:8;padding:12px 14px 11px;
  background:var(--glass-3);backdrop-filter:blur(10px)}
#nav::after{content:"";position:absolute;left:0;right:0;top:100%;height:22px;
  background:linear-gradient(180deg,var(--glass-3),var(--glass-fade));pointer-events:none}
body.navigating .maptop{display:none}
#nav{border-bottom:2px solid var(--sun)}
.nav-top{display:flex;align-items:center;gap:13px}
.nav-icon{flex:0 0 auto;width:54px;height:54px;border-radius:13px;display:grid;place-items:center;
  background:var(--sun);color:var(--on-sun);box-shadow:0 3px 14px rgba(255,176,32,.3)}
.nav-icon .ic{width:32px;height:32px;stroke-width:2.6}
.nav-say{flex:1;min-width:0}
.nav-dist{font-family:var(--mono);font-size:25px;font-weight:700;color:var(--sun-ink);line-height:1.1;
  letter-spacing:.01em}
.nav-instr{font-size:17px;font-weight:600;color:var(--plaster);line-height:1.28;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nav-end{flex:0 0 auto;width:32px;height:32px;border-radius:50%;display:grid;place-items:center;
  color:var(--muted);border:1px solid var(--line-2);background:none;cursor:pointer}
.nav-end:hover{color:var(--sun-ink);border-color:var(--sun-ink)}
.nav-end .ic{width:15px;height:15px}
.nav-next{margin-top:6px;padding-inline-start:67px;font-size:12.5px;color:var(--plaster-dim);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nav-bar{margin-top:9px;height:3px;border-radius:2px;background:var(--line-2);overflow:hidden}
.nav-bar > i{display:block;height:100%;width:0;background:var(--sun);transition:width .6s ease}
.nav-stats{display:flex;gap:14px;margin-top:7px;
  font-family:var(--mono);font-size:10px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--plaster-dim)}
.nav-alert{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin-top:9px;padding:9px 11px;
  border-radius:9px;background:var(--sun-wash);border:1px solid var(--sun);
  font-size:12px;color:var(--plaster)}
.nav-alert button{font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;
  padding:5px 10px;border-radius:99px;border:1px solid var(--sun);background:none;
  color:var(--sun);cursor:pointer}
.nav-alert .nav-accept{background:var(--sun);color:var(--on-sun);font-weight:600}
.nav-alert .nav-dismiss{border-color:var(--line-2);color:var(--muted)}

/* the walker's own position */
.me{width:34px;height:34px;display:grid;place-items:center}
.me-dot{width:24px;height:24px;border-radius:50%;background:#4EA8FF;
  border:4px solid #fff;box-shadow:0 0 0 7px rgba(78,168,255,.26),0 2px 10px rgba(0,0,0,.4)}
.me-head{position:absolute;top:-15px;width:0;height:0;
  border-left:8px solid transparent;border-right:8px solid transparent;border-bottom:13px solid #4EA8FF;
  filter:drop-shadow(0 -1px 1px rgba(255,255,255,.9))}

.navbtn{display:flex;align-items:center;justify-content:center;gap:7px;width:100%;margin-top:10px;
  padding:10px;border-radius:8px;border:0;cursor:pointer;background:var(--sun);color:var(--on-sun);
  font-family:var(--mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;font-weight:600}
.navbtn:hover{background:var(--sun-hot)}
.navbtn .ic{width:15px;height:15px}
@media (max-width:900px){
  #nav{padding:10px 12px 9px}
  .nav-instr{font-size:13.5px}
}

/* Navigating takes the whole viewport. On a walk the rail is unreadable at arm's
   length and the map is the only thing that matters; the panel carries everything
   worth reading. The basemap switcher goes too, because navigation borrows the one
   style that can draw buildings and would only be broken by switching away. */
body.navigating #app{grid-template-columns:1fr;grid-template-rows:1fr}
body.navigating #rail{display:none}
body.navigating #map{grid-column:1;grid-row:1;height:100dvh}
body.navigating .mapmenu{display:none}
@media (max-width:900px){
  body.navigating #app{grid-template-rows:1fr}
  body.navigating #map{height:100dvh}
}

/* An author `display` rule beats the UA stylesheet's [hidden]{display:none}, so every
   element toggled through .hidden needs this said explicitly. Without it the optimise
   button showed for a two-stop journey and the navigation alert rendered as an empty
   highlighted bar whenever it had nothing to say. */
[hidden]{display:none !important}

/* The turn is now: one pulse as each manoeuvre arrives, never a repeating flash.
   Reported problem was people reading the banner too late, not too quietly. */
@keyframes navflash{
  0%   {background:var(--glass-3)}
  18%  {background:var(--sun-tint)}
  46%  {background:var(--glass-3)}
  64%  {background:var(--sun-wash)}
  100% {background:var(--glass-3)}
}
@keyframes navflashicon{
  0%,100%{transform:scale(1)}
  22%    {transform:scale(1.14)}
  60%    {transform:scale(1.05)}
}
#nav.flash{animation:navflash 1.5s ease-out 1}
#nav.flash .nav-icon{animation:navflashicon 1.5s ease-out 1}
@media (prefers-reduced-motion: reduce){
  #nav.flash,#nav.flash .nav-icon{animation:none}
  #nav.flash{background:var(--sun-wash)}
}
@media (max-width:900px){
  .nav-icon{width:48px;height:48px}
  .nav-icon .ic{width:28px;height:28px}
  .nav-dist{font-size:22px}
  .nav-instr{font-size:15.5px}
  .nav-next{padding-inline-start:61px}
}

/* ---- departure ----------------------------------------------------------
   Relative chips for the common case, an exact date and time behind "Later". */
.whenchips{display:flex;gap:5px;flex-wrap:wrap;flex:1}
.whenchip{font-family:var(--mono);font-size:9.5px;letter-spacing:.08em;text-transform:uppercase;
  padding:6px 9px;border-radius:99px;border:1px solid var(--line-2);background:none;
  color:var(--muted);cursor:pointer;transition:.15s;white-space:nowrap}
.whenchip:hover{color:var(--sun-ink);border-color:var(--sun-ink)}
.whenchip.on{background:var(--sun);border-color:var(--sun);color:var(--on-sun);font-weight:600}
.whenpick{display:flex;gap:8px;margin-top:9px}
.whenpick input{flex:1;min-width:0;font-family:var(--mono);font-size:12px;color:var(--plaster);
  background:var(--ink-1);border:1px solid var(--line-2);border-radius:7px;padding:7px 9px}
.whenpick input::-webkit-calendar-picker-indicator{filter:var(--picker-filter)}
@media (pointer: coarse){
  .whenchip{padding:8px 11px;font-size:10px}
  .whenpick input{font-size:16px}   /* iOS zooms anything under 16px on focus */
}

/* ---- saved places -------------------------------------------------------- */
.iconbtn.fav.on{color:var(--sun-ink)}
.iconbtn.fav.on .ic{fill:var(--sun-ink)}

/* ---- feedback sheet ------------------------------------------------------ */
.sheet{position:fixed;inset:0;z-index:60;display:grid;place-items:center;padding:20px;
  background:var(--scrim);backdrop-filter:blur(6px)}
.sheet-card{width:min(440px,100%);max-height:88dvh;overflow:auto;padding:20px;
  background:var(--ink-1);border:1px solid var(--line-2);border-radius:14px;
  box-shadow:var(--shadow-panel)}
.sheet-head{display:flex;align-items:center;justify-content:space-between;gap:12px}
.sheet-head h2{font-size:19px;font-weight:600;color:var(--plaster);margin:0}
.sheet-note{margin:8px 0 12px;font-size:12.5px;color:var(--plaster-dim);line-height:1.45}
.sheet-fine{margin:9px 0 13px;font-size:10.5px;color:var(--muted);line-height:1.45}
.sheet-card textarea,.sheet-card input{width:100%;box-sizing:border-box;
  background:var(--ink);border:1px solid var(--line-2);border-radius:9px;padding:11px 12px;
  color:var(--plaster);font:inherit;font-size:14px;line-height:1.45;resize:vertical}
.sheet-card input{margin-top:9px;font-size:13px}
.sheet-card textarea:focus,.sheet-card input:focus{outline:none;border-color:var(--sun)}
.sheet-card .navbtn{margin-top:4px}
@media (pointer: coarse){
  .sheet-card textarea,.sheet-card input{font-size:16px}   /* stop iOS zooming on focus */
}

/* ---- coverage request --------------------------------------------------- */
.coverage{position:absolute;left:50%;transform:translateX(-50%);bottom:18px;z-index:9;
  max-width:min(430px,calc(100% - 28px));display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  padding:11px 14px;border-radius:12px;background:var(--glass-3);backdrop-filter:blur(10px);
  border:1px solid var(--sun);box-shadow:var(--shadow-float);
  font-size:12.5px;line-height:1.45;color:var(--plaster)}
.coverage span{flex:1 1 190px;min-width:0}
.coverage button{font-family:var(--mono);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;
  padding:7px 12px;border-radius:99px;border:1px solid var(--sun);background:var(--sun);
  color:var(--on-sun);font-weight:600;cursor:pointer;white-space:nowrap}
.coverage button.ghost{background:none;color:var(--muted);border-color:var(--line-2)}
.coverage button:hover{filter:brightness(1.07)}
/* Clear of the map-layers button, which is bottom-left and, at this width, under the
   coverage panel rather than beside it. */
@media (pointer: coarse){ .coverage{bottom:14px;font-size:13px} }
@media (max-width:900px){ .coverage{bottom:60px} }
body.navigating .coverage{display:none}

/* ---- appearance switch --------------------------------------------------- */
.mastbtn .ic{width:15px;height:15px}
@media (pointer: coarse){ .mastbtn .ic{width:17px;height:17px} }

/* ---- departure, from the map --------------------------------------------
   The pill used to be a label reading back the model clock. It now states the
   departure and is the way into the control that sets it: on a phone that control is
   otherwise below the fold, and the departure changes every answer on the screen. */
.pill-when{cursor:pointer;transition:border-color .18s,color .18s}
.pill-when:hover{border-color:var(--sun-ink);color:var(--plaster)}
.pill-when .caret{width:13px;height:13px;opacity:.7;margin-inline-start:-3px}
@media (pointer: coarse){ .pill-when{padding:10px 14px} }

/* The answer to the tap: the block has just scrolled into view and has to say which
   of the things now on screen it is. */
@keyframes ping{
  0%  {box-shadow:0 0 0 0 var(--sun-tint)}
  30% {box-shadow:0 0 0 5px var(--sun-wash)}
  100%{box-shadow:0 0 0 0 rgba(255,176,32,0)}
}
#dep-block.ping{animation:ping 1.4s ease-out 1;border-radius:8px}
@media (prefers-reduced-motion: reduce){#dep-block.ping{animation:none}}

/* ---- mobile: when you leave belongs with where you are going --------------
   On a phone the rail is the bottom half of the screen and the departure block was
   the sixth thing in it, so in practice nobody found it. But a departure time is an
   input to the question, not a preference: from, to and when belong together, above
   the answer. Done with `order` rather than a second copy of the markup, so there is
   still one control, one set of handlers and one place to fix. */
@media (max-width:900px){
  .rail-inner > *{order:5}
  .sec.mast{order:0}
  .sec-route{order:1}
  #dep-block{order:2;animation-delay:.16s}
  #routes-block{order:3;animation-delay:.23s}
  #advice-block{order:4;animation-delay:.30s}
  .sec:nth-child(5){animation-delay:.37s}   /* shade preference, now fifth on screen */
  footer{order:9}

  /* Compact with it: the chips are the control and lead, the curve is the evidence
     and follows at two thirds height. The pair costs about what the canvas alone used
     to, which is what keeps the results in view underneath. */
  #dep-block .day{display:flex;flex-direction:column}
  #dep-block .timerow{order:0;margin-top:0}
  #dep-block #daycurve{order:1;height:42px;margin-top:10px}
  #dep-block .day-axis{order:2}
  #dep-block .whenpick{order:3}
}

/* ---- masthead controls -----------------------------------------------------
   One group, so it wraps whole and never half of it. Wrapped it sits on the rail's
   own left edge, in line with every label and field under it. Everything narrows on
   a phone, where the rail is the bottom half of the screen and the row it costs is
   a row the route does not get. */
.mast-actions{flex:0 0 auto;display:flex;align-items:flex-start;gap:8px}
.mast-actions > *{flex:0 0 auto}
@media (max-width:900px){
  .mast{gap:9px;row-gap:9px}
  .mast p{margin-top:5px}
  h1{font-size:28px}
  .mast-actions{gap:6px}
  .mastbtn{padding:6px}
  .langbtn{padding:6px 9px;letter-spacing:.08em}
}
