/* ---- 56 DISTINCT FONT SIZES ACROSS 481 DECLARATIONS ----
   Every one was a local decision that looked right beside the thing next to it, and together
   they read as a page assembled by several people who never met. A reader cannot tell what is
   important when eleven sizes sit between .8 and 1rem, because none of them is a step - they
   are noise around a number.
   Eight steps, each far enough from the next to mean something:

     --t-micro   .68rem   credits, licences, the small print that must be legible and quiet
     --t-small   .78rem   meta lines, chips, captions
     --t-sm      .86rem   secondary prose
     --t-base    .95rem   body
     --t-lg      1.05rem  lead paragraphs
     --t-h3      1.2rem   card titles
     --t-h2      1.5rem   section headings
     --t-h1      2.2rem   page titles

   The two display sizes - the clamp() hero and the big numeric readouts - keep their own
   voice deliberately: they are not text, they are the thing the page is about. */
:root{
  --t-micro:.68rem; --t-small:.78rem; --t-sm:.86rem; --t-base:.95rem;
  --t-lg:1.05rem; --t-h3:1.2rem; --t-h2:1.5rem; --t-h1:2.2rem;
}

/* ================= THE STACKING ORDER =================
   27 z-index values were in use with nothing written down, and the map corner collided three
   times because of it: the OpenStreetMap credit under the mode bar, the layer switch under
   the legend, the dock over the bar. Each was fixed by inventing another number - 1150, then
   1160, then 1400 - which is how you get 27 values and no scheme.
   The bands below are what the file ALREADY does, written down so the next control has an
   obvious home instead of a number one higher than whatever it collided with:

     -2 .. -1     behind everything: decorative washes
      0 .. 9      inside a card: badges, credits, save stars
     30 .. 99     page furniture: sticky bars, headers
        900       map underlay: things drawn beneath the route
   1100 .. 1499   map controls: notes, mode bar, layer switch, legend
        1400      the OpenStreetMap credit - nothing on the map may cover it
   1500 .. 1999   the minimap dock and its tab
   2000 .. 2999   the expanded map, which re-stacks its own controls
   3000 .. 4999   overlays: dialogs, flashes, the lead bar
        9500      boot screen, above everything by definition

   A new control belongs IN a band, not one above its neighbour. The UI audit enforces the
   two boundaries that have actually caused bugs. */

/* DEAD CSS: MEASURED, AND DELIBERATELY LEFT.
   14 classes are styled and never referenced - bkWheel, bkFrame, bkRider, bkSteel among them,
   the parts of the rider silhouette taken off the hero. It is tempting to strip them, and I
   tried: they are not standalone rules. They live as descendants (`.social svg .fillOn`) and
   inside selector lists (`.rbMini,.suggRow,.fcRow{display:none}`), so a regex
   that removes them removes live rules with them. One rule came out cleanly; the other
   thirteen would need each selector list edited by hand and re-verified.
   That is a real tidy-up and not a safe one to do blind, so it is recorded here rather than
   half-done. The audit keeps reporting them, which is the correct outcome: a known,
   measured, harmless debt that nobody has to rediscover. */
:root{--miniW:168px;--miniH:176px;--miniMapH:140px;color-scheme:dark;
  --bg:#0b0c0e; --card:#14161a; --raise:#1b1e24; --edge:#262a31; --edge2:#31363f;
  --ink:#f4f2ec; --mut:#a9a69d; --dim:#8f8c84;
  --red:#e11b2b; --red-hot:#ff3b47; --red-dim:rgba(225,27,43,.14);
  --amber:#f2a71b; --teal:#2bbfa4; --green:#4fce7f; --blue:#4a9fd8;
  --display:'Barlow Condensed','Arial Narrow',Arial,sans-serif;
  --body:system-ui,-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
  --rad:14px; --rad-s:10px;
  --shadow:0 16px 44px rgba(0,0,0,.5);
  --maxw:1060px}
html{scroll-behavior:smooth}
body{
  /* 17px base, not 16 - this is read on a phone at arm's length, often outdoors. */
  margin:0;background:var(--bg);color:var(--ink);font-family:var(--body);
  font-size:15px;line-height:1.6;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  min-height:100vh;
}
body:before{content:"";position:fixed;inset:0;z-index:-2;
  background:
    radial-gradient(1000px 480px at 85% -8%,rgba(225,27,43,.09),transparent 60%),
    radial-gradient(760px 520px at -8% 108%,rgba(74,159,216,.06),transparent 60%),
    linear-gradient(165deg,#101216 0%,#0b0c0e 52%,#08090b 100%);}
body:after{content:"";position:fixed;inset:0;z-index:-1;opacity:.45;pointer-events:none;
  background:repeating-linear-gradient(115deg,transparent 0 130px,rgba(244,242,236,.02) 131px,transparent 133px);}
a{color:inherit}
button{font:inherit;cursor:pointer}
input,select{font:inherit}
img{max-width:100%}
::selection{background:var(--red);color:#fff}*{box-sizing:border-box;scrollbar-width:thin;scrollbar-color:#2c313a transparent}
*::-webkit-scrollbar{width:9px;height:9px}
*::-webkit-scrollbar-thumb{background:#2c313a;border-radius:99px}

h1,h2,h3,h4{font-family:var(--display);letter-spacing:.015em;margin:0}
.num{font-variant-numeric:tabular-nums}

/* Chevron ribbon - the curve-sign signature */
.chev{display:flex;align-items:center;gap:14px;margin:34px 0 16px}
.chev h2{font-size:22px;font-weight:700;text-transform:uppercase;font-style:italic;white-space:nowrap;min-width:0;overflow:hidden;text-overflow:ellipsis}
.chev .band{flex:1;height:14px;min-width:60px;border-radius:3px;opacity:.9;
  background:repeating-linear-gradient(-58deg,var(--red) 0 14px,#fff 14px 17px,transparent 17px 30px);
  mask-image:linear-gradient(90deg,#000 70%,transparent);-webkit-mask-image:linear-gradient(90deg,#000 70%,transparent)}
.chev small{color:var(--dim);font-size:15px;white-space:nowrap;min-width:0;overflow:hidden;text-overflow:ellipsis}

/* ------- views ------- */
.view{display:none;max-width:var(--maxw);margin:0 auto;padding:0 18px 90px;
  padding-left:max(18px,env(safe-area-inset-left));padding-right:max(18px,env(safe-area-inset-right));}
.view.on{display:block;animation:viewIn .3s ease both}
/* Deliberately opacity-only. A transform here makes .view a containing block for
   position:fixed descendants, which is why the expanded map never filled the screen. */
@keyframes viewIn{from{opacity:0}to{opacity:1}}

/* ------- top bar ------- */
.top{position:sticky;top:0;z-index:50;background:rgba(11,12,14,.86);
  backdrop-filter:blur(14px) saturate(1.15);-webkit-backdrop-filter:blur(14px) saturate(1.15);
  border-bottom:1px solid var(--edge)}
.topIn{max-width:var(--maxw);margin:0 auto;display:flex;align-items:center;gap:12px;padding:10px 18px;
  padding-left:max(18px,env(safe-area-inset-left));padding-right:max(18px,env(safe-area-inset-right))}
.top .mark{width:34px;height:34px;flex:0 0 auto;/* halo removed: a red glow around a mark is the same effect he has now asked me three times to take off the elevation profile. Nothing in this interface glows. */}
.top .word{font-family:var(--display);font-style:italic;font-weight:700;font-size:19px;
  text-transform:uppercase;letter-spacing:.02em;text-decoration:none;white-space:nowrap;min-width:0;overflow:hidden;text-overflow:ellipsis}
.top .word b{color:var(--red-hot)}
.top .spacer{flex:1}
.top .tbtn{background:transparent;border:1px solid var(--edge);color:var(--mut);border-radius:99px;
  padding:7px 14px;font-family:var(--display);font-weight:600;text-transform:uppercase;letter-spacing:.07em;font-size:15px;
  transition:color .15s,border-color .15s}
.top .tbtn:hover{color:var(--ink);border-color:var(--red)}
.top .tbtn.onSaved{color:var(--amber);border-color:var(--amber)}/* ------- HOME ------- */
.searchCard:before{content:"";position:absolute;left:0;right:0;top:0;height:4px;border-radius:var(--rad) var(--rad) 0 0;
  background:repeating-linear-gradient(-58deg,var(--red) 0 12px,#fff 12px 15px,#0000 15px 26px)}
.fRow{margin-top:16px}
.startWrap input:focus{outline:none;border-color:var(--red);box-shadow:none;border-width:2px}
.suggest{position:absolute;top:calc(100% + 6px);left:0;right:0;background:var(--raise);border:1px solid var(--edge2);
  border-radius:var(--rad-s);box-shadow:var(--shadow);z-index:30;overflow:hidden;display:none}
.suggest.on{display:block}
.suggest button{display:block;width:100%;text-align:left;background:none;border:0;color:var(--ink);
  padding:11px 14px;font-size:15px;border-bottom:1px solid var(--edge)}
.suggest button:last-child{border-bottom:0}
.suggest button:hover,.suggest button:focus-visible{background:var(--red-dim)}
.suggest button small{color:var(--dim);margin-left:8px}
.chips{display:flex;flex-wrap:wrap;gap:9px}
.chip{background:#0d0f12;border:1px solid var(--edge);color:var(--mut);border-radius:99px;padding:10px 16px;
  font-family:var(--display);font-weight:600;font-size:15px;letter-spacing:.03em;min-height:42px;
  transition:all .14s}
.chip:hover{border-color:var(--edge2);color:var(--ink)}
.chip.on{background:var(--red);border-color:var(--red);color:#fff;box-shadow:none}
.goBtn{width:100%;margin-top:22px;background:linear-gradient(180deg,var(--red-hot),var(--red));border:0;color:#fff;
  border-radius:var(--rad-s);min-height:54px;font-family:var(--display);font-weight:700;font-style:italic;
  font-size:22px;text-transform:uppercase;letter-spacing:.05em;
  transition:filter .15s,transform .1s}
.goBtn:hover{filter:brightness(1.07)}
.goBtn:active{transform:translateY(1px)}
.goBtn[disabled]{filter:grayscale(.6) brightness(.7);cursor:wait}
.homeStats{display:grid;grid-template-columns:repeat(2,1fr);gap:18px 10px;margin:38px 0 6px;color:var(--mut)}
@media(min-width:700px){.homeStats{grid-template-columns:repeat(4,1fr)}}
.friend{display:flex;align-items:center;gap:12px;max-width:640px;margin:26px auto 0;background:var(--card);
  border:1px solid var(--edge);border-radius:var(--rad-s);padding:12px 16px;text-decoration:none;transition:border-color .15s}
.friend:hover{border-color:var(--edge2)}
.friend img{width:38px;height:38px}
.friend b{font-family:var(--display);text-transform:uppercase;letter-spacing:.06em;font-size:15px}
.friend span{display:block;color:var(--dim);font-size:15px}
.friend strong{margin-left:auto;color:var(--red-hot);font-family:var(--display);text-transform:uppercase;font-size:15px}

/* ------- RESULTS ------- */
.resHead{display:flex;align-items:flex-end;justify-content:space-between;gap:14px;flex-wrap:wrap;padding-top:22px}
.resHead h2{font-size:22px;font-weight:700;font-style:italic;text-transform:uppercase}
.resHead p{margin:4px 0 0;color:var(--mut);font-size:15px}
.resHead .edit{background:none;border:1px solid var(--edge);border-radius:99px;color:var(--mut);padding:8px 16px;
  font-family:var(--display);text-transform:uppercase;letter-spacing:.06em;font-size:15px}
.resHead .edit:hover{color:var(--ink);border-color:var(--red)}
.filterBar .chip{flex:0 0 auto;padding:8px 14px;min-height:38px;font-size:15px}
.sortRow{display:flex;align-items:center;gap:10px;margin:8px 0 4px;color:var(--dim);font-size:15px}
.sortRow select{background:#0d0f12;border:1px solid var(--edge);color:var(--ink);border-radius:8px;padding:7px 10px;font-size:15px}
.rides{display:grid;grid-template-columns:1fr;gap:14px;margin-top:12px}
@media(min-width:760px){.rides{grid-template-columns:1fr 1fr}}
.ride:hover{transform:translateY(-2px);border-color:var(--edge2);box-shadow:var(--shadow)}
.ride:focus-within{border-color:var(--red)}
/* the card is a stack; a transparent button on top makes the whole thing clickable */
.rideOpen{position:absolute;inset:0;z-index:1;background:none;border:0;padding:0;
  border-radius:var(--rad);cursor:pointer}
.rideOpen:focus-visible{outline:2px solid var(--red-hot);outline-offset:-3px}
.scorePill{flex:0 0 auto;font-family:var(--display);font-weight:700;font-size:15px;color:#fff;
  /* the red glow read as a halo around every score in "Worth travelling for", where the
     cards sit close together - a flat pill states the number without lighting up the page */
  background:var(--red);border-radius:9px;padding:4px 10px}
.scorePill.mid{background:#8a5a12}
.ride .meta{display:flex;flex-wrap:wrap;gap:6px 14px;color:var(--mut);font-size:15px;margin-top:8px}
.ride .meta b{color:var(--ink);font-weight:600}
.ride .why{margin-top:9px;color:var(--dim);font-size:15px;display:flex;flex-wrap:wrap;gap:6px}
.ride .why span{background:#0d0f12;border:1px solid var(--edge);border-radius:99px;padding:3px 10px}
.ride .sl{display:block;margin:10px 0 0;color:var(--mut);font-size:15px;line-height:1.45}
.saveStar:hover{color:var(--amber);border-color:var(--edge2)}
.saveStar.on{color:var(--amber)}
.emptyMsg{color:var(--mut);text-align:center;padding:50px 20px;line-height:1.6}

/* ------- DETAIL ------- */
.dHead{padding-top:22px;display:flex;gap:16px;align-items:flex-start}
.backBtn{flex:0 0 auto;background:#0d0f12;border:1px solid var(--edge);color:var(--mut);border-radius:99px;
  width:44px;height:44px;font-size:19px;transition:color .15s,border-color .15s}
.backBtn:hover{color:var(--ink);border-color:var(--red)}
.dTitle{flex:1}
.dTitle .crumb{color:var(--red-hot);font-family:var(--display);text-transform:uppercase;letter-spacing:.16em;font-size:15px;font-weight:700}
.dTitle h1,.dTitle h1,.dTitle h2{font-size:clamp(1.5rem,4.5vw,2.2rem);font-weight:700;font-style:italic;line-height:1.02;margin-top:4px}
.dTitle p{color:var(--mut);margin:8px 0 0;font-size:15px;line-height:1.5}
.dial{flex:0 0 auto;width:92px;height:92px;position:relative}
.dial svg{width:100%;height:100%;transform:rotate(-90deg)}
.dial circle{fill:none;stroke-width:8}
.dial .bgc{stroke:#22262d}
.dial .fgc{stroke:var(--red);stroke-linecap:round;/* halo removed: a red glow around a mark is the same effect he has now asked me three times to take off the elevation profile. Nothing in this interface glows. */;
  transition:stroke-dashoffset .9s cubic-bezier(.2,.7,.2,1)}
.dial .val{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center}
.dial .val b{font-family:var(--display);font-size:22px;font-weight:700;line-height:1}
.dial .val small{color:var(--dim);font-size:12px;text-transform:uppercase;letter-spacing:.16em}
.statRow{display:grid;grid-template-columns:repeat(auto-fit,minmax(105px,1fr));gap:10px;margin-top:18px}
.stat{background:var(--card);border:1px solid var(--edge);border-radius:var(--rad-s);padding:12px 14px}
.stat b{display:block;font-family:var(--display);font-size:22px;font-weight:700}
.stat span{color:var(--dim);font-size:13px;text-transform:uppercase;letter-spacing:.12em}
.brk{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:8px;margin-top:10px}
.brk .b{background:#0d0f12;border:1px solid var(--edge);border-radius:8px;padding:8px 12px;font-size:15px;color:var(--mut)}
.brk .b i{display:block;height:4px;border-radius:99px;background:var(--edge);margin-top:6px;overflow:hidden;font-style:normal}
.brk .b i s{display:block;height:100%;background:var(--red);text-decoration:none}
.mapBox{margin-top:20px;border:1px solid var(--edge);border-radius:var(--rad);overflow:hidden;position:relative;background:#0d0f12}
.leaflet-container{background:#101216;font:inherit}
.wpDot.alt{background:#3b4854}
/* ---- THE ACTION BAR, REBUILT ----
   Eight items in one flex row with `flex:1` on every button - so a download, a link, two
   icons, a time input, a sentence of prose and "The way back" all demanded the same width.
   The labels had nowhere to go but downwards: "BE / BACK / BY" stacked three lines high, and
   the whole thing was sticky at bottom:0 so on a long page it sat over the map.
   Two rows, and each item sized by what it IS:
     row 1 - the things you DO with the ride: GPX, Google Maps, save, share
     row 2 - the things that CHANGE the ride: reverse, be back by, the way back
   Sticky only once the rider has scrolled past the map, so it never covers it on arrival. */
.actionBar{position:sticky;bottom:0;z-index:40;margin:20px -18px 6px;
  padding:12px 18px calc(12px + env(safe-area-inset-bottom));
  background:linear-gradient(180deg,transparent,rgba(11,12,14,.94) 26%);
  display:flex;flex-direction:column;gap:12px}
/* each group is its own grid, with a heading that says what the row is FOR */
.actGroup{display:grid;grid-template-columns:repeat(12,1fr);gap:8px}
.actGroupHead{grid-column:1/-1;margin:0;font:700 12px/1.2 var(--display);
  text-transform:uppercase;letter-spacing:.09em;color:#8e8880}
/* NOWRAP IN A GRID CELL IS THE "WHAT THE ROA..." BUG AGAIN.
   A grid column is a fixed width; nowrap with no overflow rule means a label longer than its
   column is simply cut off - which is precisely the fault he reported on the map bar, one
   layer up. The labels here are long: "Back to the scouted ride", "Stay below 1,800 m".
   They wrap, as they do everywhere else in this project. A control may take two lines; it
   may not hide its own name. */
.actionBar .abtn{flex:none;min-height:46px;font-size:16px;white-space:normal;
  line-height:1.15;padding:6px 12px;text-align:center;overflow:visible;text-overflow:clip}
/* row 1 - what you do with the ride */
.actionBar #gpxBtn{grid-column:span 4}
.actionBar #gmapA{grid-column:span 4}
.actionBar #favBtn,.actionBar #shareBtn{grid-column:span 2}
/* row 2 - what changes the ride */
.actionBar #revBtn{grid-column:span 3}
.actionBar #capBtn:disabled{opacity:.65}
.actionBar .beBack{grid-column:span 5;justify-content:flex-start}
/* the altitude cap is a fourth item on row 2, so that row spans the full twelve either way:
   3 + 4 + 5 with the cap, 3 + 5 + 4 without it. No :has() - the audit rightly pointed out
   that a :has() selector creates a child the base grid rule never covers. */
.actionBar #wayHomeBtn{grid-column:span 4}
/* row 2 spans twelve either way: reverse 3 + be-back-by 5 + way-home 4, and when the
   altitude cap is present it takes 4 and the way-home wraps to its own full-width line.
   Plain descendant selectors only - a combinator confuses the grid-child check for no gain. */
.actionBar #capBtn{grid-column:span 4}
.actionBar .backByOut{grid-column:1/-1;margin:2px 0 0}
@media(max-width:640px){
  .actionBar{grid-template-columns:repeat(6,1fr)}
  .actionBar #gpxBtn,.actionBar #gmapA{grid-column:span 3}
  .actionBar #favBtn,.actionBar #shareBtn{grid-column:span 3}
  .actionBar #revBtn,.actionBar #wayHomeBtn{grid-column:span 3}
  .actionBar .beBack{grid-column:1/-1}
}
.abtn{flex:1;min-height:50px;border-radius:var(--rad-s);font-family:var(--display);font-weight:700;font-size:16px;
  text-transform:uppercase;letter-spacing:.04em;display:flex;align-items:center;justify-content:center;gap:8px;text-decoration:none;
  border:1px solid var(--edge);background:var(--raise);color:var(--ink);transition:filter .15s,border-color .15s}
.abtn:hover{border-color:var(--edge2);filter:brightness(1.1)}
.abtn.main{background:linear-gradient(180deg,var(--red-hot),var(--red));border:0;color:#fff;box-shadow:none}
.abtn.icon{flex:0 0 54px}
.abtn.icon.on{color:var(--amber);border-color:var(--amber)}

/* Rider briefing */
.brief{display:grid;grid-template-columns:1fr;gap:10px}
@media(min-width:760px){.brief{grid-template-columns:1fr 1fr}}
.bCard{background:var(--card);border:1px solid var(--edge);border-left:4px solid var(--dim);
  border-radius:var(--rad-s);padding:13px 15px}
.bCard h4{font-size:15px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;display:flex;gap:8px;align-items:center}
.bCard p{margin:7px 0 0;color:var(--mut);font-size:15px;line-height:1.55}
.bCard p b{color:var(--ink)}
.bCard.warn{border-left-color:var(--amber)}
.bCard.risk{border-left-color:var(--red)}
.bCard.ok{border-left-color:var(--green)}
.bCard.info{border-left-color:var(--blue)}
.bCard .live{color:var(--dim);font-size:13px;text-transform:uppercase;letter-spacing:.1em;margin-left:auto}

.story{background:var(--card);border:1px solid var(--edge);border-radius:var(--rad);padding:18px 20px;
  color:var(--mut);line-height:1.65;font-size:15px}
.story b{color:var(--ink)}

/* Roadbook timeline */
.rb{position:relative;margin-top:6px}
.rbi.k-pass .n,.rbi.k-high .n,.rbi.k-serpentine .n{border-color:var(--red);color:var(--red-hot)}
.rbi.k-fuel .n{border-color:var(--amber);color:var(--amber)}
.rbi.k-food .n{border-color:var(--green);color:var(--green)}
.rbi.k-swim .n,.rbi.k-coast .n{border-color:var(--teal);color:var(--teal)}
.rbi.k-sight .n,.rbi.k-photo .n{border-color:var(--blue);color:var(--blue)}
.rbi h4{font-size:15px;font-weight:700;display:flex;flex-wrap:wrap;align-items:baseline;gap:8px}
.rbi h4 .kind{font-size:13px;color:var(--dim);text-transform:uppercase;letter-spacing:.12em;font-family:var(--body);font-weight:600}
.rbi .leg{color:var(--dim);font-size:15px;margin-top:2px}
.rbi p{margin:6px 0 0;color:var(--mut);font-size:15px;line-height:1.5}
.rbi .poi{margin-top:8px;display:flex;flex-wrap:wrap;gap:6px}
.rbi .poi a{font-size:15px;color:var(--teal);background:rgba(43,191,164,.08);border:1px solid rgba(43,191,164,.25);
  border-radius:99px;padding:3px 10px;text-decoration:none}
.rbi .poi a:hover{background:rgba(43,191,164,.16)}


/* Attractions */
.atrNote{color:var(--dim);font-size:15px;margin-top:10px;line-height:1.5}/* Attraction photo cards */
@media(min-width:700px){.atrGrid{grid-template-columns:1fr 1fr}}
.atrBody p{margin:7px 0 0;color:var(--mut);font-size:15px;line-height:1.5}
.atrLinks a{font-size:15px;color:var(--teal);border:1px solid rgba(43,191,164,.28);background:rgba(43,191,164,.07);
  border-radius:99px;padding:3px 10px;text-decoration:none}
.atrLinks a:hover{background:rgba(43,191,164,.16)}
.scanBtn{background:var(--raise);border:1px solid var(--edge);color:var(--ink);border-radius:99px;
  padding:10px 20px;font-family:var(--display);font-weight:600;text-transform:uppercase;letter-spacing:.05em;font-size:16px}
.scanBtn:hover{border-color:var(--teal);color:var(--teal)}
.scanBtn[disabled]{opacity:.55;cursor:wait}/* Service browser */
.svcChips .chip{flex:0 0 auto;padding:8px 14px;min-height:40px;font-size:15px;display:flex;align-items:center;gap:7px}
.svcChips .cnt{background:rgba(0,0,0,.32);border-radius:99px;padding:1px 7px;font-size:15px}
.svcNote{color:var(--dim);font-size:15px;line-height:1.55;margin:6px 0 12px}
.svcNote .noteWarn{color:var(--amber)}
.svcList{display:grid;gap:8px}
.svcI{display:flex;gap:12px;align-items:flex-start;background:var(--card);border:1px solid var(--edge);
  border-radius:var(--rad-s);padding:11px 14px;flex-wrap:wrap}
.svcMain{flex:1;min-width:180px}
.svcMain b{font-size:15px}
.tag24{display:inline-block;margin-left:8px;background:rgba(79,206,127,.14);color:var(--green);border:1px solid rgba(79,206,127,.3);
  border-radius:99px;padding:1px 8px;font-size:13px;font-weight:700;letter-spacing:.06em}
.svcBits{display:block;color:var(--dim);font-size:15px;margin-top:3px}
.svcHours{display:block;color:var(--mut);font-size:15px;margin-top:3px}
.svcSide{margin-left:auto;text-align:right}
.svcSide>span.num{display:block;color:var(--dim);font-size:15px;white-space:nowrap;min-width:0;overflow:hidden;text-overflow:ellipsis}
.svcLinks{display:flex;gap:7px;justify-content:flex-end;margin-top:6px}
.svcLinks a{font-size:15px;color:var(--mut);border:1px solid var(--edge);border-radius:99px;padding:2px 10px;text-decoration:none}
.svcLinks a:hover{color:var(--ink);border-color:var(--edge2)}

/* Per-checkpoint links */
.wpLinks{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
.wpLinks a{font-size:15px;color:var(--dim);border:1px solid var(--edge);border-radius:99px;padding:2px 9px;text-decoration:none}
.wpLinks a:hover{color:var(--ink);border-color:var(--edge2)}

/* Status / sources */
.srcRow{display:flex;flex-wrap:wrap;gap:9px}
.srcRow a{background:var(--card);border:1px solid var(--edge);border-radius:99px;padding:8px 15px;
  font-size:15px;color:var(--mut);text-decoration:none}
.srcRow a:hover{color:var(--ink);border-color:var(--edge2)}
footer{max-width:var(--maxw);margin:0 auto;padding:26px 18px 40px;color:var(--dim);font-size:15px;line-height:1.6;
  border-top:1px solid var(--edge)}

/* Loader */
#boot{z-index:3000;position:fixed;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:22px;
  background:radial-gradient(800px 480px at 50% 32%,#14161b,#0b0c0e 74%);transition:opacity .4s,visibility .4s}
#boot.done{opacity:0;visibility:hidden;pointer-events:none}
#boot img{width:86px;height:86px;/* halo removed: a red glow around a mark is the same effect he has now asked me three times to take off the elevation profile. Nothing in this interface glows. */}
#boot h2{font-style:italic;text-transform:uppercase;font-size:22px}
#boot p{color:var(--mut);font-size:15px;margin:0}
#boot .bar{width:min(300px,68vw);height:5px;border-radius:99px;background:#22262d;overflow:hidden}
#boot .bar i{display:block;height:100%;width:0;background:linear-gradient(90deg,var(--red),var(--red-hot));transition:width .3s ease}
#boot .err{color:var(--red-hot);display:none;max-width:320px;text-align:center;font-size:15px}

.skel{color:var(--dim);padding:20px 0}
@media(max-width:759px){
  #map{height:380px}
  .dial{width:76px;height:76px}
  .dial .val b{font-size:22px}
  .hero{padding-top:30px}
}
@media (prefers-reduced-motion:reduce){
  *,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}
}

/* ---------- Elevation profile ---------- */
.profWrap{background:var(--card);border:1px solid var(--edge);border-radius:var(--rad);padding:14px 14px 12px;margin-top:4px}
.profLegend span{display:flex;align-items:center;gap:6px}
.profLegend i{width:14px;height:4px;border-radius:99px;display:inline-block}
.profStats{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-top:14px;padding-top:13px;border-top:1px solid var(--edge)}
.profStats div{text-align:center}
.profStats b{display:block;font-family:var(--display);font-size:19px}
.profStats span{color:var(--dim);font-size:12px;text-transform:uppercase;letter-spacing:.1em}
@media(max-width:759px){.profSvg{height:170px}}

/* ---------- Map service layers ---------- */
/* clear of .mapNote above it, which is two lines tall at this width */
.mapLayers{position:absolute;left:10px;top:92px;z-index:1100;display:flex;flex-direction:column;gap:6px}
.mapLayers button:hover{border-color:var(--edge2)}
.mapLayers button.on{border-color:var(--red);background:rgba(225,27,43,.22)}

/* ---------- Offline ---------- */
.offBadge{position:sticky;top:0;z-index:70;background:var(--amber);color:#1a1204;text-align:center;
  font-weight:700;font-size:15px;padding:7px 12px;letter-spacing:.02em}
.offlineBtn{background:var(--raise);border:1px solid var(--edge);color:var(--ink);border-radius:99px;
  padding:7px 14px;font-family:var(--display);font-weight:600;text-transform:uppercase;letter-spacing:.05em;font-size:15px;margin-right:auto}
.offlineBtn:hover{border-color:var(--teal);color:var(--teal)}
.toast{position:fixed;left:50%;transform:translateX(-50%) translateY(20px);bottom:calc(24px + env(safe-area-inset-bottom));
  z-index:2600;background:var(--raise);border:1px solid var(--edge2);color:var(--ink);border-radius:99px;
  padding:11px 20px;font-size:15px;box-shadow:var(--shadow);opacity:0;pointer-events:none;transition:opacity .25s,transform .25s;max-width:88vw;text-align:center}
.toast.on{opacity:1;transform:translateX(-50%) translateY(0)}
.profNote{color:var(--dim);font-size:15px;line-height:1.5;margin:12px 0 0;padding-top:11px;border-top:1px solid var(--edge)}

/* ---------- Butler ---------- */
.butler{background:linear-gradient(180deg,var(--panel,#15181d),#101216);border:1px solid var(--edge);
  border-left:5px solid var(--dim);border-radius:var(--rad);padding:16px 18px;margin-top:18px}
.butler.ok{border-left-color:var(--green)}
.butler.warn{border-left-color:var(--amber)}
.butler.risk{border-left-color:var(--red)}
.butler .bl{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.butler .bl b{font-family:var(--display);font-size:19px;font-weight:700;letter-spacing:.01em}
.blDot{width:10px;height:10px;border-radius:99px;background:var(--dim);flex:0 0 auto}
.butler.ok .blDot{background:var(--green);box-shadow:none}
.butler.warn .blDot{background:var(--amber);box-shadow:none}
.butler.risk .blDot{background:var(--red);box-shadow:none}
.blTag{margin-left:auto;font-family:var(--display);text-transform:uppercase;letter-spacing:.14em;font-size:13px;
  color:var(--dim);border:1px solid var(--edge2);border-radius:99px;padding:3px 11px}
.butler p{margin:10px 0 0;color:var(--mut);line-height:1.65;font-size:15px}
.butler .blPass{color:var(--ink);border-top:1px solid var(--edge);padding-top:10px;font-size:15px}
.blLinks{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-top:12px}
.blLinks span{color:var(--dim);font-size:15px;text-transform:uppercase;letter-spacing:.1em}
.blLinks a{font-size:15px;color:var(--ink);border:1px solid var(--edge2);border-radius:99px;padding:3px 11px;text-decoration:none}
.blLinks a:hover{border-color:var(--red)}

/* ---------- Map furniture ---------- */
/* THREE THINGS WERE STACKED IN THE SAME CORNER.
   The base-layer switch sat at bottom:10px z-1100, the mode bar at bottom:10px z-1150, and
   the OpenStreetMap credit under both - so STREET was hidden behind the buttons and half on
   top of the credit, exactly as he photographed. The bottom-left corner now has one occupant
   per band: credit at the very bottom, mode bar above it, base switch above that. */
/* THE BOTTOM-LEFT CORNER HAD FOUR TENANTS.
   The credit, the mode bar, the road legend AND the base-layer switch - I moved the switch to
   bottom:78px and put it straight underneath the legend panel at bottom:76px, which is how it
   ended up hidden a second time. Four things cannot share one corner however carefully the
   bands are measured.
   The switch belongs with the other MAP-STATE controls, which live top-right: "Whole route"
   and "Close". It sits under them, on the opposite side from the legend, and nothing in that
   column moves when a legend grows. */
/* under .mapExpand in the right-hand column, and far above .miniDock at the bottom */
/* width and height declared so a layout check measures this rather than guessing it */
.mapBase{position:absolute;right:10px;top:94px;left:auto;bottom:auto;z-index:1160;width:96px;height:34px}
.mapBase button.on{border-color:var(--red);background:rgba(225,27,43,.22)}
.speedKey{display:flex;flex-wrap:wrap;gap:10px 16px;align-items:center;background:var(--card);border:1px solid var(--edge);
  border-radius:var(--rad-s);padding:11px 14px;margin-top:10px;color:var(--mut);font-size:15px}
.speedKey b{color:var(--ink);font-family:var(--display);text-transform:uppercase;letter-spacing:.06em;font-size:15px;width:100%}
.speedKey span{display:flex;align-items:center;gap:7px}
.speedKey i{width:16px;height:4px;border-radius:99px;display:inline-block}

/* ---------- Service extras ---------- */
.stOpen,.stShut,.stUnk{display:inline-block;margin-left:8px;border-radius:99px;padding:1px 9px;font-size:13px;font-weight:700;letter-spacing:.05em}
.stOpen{background:rgba(79,206,127,.14);color:var(--green);border:1px solid rgba(79,206,127,.3)}
.stShut{background:rgba(225,27,43,.12);color:var(--red-hot);border:1px solid rgba(225,27,43,.28)}
.stUnk{background:#22262d;color:var(--dim);border:1px solid var(--edge2)}
.sees{display:block;color:var(--mut);font-size:15px;margin-top:6px;line-height:1.5}
.sees b{color:var(--ink)}

/* ---------- Explorer ---------- */
.exGrid{display:grid;grid-template-columns:1fr;gap:14px;margin-top:14px}
@media(min-width:700px){.exGrid{grid-template-columns:1fr 1fr}}
.exCard:hover{transform:translateY(-2px);border-color:var(--edge2)}
.exCard.picked{border-color:var(--red);box-shadow:0 0 0 1px var(--red) inset}
.exPic{position:relative;height:156px;background:#0d0f12;display:flex;align-items:center;justify-content:center;overflow:hidden}
.exPic img{width:100%;height:100%;object-fit:cover;display:block}
.exPh{font-size:22px;opacity:.3}
.exCred{position:absolute;left:0;right:0;bottom:0;background:linear-gradient(180deg,transparent,rgba(0,0,0,.8));
  color:#cfcbc2;font-size:12px;padding:14px 8px 4px;text-decoration:none;text-align:right;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.exCred:hover{color:#fff}
.exBody{padding:14px 15px 15px;display:flex;flex-direction:column;flex:1}
.exTop{display:flex;gap:10px;align-items:flex-start}
.exTop h3{flex:1;font-size:15px;font-weight:700;line-height:1.15}
.exMeta{color:var(--mut);font-size:15px;margin-top:7px}
.exBody p{color:var(--dim);font-size:15px;line-height:1.5;margin:9px 0 0}
.exBars{margin-top:12px;display:grid;gap:6px}
.exBar{display:flex;align-items:center;gap:9px;font-size:13px;color:var(--dim)}
.exBar span{width:74px;flex:0 0 auto}
.exBar i{flex:1;height:5px;border-radius:99px;background:var(--edge);overflow:hidden;font-style:normal}
.exBar i s{display:block;height:100%;background:linear-gradient(90deg,var(--red),var(--red-hot));text-decoration:none}
.exBar b{width:24px;text-align:right;color:var(--mut)}
.exActs{display:flex;gap:8px;margin-top:14px}
.exActs button{flex:1;min-height:42px;border-radius:var(--rad-s);border:1px solid var(--edge);background:var(--raise);
  color:var(--ink);font-family:var(--display);font-weight:600;text-transform:uppercase;letter-spacing:.05em;font-size:15px}
.exActs .exOpen{background:linear-gradient(180deg,var(--red-hot),var(--red));border:0;color:#fff}
.exActs button:hover{filter:brightness(1.08)}
.cmpWrap{background:var(--card);border:1px solid var(--red);border-radius:var(--rad);padding:14px;margin-top:14px}
.cmpHead{display:flex;align-items:center;gap:12px;margin-bottom:10px}
.cmpHead b{font-family:var(--display);text-transform:uppercase;letter-spacing:.06em}
.cmpHead button{margin-left:auto;background:none;border:1px solid var(--edge2);color:var(--mut);border-radius:99px;padding:5px 13px;font-size:15px}
.cmpScroll{overflow-x:auto}
.cmpTable{width:100%;border-collapse:collapse;font-size:15px;min-width:420px}
.cmpTable th,.cmpTable td{text-align:left;padding:8px 10px;border-bottom:1px solid var(--edge);vertical-align:top}
.cmpTable thead th{color:var(--ink);font-family:var(--display);font-size:15px;font-weight:700}

/* Leaflet's controls get their own corners; ours sit above them */
/* ---- THE ATTRIBUTION IS A LICENCE TERM, NOT A CAPTION ----
   The mode bar sits at bottom:10px with z-index 1150 and lay straight over it, so
   "OpenStreetMap" was half-hidden behind the buttons in every screenshot. Using OSM tiles
   obliges us to show that credit clearly - it is the one thing on the map that is not ours
   to lay something on top of. It now has its own reserved strip along the bottom, above the
   controls in stacking order, and the controls sit clear of it. */
.leaflet-control-attribution{position:absolute!important;left:0!important;right:0!important;
  bottom:0!important;z-index:1400!important;
  background:rgba(11,12,14,.86)!important;color:#cfcac3!important;font-size:14px!important;
  padding:3px 10px!important;border-radius:0!important;text-align:right;
  pointer-events:auto;white-space:nowrap;overflow:visible;text-overflow:clip}
.leaflet-control-attribution a{color:var(--mut)!important}
.leaflet-bottom.leaflet-left{margin-bottom:0}.mapBase button{background:rgba(11,12,14,.88);border:1px solid var(--edge);color:var(--ink);border-radius:10px;
  padding:8px 14px;font-family:var(--display);font-weight:600;text-transform:uppercase;letter-spacing:.06em;font-size:16px;box-shadow:0 4px 14px rgba(0,0,0,.5)}.mapNote{position:absolute;left:10px;top:10px;z-index:1100;max-width:52%;background:rgba(11,12,14,.85);border:1px solid var(--edge);
  border-radius:8px;padding:6px 11px;font-size:15px;color:var(--mut);box-shadow:0 4px 14px rgba(0,0,0,.45)}
@media(max-width:759px){
  .mapNote{max-width:calc(100% - 96px);font-size:13px;padding:5px 9px}
  .mapBase{right:8px;top:52px;left:auto;bottom:auto}
  .mapLayers{top:48px;left:8px}
}

/* ---------- Swipe deck ---------- */
.swipeCta{width:100%;margin-top:14px;background:linear-gradient(180deg,#1b1f25,#141519);border:1px dashed var(--edge2);
  color:var(--ink);border-radius:var(--rad-s);min-height:48px;font-family:var(--display);font-weight:600;
  text-transform:uppercase;letter-spacing:.04em;font-size:15px;transition:border-color .15s,color .15s}
.swipeCta:hover{border-color:var(--red);color:var(--red-hot)}
.swHead{display:flex;gap:14px;align-items:center;padding-top:22px}
.swHead h2{font-size:22px;font-weight:700;font-style:italic;text-transform:uppercase}
.swHead p{margin:2px 0 0;color:var(--mut);font-size:15px}
/* ---- THE CARD IS AS TALL AS WHAT IS ON IT ----
   A fixed 520px stack left a third of the card empty under the text - dead space that made
   a finished card look unfinished. The stack takes its height from the card inside it, and
   the card sizes to its content. */
/* the action buttons overlapped the card by 34px - measured - so the last line of the card
   sat under them. The stack reserves the room the buttons need. */
/* the swipe stack has to clear the tab bar on a phone and needs nothing on a desktop */
.swStack{position:relative;margin-top:18px;margin-bottom:96px;perspective:1000px;min-height:420px;
  /* the cards are absolutely positioned, so the stack cannot grow to fit them: a long card ran under
     the action bar that follows. The stack has a height, every card fills it, and the text scrolls
     inside the card - so nothing is cut off and nothing sits beneath the buttons */
  height:min(72vh,680px)}
@media(max-width:767px){
  /* On a phone the stack, the header and the action bar must share one screen: the bar used to end
     at 1,035 px on an 844 px phone, so every decision needed a scroll. The stack takes what is left
     after the header and the bar. */
  .swStack{margin-bottom:12px;height:calc(100dvh - 350px - var(--tabbarSpace, 0px));min-height:330px}
  /* The bar stays in normal flow directly under the stack. An earlier attempt made it sticky with
     bottom:64px; the later .swBar{position:relative} cancelled the sticky but NOT the offset, and a
     relative element with bottom:64px moves up - onto the card, 44 px of overlap. The stack is sized
     so the bar fits on the first screen without being pinned at all. */
  /* the guide's portrait sits above its passage, so the passage gets the card's full width instead of
     a 189 px column beside the face */
  .swInfo .csTeaser{flex-direction:column;align-items:flex-start}
  .swInfo .csTeaser img{width:64px;height:64px}
  .swInfo{padding-left:12px;padding-right:12px}
  .swInfo .csTeaser{padding-left:0;padding-right:0}
}
.swBar{position:relative;z-index:3;margin-top:14px}
.swScope{display:flex;gap:4px;background:var(--card);border:1px solid var(--edge);
  border-radius:999px;padding:3px;margin-left:auto;width:max-content}
.scBtn{font-family:var(--display);text-transform:uppercase;letter-spacing:.05em;font-size:12px;
  padding:8px 14px;min-height:44px;border:0;border-radius:999px;background:transparent;
  color:var(--ink);opacity:.7;cursor:pointer}
.scBtn.on{background:var(--red);color:#fff;opacity:1}
.swHead{display:flex;align-items:center;gap:12px}
.swStack::after{content:'';display:block;padding-top:0}
@media(max-width:759px){.swStack{min-height:380px}}
.swCard{position:absolute;left:0;right:0;top:0;bottom:0;background:var(--card);border:1px solid var(--edge);border-radius:18px;
  overflow:hidden;box-shadow:var(--shadow);display:flex;flex-direction:column;
  transform:scale(.955) translateY(12px);opacity:.65;pointer-events:none}
.swCard.top{transform:none;opacity:1;pointer-events:auto;cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none}
.swCard.top:active{cursor:grabbing}
.swPic{position:relative;flex:1;min-height:0;background:#0d0f12;display:flex;align-items:center;justify-content:center;overflow:hidden}
.swPic img{width:100%;height:100%;object-fit:cover;pointer-events:none}
.swPh{font-size:34px;opacity:.25}
.swInfo{padding:16px 18px 18px;background:linear-gradient(180deg,rgba(20,22,26,.96),#14161a);flex:0 1 auto;
  /* the text area scrolls vertically inside the card; a horizontal drag still swipes the card */
  min-height:0;max-height:62%;overflow-y:auto;overscroll-behavior:contain;touch-action:pan-y}
.swTop{display:flex;gap:12px;align-items:flex-start}
.swTop h3{flex:1;font-size:19px;font-weight:700;line-height:1.12}
.swMeta{color:var(--mut);font-size:15px;margin-top:7px}
.swTags{display:flex;flex-wrap:wrap;gap:6px;margin-top:9px}
.swTags span{background:#0d0f12;border:1px solid var(--edge);border-radius:99px;padding:2px 10px;font-size:13px;color:var(--mut)}
/* the two-line clamp is for the ride's own short lines. It used to match every paragraph in the
   card, including the guide's passage nested inside it, so a 100-word explanation showed as one line
   after the guide's name. `>` limits it to the paragraphs that are direct children. */
.swInfo > p{margin:10px 0 0;color:var(--dim);font-size:15px;line-height:1.5;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.swStamp{position:absolute;top:26px;font-family:var(--display);font-weight:700;font-style:italic;font-size:22px;
  letter-spacing:.06em;padding:6px 16px;border:4px solid;border-radius:10px;opacity:0;pointer-events:none;transition:opacity .1s}
.swStamp.keep{left:22px;color:var(--green);border-color:var(--green);transform:rotate(-14deg)}
.swStamp.nope{right:22px;color:var(--red-hot);border-color:var(--red-hot);transform:rotate(14deg)}
.swBar{display:flex;align-items:center;justify-content:center;gap:14px;margin-top:20px}
.swBtn{border-radius:99px;border:1px solid var(--edge2);background:var(--raise);color:var(--ink);
  width:66px;height:66px;font-size:22px;line-height:1;display:flex;align-items:center;justify-content:center;
  transition:transform .12s,border-color .15s,filter .15s}
.swBtn:hover{transform:scale(1.06)}
.swBtn:active{transform:scale(.95)}
.swBtn.sm{width:50px;height:50px;font-size:15px;color:var(--mut)}
.swBtn.sm:disabled{opacity:.35;cursor:not-allowed;transform:none}
.swBtn.no{border-color:var(--red);color:var(--red-hot);background:rgba(225,27,43,.1)}
.swBtn.yes{border-color:var(--green);color:var(--green);background:rgba(79,206,127,.1)}
.swHint{text-align:center;color:var(--dim);font-size:15px;margin-top:14px;line-height:1.5}
.swDone{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:12px;text-align:center;padding:30px;background:var(--card);border:1px solid var(--edge);border-radius:18px}
.swDone h3{font-family:var(--display);font-size:22px;font-weight:700;font-style:italic;text-transform:uppercase}
.swDone p{color:var(--mut);line-height:1.6;max-width:380px;margin:0}
.swDone b{color:var(--ink)}
.swDoneActs{display:flex;flex-wrap:wrap;gap:10px;justify-content:center;margin-top:8px}
.swDoneActs .abtn{flex:0 0 auto;padding:0 20px}/* ================= HOME v3 ================= */
.heroGrain{position:absolute;inset:0;z-index:2;pointer-events:none;opacity:.5;
  background:repeating-linear-gradient(115deg,transparent 0 100px,rgba(244,242,236,.03) 101px,transparent 103px)}
@keyframes markIn{from{opacity:0;transform:translateY(-14px) scale(.85)}to{opacity:1;transform:none}}
.heroIn h1 span{display:block;animation:lineUp .8s cubic-bezier(.2,.8,.2,1) both}
.heroIn h1 .l1{animation-delay:.1s}
.heroIn h1 .l2{animation-delay:.22s}
.heroIn h1 b{color:var(--red-hot)}
@keyframes lineUp{from{opacity:0;transform:translateY(26px)}to{opacity:1;transform:none}}
.heroIn .tag{color:var(--ink);letter-spacing:.34em;text-transform:uppercase;font-size:15px;margin:18px 0 0;
  opacity:.85;animation:lineUp .8s .34s cubic-bezier(.2,.8,.2,1) both}
.heroScroll:hover{border-color:var(--red);color:var(--red-hot)}
@keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(6px)}}
.heroCred b{display:block;color:var(--ink);font-family:var(--display);font-size:15px;text-transform:uppercase;
  letter-spacing:.04em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.heroCred span{display:block;color:var(--dim);font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.heroCred:hover b{color:var(--red-hot)}
.heroDots i.on{background:var(--red-hot);width:26px}.fRow label{display:block;color:var(--dim);text-transform:uppercase;letter-spacing:.12em;font-weight:700;margin-bottom:7px;font-size:13px}.startWrap{position:relative;gap:10px;display:block}.startWrap input{flex:1;background:#0d0f12;border:1px solid var(--edge);color:var(--ink);border-radius:var(--rad-s);
  min-height:52px;font-size:15px;padding:10px 16px;transition:border-color .15s,box-shadow .15s;width:100%}
.geoBig{display:flex;align-items:center;gap:14px;width:100%;margin-top:10px;position:relative;
  background:linear-gradient(180deg,rgba(225,27,43,.16),rgba(225,27,43,.07));border:1px solid var(--red);
  color:var(--ink);border-radius:var(--rad-s);padding:12px 16px;min-height:60px;text-align:left;
  transition:filter .15s,transform .1s;overflow:hidden}
.geoBig:hover{filter:brightness(1.14)}
.geoBig:active{transform:translateY(1px)}
.geoIcon{font-size:22px;color:var(--red-hot);position:relative;z-index:2}
.geoTxt{position:relative;z-index:2}
.geoTxt b{display:block;font-family:var(--display);font-size:15px;text-transform:uppercase;letter-spacing:.04em}
.geoTxt small{display:block;color:var(--mut);font-size:15px;margin-top:2px}
.geoRing{position:absolute;left:26px;top:50%;width:12px;height:12px;border-radius:99px;
  transform:translate(-50%,-50%);background:var(--red-hot);opacity:.55;animation:ping 2.4s ease-out infinite}
@keyframes ping{0%{transform:translate(-50%,-50%) scale(.6);opacity:.6}70%{transform:translate(-50%,-50%) scale(4.2);opacity:0}100%{opacity:0}}
.geoBig.busy .geoRing{animation-duration:.9s}
.geoBig.got{border-color:var(--green);background:linear-gradient(180deg,rgba(79,206,127,.15),rgba(79,206,127,.06))}
.geoBig.got .geoIcon{color:var(--green)}
.geoBig.got .geoRing{display:none}
.goBtn.working{filter:grayscale(.3) brightness(.9)}
.goBtn.ghost{background:transparent;border:1px solid var(--red);color:var(--red-hot);box-shadow:none;max-width:320px;margin:22px auto 0;display:block}
.goBtn.ghost:hover{background:rgba(225,27,43,.1)}

.welcomeBack{display:flex;align-items:center;gap:12px;background:rgba(79,206,127,.07);
  border:1px solid rgba(79,206,127,.3);border-radius:var(--rad-s);padding:11px 14px;margin-bottom:4px;
  animation:lineUp .5s cubic-bezier(.2,.8,.2,1) both}
.wbDot{width:9px;height:9px;border-radius:99px;background:var(--green);flex:0 0 auto;box-shadow:none}
.welcomeBack b{display:block;font-family:var(--display);text-transform:uppercase;letter-spacing:.06em;font-size:15px}
.welcomeBack span{display:block;color:var(--mut);font-size:15px}
.welcomeBack strong{color:var(--ink)}
.welcomeBack button{margin-left:auto;background:var(--green);color:#06210f;border:0;border-radius:99px;
  padding:8px 16px;font-family:var(--display);font-weight:700;text-transform:uppercase;letter-spacing:.05em;font-size:15px;white-space:nowrap;min-width:0;overflow:hidden;text-overflow:ellipsis}
.privacyLine{color:var(--dim);font-size:15px;margin:14px 0 0;line-height:1.5;text-align:center}
.privacyLine button{background:none;border:0;color:var(--red-hot);text-decoration:underline;font-size:15px;padding:0 0 0 4px}.homeStats div{text-align:center}.homeStats b{display:block;font-family:var(--display);font-size:clamp(1.6rem,5vw,2.1rem);font-weight:700;color:var(--ink)}.homeStats span{font-size:12px;text-transform:uppercase;letter-spacing:.12em}

.why{margin-top:20px}
.whyGrid{display:grid;grid-template-columns:1fr;gap:14px}
@media(min-width:700px){.whyGrid{grid-template-columns:1fr 1fr}}
@media(min-width:980px){.whyGrid{grid-template-columns:repeat(3,1fr)}}
.whyCard{background:linear-gradient(180deg,var(--card),#101216);border:1px solid var(--edge);
  border-radius:var(--rad);padding:20px;position:relative;overflow:hidden;transition:border-color .2s,transform .2s}
.whyCard:before{content:"";position:absolute;left:0;top:0;height:3px;width:0;background:linear-gradient(90deg,var(--red),var(--red-hot));transition:width .5s ease}
.whyCard:hover{border-color:var(--edge2);transform:translateY(-3px)}
.whyCard:hover:before{width:100%}
.whyIco{font-size:22px;display:block}
.whyCard h3{font-size:15px;font-weight:700;margin-top:12px;line-height:1.2}
.whyCard p{color:var(--mut);font-size:15px;line-height:1.6;margin:9px 0 0}

.steps{list-style:none;counter-reset:st;padding:0;margin:0;display:grid;gap:12px}
.steps li{counter-increment:st;position:relative;padding:16px 18px 16px 66px;background:var(--card);
  border:1px solid var(--edge);border-radius:var(--rad);color:var(--mut);line-height:1.6;font-size:15px}
.steps li:before{content:counter(st);position:absolute;left:18px;top:14px;width:34px;height:34px;border-radius:99px;
  background:rgba(225,27,43,.12);border:1px solid var(--red);color:var(--red-hot);
  display:flex;align-items:center;justify-content:center;font-family:var(--display);font-weight:700;font-size:15px}
.steps li b{color:var(--ink)}

.reveal{opacity:0;transform:translateY(22px);transition:opacity .6s cubic-bezier(.2,.8,.2,1),transform .6s cubic-bezier(.2,.8,.2,1)}
.reveal.seen{opacity:1;transform:none}
.whyGrid .whyCard:nth-child(2){transition-delay:.06s}
.whyGrid .whyCard:nth-child(3){transition-delay:.12s}
.whyGrid .whyCard:nth-child(4){transition-delay:.18s}
.whyGrid .whyCard:nth-child(5){transition-delay:.24s}
.whyGrid .whyCard:nth-child(6){transition-delay:.3s}
.steps li:nth-child(2){transition-delay:.08s}
.steps li:nth-child(3){transition-delay:.16s}
.homeStats div:nth-child(2){transition-delay:.07s}
.homeStats div:nth-child(3){transition-delay:.14s}
.homeStats div:nth-child(4){transition-delay:.21s}

@media(max-width:759px){
  .hero{margin:0 -10px;min-height:min(72vh,540px)}
  .heroIn{padding:52px 18px 70px}
  .heroCred{max-width:66%}
  .searchCard{margin-top:-38px}
}
@media (prefers-reduced-motion:reduce){
  .reveal{opacity:1;transform:none}
  .heroLayer.on{transform:none}
  .geoRing,.heroScroll{animation:none}
}.hero{position:relative;margin:0 -18px;padding:0;display:flex;align-items:center;
  justify-content:center;text-align:center;overflow:hidden;border-bottom:1px solid var(--edge);min-height:100vh}
@supports (height:100dvh){.hero{min-height:100dvh}}.heroBg{position:absolute;inset:0;z-index:0;background:linear-gradient(160deg,#14171c,#0a0b0d);
  /* ---- THE PAGE HAS A PICTURE THE MOMENT IT OPENS ----
     The Wikimedia photographs now wait for the rider's first action, because a clean first
     load must make no third-party request. That was right and it left the hero blank until
     he scrolled - a background he had every reason to expect, gone. This is ours, it ships
     with the app, it needs no network, and the photographs still take over the moment he
     touches the page. It was the brand board - a logo plate, not a welcome picture, which
     is why he still said there was none. This is a drawn road climbing through mountains at
     dawn: original work, no licence to clear, a few kilobytes, and it looks like the thing
     the product is about. */
  background-image:linear-gradient(180deg,rgba(11,12,14,.10),rgba(11,12,14,.55)),url('hero-road.svg');
  background-size:cover;background-position:center}.heroLayer{position:absolute;inset:0;background-size:cover;background-position:center;opacity:0;transition:opacity 1.6s ease, transform 8s cubic-bezier(.2,.5,.3,1);transform:scale(1.02)}.heroLayer.on{opacity:1;transform:scale(1.13)}.hero:before{content:"";position:absolute;inset:0;z-index:1;background:
  linear-gradient(180deg,rgba(8,9,11,.72) 0%,rgba(8,9,11,.22) 26%,rgba(8,9,11,.30) 52%,rgba(10,11,13,.88) 86%,var(--bg) 100%)}
.heroBg.noPic ~ .heroIn .heroSub{opacity:.9}.heroIn{position:relative;z-index:3;max-width:660px;padding:0 20px;display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100svh}
@supports (height:100dvh){.heroIn{min-height:100dvh}}.heroIn .big{/* halo removed: a red glow around a mark is the same effect he has now asked me three times to take off the elevation profile. Nothing in this interface glows. */;
  animation:markIn .9s cubic-bezier(.2,.8,.2,1) both;width:118px;height:118px}.heroIn h1{font-style:italic;font-weight:700;text-transform:uppercase;
  line-height:.92;margin-top:16px;font-size:clamp(3rem,11vw,6rem);text-shadow:0 8px 40px rgba(0,0,0,.85)}.heroSub{line-height:1.65;margin:18px auto 0;
  animation:lineUp .8s .44s cubic-bezier(.2,.8,.2,1) both;color:#e6e3dc;text-shadow:0 2px 14px rgba(0,0,0,.8);font-size:15px;max-width:520px}
.heroCta{display:flex;gap:12px;flex-wrap:wrap;justify-content:center;margin-top:28px;
  animation:lineUp .8s .56s cubic-bezier(.2,.8,.2,1) both}
.heroCta button{min-height:56px;padding:0 26px;border-radius:99px;font-family:var(--display);font-weight:700;
  text-transform:uppercase;letter-spacing:.05em;font-size:15px;transition:transform .14s,filter .16s,box-shadow .16s}
.heroCta .primary{background:linear-gradient(180deg,var(--red-hot),var(--red));border:0;color:#fff;
  position:relative;overflow:hidden}
.heroCta .primary:after{content:"";position:absolute;top:0;left:-60%;width:40%;height:100%;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.35),transparent);animation:sheen 3.6s ease-in-out infinite}
@keyframes sheen{0%{left:-60%}55%,100%{left:130%}}
.heroCta .ghost2{background:rgba(10,11,13,.5);border:1px solid rgba(244,242,236,.35);color:#fff;backdrop-filter:blur(6px)}
.heroCta button:hover{transform:translateY(-2px);filter:brightness(1.08)}.heroScroll{margin-top:26px;width:44px;height:44px;border-radius:99px;background:rgba(244,242,236,.06);
  border:1px solid var(--edge2);color:var(--ink);font-size:15px;animation:bob 2.4s ease-in-out infinite;position:absolute;left:50%;transform:translateX(-50%);bottom:64px;margin:0;z-index:4}.heroDots{position:absolute;left:0;right:0;z-index:4;display:flex;justify-content:center;gap:6px;bottom:26px}.heroDots i{width:16px;border-radius:99px;background:rgba(244,242,236,.22);transition:background .3s,width .3s;cursor:pointer;height:4px}.heroCred{position:absolute;right:14px;z-index:4;text-align:right;text-decoration:none;
  background:rgba(10,11,13,.6);border:1px solid var(--edge);border-radius:10px;padding:6px 11px;max-width:60%;bottom:52px}.searchCard{background:linear-gradient(180deg,var(--card),#101216);border:1px solid var(--edge);
  border-radius:var(--rad);box-shadow:var(--shadow);padding:22px;margin:30px auto 0;max-width:640px;text-align:left;position:relative;z-index:5;margin-top:34px}

/* the map, expandable */
.mapExpand{position:absolute;right:10px;top:10px;z-index:1100;background:rgba(11,12,14,.88);
  border:1px solid var(--edge);color:var(--ink);border-radius:10px;padding:8px 14px;
  font-family:var(--display);font-weight:600;text-transform:uppercase;letter-spacing:.06em;font-size:15px;
  box-shadow:0 4px 14px rgba(0,0,0,.5)}
.mapExpand:hover{border-color:var(--red);color:var(--red-hot)}
.mapBox.expanded{position:fixed;inset:0;z-index:2000;margin:0;border-radius:0;border:0}
.mapBox.expanded #map{height:100%!important}
body.mapOpen{overflow:hidden}
.mapBox.expanded .mapExpand{position:fixed;top:14px;right:14px;z-index:2100;
  background:linear-gradient(180deg,#ff3b47,#e11b2b);color:#fff;border:0;font-weight:700;
  padding:13px 22px;border-radius:99px;box-shadow:0 8px 26px rgba(0,0,0,.6);font-size:15px}
.mapBox.expanded .mapExpand:hover{filter:brightness(1.08)}#map{height:520px;width:100%;cursor:grab}
#map:active{cursor:grabbing}/* persistent minimap dock */
@keyframes dockIn{from{opacity:0;transform:translateY(18px) scale(.95)}to{opacity:1;transform:none}}
.miniDock.gone{transform:translateY(150%);opacity:0;pointer-events:none}.miniHead{display:flex;align-items:center;gap:4px;padding:6px 6px 6px 10px;background:#0d0f12;border-bottom:1px solid var(--edge)}
.miniHead b{flex:1;font-family:var(--display);font-size:15px;text-transform:uppercase;letter-spacing:.05em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--mut)}
.miniHead button{width:32px;height:32px;border-radius:6px;background:transparent;border:1px solid var(--edge);
  color:var(--mut);font-size:15px;line-height:1;padding:0;flex:0 0 auto}
.miniHead button:hover{color:var(--ink);border-color:var(--red)}
.miniDock #mini{width:100%;height:104px  /* was 150: the dock is a locator, not a second map - 124x104 shows where you are without covering what you are reading */}
.miniShow{position:fixed;right:14px;bottom:calc(16px + env(safe-area-inset-bottom));z-index:1500;
  width:50px;height:50px;border-radius:99px;background:var(--raise);border:1px solid var(--red);
  color:var(--red-hot);font-size:19px;box-shadow:0 10px 28px rgba(0,0,0,.55)}
@media(max-width:759px){
  /* SMALLER, AND ONLY WHILE THE MAP IS THERE.
   158px of dock floated over the roadbook and the briefing on a screen with no map on it -
   a locator with nothing to locate against, covering the text he was reading. It fades with
   the map and takes back a third of its width. */
.miniDock{width:var(--miniW);right:10px;bottom:calc(12px + env(safe-area-inset-bottom));
  transition:opacity .18s,transform .18s}
  .miniDock #mini{height:var(--miniMapH)}
  .heroIn h1{font-size:clamp(2.6rem,13vw,4rem)}
  .heroScroll{bottom:52px}
}

/* top bar: a way back is always there */
.tbtn.back{border-color:var(--red);color:var(--ink);background:rgba(225,27,43,.14);font-weight:700;flex:0 0 auto}
.tbtn.back:hover{background:rgba(225,27,43,.24)}
.tbtn.cur{color:var(--ink);border-color:var(--edge2);background:#1b1f25}
.navScroll .tbtn{flex:0 0 auto}
@media(max-width:759px){
  .topIn{gap:8px}
  .top .word{font-size:15px}
  .top .mark{width:28px;height:28px}
}
.rideHero img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:0;transform:scale(1.06);transition:opacity .6s ease,transform 1.1s cubic-bezier(.2,.8,.2,1)}
.rideHero img.in{opacity:1;transform:scale(1)}
.rideHero:after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,rgba(10,11,13,.16) 0%,rgba(10,11,13,.05) 45%,rgba(20,22,26,.92) 100%)}
.rhPh{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:22px;opacity:.22}
.ride:hover .rideHero img{transform:scale(1.05)}
.rideHero .exCred{padding:16px 8px 4px;font-size:12px;z-index:3;pointer-events:auto}.ride .row1{align-items:flex-start;gap:12px;padding:14px 46px 0 16px;display:flex}
.ride .meta,.ride .why,.ride .sl{padding-left:16px;padding-right:16px}.ride h3{font-weight:700;line-height:1.1;flex:1;font-size:15px}.saveStar{position:absolute;top:8px;right:8px;z-index:3;border:1px solid transparent;border-radius:99px;
  font-size:15px;color:var(--dim);width:34px;height:34px;line-height:1;transition:color .14s;background:rgba(11,12,14,.6);backdrop-filter:blur(4px)}

.skWrap{display:block;margin:14px 0 2px;padding:0 4px 4px}
/* overflow:visible let the fill bleed outside the chart - the halo. Clip it. */
.spark{width:100%;height:104px;display:block;overflow:hidden}
/* preserveAspectRatio="none" scales x and y independently, which stretched the curve and
   its "2417 m" label by 1.6x on a wide card. vector-effect keeps the stroke honest and
   the label is counter-scaled by the viewBox clamp above. */
.spark .skTx{font-size:11px;paint-order:stroke;stroke:rgba(11,12,14,.85);stroke-width:3px;fill:#aeb6c0} /* the corner labels (class l / r) had no fill at all, so they rendered black on the dark chart */
.skBase{stroke:var(--edge);stroke-width:1}
.skArea{stroke:none}
.skLine{fill:none;stroke-width:2.6;stroke-linecap:round;stroke-linejoin:round;
  vector-effect:non-scaling-stroke}
/* THE HALO ON THE CLIMB CHART.
   A 7 px stroke blurred by 3 px under a 2 px line is a red haze the width of the curve
   itself: at card size it doubles the apparent thickness of every climb and smears the
   summit, which is the one point on the chart a rider reads. A profile is a measurement,
   not a mood. Thin, tight, and only enough to lift the line off the panel. */
.skGlow{fill:none;stroke-width:3.2;opacity:.16;filter:blur(1.2px);stroke-linecap:round;stroke-linejoin:round}
.skHi{fill:#fff;stroke:var(--red);stroke-width:2.2}
.skTx{font-family:var(--body);font-size:11px;font-weight:700;text-anchor:middle;
  paint-order:stroke;stroke:rgba(10,11,13,.85);stroke-width:2.6px}
.skTx.hi{fill:#ffb3ab}
.skTx.lo{fill:#aeb6c0} /* was var(--dim): the corner labels (start height, distance) were nearly invisible on the dark chart */
@media(max-width:759px){
  .rideHero{height:238px}
  .spark{height:88px}
}.profSvg{width:100%;display:block;overflow:visible;height:250px}
.pfLine{fill:none;stroke:var(--red);stroke-width:2.2;stroke-linejoin:round;vector-effect:non-scaling-stroke}
.pfAx{fill:var(--dim);font-size:12px;font-family:var(--body)}
.pfAx.km{text-anchor:middle;fill:var(--dim);font-size:11px}
.pfPoi{font-size:15px;text-anchor:middle;cursor:pointer}
.pfCross{stroke:#fff;stroke-width:1.4;opacity:.7;stroke-dasharray:3 4}
.pfDot{fill:#fff;stroke:var(--red);stroke-width:2.5}
.pfHit{cursor:crosshair;touch-action:none}
.pfWp{cursor:pointer}
.pfRead{margin-top:10px;background:#0d0f12;border:1px solid var(--edge);border-radius:var(--rad-s);
  padding:10px 14px;min-height:52px}
.pfRead b{display:block;font-family:var(--display);font-size:15px;letter-spacing:.02em}
.pfRead span{display:block;color:var(--mut);font-size:15px;margin-top:2px}
.pfSrc{color:var(--dim);font-size:13px;margin-left:auto}.profLegend{display:flex;flex-wrap:wrap;gap:12px;margin-top:14px;color:var(--dim);font-size:15px;align-items:center}

/* ---------- checkpoint jump strip under the map ---------- */
/* This row scrolls, but scrollbar-width:thin hid every hint of that, so it just looked
   like a list chopped off at the edge. Visible slim bar, chips that refuse to squash,
   and a fade on the right that says there is more. */
/* overflow-x:auto alone did not contain this row: as a flex item with the default min-width:auto it
   reported the full width of its buttons to its parent, so after the Swipe journey the route page
   grew to 575 px on a 390 px phone. Bounding it makes the row scroll instead of the page. */
.mapJump{display:flex;gap:8px;overflow-x:auto;padding:10px 2px 8px;-webkit-overflow-scrolling:touch;
  min-width:0;max-width:100%;box-sizing:border-box;
  scrollbar-width:thin;scrollbar-color:#3a3f48 transparent;position:relative;
  mask-image:linear-gradient(90deg,#000 0,#000 calc(100% - 34px),transparent 100%);
  -webkit-mask-image:linear-gradient(90deg,#000 0,#000 calc(100% - 34px),transparent 100%)}
.mapJump::-webkit-scrollbar-track{background:transparent}
.mapJump::-webkit-scrollbar-thumb{background:#3a3f48;border-radius:99px}
.mapJump::-webkit-scrollbar-thumb:hover{background:#e11b2b}
.mapJump>*{flex:0 0 auto}.mapJump::-webkit-scrollbar{height:8px;display:block}
.mapJump button{flex:0 0 auto;background:var(--card);border:1px solid var(--edge);color:var(--mut);
  border-radius:99px;padding:7px 14px;font-size:15px;white-space:nowrap;transition:all .14s;min-width:0;overflow:hidden;text-overflow:ellipsis}
.mapJump button:hover{color:var(--ink);border-color:var(--edge2)}
.mapJump button.on{background:var(--red);border-color:var(--red);color:#fff}/* ---------- minimap: what is in view right now ---------- */
.miWp{display:flex;align-items:center;gap:5px;font-size:13px;color:var(--mut);white-space:nowrap;min-width:0;overflow:hidden;text-overflow:ellipsis}
.miWp b{background:var(--red);color:#fff;border-radius:99px;min-width:15px;height:15px;display:inline-flex;
  align-items:center;justify-content:center;font-size:12px;font-family:var(--display)}
.miWp i{color:var(--ink);font-style:normal;font-weight:600}
.miMore,.miBand{font-size:12px;color:var(--dim)}
.miBand{width:100%;color:var(--amber);font-variant-numeric:tabular-nums}
.miNone{font-size:13px;color:var(--dim)}
@media(max-width:759px){.miniDock{width:var(--miniW)}.miniDock #mini{height:var(--miniMapH)}}
.seedNote{margin:14px 0 0;padding-top:12px;border-top:1px solid var(--edge);color:var(--amber);font-size:15px;line-height:1.55}

/* ---------- minimap: topo + live position ---------- */
.miHere{width:16px;height:16px;border-radius:99px;background:#ff5a1f;border:3px solid #12151a;
  box-shadow:0 2px 8px rgba(0,0,0,.7);}
}.svcPin{width:26px;height:26px;border-radius:99px;background:#14161a;border:2px solid var(--edge2);
  display:flex;align-items:center;justify-content:center;font-size:15px;box-shadow:0 2px 7px rgba(0,0,0,.7)}
.svcPic{width:40px;height:40px;border-radius:99px;border:2.5px solid var(--teal);background:#14161a center/cover no-repeat;
  box-shadow:0 3px 10px rgba(0,0,0,.75);position:relative}
.svcPic i{position:absolute;right:-3px;bottom:-3px;font-size:12px;background:#0d0f12;border:1px solid var(--edge2);
  border-radius:99px;width:17px;height:17px;display:flex;align-items:center;justify-content:center;font-style:normal}.mapLayers button{border-radius:10px;background:rgba(11,12,14,.88);border:1px solid var(--edge);
  font-size:15px;line-height:1;transition:border-color .14s,background .14s;position:relative;width:42px;height:42px}
.mapLayers button b{min-height:16px;position:absolute;right:-3px;top:-4px;background:var(--red);color:#fff;border-radius:99px;
  font-size:11px;min-width:16px;height:32px;display:flex;align-items:center;justify-content:center;
  font-family:var(--body);font-weight:700;border:1.5px solid #0b0c0e}
.mapLayers button:not(.on){opacity:.55;filter:grayscale(.6)}
.mapLayers button.on b{background:var(--green);color:#06210f}

/* ---------- fuel prices ---------- */
.svcPrice{display:block;color:var(--green);font-size:15px;margin-top:3px}
.svcPrice b{color:var(--ink)}
.svcNoPrice{display:block;color:var(--dim);font-size:13px;margin-top:3px;font-style:italic}
.svcCluster{width:34px;height:34px;border-radius:99px;background:#14161a;border:2.5px solid var(--edge2);
  display:flex;align-items:center;justify-content:center;font-size:15px;box-shadow:0 3px 9px rgba(0,0,0,.75);position:relative}
.svcCluster b{position:absolute;right:-4px;bottom:-4px;background:var(--red);color:#fff;border-radius:99px;
  min-width:17px;height:17px;display:flex;align-items:center;justify-content:center;font-size:12px;
  font-family:var(--body);border:1.5px solid #0b0c0e}

/* ---------- minimap POIs + focus ---------- */
.miPoi{width:14px;height:14px;border-radius:99px;border:2px solid #0b0c0e;box-shadow:0 1px 4px rgba(0,0,0,.8)}
.miPoi.camera{background:#ff2d40}
.miPoi.fuel{background:#f2a71b}
.miPoi.view{background:#2bbfa4}
.miFocus{width:16px;height:16px;border-radius:99px;background:#ffe066;border:3px solid #0b0c0e;
  box-shadow:0 0 0 3px rgba(255,224,102,.5);animation:herePulse 1.6s ease-out infinite}

/* ---------- roadbook linked to the maps ---------- */
.rbi.clickable{cursor:pointer;border-radius:10px;transition:background .18s}
.rbi.clickable:hover{background:rgba(244,242,236,.035)}
.rbi.active{background:rgba(225,27,43,.09)}
.rbi.active .n{border-color:var(--red);color:#fff;background:var(--red);box-shadow:none}
.rbi.active h4{color:#fff}

/* ---------- route line mode switch ---------- */
.lineMode{display:flex;gap:8px;margin-top:10px}
.lineMode button{flex:1;background:var(--card);border:1px solid var(--edge);color:var(--mut);border-radius:var(--rad-s);
  min-height:42px;font-family:var(--display);font-weight:600;text-transform:uppercase;letter-spacing:.05em;font-size:16px}
.lineMode button.on{background:var(--red);border-color:var(--red);color:#fff}

/* ---------- start-from-me ---------- */
.startFrom{display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin-top:12px;background:var(--card);
  border:1px solid var(--edge);border-left:4px solid var(--amber);border-radius:var(--rad-s);padding:12px 14px}
.sfBtn{background:linear-gradient(180deg,var(--red-hot),var(--red));border:0;color:#fff;border-radius:99px;
  padding:11px 20px;font-family:var(--display);font-weight:700;text-transform:uppercase;letter-spacing:.05em;
  font-size:15px;white-space:nowrap;box-shadow:none}
.sfBtn.on{background:linear-gradient(180deg,#5fd68d,#3ba86a);color:#06210f;box-shadow:none}
.sfNote{flex:1;min-width:200px;color:var(--mut);font-size:15px;line-height:1.5}
.sfNote a{color:var(--amber);text-decoration:none;white-space:nowrap}
.sfNote a:hover{text-decoration:underline}

/* ---------- approach chips ---------- */
.apChip.real{border-color:var(--edge2);color:var(--ink)}
.apChip.real b{color:var(--ink)}
.apChip.detour{border-color:var(--amber);color:var(--amber)}

/* ---------- merged roadbook: checkpoint then the leg that follows ---------- */
.rbIco{margin-right:7px;font-size:15px}


.rbLegTag{display:inline-block;font-family:var(--display);font-size:13px;text-transform:uppercase;
  letter-spacing:.12em;font-weight:700;margin-right:9px}
.rbLeg.scenic .rbLegTag{color:var(--red-hot)}
.rbLeg.transfer .rbLegTag{color:#9aa4b0}
.rbLeg b{font-size:15px}
.rbLegKm{float:right;color:var(--dim);font-size:15px}
.rbLeg p{margin:7px 0 0;color:var(--mut);font-size:15px;line-height:1.55}
.wpPic{width:46px;height:46px;border-radius:99px;border:3px solid var(--red);background:#14161a center/cover no-repeat;
  box-shadow:0 3px 12px rgba(0,0,0,.8);position:relative}
.wpPic b{position:absolute;left:-4px;top:-4px;background:var(--red);color:#fff;border-radius:99px;width:19px;height:19px;
  display:flex;align-items:center;justify-content:center;font:700 11px var(--display);border:1.5px solid #0b0c0e}
.wpPic i{position:absolute;right:-3px;bottom:-3px;background:#0d0f12;border:1px solid var(--edge2);border-radius:99px;
  width:18px;height:18px;display:flex;align-items:center;justify-content:center;font-size:12px;font-style:normal}

/* ---------- fuel cost ---------- */
.fuelCalc{margin-top:16px;background:var(--card);border:1px solid var(--edge);border-left:4px solid var(--amber);
  border-radius:var(--rad-s);padding:14px 16px}
.fcHead b{font-family:var(--display);font-size:15px;text-transform:uppercase;letter-spacing:.04em}
.fcHead span{display:block;color:var(--mut);font-size:15px;margin-top:4px;line-height:1.5}
.fcHead span b{color:var(--ink);font-family:var(--body);text-transform:none;font-size:15px}
.fcRow{display:flex;flex-wrap:wrap;gap:12px;margin-top:12px}
.fcRow label{color:var(--dim);font-size:15px;display:flex;align-items:center;gap:7px}
.fcRow input{width:84px;background:#0d0f12;border:1px solid var(--edge);color:var(--ink);border-radius:8px;
  padding:8px 10px;font-size:15px}
.fcRow input:focus{outline:none;border-color:var(--amber)}
.fcNote{color:var(--dim);font-size:15px;line-height:1.55;margin:11px 0 0}
.fcNote b{color:var(--mut)}

/* ---------- roadbook: thumbnail, facts, nearby ---------- */
.rbTop{display:flex;align-items:center;gap:14px;flex-wrap:wrap;background:var(--card);border:1px solid var(--edge);
  border-radius:var(--rad-s);padding:11px 14px;margin-bottom:14px}
.rbTop label{color:var(--dim);font-size:15px;display:flex;align-items:center;gap:8px}
.rbTop input{background:#0d0f12;border:1px solid var(--edge);color:var(--ink);border-radius:8px;padding:7px 10px;font-size:15px}
.rbTop input:focus{outline:none;border-color:var(--red)}
.rbArrive{flex:1;min-width:220px;color:var(--mut);font-size:15px;line-height:1.5}
.rbArrive b{color:var(--ink)}.rbi{position:relative;padding:0 0 18px 58px;padding-left:0;display:grid;grid-template-columns:44px 1fr;gap:12px;align-items:start}.rbi .n{left:4px;top:0;width:36px;height:36px;border-radius:99px;background:var(--raise);
  border:2px solid var(--edge2);display:flex;align-items:center;justify-content:center;
  font:700 15px var(--display);z-index:1;position:static;grid-column:1}
.rbThumb{position:relative;border-radius:10px;overflow:hidden;
  background:linear-gradient(150deg,#1a1d23,#0d0f12);border:1px solid var(--edge)}
.rbThumb img.in{opacity:1}
.rbThumb .rhPh{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:22px;opacity:.4}
.rbThumb .exCred{display:none}
.rbMain{grid-column:3;min-width:0}.rbLeg{margin:12px 0 4px;padding:11px 13px;border-radius:10px;border-left:3px solid var(--edge2);background:#0d0f12;margin-left:56px;min-width:0}
@media(max-width:680px){.rbLeg{margin-left:43px}}
.rbi .rbMedia{grid-column:2}
.rbFacts{display:flex;flex-wrap:wrap;gap:5px 10px;margin-top:5px;color:var(--dim);font-size:15px}
.rbFacts span{white-space:nowrap}
.rbFacts .up{color:var(--red-hot)}
.rbFacts .down{color:var(--blue)}
.rbFacts .rbEta{color:var(--amber)}
.rbFacts .rbEta i{color:var(--dim);font-style:normal}
.rbNear{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-top:8px}
.nearLbl{color:var(--dim);font-size:13px}
.nearChip{background:#0d0f12;border:1px solid var(--edge);color:var(--mut);border-radius:99px;
  padding:2px 9px;font-size:15px;line-height:1.6}
.nearChip:hover{border-color:var(--red);color:var(--ink)}
.wpLinks .rbShow{background:#0d0f12;border:1px solid var(--edge);color:var(--dim);border-radius:99px;
  padding:2px 9px;font-size:16px}
.wpLinks .rbShow:hover{color:var(--ink);border-color:var(--red)}
.rbi.flash{animation:rbFlash 1.4s ease-out}
@keyframes rbFlash{0%{background:rgba(255,224,102,.22)}100%{background:transparent}}.rb:before{content:"";position:absolute;top:8px;bottom:8px;width:2px;
  background:repeating-linear-gradient(180deg,var(--edge2) 0 10px,transparent 10px 18px);left:21px}
@media(max-width:600px){
  .rbi{grid-template-columns:34px 1fr;gap:9px}
    .rbi .n{width:30px;height:30px;font-size:15px}
  .rb:before{left:17px}
}

/* ---------- climb: checkpoint picture strip ---------- */
.climbStrip{position:relative;height:96px;margin:18px 0 4px;border-top:1px dashed var(--edge2);padding-top:10px;overflow:visible}
.csPic{position:relative;width:44px;height:44px;border-radius:99px;overflow:hidden;border:2px solid var(--edge2);
  background:#14161a;display:block;transition:border-color .15s,transform .15s}
.csPic img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .5s}
.csPic img.in{opacity:1}
.csPic .rhPh{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:15px;opacity:.5}
.csPic .exCred{display:none}
.csItem:hover .csPic,.csItem.on .csPic{border-color:var(--red);transform:scale(1.08)}
.csItem b{font-family:var(--display);font-size:13px;color:var(--mut);line-height:1}
.csItem i{font-style:normal;font-size:12px;color:var(--dim);white-space:nowrap}
.csItem.on b{color:var(--red-hot)}
@media(max-width:600px){
  
  .csPic{width:34px;height:34px}
  
  .csItem i{font-size:11px}
}/* social:start */
.footSocial{margin-bottom:16px}

.social{display:flex;flex-wrap:wrap;gap:9px;align-items:center;margin:2px 0 14px}
.social a,.social span.soon{display:inline-flex;align-items:center;justify-content:center;
  width:40px;height:40px;border-radius:11px;border:1px solid var(--edge,#262a31);
  background:rgba(244,242,236,.02);color:var(--dim,#8f8c84);text-decoration:none;
  transition:color .18s,border-color .18s,background .18s,transform .18s}
.social svg{fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.social a:hover,.social a:focus-visible{color:#f4f2ec;border-color:var(--red,#e11b2b);
  background:rgba(225,27,43,.12);transform:translateY(-2px)}
.social a:focus-visible{outline:2px solid var(--red-hot,#ff3b47);outline-offset:2px}
.social span.soon{opacity:.34;cursor:default;position:relative}
.social span.soon:after{content:"soon";position:absolute;bottom:-3px;right:-3px;font:600 7px/1 system-ui,sans-serif;
  letter-spacing:.04em;background:#0b0c0e;border:1px solid var(--edge,#262a31);border-radius:5px;padding:2px 3px;color:var(--dim,#8f8c84)}
@media(max-width:600px){.social a,.social span.soon{width:38px;height:38px}}
/* social:end */

/* ---------- reachable today vs worth travelling for ---------- */
.tierHead{margin:30px 0 12px;padding-top:20px;border-top:1px solid var(--edge)}
.tierHead h3{font-family:var(--display);font-size:19px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--amber)}
.tierHead p{margin:4px 0 0;color:var(--dim);font-size:15px;line-height:1.5;max-width:60ch}
.apChip.trip{border-color:var(--amber);color:var(--amber)}
.apChip.trip b{color:var(--amber)}
.est{color:var(--dim);font-size:15px;border:1px solid var(--edge);border-radius:99px;padding:1px 8px;margin-left:6px}
#rideList > .rides + .tierHead{margin-top:34px}
.why .warnChip{background:rgba(242,167,27,.12);border-color:rgba(242,167,27,.4);color:var(--amber)}
.why .goodChip{background:rgba(79,206,127,.1);border-color:rgba(79,206,127,.32);color:var(--green)}

/* ---- the shortlist your saved rides earn ---- */
.sugg{background:linear-gradient(180deg,rgba(225,27,43,.10),rgba(225,27,43,.02));
  border:1px solid rgba(225,27,43,.30);border-radius:16px;padding:16px 16px 18px;margin:0 0 20px}
.sugg.thin{padding:14px 16px}
.sugg.thin b{display:block;color:#ff6a4d;font-size:15px;margin-bottom:5px}
.sugg.thin span{color:#a9a69d;font-size:13px;line-height:1.55}
.suggHead{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;margin-bottom:13px}
.suggHead b{color:#ff6a4d;font-size:15px}
.suggHead span{color:#8f8c84;font-size:13px}
.suggRow{display:grid;gap:11px;grid-template-columns:repeat(auto-fill,minmax(232px,1fr))}
.suggCard{display:block;position:relative;background:#14161a;border:1px solid #262a31;
  border-radius:12px;padding:13px 14px;text-decoration:none;transition:border-color .15s,transform .15s}
.suggCard:hover{border-color:#e11b2b;transform:translateY(-2px)}
.suggMatch{position:absolute;top:11px;right:12px;color:#4fce7f;font:700 13px/1 system-ui,sans-serif}
.suggCard b{display:block;color:#f4f2ec;font-size:15px;line-height:1.3;padding-right:46px;margin-bottom:5px}
.suggWhy{display:block;color:#a9a69d;font-size:13px;line-height:1.45;margin-bottom:6px}
.suggNums{display:block;color:#8f8c84;font-size:12px}

/* ---- what changes when you cross a border ---- */
.borderBox{background:#14161a;border:1px solid #262a31;border-left:4px solid #3ba6dd;
  border-radius:14px;padding:15px 17px;margin:0 0 16px}
.borderBox.hard{border-left-color:#f2a71b;background:rgba(242,167,27,.06)}
.borderBox.one{border-left-color:#4fce7f;padding:12px 16px}
.bbHead{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;margin-bottom:10px}
.bbHead b{font-size:15px;color:#f4f2ec}
.bbHead span{color:#a9a69d;font-size:13px}
.bbLeg{border-top:1px solid #1e2228;padding-top:10px;margin-top:10px}
.bbLeg>b{display:block;font-size:15px;margin-bottom:6px}
.bbLeg>b i{color:#8f8c84;font-style:normal;font-weight:400}
.bbLeg ul{margin:0;padding-left:20px}
.bbLeg li{color:#c9c6bf;font-size:13px;line-height:1.6;margin-bottom:4px}
.bbFine{color:#8f8c84;font-size:12px;line-height:1.5;margin:10px 0 0}

/* ---- hover, anchored ---- */
.rbi.hoverlit{background:rgba(225,27,43,.08);border-color:rgba(225,27,43,.4)}
.leaflet-marker-icon.pulse{filter:drop-shadow(0 0 10px #ff3b47) brightness(1.25);z-index:900!important}/* ---- a minimap on every waypoint ---- */
@media(max-width:680px){}
.exPh{min-height:210px}
.read figure img{min-height:300px;object-fit:cover}
.hl img,.hl .ph{width:190px;min-width:190px;height:136px}

/* the map bar owns bottom:32 and the credit owns bottom:0 - the badge goes right */
/* the bottom-right is the minimap dock's corner (dock, and the tab that reopens it), and
   the bottom-left band belongs to the map bar and the credit. The badge is the least
   important thing on the page, so it takes the space nothing else wants: hard left, under
   the map bar's band, on its own line. */
#buildBadge{position:fixed;left:10px;bottom:-2px;right:auto;z-index:1500;width:120px;height:12px;color:#4a4d54;font:500 11px/1 system-ui,sans-serif;
  background:rgba(11,12,14,.72);border:1px solid #1e2228;border-radius:7px;padding:4px 9px;pointer-events:none;opacity:.85}:focus-visible{outline:2.5px solid #3ba6dd;outline-offset:2px;border-radius:6px}
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important}
}
/* Print the ride page and you get the roadbook, briefing and stops - no chrome, no maps,
   dark ink on white. Riders tape this to a tank bag. */
@media print{body{background:#fff;font-size:11pt}
  header,.mapBox,.miniDock,.mapJump,.startFrom,.lineMode,.speedKey,#pfHost,.chev,
  .saveStar,.abtn,.rbMini,.suggRow,#buildBadge,.wpLinks,.fcRow{display:none!important}
  .rbi,.brief,.borderBox{break-inside:avoid;border:1px solid #bbb;color:#111}
  .rbi *,.brief *,.borderBox *{color:#111!important;background:transparent!important}
  a{color:#111;text-decoration:none}
  .rbThumb{display:none!important}
  h1,h2,h3,h4{color:#000}}

.rideChar h2{font:700 19px/1 'Barlow Condensed',Arial Narrow,sans-serif;text-transform:uppercase;color:#ff6a4d;margin:4px 0 10px}
.rideChar p{color:#c9c6bf;font-size:15px;line-height:1.7;margin:0 0 12px}
.rideChar b{color:#f4f2ec}

/* ---- a stale download says so ---- */
#staleBar{position:fixed;left:0;right:0;top:0;z-index:4000;background:linear-gradient(180deg,#8a1420,#5e0d16);
  color:#fff;padding:12px 46px 13px 16px;font-size:13px;line-height:1.5;box-shadow:0 6px 20px rgba(0,0,0,.5)}
#staleBar b{display:block;font-size:15px;margin-bottom:3px}
#staleBar span{display:block;opacity:.92;max-width:70ch}
#staleX{position:absolute;top:9px;right:11px;background:rgba(255,255,255,.14);color:#fff;border:0;
  border-radius:99px;width:30px;height:30px;font-size:15px;cursor:pointer}
#staleX:hover{background:rgba(255,255,255,.26)}
body:has(#staleBar) .top{top:78px}

/* ---- one tap back to the whole route ---- */
/* .mapExpand is right:10 and about 96px wide - this must start beyond it */
.mapHome{position:absolute;top:12px;right:124px;z-index:1100;background:rgba(11,12,14,.82);color:#f4f2ec;
  border:1px solid #31363f;border-radius:99px;padding:7px 13px;font-size:12px;cursor:pointer}
.mapHome:hover{border-color:#e11b2b;background:rgba(11,12,14,.95)}
.mapBox.expanded .mapHome{position:fixed;top:14px;right:150px;z-index:2100;padding:12px 18px;font-size:15px}

/* ---- roadbook: photo and map side by side, both big enough to read ---- */
.rbMedia{display:flex;gap:12px;align-items:stretch;margin:10px 0 12px}
.rbMedia>*{flex:1 1 0;min-width:0;height:190px}.rbThumb img{position:absolute;inset:0;opacity:0;transition:opacity .5s;width:100%;height:100%;object-fit:cover}.rbMini b{position:absolute;background:rgba(11,12,14,.85);color:#fff;
  border-radius:7px;right:7px;bottom:6px;font-size:12px;padding:2px 9px}
@media(max-width:680px){.rbMedia>*{height:132px}.rideHero{height:186px}}

/* ---- what the colours on the line mean ---- */
.mapNote .lgd{display:inline-flex;align-items:center;gap:6px;margin-right:14px;font-size:12px;color:#c9c6bf}
.mapNote .lgd i{width:20px;height:5px;border-radius:3px;display:inline-block;
  box-shadow:0 0 0 1.5px #0b0c0e}

/* ---- terms, privacy, licences ---- */
.legalRow{margin:0 0 14px;font-size:13px;color:#8f8c84}
.legalRow a{color:#ff6a4d;text-decoration:none;border-bottom:1px solid rgba(255,106,77,.4)}
.legalRow a:hover{color:#fff}
.legalBody{max-width:74ch;padding:8px 0 40px}
.legalBody h1{font:700 italic 34px/1.06 'Barlow Condensed',Arial Narrow,sans-serif;text-transform:uppercase;margin:0 0 12px}
.legalBody h2{font:700 19px/1.15 'Barlow Condensed',Arial Narrow,sans-serif;text-transform:uppercase;
  color:#ff6a4d;margin:30px 0 8px;padding-top:14px;border-top:1px solid #1e2228}
.legalBody p{color:#c9c6bf;line-height:1.72;margin:0 0 12px}
.legalBody .lgLead{font-size:15px;color:#f4f2ec;background:#14161a;border-left:4px solid #e11b2b;
  border-radius:0 12px 12px 0;padding:14px 18px}
.legalBody b{color:#f4f2ec}
.lgList{margin:0 0 14px;padding-left:22px}
.lgList li{color:#c9c6bf;line-height:1.7;margin-bottom:7px}
.legalBody a{color:#3ba6dd}
.lgTable{width:100%;border-collapse:collapse;margin:0 0 14px;font-size:13px}
.lgTable th{text-align:left;color:#8f8c84;font-weight:600;padding:7px 10px;border-bottom:1px solid #262a31}
.lgTable td{color:#c9c6bf;padding:9px 10px;border-bottom:1px solid #171a1f;vertical-align:top;line-height:1.55}
.lgWipe{background:#14161a;color:#f4f2ec;border:1px solid #3a3f48;border-radius:99px;
  padding:11px 18px;cursor:pointer;font-size:15px}
.lgWipe:hover{border-color:#e11b2b;background:#1a1d23}
.lgWipeNote{display:block;margin-top:8px;color:#4fce7f;font-size:13px}
.lgUpd{color:#8f8c84;font-size:13px;margin-top:24px}

/* ---- speed cameras ---- */
.camBox{background:#14161a;border:1px solid #262a31;border-left:4px solid #8f8c84;border-radius:14px;padding:14px 17px;margin:0 0 16px}
.camBox.has{border-left-color:#f2a71b;background:rgba(242,167,27,.06)}
.camHead{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;margin-bottom:7px}
.camHead b{font-size:15px;color:#f4f2ec}
.camHead span{color:#c9c6bf;font-size:13px}
.camFine{color:#a9a69d;font-size:13px;line-height:1.6;margin:0}
.camPin{background:none;border:0}
.camPin span{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:99px;
  background:#f2a71b;color:#111;font-size:12px;box-shadow:0 2px 8px rgba(0,0,0,.55);border:2px solid #fff}
.rbCam{margin:8px 0 0;color:#f2a71b;font-size:13px;background:rgba(242,167,27,.08);
  border-radius:8px;padding:6px 10px;display:inline-block}

/* ---- worth stopping for ---- */
.atrTag{display:inline-block;margin-left:8px;background:rgba(225,27,43,.16);color:#ff6a4d;
  border-radius:99px;padding:2px 10px;font-size:11px;text-transform:uppercase;letter-spacing:.05em;vertical-align:middle}
.atrCard.noPic 
@media(max-width:680px){}
.mapNote .lgd.dim{color:#8f8c84;font-size:12px}

/* ---- profile annotations: the summit and the passes, named on the chart ---- */
.pfAnno{font:700 15px 'Barlow Condensed',Arial Narrow,sans-serif;text-transform:uppercase;letter-spacing:.02em;
  paint-order:stroke;stroke:#0b0c0e;stroke-width:4px;stroke-linejoin:round}
.pfAnno.big{font-size:19px}
.pfAnnoSub{font:500 11px system-ui,sans-serif;fill:#a9a69d;paint-order:stroke;stroke:#0b0c0e;stroke-width:3.5px}
@media print{.pfAnno,.pfAnnoSub{stroke:#fff;fill:#111}.pfAnno{fill:#111}}/* ---- THE SCORE STRADDLED THE CORNER OF THE PHOTOGRAPH ----
   position:relative with left and bottom offsets does not place an element, it SHIFTS it from
   wherever the flow put it - so the badge ended up half on the picture and half off its top
   edge, cut by the card's rounded corner. Torsten circled it three times; I searched for the
   wrong class twice, failed to find it, and moved on without saying so, which is worse than
   not fixing it.
   Absolute, inside the hero, inset from the corner: it sits ON the photograph, clear of the
   radius, with a shadow so a light picture cannot swallow it. */
.rideHero{position:relative}
.rhScore{position:absolute;left:12px;top:12px;bottom:auto;z-index:3;font-size:19px;
  padding:4px 12px;cursor:help;box-shadow:0 2px 10px rgba(0,0,0,.55)}
@media(max-width:620px){.rhScore{left:10px;top:10px;font-size:15px;padding:3px 10px}}
.whyPop{display:none;position:absolute;top:calc(100% + 9px);right:0;z-index:40;width:270px;
  background:#0f1114;border:1px solid #3a3f48;border-radius:12px;padding:11px 13px;
  box-shadow:0 14px 34px rgba(0,0,0,.62);font-style:normal;text-align:left;pointer-events:none}
.whyPop span{display:block;color:#c9c6bf;font:400 13px/1.5 system-ui,sans-serif;margin-bottom:5px;text-transform:none;letter-spacing:0}
.whyPop span:last-child{margin-bottom:0}
.rhScore:hover .whyPop,.rhScore:focus-visible .whyPop{display:block}
.rTags{display:flex;flex-wrap:wrap;gap:6px;margin:8px 0 0}
.rTag{background:#1a1d23;border:1px solid #2b3038;color:#a9a69d;border-radius:99px;
  padding:3px 10px;font-size:12px;cursor:help}
.rTag:hover{border-color:#e11b2b;color:#f4f2ec}
.fcRate{color:#8f8c84;font-size:12px;font-style:normal}

/* ---- explore filters ---- */
.exFilters{display:flex;flex-wrap:wrap;gap:9px;align-items:center;margin:0 0 18px;
  background:#14161a;border:1px solid #262a31;border-radius:14px;padding:13px 15px}
.exFilters input[type=search]{flex:1 1 230px;min-width:180px;background:#0d0f12;border:1px solid #31363f;
  color:#f4f2ec;border-radius:99px;padding:10px 16px;font-size:15px}
.exFilters select{background:#0d0f12;border:1px solid #31363f;color:#f4f2ec;border-radius:99px;
  padding:10px 14px;font-size:13px;cursor:pointer;max-width:230px}
.exFilters input:focus,.exFilters select:focus{border-color:#e11b2b;outline:none}
.exFound{color:#8f8c84;font-size:13px;margin-left:auto}.exCard{background:linear-gradient(180deg,var(--card),#101216);border:1px solid var(--edge);border-radius:var(--rad);
  overflow:hidden;display:flex;flex-direction:column;transition:border-color .15s,transform .15s;position:relative}
.exStar{position:absolute;top:10px;left:10px;z-index:5}
@media(max-width:680px){.exFilters select{max-width:none;flex:1 1 44%}.exFound{margin-left:0;width:100%}}

/* ---- roadbook prose ---- */
.rbLead{color:#f4f2ec;font-size:15px;line-height:1.68;margin:10px 0 10px}
.rbMore{color:#c9c6bf;font-size:15px;line-height:1.72;margin:0 0 10px}
.rbMore b{color:#f4f2ec}.filterBar{display:flex;gap:9px;overflow-x:auto;padding:16px 0 4px;-webkit-overflow-scrolling:touch;scrollbar-width:thin;scrollbar-color:#3a3f48 transparent}.filterBar::-webkit-scrollbar{display:none;height:7px}
.filterBar::-webkit-scrollbar-track{background:transparent}
.filterBar::-webkit-scrollbar-thumb{background:#3a3f48;border-radius:99px}
.filterBar>*{flex:0 0 auto}.svcChips{display:flex;gap:8px;overflow-x:auto;padding:4px 0 6px;-webkit-overflow-scrolling:touch;scrollbar-width:thin;scrollbar-color:#3a3f48 transparent}.svcChips::-webkit-scrollbar{display:none;height:7px}
.svcChips::-webkit-scrollbar-track{background:transparent}
.svcChips::-webkit-scrollbar-thumb{background:#3a3f48;border-radius:99px}
.svcChips>*{flex:0 0 auto}.navScroll{display:flex;gap:8px;overflow-x:auto;-webkit-overflow-scrolling:touch;padding-bottom:2px;scrollbar-width:thin;scrollbar-color:#3a3f48 transparent}.navScroll::-webkit-scrollbar{display:none;height:7px}
.navScroll::-webkit-scrollbar-track{background:transparent}
.navScroll::-webkit-scrollbar-thumb{background:#3a3f48;border-radius:99px}
.navScroll>*{flex:0 0 auto}

.fcGuess{color:#8f8c84;font-style:normal;font-size:12px}
.exCmp{background:#1a1d23;color:#c9c6bf;border:1px solid #31363f;border-radius:99px;
  padding:9px 15px;cursor:pointer;font-size:13px}
.exCmp:hover{border-color:#e11b2b;color:#f4f2ec}
.exCard.picked .exCmp{background:rgba(225,27,43,.18);border-color:#e11b2b;color:#ff6a4d}
.measured{color:#4fce7f;font-size:12px}
.heroHidden{opacity:0;pointer-events:none}

.how{display:block}

.rbMini .rbWay{position:absolute;left:8px;bottom:8px;right:auto;background:rgba(11,12,14,.82);color:#f4f2ec;font-size:12px;padding:4px 10px;border-radius:99px;text-align:left;letter-spacing:.02em}
.rbMini .num{position:absolute;left:7px;top:7px;background:rgba(11,12,14,.85);color:#fff;
  border-radius:7px;padding:2px 9px;font-size:12px}.rbMini:hover{border-color:#e11b2b}

/* ---- the riding day's weather, per waypoint ---- */
.rbWx{margin:12px 0 4px;background:#0d0f12;border:1px solid #232830;border-radius:12px;padding:11px 12px 9px}
.wxHead{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:9px}
.wxHead b{font-size:15px;color:#f4f2ec}
.wxHead span{font-size:13px;color:#a9a69d}
.wxStrip{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(56px,1fr);gap:6px;overflow-x:auto;
  scrollbar-width:thin;scrollbar-color:#3a3f48 transparent;padding-bottom:4px}
.wxStrip::-webkit-scrollbar{height:6px}
.wxStrip::-webkit-scrollbar-thumb{background:#3a3f48;border-radius:99px}
.wxCell{display:flex;flex-direction:column;align-items:center;gap:2px;background:#14161a;
  border:1px solid #232830;border-radius:10px;padding:7px 4px 6px;cursor:help}
.wxCell.wet{border-color:rgba(59,166,221,.55);background:rgba(59,166,221,.08)}
.wxCell.windy{box-shadow:inset 0 -2px 0 #f2a71b}
.wxHr{font-size:11px;color:#8f8c84;letter-spacing:.04em}
.wxIco{width:28px;height:28px;display:block}
.wxT{font-size:13px;color:#f4f2ec;font-weight:600}
.wxP{font-size:11px;color:#8f8c84}
.wxP.on{color:#3ba6dd;font-weight:600}
.wxW{width:15px;height:15px;color:#8d99a6;display:block;margin-top:1px}
.wxWs{font-size:11px;color:#8f8c84}
.wxFine{margin:8px 0 0;font-size:12px;color:#8f8c84;line-height:1.5}
@media(max-width:680px){.wxStrip{grid-auto-columns:minmax(50px,1fr)}.wxIco{width:24px;height:24px}}.atrGrid{margin-top:14px;display:grid;gap:16px;grid-template-columns:repeat(auto-fill,minmax(310px,1fr))}
.atrCard{display:flex;flex-direction:column;background:#14161a;border:1px solid #262a31;
  border-radius:14px;overflow:hidden;transition:border-color .16s,transform .16s}.atrCard:hover{border-color:#e11b2b;transform:translateY(-2px)}.atrPic.ph{opacity:.35;min-height:104px;display:flex;align-items:center;justify-content:center;font-size:34px;color:#31363f}
.atrCard.noPic .atrPic{height:96px}
.atrBody{padding:14px 16px 16px;display:flex;flex-direction:column;gap:7px}.atrBody h4{font-size:15px;font-weight:700;line-height:1.15;margin:0;font:700 15px/1.25 'Barlow Condensed',Arial Narrow,sans-serif;
  text-transform:uppercase;color:#f4f2ec;letter-spacing:.01em}.atrMeta{margin-top:3px;color:#8f8c84;font-size:12px;text-transform:uppercase;letter-spacing:.06em}.atrTxt{color:#a9a69d;font-size:13px;line-height:1.6;margin:0;
  display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}
.atrCard:hover .atrTxt{-webkit-line-clamp:unset;overflow:visible}.atrLinks{display:flex;flex-wrap:wrap;gap:7px;margin-top:auto;padding-top:4px}
@media(max-width:680px){.atrGrid{grid-template-columns:1fr}.atrPic{height:200px}}.rideBody{padding:0 0 14px;position:relative;padding-bottom:16px}.ride{position:relative;background:linear-gradient(180deg,var(--card),#101216);border:1px solid var(--edge);
  border-radius:var(--rad);color:var(--ink);transition:transform .16s,border-color .16s,box-shadow .16s;display:block;overflow:visible}.rideHero{position:relative;display:block;width:100%;
  background:linear-gradient(150deg,#1a1d23,#0d0f12);border-bottom:1px solid var(--edge);height:238px;
  border-radius:14px 14px 0 0;overflow:visible}
/* Clip the PHOTOGRAPH, never the box: overflow:hidden on .rideHero cut the score badge in
   half, because the badge is a child of the hero. */
.rideHero img,.rideHero .rhPh{border-radius:14px 14px 0 0}
.rideHero>img{overflow:hidden}

/* ---- waypoint minimap: real tiles, overlay on top ---- */




/* the leg divider takes its colour from the same grade the map drew */
.rbLeg.twisty{border-left-color:#ff2d40;background:rgba(255,45,64,.07)}
.rbLeg.good{border-left-color:#ff8a3d;background:rgba(255,138,61,.06)}
.rbLeg.ordinary{border-left-color:#c8b06a;background:rgba(200,176,106,.05)}
.rbLeg.direct{border-left-color:#7b8794}
.rbLeg.unrated{border-left-color:#3a3f48}
.rbLegTag.plain{color:#8f8c84}

/* ---- named stops at each waypoint ---- */
.stopHead{display:flex;align-items:center;gap:7px;margin-bottom:6px}
.stopHead span{font-size:15px}
.stopHead b{font-size:12px;text-transform:uppercase;letter-spacing:.05em;color:#a9a69d}
.stopItem{display:block;text-decoration:none;padding:6px 0;border-top:1px solid #171a1f}
.stopItem b{display:block;color:#f4f2ec;font-size:13px;line-height:1.3;font-weight:600}
.stopKm{float:right;color:#8f8c84;font-size:12px;margin-left:8px}
.stopWhy{display:block;color:#8fbf9f;font-size:12px;line-height:1.4;margin-top:2px}
.stopHrs{display:block;color:#8f8c84;font-size:11px;margin-top:1px}
.stopItem:hover b{color:#ff6a4d}
.stopNone{color:#8f8c84;font-size:12px;line-height:1.5;margin:2px 0 6px}
.nearRow{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-top:4px}
@media(max-width:680px){}
.csItem:hover .csName{color:#f4f2ec}
@media(max-width:680px){.csName{font-size:11px;max-width:58px}}.csItem{transform:translateX(-50%);gap:3px;width:74px;margin-left:-37px;position:absolute;top:0;display:flex;flex-direction:column;align-items:center;
  background:none;border:0;cursor:pointer;padding:0}
.csItem.lane2:before{content:"";position:absolute;top:-9px;left:50%;width:1px;height:9px;
  background:var(--edge2)}.csName{display:block;color:#c9c6bf;font-size:12px;line-height:1.2;font-style:normal;
  margin-top:2px;text-align:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%}

.rbNorthBadge{position:absolute;top:8px;right:8px;border:1.5px solid rgba(255,255,255,.55);display:flex;align-items:center;gap:2px;
  background:rgba(11,12,14,.78);color:#fff;border-radius:99px;padding:3px 8px 3px 5px;
  font:800 13px/1 system-ui,sans-serif;letter-spacing:.06em}
.rbNorthBadge svg{width:15px;height:15px;display:block}

/* ---- three scenic pictures per waypoint, cycling ---- */
.rotBox{position:relative;overflow:hidden}
.rotBox img.rot{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:0;transition:opacity .9s ease}
.rotBox img.rot.on{opacity:1}
.rotCred{text-decoration:none;position:absolute;right:6px;bottom:5px;z-index:3;color:#f4f2ec;font-size:11px;
  background:rgba(11,12,14,.6);border-radius:5px;padding:1px 6px;max-width:82%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media (prefers-reduced-motion: reduce){.rotBox img.rot{transition:none}}

/* ---- the minimap must not be mistaken for decoration ----
   Tiles are the only images on the page a browser is likely to auto-darken, so the scheme
   is declared and the marks on top are sized to read at a glance. */
.rbMini img{color-scheme:light}

/* ---- what the place is ---- */
.rbPlace{margin:8px 0 2px}
.rbPlaceLine{color:#f4f2ec;font-size:15px;line-height:1.72;margin:0 0 10px;
  border-left:3px solid rgba(59,166,221,.5);padding-left:12px}
.rbPlaceLine b{color:#fff}

/* ---- conditions layer ---- */
.condPin{background:none;border:0}
.condPin span{display:flex;align-items:center;justify-content:center;width:26px;height:26px;
  border-radius:99px;font-size:12px;border:2px solid #fff;box-shadow:0 2px 8px rgba(0,0,0,.6);color:#0b0c0e}
.condPin.c-rough span{background:#c77dff}
.condPin.c-works span{background:#ffb300}
.condPin.c-pass span{background:#4fce7f}
.condPin.c-camera span{background:#f2a71b}
.condPin.c-queue span{background:#3ba6dd}

/* the waypoint minimap's road, replaced in place when the real geometry arrives */

.condPin.c-hazard span{background:#ff2d55;color:#fff}
.condPin.c-toll span{background:#f2f0ea}
.condPin.c-border span{background:#8b5cf6;color:#fff}

/* ---- rider gatherings ---- */
.evBox{background:rgba(139,92,246,.08);border:1px solid rgba(139,92,246,.35);
  border-left:4px solid #8b5cf6;border-radius:14px;padding:14px 17px;margin:0 0 16px}
.evHead b{font-size:15px;color:#f4f2ec}
.evItem{display:block;text-decoration:none;padding:9px 0;border-top:1px solid rgba(139,92,246,.18)}
.evBox .evItem:first-of-type{border-top:0}
.evItem b{display:block;color:#f4f2ec;font-size:15px}
.evWhen{display:block;color:#c4b5fd;font-size:13px;margin-top:2px}
.evNote{display:block;color:#a9a69d;font-size:13px;line-height:1.55;margin-top:3px}
.evCheck{display:block;color:#8f8c84;font-size:12px;margin-top:3px}
.evItem:hover b{color:#c4b5fd}

/* ---- the drawn rider: shown only when no riding photograph was found ---- */
/* THE RIDER SILHOUETTE IS GONE.
   A near-black motorcycle at 82% opacity, 420px wide, sitting over the photograph and behind
   the buttons - on a dark hero it reads as a smudge rather than a motorcycle, and it competes
   with the one thing that screen has to do: get the rider to press "use my location". The
   logo already says this is about motorcycles. */
.heroRider{display:none}
.heroRider path,.heroRider circle{transition:none}
@media(max-width:760px){.heroRider{width:64vw;right:-4%;bottom:14%;opacity:.7}}
@media print{.heroRider{display:none}}
/* marks a hero that fell back to the drawn rider - lifts the text clear of it */
.heroIn.heroDrawn .heroCta{position:relative;z-index:3}
.spark.altBand{opacity:.95}
.bandNote{font-size:11px;fill:#8f8c84;letter-spacing:.02em}/* ---- the bike that rides the route ---- */
.rideBtn:hover{border-color:#ff2d55}
.rideBtn.on{background:#ff2d55;color:#0b0c0e;border-color:#ff2d55}

/* ---- out-and-back stretches ---- */
.spurBox{background:#14161a;border:1px solid #262a31;border-left:4px solid #f2a71b;
  border-radius:14px;padding:14px 17px;margin:0 0 16px}
.spHead{display:flex;gap:12px;align-items:baseline;flex-wrap:wrap;margin-bottom:8px}
.spHead b{font-size:15px;color:#f4f2ec}
.spHead span{font-size:13px;color:#a9a69d}
.spItem i{flex:0 0 auto;width:20px;height:20px;border-radius:99px;background:#4fce7f;color:#06121a;
  font-style:normal;font-weight:700;font-size:12px;display:flex;align-items:center;justify-content:center;margin-top:2px}
.spItem.bad i{background:#f2a71b}
.spItem b{color:#f4f2ec}
.flagSvg{width:20px;height:20px;display:inline-block;vertical-align:-4px;margin-right:5px}
@keyframes bikeBob{0%,100%{transform:translateY(0)}50%{transform:translateY(-1.5px)}}
@media (prefers-reduced-motion: reduce){.rideBike svg{animation:none}}.rbMini .rbAtr{position:absolute;display:flex;flex-wrap:wrap;gap:4px;max-width:none;bottom:auto;top:8px;left:8px;right:64px}.rbMini .rbAtr i{padding:2px 8px;
  font-size:11px;font-style:normal;white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis;width:auto;height:auto;border-radius:99px;border:0;box-shadow:0 1px 6px rgba(0,0,0,.5);background:rgba(255,255,255,.94);color:#0b0c0e;font-weight:600}
/* the bearing rides as a chip now, not a scrim across a third of the map */
.rbWayChip{white-space:nowrap;max-width:calc(100% - 16px);overflow:hidden;text-overflow:ellipsis}

/* ---- the control bar that travels with the map ---- */
/* clear of the attribution strip below it - see .leaflet-control-attribution */
.mapBar{position:absolute;left:10px;right:10px;bottom:32px;z-index:1150;display:flex;
  gap:10px;align-items:center;justify-content:space-between;flex-wrap:wrap;pointer-events:none}
.mapBar>*{pointer-events:auto}
.mapBarRight{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.mapBar .lineMode{display:flex;gap:6px;margin:0;background:rgba(11,12,14,.82);
  border:1px solid #31363f;border-radius:99px;padding:4px}
.mapBar .lineMode button.on{background:#ff2d55;color:#0b0c0e}
.pinStart{background:rgba(11,12,14,.86);color:#f4f2ec;border:1px solid #31363f;border-radius:99px;
  padding:8px 14px;cursor:pointer;font:700 12px/1 'Barlow Condensed',sans-serif;
  text-transform:uppercase;letter-spacing:.06em;white-space:nowrap}
.pinStart:hover{border-color:#ff2d55}
.pinStart.on{background:#f2a71b;color:#0b0c0e;border-color:#f2a71b}.rideBtn{z-index:1100;background:rgba(11,12,14,.86);
  color:#f4f2ec;border:1px solid #31363f;border-radius:99px;padding:8px 15px;cursor:pointer;
  font:700 13px/1 'Barlow Condensed',sans-serif;text-transform:uppercase;letter-spacing:.06em;position:static;left:auto;bottom:auto}

@media(max-width:680px){.mapBar{gap:6px}.mapBar .lineMode button{padding:6px 10px;font-size:16px}}
.rideBike .bkSpeed{stroke:#ff2d55;stroke-width:1.6;stroke-linecap:round;opacity:.85;
  animation:bkDash .45s linear infinite}
.rideBike.isResting svg{transform:scale(.94)}
@keyframes bkDash{0%{opacity:.9;transform:translateX(0)}100%{opacity:.25;transform:translateX(-4px)}}
@keyframes bkZ{0%{opacity:0;transform:translate(0,2px)}30%{opacity:1}100%{opacity:0;transform:translate(2px,-5px)}}
@media (prefers-reduced-motion: reduce){
  .rideBike .bkSpeed,.rideBike .bkZzz text{animation:none}
  .rideBike .bkZzz text{opacity:.85}
}/* the two artwork states swap inside the same marker, so the animation never restarts */
.rideBike .bkRest{display:block}

/* ---- no blink, no jump ----
   Every section below the map fills in after the page paints. Without a reserved height
   the page shuffles under the reader's thumb as each one lands, which is the thing that
   makes an app feel slow even when it is fast. Hold the space, then fade the content in
   once - never a spinner that appears and disappears. */
#svcBox:empty,#atrBox:empty{min-height:132px;border-radius:14px;
  background:linear-gradient(100deg,#14161a 30%,#1b1e24 50%,#14161a 70%);
  background-size:220% 100%;animation:settle 1.4s ease-in-out infinite}
.rbWx:empty{min-height:96px;border-radius:12px;background:#0d0f12}
.rbPlace:empty{min-height:0}
@keyframes settle{0%{background-position:120% 0}100%{background-position:-20% 0}}
@media (prefers-reduced-motion: reduce){
  #svcBox:empty,#atrBox:empty{animation:none;background:#14161a}
}
/* content arrives once, gently, and never flashes back out */
#svcBox>*,#atrBox>*,.rbWx>*{animation:arrive .22s ease-out both}
/* Opacity only. Animating transform makes the element a containing block, and any
   position:fixed descendant then resolves against IT rather than the viewport - the exact
   trap that broke the expanding map for days. The audit caught this one before it shipped. */
@keyframes arrive{from{opacity:0}to{opacity:1}}

/* ---- one legend, collapsed, so the map is the map ---- */
.mapNote.lgdBox{max-width:min(58%,420px)}
.mapNote.lgdBox.shut .lgd,.mapNote.lgdBox.shut .pfSrc,.mapNote.lgdBox.shut span:not(.lgdMore){display:none}
.mapNote.lgdBox.shut .lgdToggle{display:flex}
.lgdToggle{display:flex;align-items:center;gap:8px;background:none;border:0;color:#f4f2ec;
  cursor:pointer;font:600 13px/1.2 inherit;padding:0;width:100%;text-align:left}
.lgdToggle i{width:18px;height:5px;border-radius:3px;flex:0 0 auto;box-shadow:0 0 0 1.5px #0b0c0e}
.lgdToggle .lgdMore{margin-left:auto;color:#8f8c84;font-size:11px;text-transform:uppercase;
  letter-spacing:.06em}
.mapNote.lgdBox:not(.shut) .lgdToggle{margin-bottom:8px}

/* ---- the scenic badge ---- */
.scenicTag span{position:absolute;transform:translate(-50%,-50%);white-space:nowrap;
  background:rgba(11,12,14,.86);color:#fff;border-radius:99px;padding:3px 10px;
  font:800 12px/1 'Barlow Condensed',sans-serif;text-transform:uppercase;letter-spacing:.07em;
  box-shadow:0 2px 8px rgba(0,0,0,.55)}
.scenicTag.t-twisty span{border:1.5px solid #ff2d55;color:#ffd7de}
.scenicTag.t-good span{border:1.5px solid #ffb300;color:#ffeec2}

/* ---- setting the start: a flag you drag, or a name you type ---- */
.startFlag svg{width:34px;height:42px;overflow:visible;filter:drop-shadow(0 3px 6px rgba(0,0,0,.6));cursor:grab}
.startFlag svg:active{cursor:grabbing}
.startFlag .fpole{stroke:#0b0c0e;stroke-width:2.4;stroke-linecap:round}
.startFlag .fcloth{fill:#ff2d55;stroke:#0b0c0e;stroke-width:1.2}
.startFlag .fdot{fill:#ff2d55;stroke:#0b0c0e;stroke-width:1.4}
.startPanel{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:1300;
  width:min(360px,88%);background:rgba(11,12,14,.96);border:1px solid #31363f;border-radius:14px;
  padding:16px 18px;box-shadow:0 18px 50px rgba(0,0,0,.65)}
.startPanel label{display:block;color:#a9a69d;font-size:13px;margin-bottom:8px}
.startPanel input{width:100%;margin-top:6px;background:#14161a;border:1px solid #31363f;
  border-radius:10px;color:#f4f2ec;padding:10px 12px;font-size:15px}
.startPanel input:focus{outline:none;border-color:#ff2d55}
.spRow{display:flex;gap:8px;margin-top:10px}
.spRow button{flex:1;background:#ff2d55;color:#0b0c0e;border:0;border-radius:99px;padding:10px;
  cursor:pointer;font:700 13px/1 'Barlow Condensed',sans-serif;text-transform:uppercase;letter-spacing:.06em}
.spRow button:last-child{background:none;color:#c9c6bf;border:1px solid #31363f}
.spHint{color:#8f8c84;font-size:12px;line-height:1.5;margin:10px 0 0}

/* ---- waypoint minimaps: real Leaflet maps ----
   Hand-placed tiles were wrong five times in a row. These are the same library and tiles as
   the map at the top of the page. Non-interactive: the whole tile is a link to the real map. */
.rbMiniMap{position:absolute;inset:0;display:block;background:#e8e3da;border-radius:10px}
.rbMiniMap .leaflet-container{background:#e8e3da;font:inherit}
.rbMiniMap .leaflet-control-container{display:none}.rbMini{position:relative;display:block;border-radius:10px;overflow:hidden;border:1px solid #31363f;background:#e8e3da;box-shadow:0 0 0 1px rgba(255,255,255,.14), 0 6px 18px rgba(0,0,0,.5);cursor:pointer}
.rbMini .leaflet-pane{pointer-events:none}/* ---- what the route itself knows, shown before any network answers ---- */
.svcSeedRow span{color:#a9a69d;font-size:13px}/* ---- the week's-road dock must not sit on the map's own controls ----
   .miniShow / .miniDock are fixed to the bottom-right. The map bar lives at the bottom of
   the map box, and when the map is expanded that box IS the viewport - so the two collided
   exactly when the map was full screen and the controls mattered most. */
body.mapOpen #buildBadge{display:none}
@media(max-width:760px){
  body.mapOpen .miniShow,body.mapOpen .miniDock{bottom:calc(112px + env(safe-area-inset-bottom))}
  .mapBar{flex-direction:column;align-items:stretch;gap:6px}
  .mapBarRight{justify-content:flex-end}
}
/* a ride being re-cut stays on screen, just quieter - it never blanks */
.recutting{opacity:.55;transition:opacity .15s;pointer-events:none}.wpDot{width:30px;height:30px;border-radius:99px;background:var(--red);color:#fff;border:2.5px solid #fff;
  display:flex;align-items:center;justify-content:center;font:700 13px var(--display);box-shadow:0 2px 8px rgba(0,0,0,.55),0 0 0 2px rgba(11,12,14,.55)}

/* ---- what the score has learned ---- */
.liveTags{display:flex;gap:6px;flex-wrap:wrap;margin:2px 0 6px}
.legendTag{background:rgba(6,42,30,.92);color:#7ee7bb;border:1px solid rgba(14,159,110,.7);border-radius:99px;
  padding:3px 10px;font:800 12px/1 'Barlow Condensed',sans-serif;text-transform:uppercase;letter-spacing:.06em}
.liveTag{background:rgba(255,45,85,.12);border:1px solid rgba(255,45,85,.4);color:#ff8fa6;
  border-radius:99px;padding:3px 10px;font-size:12px}

/* ---- where the day stops ---- */
.restPin span{position:absolute;transform:translate(-50%,-120%);white-space:nowrap;
  color:#8fd3f4;font:800 13px/1 'Barlow Condensed',sans-serif;letter-spacing:.06em;
  text-shadow:0 1px 4px rgba(0,0,0,.9)}
.restPin i{font-style:normal;font-size:13px;opacity:.85}
.restPin b{font-size:15px;opacity:.7}
/* the legend must be readable when the map is full screen too */
body.mapOpen .mapNote.lgdBox{max-width:min(46%,520px)}.svcSeed{display:grid;gap:8px;margin-top:10px;grid-template-columns:repeat(auto-fill,minmax(300px,1fr))}.svcSeedRow{background:#14161a;border:1px solid #262a31;border-radius:11px;display:flex;gap:12px;align-items:flex-start;padding:11px}
.svcSeedRow>div:last-child{min-width:0}
.svcSeedKind{display:block;color:#a9a69d;font-size:12px;margin:1px 0 4px}
.svcSeedRow:hover p{-webkit-line-clamp:unset}body.mapOpen .speedKey{position:fixed;left:14px;right:auto;z-index:2100;
/* 62% OF THE MAP IS NOT A LEGEND, IT IS A WALL. Twelve lines of solid black sat over the
   country he was trying to read. The grades stay - the colours on the road mean nothing
   without them - and the glossary folds away behind a summary. */
/* SEMI-TRANSPARENT AND DETACHED, as asked: the country stays readable through the legend,
   and a clear gap above the mode toggle stops the two reading as one welded block. */
  max-width:min(30%,330px);background:rgba(11,12,14,.55);border:1px solid rgba(63,70,80,.7);
  -webkit-backdrop-filter:blur(7px);backdrop-filter:blur(7px);
  border-radius:12px;padding:11px 15px;display:block;font-size:15px;
  bottom:158px;box-shadow:0 4px 16px rgba(0,0,0,.35)}
body.mapOpen .speedKey span{font-size:15px}body.mapOpen .miniShow,body.mapOpen .miniDock{bottom:calc(74px + env(safe-area-inset-bottom));z-index:2100}

/* ---- slightly larger type and thumbnails, as asked ---- */
.atrCard h4{font-size:15px}.atrWhy{color:#f4f2ec;margin:0;font-size:15px;line-height:1.65}.svcSeedRow b{display:block;color:#f4f2ec;font-size:15px}.svcSeedRow p{margin:0;color:#a9a69d;line-height:1.55;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;font-size:15px}.svcSeedPic{border-radius:10px;overflow:hidden;
  background:#0d0f12;position:relative;display:flex;align-items:center;justify-content:center;font-size:22px;flex:0 0 92px;width:92px;height:92px}.atrPic{width:100%;height:216px;object-fit:cover;display:block;background:#0d0f12;min-height:132px}
.rbi .rbMedia>*{min-height:214px}.spItem{display:flex;gap:10px;align-items:flex-start;color:#a9a69d;
  line-height:1.65;margin:0 0 8px;font-size:15px}
.pinStart,.rideBtn{font-size:12px;padding:9px 16px}
/* 700 like everything else: this was the only 800 in the file against 42 uses of 700, and a
   single heavier weight reads as a rendering accident rather than emphasis. */
.spOpt{background:#4fce7f;color:#06121a;font-weight:700}
.spItem.bad .spOpt{background:#f2a71b}
.spFoot{color:#8f8c84;font-size:13px;margin:10px 0 0;line-height:1.55}

/* ---- which GPX do you want ---- */
.gpxAsk{position:fixed;inset:0;z-index:2600;background:rgba(6,7,9,.72);display:flex;
  align-items:center;justify-content:center;padding:20px}
.gpxCard{background:#14161a;border:1px solid #31363f;border-radius:16px;padding:20px 22px;
  width:min(400px,100%);box-shadow:0 20px 60px rgba(0,0,0,.7)}
.gpxCard b{display:block;color:#f4f2ec;font-size:15px;margin-bottom:6px}
.gpxCard p{color:#a9a69d;font-size:15px;line-height:1.6;margin:0 0 14px}
.gpxCard button{display:block;width:100%;margin-top:8px;background:#ff2d55;color:#0b0c0e;
  border:0;border-radius:99px;padding:12px;cursor:pointer;
  font:700 15px/1 'Barlow Condensed',sans-serif;text-transform:uppercase;letter-spacing:.06em}
.gpxCard .gpxCancel{background:none;color:#a9a69d;border:1px solid #31363f}
.camLaw{border-top:1px solid #262a31;margin-top:10px;padding-top:10px;color:#8f8c85}

/* ---- somewhere to eat, at every checkpoint ---- */
.eatBox{background:#0f1216;border:1px solid #242830;border-radius:12px;padding:12px 15px;margin:12px 0 0}
.eatHead{color:#f4f2ec;font-weight:700;font-size:15px;margin-bottom:9px}
.eatHead span{display:block;color:#8f8c84;font-weight:400;font-size:12px;line-height:1.5;margin-top:3px}
.eatRow{border-top:1px solid #1d2027;padding:9px 0 2px}
.eatRow:first-of-type{border-top:0}
.eatRow b{color:#f4f2ec;font-size:15px}
.eatStyle{display:block;color:#ffb300;font-size:13px;margin:1px 0 3px}
.eatRow p{margin:0 0 4px;color:#a9a69d;font-size:13px;line-height:1.55}
.eatRow a{color:#ff8fa6;font-size:12px;text-decoration:none;margin-right:10px}
.eatRow a:hover{text-decoration:underline}/* ---- the famous roads a ride actually uses ---- */.legendBox{background:#14161a;border:1px solid #262a31;border-left:4px solid #ffb300;
  border-radius:14px;padding:14px 17px;margin:0 0 16px}.lgHead b{color:#f4f2ec;font-size:15px}.lgHead span{display:block;color:#8f8c84;font-size:13px;line-height:1.55;margin:3px 0 9px}.lgItem{margin:0 0 11px;color:#a9a69d;font-size:15px;line-height:1.62}.lgItem b{display:block;color:#ffb300;font-size:15px}.lgItem i{display:block;color:#8f8c84;font-style:normal;font-size:12px;margin-bottom:3px}/* THE LABEL SAT ON THE ROAD IT NAMES.
   translate(-50%,-50%) centres it exactly on the point, so "BLACK FOREST PANORAMA ROUTE
   B500 SOUTH" lay across the trail and hid the thing it was pointing at. Lifted clear, with
   a tail so it still reads as belonging to that spot. */
.legendPin span{position:absolute;transform:translate(-50%,-165%);white-space:nowrap;
  background:rgba(6,42,30,.92);color:#7ee7bb;border:1px solid rgba(14,159,110,.7);border-radius:99px;
  padding:3px 11px;font:800 12px/1 'Barlow Condensed',sans-serif;text-transform:uppercase;
  letter-spacing:.06em;box-shadow:0 2px 8px rgba(0,0,0,.6)}
.regTag{font-style:normal;color:#8f8c84;font-size:13px;margin-left:6px}
.regTag::before{content:'· '}

/* ---- recommended, and the roads not yet ridden ---- */
.recTag{background:#4fce7f;color:#06121a;border-radius:99px;padding:3px 11px;
  font:800 12px/1 'Barlow Condensed',sans-serif;text-transform:uppercase;letter-spacing:.06em}
.exLegends{margin:26px 0 0;background:#14161a;border:1px solid #262a31;
  border-left:4px solid #ffb300;border-radius:14px;padding:16px 19px}
.exLegends h3{margin:0 0 6px;color:#f4f2ec;font-size:15px}
.exLegNote{color:#8f8c84;font-size:13px;line-height:1.6;margin:0 0 12px}
.exLegRow{border-top:1px solid #1d2027;padding:10px 0 2px;color:#a9a69d;font-size:15px;line-height:1.6}
.exLegRow:first-of-type{border-top:0}
.exLegRow b{display:block;color:#ffb300;font-size:15px}
.exLegRow i{display:block;color:#8f8c84;font-style:normal;font-size:12px;margin-bottom:3px}
.regFlag{width:20px;height:14px;border-radius:2px;vertical-align:-2px;margin:0 5px 0 6px;
  box-shadow:0 0 0 1px rgba(0,0,0,.35)}

/* ---- the week's-road dock must never share a row with the map controls ----
   The audit could not see this because JSDOM gives every element a zero-sized box at 0,0.
   With the map open the controls occupy the bottom edge, so the dock moves to the RIGHT
   edge, vertically clear of them, rather than sharing the corner. */
body.mapOpen .miniDock{bottom:auto;top:calc(50% - 90px);right:12px;z-index:2100;max-width:300px}
body.mapOpen .miniShow{bottom:auto;top:calc(50% - 90px);right:12px;z-index:2100}
@media(max-width:900px){
  body.mapOpen .miniDock,body.mapOpen .miniShow{top:auto;bottom:calc(150px + env(safe-area-inset-bottom))}
}
.svcPin span{position:absolute;transform:translate(-50%,-50%);font-size:15px;line-height:1;
  filter:drop-shadow(0 1px 3px rgba(0,0,0,.8));cursor:pointer}
.svcPin.s-camera span,.svcPin.s-works span{font-size:15px}

/* The legend, once it has been MOVED inside the expanded map box. Positioned relative to
   that box rather than the viewport, so no z-index race with the map can hide it. */
.mapBox.expanded > /* THE LEGEND MUST NOT GROW INTO THE CONTROLS BELOW IT.
   bottom:76px with no height limit: the panel grew upward as content was added and its own
   box still started 76px off the floor - but the mode bar sits at bottom:32 and the base
   switch above that, so anything that made the legend taller eventually met them. It now has
   a ceiling: at most the map height less the bands the controls own, and it scrolls inside
   itself rather than pushing into them. A legend that covers the buttons is worse than a
   legend that scrolls. */
/* NARROWER AND SHORTER. 60% of the map, permanently, is not a legend - it is a wall. The
   grades stay visible because the colours mean nothing without them; everything else folds. */
.speedKey.inMap{position:absolute;left:14px;bottom:92px;right:auto;
  max-height:calc(100% - 190px);overflow-y:auto;overscroll-behavior:contain;
  z-index:1200;max-width:min(30%,330px);background:rgba(11,12,14,.55);border:1px solid rgba(63,70,80,.7);
  -webkit-backdrop-filter:blur(7px);backdrop-filter:blur(7px);
  border-radius:12px;padding:11px 15px;display:block;font-size:15px;box-shadow:0 4px 16px rgba(0,0,0,.35)}
/* a label that had to move keeps a thin tether to the point it describes */
/* the famous-road chips are the way into what the road IS - they must accept a tap.
   scenicTag stays inert; it labels, it does not lead anywhere. */
.scenicTag span{pointer-events:none}
.legendPin span{pointer-events:auto;cursor:pointer}

/* ---- not enough day left ---- */
.dayWarn{background:#14161a;border:1px solid #262a31;border-left:4px solid #f2a71b;
  border-radius:14px;padding:14px 17px;margin:0 0 16px}
.dayWarn.hard{border-left-color:#ff2d55}
.dayWarn b{color:#f2a71b;font-size:15px}
.dayWarn.hard b{color:#ff8fa6}
.dayWarn p{color:#a9a69d;font-size:15px;line-height:1.6;margin:6px 0 0}
/* a famous road the ride does not use: outlined, plainly not part of today */
.legendPin.nearby span{background:rgba(11,12,14,.82);color:#ffd88a;
  border:1px dashed rgba(255,179,0,.75);box-shadow:none;font-weight:600;text-transform:none;
  letter-spacing:.01em}
/* a camera pin standing for several: the shared cluster badge sits inside it */
.camPin.camCluster span,.camPin.camCluster{overflow:visible}

/* ---- advertising consent: a strip, never a wall ---- */
.adConsent{position:fixed;left:12px;right:12px;bottom:12px;z-index:9500;background:#14161a;
  border:1px solid #31363f;border-left:4px solid #ffb300;border-radius:14px;padding:14px 17px;
  max-width:760px;margin:0 auto;box-shadow:0 10px 30px rgba(0,0,0,.6)}
.adConsent p{margin:0 0 10px;color:#a9a69d;font-size:13px;line-height:1.6}
.adConsent b{color:#f4f2ec}
.adConsent a{color:#ffb300}
.adConsent div{display:flex;gap:9px;justify-content:flex-end}
.adConsent button{background:#1b1e24;color:#d7d4cc;border:1px solid #31363f;border-radius:99px;
  padding:9px 17px;font:700 13px 'Barlow Condensed',sans-serif;text-transform:uppercase;
  letter-spacing:.05em;cursor:pointer}
.adConsent button.p{background:#e6002e;border-color:#e6002e;color:#fff}
/* an ad slot occupies no space at all until something is actually in it */
.adSlot:empty{display:none}
.adSlot{margin:18px 0;min-height:0}
/* Google styles .adsbygoogle itself; this only stops it inheriting anything of ours and
   keeps it visually separate from the writing, which their policy requires. */
.adsbygoogle{display:block;margin:0;border:0;background:transparent;font:inherit}
/* a button on the legal page - the withdraw-consent control */
.lgBtn{background:#1b1e24;color:#d7d4cc;border:1px solid #31363f;border-radius:99px;
  padding:8px 16px;font:700 13px 'Barlow Condensed',sans-serif;text-transform:uppercase;
  letter-spacing:.05em;cursor:pointer}
.lgBtn:hover{border-color:#7a8190;color:#f4f2ec}

/* confirm a dragged flag instead of re-cutting on every nudge */
.flagOk{position:absolute;left:50%;transform:translateX(-50%);bottom:96px;z-index:2200;
  display:flex;align-items:center;gap:9px;background:#14161a;border:1px solid #31363f;
  border-radius:99px;padding:8px 10px 8px 16px;box-shadow:0 8px 26px rgba(0,0,0,.6)}
.flagOk span{color:#f4f2ec;font:700 15px 'Barlow Condensed',sans-serif;text-transform:uppercase;
  letter-spacing:.05em}
.flagOk button{background:#e6002e;color:#fff;border:0;border-radius:99px;padding:8px 15px;
  font:700 13px 'Barlow Condensed',sans-serif;text-transform:uppercase;letter-spacing:.05em;
  cursor:pointer}
.flagOk button#flagNo{background:#1b1e24;color:#d7d4cc;border:1px solid #31363f}

/* ---- concrete named places ---- */
.plBox{background:#14161a;border:1px solid #262a31;border-radius:14px;padding:16px 19px;margin:0 0 16px}
.plBox h3{margin:0 0 4px;color:#f4f2ec;font-size:15px}
.plGroup{border-top:1px solid #1d2027;padding:13px 0 2px}
.plGroup:first-of-type{border-top:0;padding-top:8px}
.plGroup h4{margin:0 0 3px;color:#f4f2ec;font-size:15px}
.plLead{color:#8f8c84;font-size:13px;line-height:1.55;margin:0 0 9px}
.plBox ul{list-style:none;margin:0;padding:0}
.plRow{display:flex;flex-wrap:wrap;align-items:baseline;gap:8px;padding:6px 0;
  border-top:1px dashed #1d2027;color:#a9a69d;font-size:15px}
.plRow:first-child{border-top:0}
.plRow b{color:#f4f2ec;font-size:15px}
.plRow i{color:#ffb300;font-style:normal;font-size:12px;white-space:nowrap}
.plRow span{color:#8a8f98;font-size:13px}
.plRow a{color:#8f8c84;font-size:12px;text-decoration:underline;margin-left:auto}
.plRow a:hover{color:#e6002e}
.plHost:empty{display:none}

/* ---- shared with a famous road ---- */
.icTag{background:linear-gradient(90deg,#0e9f6e,#0b7a55);color:#fff;border-radius:99px;
  padding:3px 11px;font:800 12px/1 'Barlow Condensed',sans-serif;text-transform:uppercase;
  letter-spacing:.05em;white-space:nowrap}
.icBox{background:#14161a;border:1px solid #262a31;border-left:4px solid #0e9f6e;
  border-radius:14px;padding:15px 18px;margin:0 0 16px}
.icBox h3{margin:0 0 8px;color:#f4f2ec;font-size:15px}
.icRow{margin:0 0 11px;color:#a9a69d;font-size:15px;line-height:1.62}
.icRow b{display:block;color:#5ed6a4;font-size:15px}
.icRow i{display:block;color:#8f8c84;font-style:normal;font-size:12px;margin-bottom:3px}
/* an anchor on a famous road: a named point, never joined into a fake line */
.legendPin.anchorPin span{background:rgba(6,42,30,.86);color:#7ee7bb;
  border:1px solid rgba(14,159,110,.55);box-shadow:none;font-weight:600;text-transform:none;
  letter-spacing:.01em;font-size:11px}/* ---- the rider turns instead of snapping ----
   A bike that instantly faces the other way reads as a glitch; one that swings round reads
   as a bend. The wrapper carries both the mirror and the lean so a single transition covers
   both, and the origin is the contact patch so it pivots on its wheels, not its head. */.rideBike svg{fill:#ff2d55;stroke:#0b0c0e;stroke-width:1.2;animation:bikeBob 1.1s ease-in-out infinite;width:34px;height:28px;
  filter:drop-shadow(0 2px 5px rgba(0,0,0,.75));overflow:visible}
.rideBike .bkHead{fill:currentColor}/* the speed lines trail behind whichever way it faces, because they live inside the mirror */
@media (prefers-reduced-motion: reduce){ .rideBike .bkTurn{transition:none} }
.rideBike .bkZzz text:nth-child(2){animation-delay:.9s}
.rideBike.isResting .bkTurn{transform:scaleX(1) rotate(0deg) !important}
@keyframes bkDrift{0%,100%{opacity:.25;transform:translateY(0)}50%{opacity:.9;transform:translateY(-2px)}}

/* a camera block with nothing in it, or one in a country that restricts warning devices,
   sits at the end and stays quiet - it is a footnote, not a headline */
.camBox.tail{opacity:.72}
.camBox.tail .camHead b{font-size:15px;color:#a9a69d}
.camBox.lead{border-left:4px solid #f2a71b;opacity:1}
.camBox.lead .camHead b{color:#f4f2ec}
#camLead:empty,#camTail:empty{display:none}
/* a country that restricts warning devices: the block is present, factual and unemphatic */
.camBox.restricted .camHead span{color:#8f8c84}
.rideBike .bkSpokes{stroke:#c3cad4;stroke-width:1;stroke-linecap:round}
.rideBike .bkLeg{fill:#262c36;stroke:#0b0c0e;stroke-width:.6}

/* ---- movement ----
   Wheels turn continuously and linearly, because a wheel that eases is a wheel that is
   slipping. The speed lines breathe on their own offset cycle so the two never lock into a
   single pulse, which is what made the old one look mechanical. */
/* TRANSFORM-BOX: VIEW-BOX, NOT FILL-BOX.
   `fill-box` resolves transform-origin against the element's OWN bounding box, so
   `16px 31px` on a wheel whose box starts at (8,23) lands at (24,54) - outside the bike
   entirely. The wheels orbited that point, which is why they appeared to circle the rider.
   `view-box` resolves against the SVG's own grid, where 16,31 is the hub. */
.rideBike .bkAxle{transform-box:view-box;animation:bkRoll 1.5s linear infinite}
/* RESTORED - I REMOVED THIS AS DEAD AND IT IS NOT.
   .bkAxleB is the SECOND wheel, offset half a rotation so the two do not spin in lockstep.
   Its class never appears in app.js because the wheel is drawn by RIDER_DEFS, a template
   string the "unreferenced class" scan cannot see through. The capability
   the-two-animations-never-lock caught it within one run - which is exactly the kind of
   removal that looks safe, measures safe, and is not. */
.rideBike .bkAxleB{animation-delay:-.5s}
@keyframes bkRoll{to{transform:rotate(360deg)}}.rideBike .bkSpeed path{stroke:#ffb300;stroke-width:2;stroke-linecap:round;fill:none;opacity:0;animation:bkStream 1.8s cubic-bezier(.4,0,.5,1) infinite}
.rideBike .bkSpeed path:nth-child(2){animation-delay:.4s}
.rideBike .bkSpeed path:nth-child(3){animation-delay:.8s}
/* SOFTER. The old stream jumped in at 85% opacity within a third of its cycle and slid
   nine pixels - read as flicker rather than motion. Half the travel, a third of the
   brightness, and a symmetrical ease so it fades in and out at the same rate. */
@keyframes bkStream{
  0%{opacity:0;transform:translateX(3px) scaleX(.7)}
  40%{opacity:.42}
  60%{opacity:.42}
  100%{opacity:0;transform:translateX(-5px) scaleX(1)}
}
/* standing still: wheels stop, no stream, and the machine settles a fraction */
.rideBike.isResting .bkAxle{animation:none}
.rideBike.isResting .bkSpeed{display:none}
@media (prefers-reduced-motion: reduce){
  .rideBike .bkAxle,.rideBike .bkSpeed path{animation:none}
  .rideBike .bkSpeed path{opacity:.5}
}.rideBike .bkZzz text{animation:bkDrift 2.6s ease-in-out infinite;fill:#7ee0c8;font:700 11px 'Barlow Condensed',sans-serif}.rideBike .bkStand{stroke:#7a8190;stroke-width:2;stroke-linecap:round;fill:none}/* ---- hover explainer ----
   Dark, narrow, and out of the way: it appears above the cursor so it never covers the
   thing you are pointing at, and it carries no close button because it needs none. */.rideBike .bkSuit{fill:url(#bkSuitG);stroke:#0b0c0e;stroke-width:.6}

/* ---- the bike leans, the tyres stay down ----
   transform-origin is the contact patch, so the machine pivots where rubber meets road.
   A shorter, softer transition than the mirror flip: leaning is continuous. */
.rideBike .bkLean{transform-box:view-box;transform-origin:31px 39px;
  transition:transform .18s cubic-bezier(.4,0,.3,1)}
.rideBike .bkBody{transform-box:view-box;transform-origin:34px 22px;
  transition:transform .45s cubic-bezier(.32,1.2,.5,1)}
.rideBike .bkHeadG{transform-box:view-box;transform-origin:43px 9px;
  transition:transform .45s cubic-bezier(.32,1.2,.5,1)}

/* ---- what he is doing ---- */
/* cruising: sitting up, nothing to prove */
.rideBike.mCruise .bkBody{transform:none}
/* racing: tucked down and forward, head low behind the screen */
.rideBike.mRace .bkBody{transform:translate(1.5px,1.6px) rotate(7deg)}
.rideBike.mRace .bkHeadG{transform:translate(.5px,1.4px)}
.rideBike.mRace .bkSpeed path{opacity:.7}
.rideBike.mRace .bkAxle{animation-duration:.9s}
/* a real bend: hanging off the inside, weight low */
.rideBike.mBend .bkBody{transform:translate(-1px,1.2px) rotate(-6deg)}
.rideBike.mBend .bkHeadG{transform:translate(-.8px,.4px) rotate(-4deg)}
/* climbing: weight forward over the bars */
.rideBike.mClimb .bkBody{transform:translate(1px,-.6px) rotate(4deg)}
.rideBike.mClimb .bkAxle{animation-duration:2.4s}.rideBike .bkRide{display:block;width:60px;height:44px;overflow:visible;
  filter:drop-shadow(0 3px 6px rgba(0,0,0,.55));animation:bkFloat 3.4s ease-in-out infinite}
@keyframes bkFloat{0%,100%{transform:translateY(0)}50%{transform:translateY(-.6px)}}.rideBike.isResting .bkRide{transform:translateY(1px);animation:none}
@media (prefers-reduced-motion: reduce){
  .rideBike .bkRide{animation:none}
  .rideBike .bkLean,.rideBike .bkBody,.rideBike .bkHeadG{transition:none}
}.footSocial{margin-bottom:16px;display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin:0 0 12px}
.footSocial b{color:#8f8c84;font:700 12px 'Barlow Condensed',sans-serif;
  text-transform:uppercase;letter-spacing:.08em}
.footSocial a{color:#a9a69d;font-size:13px;text-decoration:none;border-bottom:1px solid #31363f;
  padding-bottom:1px}
.footSocial a:hover{color:#e6002e;border-color:#e6002e}
.footSocial:empty{display:none}
/* base tiles never intercept a hover meant for a marker */
/* ---- THE BASEMAP MUST NOT EAT POINTER EVENTS, WHATEVER DRAWS IT ----
   This rule covered raster tile IMAGES. MapLibre draws to a CANVAS in the same pane, so the
   vector migration would have reintroduced the exact bug it was written to prevent - markers
   above a basemap that swallows every hover and tap. Both kept here, together, because I put
   the canvas rule 1,372 lines away the first time and the register could not see it. */
.leaflet-tile-pane .baseTiles,.leaflet-tile-pane img{pointer-events:none}
.leaflet-tile-pane canvas,.leaflet-maplibre-gl-layer,
.leaflet-maplibre-gl-layer canvas,.maplibregl-canvas{pointer-events:none!important}
/* a category that could not be fetched, said once and quietly */
.plGroup.plMiss h4{color:#8a8f98}
.plGroup.plMiss .plLead{color:#8f8c84}

/* who to call, in the road status block */
.helpBox{border-top:1px solid #262a31;margin-top:12px;padding-top:11px}
.helpBox h4{margin:0 0 8px;color:#f4f2ec;font-size:15px}
.helpBox ul{list-style:none;margin:0 0 8px;padding:0;display:flex;flex-wrap:wrap;gap:8px}
.helpBox li{display:flex;flex-direction:column;gap:1px;background:#1b1e24;border:1px solid #31363f;
  border-radius:9px;padding:7px 12px;min-width:132px}
.helpBox li b{color:#8f8c84;font:700 12px 'Barlow Condensed',sans-serif;
  text-transform:uppercase;letter-spacing:.07em}
.helpBox li span{color:#f4f2ec;font-size:15px}.rideClock{z-index:1100;background:rgba(11,12,14,.88);
  color:#f4f2ec;border:1px solid #31363f;border-radius:99px;padding:6px 13px;letter-spacing:.03em;pointer-events:none;position:static;left:auto;bottom:auto;font-size:13px;min-width:23ch;text-align:right;flex:0 0 auto;white-space:nowrap;
  font-variant-numeric:tabular-nums}

/* a famous road's own sequence of places, the way you would say it out loud */
.lgSeq{display:flex;flex-wrap:wrap;align-items:center;gap:5px;margin-top:7px}
.lgSeq i{font-style:normal;color:#7ee7bb;background:rgba(6,42,30,.7);
  border:1px solid rgba(14,159,110,.4);border-radius:99px;padding:2px 9px;font-size:12px}
.lgSeq b{color:#7a8190;font-weight:400}
.leaflet-tooltip.mapTip.tipRoad{max-width:300px}/* the arrow has to follow whichever side Leaflet picked *//* TEXT WAS BEING CUT OFF, AND I DID IT.
   I capped the tooltip at 9.5em with overflow:hidden to stop it becoming a panel. That does
   not shorten anything - it hides the end of the sentence, which is worse than a tall
   tooltip. The right control is WIDTH plus short text, not a guillotine. Wide enough for a
   sentence, no clipping, and it keeps clear of the map furniture. */
@media(max-width:900px){}

/* ---- the turn happens in space ----
   The wrapper holds the perspective so the bike rotates through an edge-on view instead of
   snapping to its mirror image. 520px is close enough to be visible on a 60px object and
   far enough that it does not distort at rest. The ease overshoots slightly, the way a bike
   settles after coming round. */
.rideBike{perspective:520px;perspective-origin:50% 60%}.rideBike .bkTurn{transform-origin:50% 78%;display:block;transform-style:preserve-3d;backface-visibility:visible;
  transition:transform .46s cubic-bezier(.3,.9,.35,1.06);will-change:transform}.rideBike .bkTyre{fill:url(#bkTyreG);stroke:#05070a;stroke-width:.9}.rideBike .bkRim{fill:none;stroke:url(#bkRimG);stroke-width:1.7}
.rideBike .bkDisc{fill:none;stroke:#8a939f;stroke-width:.7;opacity:.8}
.rideBike .bkSpokes path{stroke:#aeb7c2;stroke-width:.85;stroke-linecap:round}.rideBike .bkHub{fill:#d6dce3}
.rideBike .bkSwing{stroke:#7a8190;stroke-width:2.6;stroke-linecap:round;fill:none}.rideBike .bkFork{stroke:#b6c0cc;stroke-width:1.9;stroke-linecap:round;fill:none}.rideBike .bkEngine{fill:url(#bkEngG);stroke:#171b21;stroke-width:.6}
.rideBike .bkCase{fill:#6b7684;opacity:.55}.rideBike .bkPipe{opacity:.95;stroke:url(#bkPipeG);stroke-width:2.4;stroke-linecap:round;fill:none}
.rideBike .bkCan{fill:url(#bkPipeG);stroke:#5c4810;stroke-width:.5;rx:1}.rideBike .bkTank{fill:url(#bkTankG);stroke:#5e0016;stroke-width:.6}.rideBike .bkTail{fill:#b8001f;stroke:#5e0016;stroke-width:.5}
.rideBike .bkShine{fill:#fff;opacity:.28}
.rideBike .bkPlate{fill:#e8e4da;stroke:#8a8578;stroke-width:.4}.rideBike .bkBar{stroke:#b6c0cc;stroke-width:1.8;stroke-linecap:round;fill:none}
.rideBike .bkMirror{fill:#9aa4b2;stroke:#2b3038;stroke-width:.4}
.rideBike .bkSuit,.rideBike .bkHump{fill:url(#bkSuitG);stroke:#05070a;stroke-width:.5}
.rideBike .bkLeg,.rideBike .bkBoot{fill:#262c36;stroke:#05070a;stroke-width:.45}.rideBike .bkArm{stroke:#1d222a;stroke-width:2.8;stroke-linecap:round;fill:none}
.rideBike .bkGlove{fill:#3a414c;stroke:#05070a;stroke-width:.4}.rideBike .bkHelmet{fill:url(#bkHelmG);stroke:#8d897f;stroke-width:.6}.rideBike .bkVisor{fill:#2f6f8f;opacity:.94}
.rideBike .bkHelmLine{stroke:#b9b5ab;stroke-width:.5;fill:none;opacity:.8}.rideBike .bkShadow{fill:url(#bkGlow)}

/* ---- movement ----
   Suspension is what makes a drawn bike look like it has weight. Front and rear travel on
   different periods, because they do. */
.rideBike .bkSusR{transform-box:view-box;transform-origin:16px 31px;
  animation:bkSusR 1.1s ease-in-out infinite}
.rideBike .bkSusF{transform-box:view-box;transform-origin:46px 31px;
  animation:bkSusF 1.4s ease-in-out infinite}
@keyframes bkSusR{0%,100%{transform:translateY(0)}50%{transform:translateY(.5px)}}
@keyframes bkSusF{0%,100%{transform:translateY(0)}45%{transform:translateY(-.45px)}}
.rideBike.isResting .bkSusR,.rideBike.isResting .bkSusF{animation:none}
@media(prefers-reduced-motion:reduce){
  .rideBike .bkSusR,.rideBike .bkSusF{animation:none}
  .rideBike .bkTurn{transition:none}
}/* WHY IT WENT NARROW AND TALL.
   A Leaflet tooltip is absolutely positioned, so it shrinks to fit its content. I had set
   overflow-wrap:anywhere, which tells the browser a line may break between any two
   characters - so the minimum content width became ONE CHARACTER, the box collapsed to a
   thin column, and the text ran down past the bottom of the map. max-width cannot stop
   that: it caps a width, it does not establish one.
   width:max-content asks for the natural single-line width first, and max-width then reins
   it in - which gives a wide, short box instead of a tall thin one. And no anywhere-breaks:
   a long word may overflow a fraction, which is far better than a column of letters. */.miniInfo{padding:7px 9px;display:flex;flex-wrap:wrap;gap:4px 8px;background:#161a20;border-top:1px solid #3a414c}.miniDock .miWp{color:#d7d4cc}
.miniDock .miWp b{color:#0b0c0e;background:#ff5a1f;border-radius:99px;
  min-width:15px;height:15px;display:inline-flex;align-items:center;justify-content:center;
  font:800 12px/1 'Barlow Condensed',sans-serif}.miniDock .miBand{color:#7ee7bb}.miniDock .miNone{color:#8a8f98}
/* clear of the minimap, whether or not the map is expanded */
/* the !important rule is the one that actually decides where this button sits, so it is
   the one that must be tied to the dock's real height - a hard 206 here is what puts the
   button back on the minimap the next time the dock grows. */
#csLeadOpen{bottom:calc(var(--miniH) + 44px + env(safe-area-inset-bottom)) !important}
body.mapOpen #csLeadOpen{bottom:calc(78px + env(safe-area-inset-bottom)) !important}
@media(max-width:900px){
  #csLeadOpen{bottom:calc(var(--miniH) + 44px + env(safe-area-inset-bottom)) !important}
  body.mapOpen #csLeadOpen{bottom:calc(126px + env(safe-area-inset-bottom)) !important}
}.miniDock{position:fixed;right:14px;bottom:calc(16px + env(safe-area-inset-bottom));z-index:1500;transition:transform .28s cubic-bezier(.2,.8,.2,1),opacity .25s;
  animation:dockIn .35s cubic-bezier(.2,.8,.2,1) both;width:var(--miniW);/* bigger, as asked twice: one variable now, so a later rule cannot quietly shrink it again *//* THIS is the rule that decides the dock's width - the one carrying position:fixed. I set 124px in three earlier rules and reported it done; this later one kept it at 236 and the box on screen never changed. The audit now reads the LAST matching rule. */background:#12151a;border:1px solid #3a414c;border-radius:14px;overflow:hidden;
  box-shadow:0 10px 28px rgba(0,0,0,.65),0 0 0 1px rgba(0,0,0,.5);height:var(--miniH)}
/* Written against a distinct selector because my own dedupe pass groups rules by selector
   across @media boundaries and had been collapsing .miniDock down to whichever copy came
   last, silently dropping the panel styling three times. The dock carries this class. */
.miniDock.dockSkin{background:#12151a;border:2px solid #7a8492;border-radius:14px;
  height:var(--miniH);overflow:hidden;box-shadow:0 10px 28px rgba(0,0,0,.65)}
.miniDock.dockSkin .miniHead{background:#161a20;border-bottom:1px solid #7a8492}
.miniDock.dockSkin .miniInfo{background:#1b2027;border-top:1px solid #7a8492}
.miniDock.dockSkin .miWp{color:#d7d4cc}
.miniDock.dockSkin .miBand{color:#7ee7bb}

/* ---- one machine per profile ----
   New parts get their own material. The rider's posture changes too: a sport rider is
   tucked and forward, a cruiser sits back, an adventure rider stands tall on the pegs.
   That is the difference a profile should make - not a badge, a silhouette. */
.rideBike .bkFair{fill:url(#bkTankG);stroke:#5e0016;stroke-width:.6}
.rideBike .bkScreen{fill:#8fb8cc;opacity:.55;stroke:#5d7f92;stroke-width:.4}
.rideBike .bkBeak{fill:#e6002e;stroke:#5e0016;stroke-width:.5}
.rideBike .bkCase2{fill:#3a414c;stroke:#12151a;stroke-width:.6;rx:1}
.rideBike .bkHump2{fill:url(#bkSuitG);stroke:#05070a;stroke-width:.4}
.rideBike .bkLamp{fill:#ffe9a8;stroke:#b39a45;stroke-width:.5}

/* posture by profile: the rider sits differently on each machine */
.rideBike.p-sport .bkBody{transform:translate(1.4px,1.4px) rotate(6deg)}
.rideBike.p-sport .bkHeadG{transform:translate(.4px,1.1px)}
.rideBike.p-touring .bkBody{transform:translate(-.4px,-.5px) rotate(-2deg)}
.rideBike.p-adventure .bkBody{transform:translate(0,-1.6px) rotate(-1deg)}
.rideBike.p-adventure .bkLean{transform-origin:31px 39px}
.rideBike.p-easy .bkBody{transform:translate(-1.2px,.2px) rotate(-4deg)}
/* an adventure bike sits taller and runs knobbly tyres */
.rideBike.p-adventure .bkTyre{stroke-dasharray:2 1.4;stroke-width:1.6;stroke:#2c323b}
.rideBike.p-adventure .bkRide{transform:translateY(-1.5px)}.leaflet-tooltip.mapTip::before{border-top-color:#6b7684}.leaflet-tooltip-left.mapTip::before{border-left-color:#6b7684}.leaflet-tooltip-right.mapTip::before{border-right-color:#6b7684}.leaflet-tooltip-bottom.mapTip::before{border-bottom-color:#6b7684}

/* the famous-roads key: two line styles with no legend is a puzzle */
.lgKey{display:flex;flex-direction:column;gap:5px;margin:9px 0 4px}
.lgKey span{display:flex;align-items:center;gap:8px;color:#8a8f98;font-size:12px;line-height:1.4}
.lgKey i{flex:0 0 30px;height:5px;border-radius:2px;display:block}



/* the eating card: address, website, and whether riders would like it */
.eatRow .eatAddr{color:#8a8f98;font-size:12px;margin:2px 0 0}
.eatRow .eatBk{font-size:12px;margin:3px 0 0}
.eatRow .eatBk.b-yes{color:#7ee7bb}
.eatRow .eatBk.b-likely{color:#9fd8bd}
.eatRow .eatBk.b-maybe{color:#8a8f98}
.eatLinks{display:block;margin-top:4px}
.eatLinks a{color:#ff8b5e;font-size:12px;text-decoration:none;border-bottom:1px solid #4a3a30}
.eatLinks a:hover{color:#ff5a1f;border-color:#ff5a1f}
.eatLinks i{color:#8f8c84;font-size:12px;font-style:normal}
.eatMore{margin-top:8px;border-top:1px solid #262a31;padding-top:6px}
.eatMore summary{cursor:pointer;color:#a9a69d;font-size:12px;padding:3px 0;
  list-style:none;display:flex;align-items:center;gap:6px}
.eatMore summary::-webkit-details-marker{display:none}
.eatMore summary::before{content:'+';color:#ff5a1f;font-weight:700}
.eatMore[open] summary::before{content:'\2212'}
.eatMore summary:hover{color:#f4f2ec}

/* ---- wind, the finish flag, and flags planted along the way ----
   Each is driven by a class the animation loop sets, so they cost nothing when idle. */
.rideBike .bkWind path{stroke:#f4f2ec;stroke-width:1.1;stroke-linecap:round;fill:none;
  opacity:0;transition:opacity .3s}
.rideBike.mRace .bkWind path{opacity:.5;animation:bkGust .5s linear infinite}
.rideBike.mRace .bkWind path:nth-child(2){animation-delay:.16s}
.rideBike.mRace .bkWind path:nth-child(3){animation-delay:.32s}
@keyframes bkGust{0%{transform:translateX(0);opacity:.5}100%{transform:translateX(-9px);opacity:0}}

.rideBike .bkFinish{opacity:0;transform-box:view-box;transform-origin:52px 22px;
  transform:scale(.6);transition:opacity .3s,transform .45s cubic-bezier(.3,1.3,.5,1)}
.rideBike.atFinish .bkFinish{opacity:1;transform:none}
.rideBike .bkPole{stroke:#c9cdd4;stroke-width:1.2;stroke-linecap:round}
.rideBike.atFinish .bkCloth{animation:bkWave 1.1s ease-in-out infinite;
  transform-box:view-box;transform-origin:52px 8px}
@keyframes bkWave{0%,100%{transform:skewY(0)}50%{transform:skewY(-7deg)}}

.plantWrap{pointer-events:none}
.bkPlant{animation:bkPlantIn .5s cubic-bezier(.2,1.4,.4,1) both;transform-origin:3px 17px}
@keyframes bkPlantIn{from{transform:scale(.3) rotate(-25deg);opacity:0}to{transform:none;opacity:1}}
@media(prefers-reduced-motion:reduce){
  .rideBike.mRace .bkWind path{animation:none;opacity:.4}
  .rideBike.atFinish .bkCloth{animation:none}
  .bkPlant{animation:none}
}.mapBar .lineMode button{border:0;background:none;color:#c9c6bf;border-radius:99px;cursor:pointer;font:700 12px/1 'Barlow Condensed',sans-serif;
  text-transform:uppercase;letter-spacing:.02em;white-space:normal;line-height:1.12;padding:7px 12px;font-size:16px}.csItem i sup{color:#8f8c84;margin-left:1px;font-size:11px}

/* nowrap with no overflow handling: the text does not wrap AND cannot be scrolled to, so a
   long place name is simply cut. These are the ones carrying names we do not control -
   Swiss and Italian place names run long, and the reader loses the end of them. */
.chev h2,.chev small,.top .word,.welcomeBack button{
  min-width:0;overflow:hidden;text-overflow:ellipsis}.cmpTable td:first-child,.cmpTable th:first-child{color:var(--dim);font-size:15px;text-transform:uppercase;letter-spacing:.08em;white-space:nowrap;
  max-width:14ch;overflow:hidden;text-overflow:ellipsis}.leaflet-tooltip.mapTip{width:max-content;
  max-width:min(340px,72vw);
  white-space:normal;
  overflow-wrap:break-word;
  word-break:normal;
  max-height:none;
  overflow:visible;
  margin:0 6px;
;
  background:#0d1013;
  border:1px solid #6b7684;
  box-shadow:0 0 0 1px rgba(255,255,255,.10), 0 8px 22px rgba(0,0,0,.7);
  color:#e8e5dd !important;
  font:400 13px/1.42 'Barlow',system-ui,sans-serif !important;
  padding:7px 11px !important}.leaflet-tooltip.mapTip b{color:#ffffff !important;display:block;margin:0 0 2px;
  font:700 15px/1.25 'Barlow Condensed',sans-serif;text-transform:uppercase;letter-spacing:.04em}.leaflet-tooltip.mapTip i{color:#8fe3c0 !important;display:block;font-style:normal;
  font-size:12px;margin:1px 0 3px}


/* ---- ITEM 3: is it still working? ----
   A line in the board header rather than a spinner over the page: it answers the question
   ("is the search still running, or is everything in?") without claiming the screen. */
.workRow{display:flex;align-items:center;gap:8px;margin:4px 0 0;color:#8c8f97;
  font:500 13px/1.3 system-ui,sans-serif}
.workRow[hidden]{display:none}
.workDot{width:8px;height:8px;border-radius:99px;background:var(--red-hot);flex:0 0 auto;
  animation:workPulse 1.1s ease-in-out infinite}
.workRow.done .workDot{background:#4fce7f;animation:none}
@keyframes workPulse{0%,100%{opacity:.25;transform:scale(.8)}50%{opacity:1;transform:scale(1.15)}}
@media(prefers-reduced-motion:reduce){.workDot{animation:none;opacity:.9}}

/* ---- ITEM 2: back to the top ----
   Left side, clear of the minimap dock (right, 16-204px) and the week button (right, 206px).
   Width and height are declared so the overlap audit measures rather than guesses. */
#toTop{position:fixed;left:16px;bottom:calc(46px + env(safe-area-inset-bottom));z-index:1500;
  width:52px;height:44px;display:flex;align-items:center;justify-content:center;gap:5px;
  background:var(--raise);border:1px solid #3a414c;border-radius:99px;color:var(--ink);
  font:600 12px/1 system-ui,sans-serif;cursor:pointer;box-shadow:0 8px 22px rgba(0,0,0,.55);
  opacity:0;transform:translateY(8px);transition:opacity .2s,transform .2s}
#toTop.on{opacity:1;transform:none}
#toTop[hidden]{display:none}
#toTop:hover{border-color:var(--red);color:var(--red-hot)}
#toTop:focus-visible{outline:2px solid var(--red-hot);outline-offset:2px}
#toTop span{letter-spacing:.03em}
/* the expanded map is z-2000 and owns the screen; nothing from the page belongs on top of it */
body.mapOpen #toTop{display:none}
@media(max-width:759px){#toTop{width:44px;left:10px}#toTop span{display:none}}

/* ---- ITEM 4: the picture opens the ride ----
   The click handler went on without a single style, so the picture became a click target
   that looked exactly like a picture - which the UI audit caught as a class rendered but
   never styled. A target has to say it is one: a cursor, a hint on hover, and a focus ring
   for anyone arriving by keyboard. The credit anchor inside keeps its own cursor. */
.exPic.opensRide{cursor:pointer}
.exPic.opensRide:hover img{transform:scale(1.03)}
.exPic.opensRide img{transition:transform .35s cubic-bezier(.2,.8,.2,1)}
.exPic.opensRide:focus-visible{outline:2px solid var(--red-hot);outline-offset:-3px}
.exPic.opensRide .exCred{cursor:pointer}
@media(prefers-reduced-motion:reduce){.exPic.opensRide:hover img{transform:none}}

/* ---- UI REVIEW: TWELVE PLACES A LONG WORD COULD RUN OFF THE EDGE ----
   Every one of these declares white-space:nowrap with nothing to catch the overflow, so a
   long place name, a translated label or a big number simply left the box. That is the
   family the "rank is cut off" and "tooltips are cut off" reports came from, and fixing
   them one at a time is how three of them survived.

   Two different treatments, deliberately:
     - LABELS on the map (scenic badge, rest pin, legend pin, shared-road tag) get an
       ellipsis and a max width. A famous road's name truncated with a "..." still reads as
       that road; the same name spilling across the tarmac makes the map unreadable.
     - CONTROLS and figures (the clock, the mode buttons, the roadbook facts) get
       min-width:0 and an ellipsis so a flex parent is allowed to shrink them at all.
       Without min-width:0 a flex child NEVER goes below its content width, which is why
       these pushed their neighbours out of the row instead of getting smaller. */
.sfBtn, .pinStart, .rideClock{min-width:0;overflow:hidden;text-overflow:ellipsis}
/* THE MODE BUTTONS ARE OUT OF THE TRUNCATING FAMILY.
   They were swept in with the controls that get an ellipsis so a flex parent may shrink
   them - right for a clock, wrong for a button whose whole job is to say what it does.
   "WHAT THE ROA..." is a control hiding its own name. Fixed in the base rule above by
   letting them wrap, rather than by adding a third rule that fights the other two. */
.rbFacts span, .csItem i, .plRow i, .sfNote a{min-width:0;overflow:hidden;text-overflow:ellipsis}
.scenicTag span, .restPin span, .legendPin span, .icTag{
  max-width:min(46vw,300px);overflow:hidden;text-overflow:ellipsis;display:inline-block;vertical-align:bottom}
/* The clock must not be ellipsised into uselessness - it is padded to a fixed width
   already, so give it the room it needs and let something else shrink first. */
.rideClock{flex:0 0 auto}

/* ---- UNESCO WORLD HERITAGE ON A RIDE ----
   Reads as a sibling of the services list, not as a new kind of thing: same card, same
   spacing. The cost line is the part he asked for and it is set apart, because "23 km there
   and back, about 30 min" is the sentence that decides whether he goes. */
.whBox{margin:18px 0 0;padding:16px 18px;background:var(--raise);border:1px solid #2b323c;
  border-radius:14px}
.whBox h3{margin:0 0 4px;font:700 15px/1.3 system-ui,sans-serif;color:var(--ink)}
.whNote{margin:0 0 12px;color:#8c8f97;font:400 13px/1.45 system-ui,sans-serif}
.whList{list-style:none;margin:0;padding:0;display:grid;gap:12px}
.whRow{padding:11px 13px;background:#171b21;border:1px solid #262c35;border-radius:11px;
  border-left:3px solid #c9a227}
.whRow.nat{border-left-color:#4fce7f}
.whRow>b{display:block;font:600 15px/1.35 system-ui,sans-serif;color:var(--ink)}
.whTags{display:flex;flex-wrap:wrap;gap:6px;margin:6px 0 0}
.whTags i{font:500 11px/1 system-ui,sans-serif;font-style:normal;color:#9aa0a8;
  background:#20262e;border:1px solid #2d343d;border-radius:99px;padding:4px 8px;
  max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.whTags i.whDanger{color:#ffb4a2;background:#2c1c1a;border-color:#4a2b26}
.whWhy{display:block;margin:8px 0 0;color:#b6bcc4;font:400 13px/1.5 system-ui,sans-serif}
.whCost{display:block;margin:8px 0 0;padding-top:8px;border-top:1px solid #262c35;
  color:#c9cfd6;font:400 13px/1.55 system-ui,sans-serif}
.whCost b{color:var(--ink);font-weight:600}
@media(max-width:759px){.whBox{padding:13px 14px}.whRow{padding:10px 11px}}

/* ---- UNESCO AND EVENT PINS ----
   Deliberately not the round service pin: a heritage site is not a fuel station and the
   difference must be readable at a glance, without opening a tooltip. Square-ish, gold,
   and green for natural sites so the two categories separate on a busy map. */
.whPin span{display:flex;align-items:center;justify-content:center;width:24px;height:24px;
  margin:-12px 0 0 -12px;background:#1b1508;border:1.5px solid #c9a227;border-radius:6px;
  font-size:12px;line-height:1;box-shadow:0 2px 7px rgba(0,0,0,.55)}
.whPin.nat span{background:#0d1a12;border-color:#4fce7f}
.whPin.danger span{border-color:#e2725b;background:#241412}
/* (the round icon-only event pin was replaced by the dated pill below - a pin you have to
   hover to learn the date of is not much of an answer to "when is it") */

/* ---- the way back, for a ride that does not return ---- */
.backBox{margin:10px 0 0;padding:14px 16px;background:var(--raise);border:1px solid #2b323c;
  border-radius:12px}
.backBox[hidden]{display:none}
.backBox h4{margin:0 0 8px;font:700 15px/1.3 system-ui,sans-serif;color:var(--ink)}
.bkFig{margin:0 0 8px;display:flex;flex-wrap:wrap;align-items:baseline;gap:6px;
  font:400 13px/1.4 system-ui,sans-serif;color:#8c8f97}
.bkFig b{font:700 19px/1 system-ui,sans-serif;color:var(--red-hot)}
.bkNote{margin:0 0 8px;color:#a8aeb6;font:400 13px/1.55 system-ui,sans-serif}
.bkNote b{color:var(--ink)}
.bkActs{margin:10px 0 0;display:flex;flex-wrap:wrap;gap:8px}
.vFlag{width:20px;height:15px;object-fit:cover;border-radius:2px;vertical-align:-2px}

/* a pass in a famous road's checkpoint chain, with its height */
.lgSeq i.isPass{border-color:#5a4a12;background:#211c0c;color:#e8d9a0}
.lgSeq i .lgAlt{margin-left:5px;font-weight:600;opacity:.75;font-size:15px}

/* ---- UNESCO AS A THUMBNAIL, GREY WHEN IT IS NOT ON THE TRAIL ----
   A pictogram says what kind of thing it is; a photograph says whether you want to go. So
   colour carries the information that matters on a map: in colour = on the road you are
   riding, grey = a detour off it. The pictogram stays underneath as the fallback for a
   picture that will not load. */
/* ---- BIG ENOUGH TO RECOGNISE ----
   34x26 px, fully desaturated, at 82% opacity. A cathedral at that size is a grey smudge,
   and a thumbnail nobody can read is worse than a pictogram - it takes the space of
   information and delivers none. Half again as large, and legibility comes back. */
.whPin .whThumb{position:relative;display:block;width:52px;height:40px;margin:-20px 0 0 -26px;
  border-radius:6px;overflow:hidden;border:1.5px solid #c9a227;background:#1b1508;
  box-shadow:0 2px 10px rgba(0,0,0,.65)}
.whPin.nat .whThumb{border-color:#4fce7f}
.whPin.danger .whThumb{border-color:#e2725b}
.whPin .whThumb img{width:100%;height:100%;object-fit:cover;display:block}
.whPin .whThumb i{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font-style:normal;font-size:12px;opacity:0}
/* NO PICTURE, NO PICTURE FRAME. An empty 34x26 grey rectangle standing on the map is worse
   than the small marker it replaced - it looks like a broken image, because it is one. */
.whPin .whThumb.noPic{width:20px;height:20px;margin:-10px 0 0 -10px;border-radius:99px;
  border-width:1.5px;background:#1b1508}
.whPin .whThumb.noPic i{opacity:1;font-size:11px}
.whPin.nat .whThumb.noPic{background:#0d1a12}
/* OFF THE TRAIL: drained of colour, and slightly dimmed so the eye goes to what is on the road */
/* OFF THE ROUTE IS A HINT, NOT A PUNISHMENT.
   grayscale(1) at 82% removed the one thing a photograph is for. Off-trail places are still
   worth seeing - they are just further away - so they are muted, not erased, and they come
   back to full colour when he points at them. */
.whPin.offTrail .whThumb{filter:grayscale(.55) contrast(1.08) brightness(1.06);opacity:.95;
  border-color:#8d7f5e}
.whPin.offTrail:hover .whThumb,.whPin.offTrail:focus-within .whThumb{filter:none;opacity:1;
  border-color:#c9a227}
.whPin.offTrail span{filter:grayscale(.55);opacity:.9}
.whPin.onTrail .whThumb{filter:none}
@media(prefers-reduced-motion:no-preference){
  .whPin.offTrail .whThumb{transition:filter .25s,opacity .25s}
  .whPin .whThumb:hover{filter:none;opacity:1}
}
/* a heritage pin that carries a real photograph rather than the fallback pictogram */
.whPin.hasPic .whThumb{background:#0f1216}

/* ---- A FESTIVAL PIN CARRIES ITS DATE ----
   You must be able to see WHEN without touching anything. A confirmed date is solid; a
   month window ends in a question mark and is outlined rather than filled, so the two are
   never confused at a glance. */
.evPin span{display:flex;align-items:center;gap:3px;height:22px;padding:0 7px 0 5px;
  margin:-11px 0 0 -14px;background:#101a24;border:1.5px solid #4fa8ff;border-radius:99px;
  font:600 11px/1 system-ui,sans-serif;color:#dbe7f3;white-space:nowrap;
  box-shadow:0 2px 7px rgba(0,0,0,.55)}
.evPin span b{font-weight:700;letter-spacing:.01em}
.evPin.window span{border-style:dashed;color:#a9c2d8}
.evPin.exact span{background:#12283a}

/* ---- A PASS, WITH ITS HEIGHT ----
   The height is on the pin, not behind a hover: 2,509 m is the whole story of a day and it
   decides whether the ride is possible at all. */
.passPin svg{width:13px;height:12px;flex:0 0 auto;display:block}
.passPin span{display:flex;align-items:center;gap:4px;height:21px;padding:0 6px 0 5px;
  margin:-10px 0 0 -12px;background:#1a1410;border:1.5px solid #b98a3c;border-radius:99px;
  font:700 11px/1 system-ui,sans-serif;color:#f0dfc2;white-space:nowrap;
  box-shadow:0 2px 6px rgba(0,0,0,.5)}

/* the return leg of a ride that does not come home: stated, not hidden */
.stat.oneWay b{color:#f0b429}
.stat.oneWay span{color:#a58a4e}

/* ---- where the night falls ---- */
.stayBox{margin:18px 0 0;padding:16px 18px;background:var(--raise);border:1px solid #2b323c;
  border-radius:14px;border-left:3px solid #6f7ce0}
.stayBox h3{margin:0 0 6px;font:700 15px/1.3 system-ui,sans-serif;color:var(--ink)}
.stayWhy{margin:0 0 8px;color:#c9cfd6;font:400 15px/1.55 system-ui,sans-serif}
.stayWhy b{color:var(--ink)}
.stayNote{margin:0 0 10px;color:#8c8f97;font:400 13px/1.5 system-ui,sans-serif}
.stayActs{margin:0;display:flex;flex-wrap:wrap;gap:8px}

/* ---- A GROUPED HERITAGE SITE ----
   One card per site rather than one per component: the same paragraph printed five times
   under five names is not five things to see. */
.whParts{display:block;margin:4px 0 0;font-size:12px;color:#9fb0c0}
.whShot{display:block;position:relative;margin:8px 0 0;border-radius:8px;overflow:hidden;
  max-width:280px;border:1px solid rgba(244,242,236,.14)}
.whShot img{display:block;width:100%;height:auto;max-height:150px;object-fit:cover}
.whShot em{position:absolute;right:0;bottom:0;padding:2px 6px;font:400 11px/1.3 system-ui,sans-serif;
  font-style:normal;background:rgba(8,9,11,.72);color:#cfd6de}
.whLink{display:inline-block;margin:7px 0 0;font-size:12px;color:#7fc4ff;text-decoration:none}
.whLink:hover,.whLink:focus{text-decoration:underline}
/* NEVER CUT OFF A TEXT. Any clamp on these blocks hid the end of a sentence, which is worse
   than a longer card - the rider cannot tell that something was removed. */
.whWhy,.whParts{overflow:visible;text-overflow:clip;display:block;-webkit-line-clamp:none}

/* (the three-picture strip was reverted - it rendered outside the roadbook row. See
   app.js for why it is not coming back until it is designed rather than assumed.) */

/* ---- THE PANEL POINTS AT THE MAP ----
   Hovering an entry lifts that road on the map and dims the rest, so the list and the
   picture are tied together by pointing rather than by remembering. */
/* the existing rule already sets the vertical rhythm (margin:0 0 11px) - only widen the
   hit area sideways, or the two rules fight and the audit is right to say so */
.lgItem{cursor:default;border-radius:8px;padding:6px 8px;margin-left:-8px;margin-right:-8px;transition:background .12s}
.lgItem:hover,.lgItem:focus{background:rgba(107,114,128,.16);outline:none}
.lgItem:focus-visible{box-shadow:0 0 0 2px rgba(127,196,255,.55)}

/* ---- NEVER CUT OFF A LABEL ----
   "WHAT THE ROA…" - a button that hides its own name. Told not to do this, twice. A control
   may wrap onto two lines or shrink its type; it may not truncate, because the reader cannot
   tell what was removed and the ellipsis costs as much width as two more characters. */
.lineMode button,.lineMode a{white-space:normal;overflow:visible;text-overflow:clip;
  line-height:1.12;padding:7px 10px;font-size:16px;letter-spacing:.03em;hyphens:none}
@media(max-width:560px){.lineMode button{font-size:16px;letter-spacing:.01em}}

/* the one-line key: a dotted grey sample, matching what the map actually draws */
.lgKey .lgDot{display:inline-block;width:26px;height:0;vertical-align:middle;margin-right:7px;
  border-top:2.4px dotted #6b7280}

/* ---- A BORDER THAT CANNOT SIMPLY BE RIDDEN ACROSS ----
   Ranked above passports and vignettes, because a closed crossing is not paperwork. */
.borderBox.shut{border-color:#e2725b}
.bbShut{display:block;padding:10px 12px;margin:0 0 10px;border-radius:10px;
  background:rgba(226,114,91,.12);border:1px solid rgba(226,114,91,.5)}
.bbShut b{display:block;font-size:15px;color:#ffb3a3;margin-bottom:4px}
.bbShut span{display:block;color:#e8dfd8;font-size:15px;line-height:1.45}
.bbShutNote{margin-top:6px;color:#b9a9a2;font-size:13px}

/* ---- ONE LINE, UNDER THE BUTTON ----
   Three cards between the promise and the CTA pushed "use my location" off the fold, and
   led with a negative. The way in comes first; the reason to trust it comes after. */
.heroWhy{margin:14px auto 0;max-width:56ch;color:#cdc9c2;font-size:15px;line-height:1.5}
@media(max-width:560px){.heroWhy{font-size:13px}}

/* the verdict fragments that can be known for every card without a live lookup */
.cardVerdict{display:flex;flex-wrap:wrap;gap:6px;margin:6px 0 2px}
.cardVerdict span{font-size:12px;padding:3px 8px;border-radius:99px;
  border:1px solid rgba(244,242,236,.2);color:#d7d2ca;background:rgba(12,13,16,.45)}
.cardVerdict .cvAlt{border-color:rgba(240,180,41,.5);color:#f0b429}
.cardVerdict .cvOw{border-color:rgba(127,196,255,.4);color:#9fd0ff}

/* interest is a separate fact from road quality, and is coloured so it cannot be mistaken
   for a score: what riders are doing, not what the road is */
.cardVerdict .cvHot{border-color:rgba(225,27,43,.45);color:#ff8a7a}
.cardVerdict .cvWarm{border-color:rgba(244,242,236,.24);color:#bdb8b0}

/* ---- BRING YOUR OWN ROUTE ----
   Read in the browser, graded, briefed, and never stored. Sits under the board because it is
   an alternative way IN to the same answer, not a separate product. */
.ownRoute{margin:14px 0 6px;padding:14px 16px;border-radius:14px;background:var(--card);
  border:1px dashed rgba(244,242,236,.28)}
.ownRoute.over{border-color:var(--red);background:rgba(225,27,43,.08)}
.ownRoute b{display:block;font:700 15px/1.2 var(--display);color:#fff}
.ownRoute span{display:block;margin:4px 0 10px;color:var(--mut);font-size:15px;line-height:1.45;max-width:62ch}
.ownBtn{display:inline-block;padding:8px 14px;border-radius:99px;background:var(--red);color:#fff;
  font:700 15px/1 var(--display);text-transform:uppercase;letter-spacing:.04em;cursor:pointer}
.ownBtn:hover{filter:brightness(1.08)}
.ownRoute em{display:block;margin-top:9px;font-style:normal;font-size:13px;color:#f0b429}

/* the inventory says what each number IS - a count that flatters is worth less than one
   that can be checked */
.statNote{grid-column:1/-1;margin:8px 0 0;color:var(--mut);font-size:13px;line-height:1.5;max-width:64ch}

/* an assembled ride says so - a disclosure, not a decoration, so it is quiet */
.cardVerdict .cvBuilt{border-color:rgba(244,242,236,.18);color:#9c968e}

/* ---- WHEN TO LEAVE, AND WHICH WAY ROUND ----
   An instruction, not a description, so it sits apart from the verdict prose. */
.planNow{margin:10px 0 0;padding:10px 12px;border-radius:10px;
  background:rgba(63,156,124,.10);border:1px solid rgba(63,156,124,.42)}
.planNow b{display:block;color:#8fe0bd;font-size:15px;line-height:1.4}
.planNow span{display:block;margin-top:5px;color:#dcd8d1;font-size:15px;line-height:1.45}
.planNow em{display:block;margin-top:6px;font-style:normal;color:#9aa39d;font-size:13px;line-height:1.4}

/* ---- THE CHARTER ----
   Promises a rider can quote back, each naming what it costs us. */
.lgCharter{margin:22px 0 8px;font:700 19px/1.3 var(--display);color:#fff}
.lgVows{list-style:none;margin:0;padding:0;display:grid;gap:8px}
.lgVows li{padding:10px 12px;border-radius:10px;background:var(--card);
  border-left:3px solid var(--red);color:var(--mut);font-size:15px;line-height:1.5}
.lgVows b{color:#f4f2ec}

/* ---- A WORLD-CLASS PASS CARRIES ITS PICTURE ----
   Grey, because it is information about the country the ride crosses, not the ride itself.
   The thumbnail sits behind the summit mark so the pin keeps its shape and its height. */
/* the same correction for a pass summit: readable, muted rather than erased */
.passPin .psShot{position:absolute;left:-4px;top:-6px;width:44px;height:34px;border-radius:6px;
  overflow:hidden;background:#1a1410 center/cover no-repeat;
  filter:grayscale(.5) contrast(1.08) brightness(1.05);
  opacity:.95;border:1px solid rgba(232,201,138,.6)}
.passPin .psBig:hover .psShot{filter:none;opacity:1}
.passPin .psBig{padding-left:46px;position:relative}
.passPin .psBig svg{position:relative;z-index:1}

/* the reverse control shows when the ride is being read backwards */
.abtn#revBtn.on{background:var(--red);border-color:var(--red);color:#fff}

/* ---- BE BACK BY ----
   The question a rider with a family actually asks, answered by working backwards. */
.abtn.beBack{display:inline-flex;align-items:center;gap:7px;cursor:default}
.abtn.beBack input{background:rgba(0,0,0,.35);border:1px solid rgba(244,242,236,.28);
  color:#f4f2ec;border-radius:8px;padding:3px 6px;font:inherit;font-size:15px}
.backByOut{flex-basis:100%;margin:8px 0 0;padding:9px 12px;border-radius:10px;
  background:rgba(240,180,41,.10);border:1px solid rgba(240,180,41,.4);
  color:#e8dfd2;font-size:15px;line-height:1.45}

/* the flag bar reports what happened and offers the only useful control - putting it back */
.flagOk #flagUndo{background:transparent;border:1px solid rgba(244,242,236,.4);color:#f4f2ec}

/* a road we have not traced says so, rather than letting the reader hunt for a line that
   was never drawn */
.lgKey .lgHeld{display:block;margin-top:5px;color:#9c968e;font-size:13px;line-height:1.45}

/* the road's source, not an invented "official website" - OpenStreetMap is where its shape
   and name come from, and where a rider can correct it */
.lgItem{position:relative}
/* two links, not one: where the road IS, and what it IS. A name search answered "Grand Tour
   of Switzerland" with a signpost in Chexbres, so the map link now carries coordinates. */
.lgLook{position:absolute;right:8px;top:8px;display:flex;gap:10px;
  opacity:0;transition:opacity .12s}
/* these two are genuinely short and sit in a flex row that can grow - nowrap is right, but
   it needs to say what happens if it ever cannot fit */
.lgLook a{font-size:12px;color:#7fc4ff;text-decoration:none;white-space:nowrap;
  overflow:visible;text-overflow:clip}
.lgItem:hover .lgLook,.lgItem:focus .lgLook,.lgLook:focus-within{opacity:1}
.lgLook a:hover,.lgLook a:focus{text-decoration:underline}

/* the overlap glow, explained in the key and named on the road it belongs to */
.lgKey .lgGlow{display:inline-block;width:26px;height:7px;vertical-align:middle;margin-right:7px;
  border-radius:4px;background:rgba(63,208,138,.42)}
.lgShare{display:inline-block;margin-left:8px;padding:2px 8px;border-radius:99px;font-style:normal;
  font-size:12px;background:rgba(63,208,138,.16);border:1px solid rgba(63,208,138,.5);color:#8fe0bd}

/* ---- WHAT THE MARKS MEAN ----
   The key explained the line and left every pin unexplained - so the map had a legend for
   the part that needed one least. */
.pinKeyHead{display:block;margin:10px 0 4px;font:700 13px/1.2 var(--display);
  text-transform:uppercase;letter-spacing:.06em;color:#9c968e}
.pinKey{display:flex;align-items:flex-start;gap:8px;margin:3px 0;font-size:12px;
  line-height:1.4;color:#cfcac3}
.pinKey i{flex:0 0 auto;width:20px;text-align:center;font-style:normal;font-size:15px}

/* "cut it to my day" - the answer to a ride that is too long, offered where the mismatch
   is reported instead of only naming the gap */
.cutChip{margin-left:6px;padding:3px 10px;border-radius:99px;cursor:pointer;
  background:rgba(225,27,43,.16);border:1px solid rgba(225,27,43,.55);color:#ff9d92;
  font:600 13px/1.3 inherit}
.cutChip:hover:not(:disabled){background:rgba(225,27,43,.3);color:#fff}
.cutChip:disabled{opacity:.6;cursor:default}

/* the bar only pins itself once the map is out of the way - see data-stick in app.js */
.actionBar[data-stick="off"]{position:static;background:none;padding-top:0}

/* a small tail so a lifted label still reads as belonging to its point on the road */
.legendPin::after{content:'';position:absolute;left:50%;bottom:-5px;width:1px;height:5px;
  background:rgba(14,159,110,.8);transform:translateX(-50%)}

/* a checkpoint that can be moved should look like it can - the cursor is the only hint a
   rider gets before he tries */
.wpDot{cursor:grab}
.leaflet-marker-draggable .wpDot:active{cursor:grabbing;transform:scale(1.12)}

/* ---- AN EDITED RIDE SAYS SO ----
   It should not pretend to be the scouted one, and a rider three drags deep needs a door
   marked exit. */
.editedBar{border-left:3px solid var(--amber);padding-left:10px}
.editedNote{grid-column:1/-1;margin:-2px 0 4px;color:var(--mut);font-size:13px;line-height:1.45}
.actionBar #undoEditBtn{grid-column:span 5}
.actionBar #resetEditBtn{grid-column:span 7}

/* ---- TOUCH TARGETS ON A PHONE ----
   Nine interactive controls were between 32 and 42 px tall. That is fine for a mouse and
   wrong for a thumb: 44 px is the floor both Apple and Google publish, and a rider tapping
   at the side of a road with gloves on has less accuracy than either assumes.
   Raised for touch only - the desktop layout keeps its tighter rhythm, because a mouse does
   not need the room and the board fits more rides without it. */
@media (pointer: coarse), (max-width: 680px) {
  .chip, .filterBar .chip, .svcChips .c, .exActs button,
  .mapLayers button, .miniHead button, .cutChip, .ownBtn {
    min-height:44px; padding-top:0; padding-bottom:0;
    display:inline-flex; align-items:center; justify-content:center;
  }
  /* the map's own furniture is small on purpose, but not smaller than a thumb */
  .mapBase, .mapHome, .mapExpand { min-height:44px; }
  .mapBase { height:44px; }
  /* and a draggable checkpoint needs a bigger grab area than its dot */
  .wpDot { min-width:34px; min-height:34px; }
  .leaflet-marker-draggable { touch-action:none; }
}


/* the dock follows the map: present while the map is on screen, out of the way once he has
   scrolled past it to read. Never display:none - a dock that vanishes cannot be brought back
   by the tab that reopens it. */
/* "on" - the map has scrolled away, so the dock is the only locator left and takes the
   bottom-right corner it has always had. */
.miniDock[data-with-map="on"]{opacity:1;transform:none;pointer-events:auto}
/* "beside" - the map is on screen. The dock must not sit on top of it, so it moves to the
   very bottom-left, clear of the map's own controls (which own the left band up to 78px) and
   clear of the route line, which is centred. Both are readable at once. */
.miniDock[data-with-map="beside"]{opacity:1;pointer-events:auto;
  left:auto;right:10px;bottom:calc(96px + env(safe-area-inset-bottom));transform:none}
/* 68px, not 12: #toTop is a 44px button in the same corner at the same z-index, and at 12px
   the dock landed squarely on it. Found by the overlap audit only after I taught it to
   measure attribute states - before that, this second position was invisible to every check
   and I was one command away from shipping it. */
/* neither state hides it outright: a dock that vanishes cannot be brought back by its tab */
.miniDock[data-with-map="off"]{opacity:0;transform:translateY(8px) scale(.96);pointer-events:none}

/* ---- THE RECORDER ----
   It sits with the things you take away with you. The warning about screen lock is part of
   the feature, not a footnote: a rider who finds out on a mountain that the tab slept has
   been let down, and one line here prevents that. */
.recBox{grid-column:1/-1;margin:0 0 2px;color:var(--mut);font-size:12px;line-height:1.45;
  display:flex;flex-wrap:wrap;gap:8px;align-items:baseline}
.recBox b{color:var(--ink);font-family:var(--display);letter-spacing:.03em}
.recBox .recLive{color:#ff3b30}
.recBox .recWarn{flex-basis:100%;color:#c9a227}
.actionBar #recBtn{grid-column:span 6}
.actionBar #recSave{grid-column:span 6}
.actionBar #recBtn.on{border-color:#ff3b30;color:#ff6b6b}



/* the marks glossary folds away - needed once, and every mark explains itself on hover */
.markFold{margin:6px 0 0;border-top:1px solid rgba(255,255,255,.09);padding-top:5px}
.markFold>summary{cursor:pointer;list-style:none;font:700 12px/1.3 var(--display);
  text-transform:uppercase;letter-spacing:.09em;color:#8e8880}
.markFold>summary::-webkit-details-marker{display:none}
.markFold>summary::after{content:' +';color:#6f7a86}
.markFold[open]>summary::after{content:' \2212'}
.speedKey.inMap .pinKey{font-size:12px;line-height:1.35}
.speedKey.inMap .lgd{font-size:12px}

/* a photo pin can be dragged like any other checkpoint - the cursor is the only hint before
   he tries, and without it the pin looks like decoration */
.wpPic{cursor:grab}
.leaflet-marker-draggable .wpPic:active{cursor:grabbing;transform:scale(1.08)}

/* ---- THE ROAD IS A HANDLE, AND MUST LOOK LIKE ONE ----
   An invisible 18px line carries the grab because a 4.5px path cannot be hit reliably. The
   cursor is the only signal before he tries, so it has to be right. */
.roadGrab{cursor:grab}
.roadGrab:active{cursor:grabbing}
.leaflet-container .roadGrab{pointer-events:stroke}

/* the editing hint sits under the note, quieter than it but always there - a rider should
   not have to discover a route editor by accident */
.noteEdit{display:block;margin-top:3px;font:600 12px/1.4 var(--body);color:#9fd8ff;
  letter-spacing:.01em}

/* the lettered country badge, for the 68 countries with no drawn flag - it exists so a ride
   never renders as belonging nowhere */
.flagCode{border-radius:3px}
.flagCode text{letter-spacing:.02em}

/* the country badge itself - it was only ever styled via .flagCode and the plain .flag class
   that every drawn flag carries had no rule at all */
.flag{width:20px;height:14px;border-radius:2px;vertical-align:-2px;flex:none}

/* ---- THE EDIT BAR, ON THE MAP ----
   Top-centre: clear of the note at top-left, the whole-route and close buttons at top-right,
   the layer switch below them, and the mode bar and legend at the bottom. It appears only
   once there is a change to undo, so it costs nothing on a ride he has not touched. */
.mapEdit{position:absolute;top:10px;left:50%;transform:translateX(-50%);z-index:1250;
  display:flex;gap:8px;align-items:center;padding:6px 10px;border-radius:99px;
  background:rgba(11,12,14,.92);border:1px solid #3a4048;box-shadow:0 4px 16px rgba(0,0,0,.45)}
.mapEdit[hidden]{display:none}
.mapEdit button{background:var(--raise);border:1px solid var(--edge);color:var(--ink);
  border-radius:99px;padding:5px 12px;font:700 13px/1 var(--display);cursor:pointer;
  letter-spacing:.03em;white-space:nowrap}
.mapEdit button:hover{border-color:#7fc4ff;color:#cfe9ff}
.mapEditN{color:var(--mut);font-size:12px;white-space:nowrap}

/* the warning text stands alone, so it needs its own rule rather than only a descendant one */
.bbWarn{margin:6px 0 0;color:var(--ink);font-size:13px;line-height:1.5}

/* the rope grips are gone with the code that made them - a style for an element nothing
   creates is the kind of thing an audit reports for months and nobody dares delete */

/* ---- A WAYPOINT ON THE TRAIL IS A HANDLE ----
   It sits on the road now rather than floating beside it, so it has to read as something you
   take hold of. A ring the colour of the route, a white core, and a cursor that says grab. */
/* the shadow is already set where .wpDot is defined - repeating it here only creates a
   conflict for the next reader to resolve */
.wpDot{cursor:grab;transition:transform .12s}
.wpDot:hover{transform:scale(1.18)}
.leaflet-marker-draggable:active .wpDot{cursor:grabbing;transform:scale(1.3)}
.wpPic{cursor:grab}
.leaflet-marker-draggable:active .wpPic{cursor:grabbing}

/* the drag handle on a bend the rider made - a dot, deliberately not a numbered pin */
.bendGrip i{display:block;width:14px;height:14px;border-radius:50%;
  background:#e6002e;border:2.5px solid #fff;box-shadow:0 1px 4px rgba(0,0,0,.55);cursor:grab}
.bendGrip i:active{cursor:grabbing}

/* ---- famous roads, in words, under the map ---- */
.famousBox{background:var(--card);border:1px solid var(--edge);border-radius:var(--rad-s);
  padding:14px 16px;margin:14px 0}
.famousBox h3{font-family:var(--display);text-transform:uppercase;letter-spacing:.06em;
  font-size:15px;color:var(--ink);margin:0 0 10px}
.famousBox h3.fmNear{margin-top:16px;color:var(--mut)}
.fmRoad{border-left:3px solid var(--red);padding:2px 0 2px 12px;margin:0 0 12px;transition:background .3s}
.fmRoad.off{border-left-color:#5a6270;opacity:.82}
.fmRoad b{display:block;font-size:15px;color:var(--ink)}
.fmRoad .fmMeta{display:block;font-size:13px;color:var(--mut);margin:1px 0 4px}
.fmRoad p{margin:0;color:var(--mut);font-size:15px;line-height:1.55}
.fmRoad.fmLit{background:rgba(230,0,46,.13);border-radius:0 8px 8px 0}

/* the card carries its own map, so the floating dock has no business over the deck */
body[data-view="swipe"] .miniDock,body[data-view="swipe"] .miniShow{display:none!important}
/* the map used to be pinned over the photograph. Side by side, nothing covers anything. */
/* ---- THE MEDIA IS A BAND, NOT THE CARD ----
   Side by side fixed the overlap and then ate the card: photo and map grew to the full
   height and pushed the title, the numbers and the teaser out of sight. A band with a
   height, and the words below it where a rider reads them. */
.swMedia{display:flex;gap:8px;align-items:stretch;height:clamp(150px,26vh,230px);flex:0 0 auto}
.swMedia .swPic{flex:1 1 62%;min-width:0;height:100%}
.swMini{flex:0 0 36%;position:relative;right:auto;top:auto;width:auto;height:100%;border-radius:12px;
  overflow:hidden;border:2px solid rgba(255,255,255,.85);box-shadow:0 6px 18px rgba(0,0,0,.55);
  z-index:4;background:#12151a;display:block}
.swMini .rbMiniMap{display:block;width:100%;height:100%}
@media(max-width:759px){.swMedia{height:clamp(120px,20vh,170px)}.swMini{flex:0 0 40%}}

/* ================= MOBILE: NOTHING FLOATS OVER WHAT HE IS READING =================
   The audit's mobile findings, taken one by one at 390x844. Every one of them is a
   floating element written for a desktop corner and then left to land wherever a phone
   puts it: the week's-road card over the location button, the minimap over the lower
   controls, the action panel over the score breakdown. On a phone there are no spare
   corners. So below 768px the floating layer is switched off and the page is allowed to
   be a page - and every control gets a thumb-sized target, because this is used in
   gloves. */
@media(max-width:767px){
  /* ---- SWITCHING A FEATURE OFF IS NOT MAKING IT FIT ----
     These two rules hid Road of the Week and the route minimap on every phone, with
     !important, and my own never-regress gate reported "features lost: 0" the whole time -
     because it renders at desktop width and never looked at a phone. Two capabilities were
     gone for the majority of riders and every test I had said otherwise.
     The original reasoning was sound and the conclusion was wrong: a phone has no spare
     corners, so a FLOATING presentation cannot work. That is an argument for changing the
     presentation, not for deleting the feature. Both are now in the page flow, where a page
     has as much room as it needs. */
  #csLead{position:static!important;inset:auto!important;width:auto!important;
    max-width:none!important;max-height:none!important;margin:0 var(--mobGutter) 18px!important;
    transform:none!important;z-index:auto!important;box-shadow:none!important}
  #csLeadOpen{position:static!important;inset:auto!important;display:block!important;
    width:calc(100% - var(--mobGutter)*2)!important;margin:14px var(--mobGutter)!important;
    min-height:var(--tapMin);z-index:auto!important}
  .miniDock{position:static!important;inset:auto!important;width:auto!important;
    height:auto!important;margin:0 0 16px!important;transform:none!important;
    z-index:auto!important;box-shadow:none!important;resize:none!important}
  .miniDock #mini{height:220px!important;width:100%!important}
  /* display:block!important defeated the element's hidden attribute, so at 390 px the
     show-map button stayed on screen above the minimap it was meant to reveal. Style it only
     while it is not hidden. */
  .miniShow:not([hidden]){position:static!important;inset:auto!important;display:block!important;
    width:100%!important;margin:0 0 14px!important;min-height:var(--tapMin);z-index:auto!important}
  .miniShow[hidden]{display:none!important}
  /* 2. thumb-sized targets, gloves included - 44px is the floor, not the aspiration.
        A real browser at 390x844 found this list missing several: the wordmark link, the
        sort dropdown, the "back by" control and the small pill buttons inside panels. The
        list was written from memory; these came from measurement. */
  button,.tbtn,.chip,.mapJump button,.lineMode button,.miniHead button,
  .rideOpen,.geoBtn,.swBtn,a.btn,input[type=button],input[type=submit],
  select,.top .word,#sortSel,#backBy,.backByOut button,.pvChip,.rbShow,.nearChip,
  .cutChip,.atrLinks a,.fcHead button,summary,
  /* the browser found these and a stylesheet reading never could: the per-checkpoint links
     (Maps, Street View, OSM, Weather) at 30px and the road-status links at 34px. They are
     what a rider taps at the roadside in gloves - the exact case this floor exists for. */
  .wpLinks a,.blLinks a{
    min-height:44px;min-width:44px}
  .wpLinks a,.blLinks a{display:inline-flex;align-items:center}
  /* a select cannot centre its own text once it is 44px tall */
  select,#sortSel{padding-top:0;padding-bottom:0}
  /* the wordmark is a link, so it gets the target without becoming a giant block */
  .top .word{display:inline-flex;align-items:center}
  /* 3. the header carries what a phone can show without clipping: mark, back, menu */
  header .tbtn span.tbTxt{display:none}
  header{padding-left:10px;padding-right:10px;gap:6px}
  /* 4. the action panel belongs in the flow, not on top of the text it explains.
        The previous rule named .actPanel and .rideActs - neither of which exists. The
        control is .actionBar, so the rule did nothing at all and the bar stayed sticky,
        541 px of it, over the score breakdown on a 844 px screen. Name the real element. */
  .actionBar{position:static!important;bottom:auto!important;margin:12px -18px 6px;
    padding-top:0;background:none;box-shadow:none}
  /* 5. the header shows a mark, a way back and a menu - every other label is noise at
        390 px and was clipping. Hiding .tbTxt was not enough: some labels are plain text. */
  /* the blank-pill rule is gone: the phone gets .bottomNav with words on it instead */
  /* 6. and the map keeps a workable height instead of eating the screen */
  .mapBox #map{height:min(58vh,420px)}
  /* 6. the toast clears the bottom of a phone. It cannot be clicked through - it is
        pointer-events:none and transient - but a message that lands on top of the row of
        controls a rider is reaching for is still in the way of what he is doing. */
  /* 84px was the old two-row nav guessed at; it now measures from the token like everything
     else fixed to the bottom edge */
  .toast{bottom:calc(var(--tabbarSpace) + var(--toastGap) + 46px);max-width:92vw}
}

/* ---- where a ride came from, and how sure we are: never blended into the score ---- */
.provBox{background:var(--card);border:1px solid var(--edge);border-radius:var(--rad-s);
  padding:11px 14px;margin:12px 0}
.provRow{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.provTag{font-family:var(--display);text-transform:uppercase;letter-spacing:.05em;font-size:12px;
  padding:4px 10px;border-radius:999px;border:1px solid}
.provTag.scouted{color:#7ee7bb;border-color:#2f7a5c;background:rgba(6,42,30,.55)}
.provTag.built{color:#ffd88a;border-color:#7a6330;background:rgba(42,32,6,.5)}
.provTag.listed{color:#c9d2de;border-color:#4a525e;background:rgba(20,24,30,.6)}
.provConf{font-size:13px;color:var(--mut);border-left:1px solid var(--edge);padding-left:9px}
.provConf.confHigh{color:#7ee7bb}
.provConf.confLow{color:#ffb0b0}
.provWhy{margin:6px 0 0;font-size:13px;color:var(--mut);line-height:1.5}

/* what a ride is, said on the card itself */
/* ---- THE BADGE AND THE SCORE SHARED A CORNER ----
   Measured in Chromium: .pvTag over .rhScore by 42x9px on every card. The score is anchored
   bottom-left of the hero and the provenance badge was put top-left - which reads as the
   same corner once the hero is short, and on a card they are simply stacked on each other.
   The badge goes to the opposite corner: nothing else lives top-right except the save star,
   which is a fixed 34px, so the badge stops short of it. */
.pvTag{position:absolute;right:52px;top:10px;left:auto;z-index:3;font-family:var(--display);
  text-transform:uppercase;letter-spacing:.05em;font-size:11px;padding:3px 8px;border-radius:999px;
  border:1px solid;background:rgba(8,10,13,.72);backdrop-filter:blur(4px)}
.pvTag.pv-r{color:#7ee7bb;border-color:#2f7a5c}
.pvTag.pv-e{color:#ffd88a;border-color:#7a6330}
.pvTag.pv-a{color:#c9d2de;border-color:#4a525e}
.pvTag.pv-p{color:#9aa4b2;border-color:#3a414c}

/* the trust filter: a choice with its number attached, not a silent default */
#pvFilter{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:0 0 12px}
.pvChip{font-family:var(--display);text-transform:uppercase;letter-spacing:.05em;font-size:12px;
  padding:8px 14px;min-height:44px;border-radius:999px;border:1px solid var(--edge);
  background:transparent;color:var(--mut);cursor:pointer}
.pvChip.on{background:var(--red);border-color:var(--red);color:#fff}
#pvNote{font-size:13px;color:var(--mut)}

/* a picture that could not be fetched explains itself instead of leaving a hole */
.picFail{display:flex;align-items:center;justify-content:center;background:#111318;
  border:1px dashed var(--edge2);border-radius:10px;min-height:64px}
.picNone{margin:0;padding:8px 12px;color:var(--mut);font-size:13px;line-height:1.45;text-align:center}

/* why this ride, and why today - the two questions a card was leaving unanswered */
.swWhy{margin:6px 0 0;font-size:15px;line-height:1.5;color:var(--ink)}
.swInfo{padding-bottom:16px}
.swWhy b{color:var(--ink);font-family:var(--display);text-transform:uppercase;
  letter-spacing:.04em;font-size:12px;margin-right:6px}

/* ---- the atlas: the whole inventory, where it actually is ---- */
.atlasBar{display:flex;gap:8px;align-items:center;flex-wrap:wrap;padding:12px 0}
#atlasSearch{flex:1 1 220px;min-width:0;background:var(--card);border:1px solid var(--edge);
  color:var(--ink);border-radius:10px;padding:11px 13px;font-size:15px;min-height:44px}
.atlasCount{color:var(--mut);font-size:13px;font-family:var(--body)}
/* the .tbtn styling is scoped to the header, so these three rendered as raw white browser
   buttons in the middle of a dark product - the kind of detail that makes a page look
   half-finished however well it works */
.atlasBar .tbtn{font-family:var(--display);text-transform:uppercase;letter-spacing:.05em;
  font-size:12px;padding:11px 16px;min-height:44px;border-radius:999px;
  border:1px solid var(--edge);background:var(--card);color:var(--ink);cursor:pointer}
.atlasBar .tbtn:hover{border-color:var(--edge2)}
.atlasBar #atlasGo{background:var(--red);border-color:var(--red);color:#fff}
/* the legend: a colour on a map means nothing until it is named */
.atlasLegend{display:flex;flex-wrap:wrap;gap:14px;align-items:center;margin:0 0 10px;
  font-family:var(--body);font-size:13px;color:var(--mut)}
.atlasLegend span{display:inline-flex;align-items:center;gap:7px}
.atlasLegend .lgW{width:26px;height:4px;border-radius:2px;display:inline-block}
.lgHi{background:#ff2d43}
.lgDash{background:repeating-linear-gradient(90deg,#9aa4b2 0 7px,transparent 7px 13px)}.lgMid{background:#ffa62b}.lgLow{background:#4db8ff}
.atlasLegend .lgNote{color:var(--dim);flex:1 1 260px;line-height:1.45}
/* the list was using whatever the browser felt like - the app has a display face */
.atlasRow b{font-family:var(--display);font-size:15px;letter-spacing:.01em;line-height:1.3}
.atlasRow span{font-family:var(--body);font-size:13px}
#atlasSearch{font-family:var(--body)}
.atlasMap{height:min(70vh,720px);border-radius:var(--rad);overflow:hidden;border:1px solid var(--edge)}
.atlasList{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:8px;margin:12px 0 28px}
.atlasRow{display:flex;justify-content:space-between;gap:10px;align-items:baseline;text-align:left;
  background:var(--card);border:1px solid var(--edge);border-radius:10px;padding:10px 12px;
  color:var(--ink);cursor:pointer;min-height:44px}
.atlasRow:hover{border-color:var(--edge2)}
.atlasRow span{color:var(--mut);font-size:13px;white-space:nowrap}
@media(max-width:767px){.atlasMap{height:56vh}}

/* what shape the day is - said on the card, because it is what he is choosing between */
.shTag{position:absolute;right:52px;top:44px;z-index:3;font-family:var(--display);
  text-transform:uppercase;letter-spacing:.05em;font-size:11px;padding:3px 8px;border-radius:999px;
  border:1px solid;background:rgba(8,10,13,.72);backdrop-filter:blur(4px)}
.shTag.sh-circuit{color:#7ee7bb;border-color:#2f7a5c}
.shTag.sh-retrace{color:#ffd88a;border-color:#7a6330}
.shTag.sh-a2b{color:#c9d2de;border-color:#4a525e}

/* ---- the three ways of looking at one set of rides ---- */
.viewModes{display:flex;gap:6px;margin:0 auto;padding:10px 20px 0;max-width:var(--maxw)}
.viewModes[hidden]{display:none}
/* three grey ghosts in a corner read as nothing - he looked straight past them twice.
   One segmented control, on the card surface, with the live mode filled in red. */
.viewModes{background:var(--card);border:1px solid var(--edge);border-radius:999px;
  padding:4px;gap:2px;width:max-content}
.vmBtn{font-family:var(--display);text-transform:uppercase;letter-spacing:.06em;font-size:15px;
  padding:10px 22px;min-height:44px;border-radius:999px;border:0;
  background:transparent;color:var(--ink);cursor:pointer;opacity:.72}
.vmBtn:hover{opacity:1}
.vmBtn.on{background:var(--red);color:#fff;opacity:1}
.tbtn.cur{border-color:var(--red);color:var(--ink)}
.tbtn.ghostBtn{color:var(--mut)}

/* ---- a phone gets a real menu with real words ---- */
.bottomNav{display:none}
@media(max-width:767px){
  header .navScroll{display:none}
  /* ---- FIVE DESTINATIONS IN THREE COLUMNS IS TWO ROWS ----
     The nav holds Find, Atlas, Swipe, Explore and Saved. Three columns wrapped them onto two
     rows, so the bar stood about 113px tall while --bottomNavH said 57 and main reserved 68.
     Every fixed element that clears the nav - back-to-top, the toast, the week button, the
     minimap, the map controls - was short by a full row on every phone. One row, five equal
     columns, and the height comes from the token below rather than from a guess. */
  .bottomNav{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:0;position:fixed;
    left:0;right:0;bottom:0;z-index:2200;background:rgba(11,12,14,.96);
    border-top:1px solid var(--edge);padding-bottom:env(safe-area-inset-bottom)}
  .bottomNav button{min-height:var(--tapMin);height:var(--tabbarH);background:none;border:0;
    color:var(--mut);font-family:var(--display);text-transform:uppercase;letter-spacing:.03em;
    font-size:13px;padding:0 2px;display:flex;align-items:center;justify-content:center;
    text-align:center;line-height:1.1;overflow:hidden}
  /* at 320px five words need the room; shorten the label rather than hide it */
  .bottomNav button span{display:block;max-width:100%;overflow:hidden;text-overflow:ellipsis;
    white-space:nowrap}
  @media(max-width:359px){ .bottomNav button{font-size:11px;letter-spacing:0} }
  .bottomNav button.cur{color:var(--ink);box-shadow:inset 0 2px 0 var(--red)}
  main{padding-bottom:calc(var(--tabbarSpace) + 12px)}
  /* ---- THE BACK-TO-TOP BUTTON SAT UNDER THE NAV ----
     #toTop is pinned 46px from the bottom; the bottom nav is a 56px button plus a 1px
     border, so 11px of the button was behind it and the bottom of the tap target was dead.
     The nav's height lives in one place now and #toTop clears it with a real gap, rather
     than two numbers guessed separately and drifting apart. */
  /* ---- ONE NUMBER, NOT SEVEN GUESSES ----
     --bottomNavH was set here and other selectors carried their own pixel offsets that drifted
     from it. Everything fixed to the bottom edge now measures from --tabbarSpace, which is the
     bar plus the phone's own inset. */
  :root{--tabbarH:58px; --tapMin:44px; --tabbarSpace:calc(var(--tabbarH) + env(safe-area-inset-bottom));
        --bottomNavH:var(--tabbarH); --mobGutter:14px; --toastGap:12px}
  #toTop{bottom:calc(var(--tabbarSpace) + var(--toastGap))}
  /* the hero is full height, so its last line ended up behind the bottom menu - the same
     class of overlap he has caught three times, and the padding on main cannot reach
     inside a full-height section. */
  .heroIn{padding-bottom:calc(var(--tabbarSpace) + 26px)}
  /* the badge sat under the new phone menu, and moving it to the top put it under the
     header instead. It is a build stamp, not something a rider needs: on a phone it goes
     into the page flow at the very end, where it can sit on nothing. */
  #buildBadge{display:none}
  /* the old rule squashed header text to nothing and left blank pills - gone */
  header .tbtn{font-size:13px}
  .viewModes{overflow-x:auto}
}

/* three decisions waiting, each naming its own road */
.swTeaser{margin:14px 0 6px}
.swTeaserRow{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:8px}
.swTz{display:flex;flex-direction:column;gap:2px;text-align:left;background:var(--card);
  border:1px solid var(--edge);border-radius:12px;padding:11px 13px;color:var(--ink);
  cursor:pointer;min-height:44px}
.swTz:hover{border-color:var(--edge2)}
.swTz b{font-family:var(--display);text-transform:uppercase;letter-spacing:.05em;
  font-size:12px;color:var(--red-hot)}
.swTz span{font-size:15px;line-height:1.3}
.swTz em{font-style:normal;color:var(--mut);font-size:13px}
.swipeCta{margin-top:8px}

/* the ride's own account, under the two reasons */
.swStory{margin:8px 0 0;color:var(--mut);font-size:15px;line-height:1.55}
.swStory:empty{display:none}

/* the five best, named on their own road */
.atLabel{pointer-events:none;display:flex;align-items:center;gap:7px;white-space:nowrap;
  background:rgba(10,12,16,.86);border:1px solid var(--edge2);border-radius:999px;
  padding:3px 9px;backdrop-filter:blur(3px)}
.atLabel b{font-family:var(--display);text-transform:uppercase;letter-spacing:.04em;
  font-size:11px;color:#fff;overflow:hidden;text-overflow:ellipsis}
.atLabel i{font-style:normal;font-family:var(--display);font-size:11px;color:#ff2d43}
/* a tooltip that wraps instead of being cut off at the map edge */
.atTip{max-width:260px;white-space:normal;line-height:1.35}

/* while one road is picked out, the labels step back so they do not compete with it */
.leaflet-container.atFocus .atLabel{opacity:.18;transition:opacity .12s}
.atLabel{transition:opacity .12s}
/* the tooltip was rendering as a one-word-wide column: give it room to be a sentence */
.atTip{max-width:280px;min-width:200px;white-space:normal;line-height:1.4}
.atTip .leaflet-tooltip-content{white-space:normal}
.leaflet-tooltip.atTip{width:auto}

/* the hover card lives inside the map and never crosses its edge */
.atlasMap{position:relative}
.atHover{position:absolute;left:12px;bottom:12px;z-index:900;pointer-events:none;
  max-width:min(340px,calc(100% - 24px));background:rgba(10,12,16,.94);
  border:1px solid var(--edge2);border-radius:12px;padding:10px 13px;
  display:flex;flex-direction:column;gap:3px;backdrop-filter:blur(4px)}
.atHover b{font-family:var(--display);text-transform:uppercase;letter-spacing:.04em;
  font-size:15px;color:#fff;line-height:1.25}
.atHover span{color:var(--mut);font-size:13px}
.atHover em{font-style:normal;color:#ffa62b;font-size:12px}

.atHover em.ok{color:#7ee7bb}
.atHover.picked{border-color:var(--red)}
.atOpen{pointer-events:auto;margin-top:8px;align-self:flex-start;background:var(--red);
  border:0;border-radius:999px;color:#fff;font-family:var(--display);text-transform:uppercase;
  letter-spacing:.05em;font-size:12px;padding:9px 15px;min-height:44px;cursor:pointer}
.atHover.picked{pointer-events:auto}

/* a detour you can act on, not just read about */
.spAdd{margin-left:10px;background:var(--red);border:0;border-radius:999px;color:#fff;
  font-family:var(--display);text-transform:uppercase;letter-spacing:.05em;font-size:11px;
  padding:7px 13px;min-height:44px;cursor:pointer;vertical-align:middle}
.spAdd:disabled{opacity:.55;cursor:default}
.spItem{display:flex;align-items:center;gap:6px;flex-wrap:wrap}

/* what applies once you are across, country by country */
.bbCountry{margin-top:10px;padding:10px 12px;border:1px solid var(--edge);border-radius:10px;
  background:rgba(255,255,255,.02)}
.bbCountry b{display:block;font-family:var(--display);text-transform:uppercase;
  letter-spacing:.04em;font-size:13px;margin-bottom:5px}
.bbCountry ul{margin:0;padding-left:17px}
.bbCountry li{color:var(--mut);font-size:13px;line-height:1.45}
.bbCountry .bbSub{display:block;color:var(--mut);font-size:13px;margin:-2px 0 6px}

/* provenance: present, quiet, and available on demand */
.provFold{border:0}
.provFold > summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:9px;
  flex-wrap:wrap;padding:4px 0;min-height:44px}
/* a caret, so it reads as something that opens rather than three labels in a row */
.provFold > summary::after{content:'\203a';color:var(--dim);font-size:15px;
  transform:rotate(90deg);transition:transform .15s}
.provFold[open] > summary::after{transform:rotate(270deg)}
.provFold > summary::-webkit-details-marker{display:none}
.provFold .provMore{font-style:normal;color:var(--dim);font-size:13px}
.provFold[open] .provMore{color:var(--mut)}
.provFold .provConf{font-size:11px;padding:2px 8px;border-radius:999px;
  border:1px solid var(--edge);color:var(--mut);background:transparent;text-transform:lowercase}
.provFold .provTag{font-size:11px;opacity:.85}
.provFold .provWhy{margin-top:8px}

/* the detour row says what is happening while the day is re-measured */
.spState{display:block;margin-top:6px;font-size:13px;color:var(--mut)}
.spState.busy{color:#ffa62b}
.spState.done{color:#7ee7bb}
.spState.bad{color:var(--red-hot)}

/* a sight you can put on the route, not just look at */
.atrAdd{margin-top:9px;background:var(--red);border:0;border-radius:999px;color:#fff;
  font-family:var(--display);text-transform:uppercase;letter-spacing:.05em;font-size:11px;
  padding:8px 14px;min-height:44px;cursor:pointer}
.atrAdd:disabled{opacity:.55;cursor:default}
.atrState{display:block;margin-top:6px;font-size:13px;color:var(--mut)}
.atrState.busy{color:#ffa62b}.atrState.done{color:#7ee7bb}.atrState.bad{color:var(--red-hot)}

/* what just happened, on the page that comes back */
.addedBar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:0 0 14px;
  padding:11px 14px;border-radius:12px;border:1px solid #2f7a5c;
  background:linear-gradient(180deg,rgba(126,231,187,.10),rgba(126,231,187,.04))}
.addedBar b{font-family:var(--display);text-transform:uppercase;letter-spacing:.04em;
  font-size:13px;color:#7ee7bb}
.addedBar span{color:var(--mut);font-size:13px}
.addedBar button{margin-left:auto;background:transparent;border:1px solid var(--edge2);
  border-radius:999px;color:var(--ink);font-family:var(--display);text-transform:uppercase;
  letter-spacing:.05em;font-size:12px;padding:8px 14px;min-height:44px;cursor:pointer}
.spSkip{margin-left:10px;background:transparent;border:1px solid var(--edge2);border-radius:999px;
  color:var(--ink);font-family:var(--display);text-transform:uppercase;letter-spacing:.05em;
  font-size:11px;padding:7px 13px;min-height:44px;cursor:pointer;vertical-align:middle}
.spSkip:hover{border-color:var(--red)}
.spSkip:disabled{opacity:.55;cursor:default}

/* add a stop: the one place a rider can put something on his route */
.addStop{margin-top:22px}
.addRow{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:11px 13px;
  border:1px solid var(--edge);border-radius:11px;margin-top:8px;
  background:rgba(255,255,255,.02)}
.addRow b{font-size:15px}
.addRow span{color:var(--mut);font-size:13px}
/* A row now answers four questions - what it is, why it is worth stopping, how far off the
   road, what it costs - so the name and the cost stay on the first line and the two new
   lines run full width underneath rather than fighting the Add button for space. */
.addRow .addKind{flex-basis:100%;order:2;color:var(--ink);font-size:12px;
  text-transform:uppercase;letter-spacing:.06em;opacity:.75}
.addRow .addWhy{flex-basis:100%;order:3;color:var(--mut);font-size:13px;line-height:1.45}
@media(max-width:520px){.addRow .addWhy{display:-webkit-box;-webkit-line-clamp:3;
  -webkit-box-orient:vertical;overflow:hidden}}
.addRow.addNone{border-style:dashed;opacity:.9}
.addRow.addNone b{font-weight:600}
.addStopBtn{margin-left:auto;background:var(--red);border:0;border-radius:999px;color:#fff;
  font-family:var(--display);text-transform:uppercase;letter-spacing:.05em;font-size:16px;
  padding:9px 15px;min-height:44px;cursor:pointer}
.addStopBtn:disabled{opacity:.55;cursor:default}
.addState{flex-basis:100%;color:var(--mut);font-size:13px}
.addState.busy{color:#ffa62b}.addState.done{color:#7ee7bb}.addState.bad{color:var(--red-hot)}

/* an unverified verdict is neutral: no green, no departure advice */
.butler.unknown{border-color:var(--edge2)}
.butler.unknown .blDot{background:var(--mut)}
.butler.unknown .blTag{background:transparent;border:1px solid var(--edge2);color:var(--mut)}

/* a ride nobody has measured: neutral, not the worst possible score */
.scorePill.unscored{background:transparent;border:1px solid var(--edge2);color:var(--mut);
  font-family:var(--display);text-transform:uppercase;letter-spacing:.05em;font-size:11px;
  padding:0 9px;min-width:0}
.atrOn{display:inline-block;margin-top:9px;color:var(--mut);font-size:13px}

/* the detour panel's other half: places worth turning off for */
.spSugHead{margin-top:14px;font-family:var(--display);text-transform:uppercase;
  letter-spacing:.05em;font-size:12px;color:var(--ink)}
.spSkip.alt{background:transparent;border:1px solid var(--edge2);color:var(--mut);font-size:11px;
  padding:6px 11px}
.spSkip.alt:hover{border-color:var(--red);color:var(--ink)}

/* what is within reach of the road but not on it yet */
.atrReach{margin-top:14px}
.atrReachNote{color:var(--mut)}
.atrWhere{color:var(--mut);font-size:13px;margin:2px 0 9px}

/* ---- THE RIDING-CHARACTER SCALE ----
   Five named bands, never a bare decimal: an unexplained "6.3/10" implies a precision the
   underlying data has not got. A dimension nobody has data for is drawn as an empty track and
   says Not known, because a missing bar reads as zero and zero is a claim. */
.charGrid{display:grid;gap:10px;margin:14px 0 18px}
.charRow{display:grid;grid-template-columns:8.5rem 1fr auto;gap:10px 12px;align-items:center}
.charLabel{font-family:var(--display);text-transform:uppercase;letter-spacing:.06em;
  font-size:12px;color:var(--mut)}
.charBar{display:block;height:8px;border-radius:99px;background:rgba(255,255,255,.08);overflow:hidden}
.charBar i{display:block;height:100%;background:linear-gradient(90deg,var(--red),#ff7a55);border-radius:99px}
.charBarNone{background:repeating-linear-gradient(90deg,rgba(255,255,255,.10) 0 6px,transparent 6px 12px)}
.charVal{font-size:13px;color:var(--ink);white-space:nowrap}
.charWhy{grid-column:2 / -1;font-size:12px;color:var(--dim);margin-top:-4px}
.charUnknown .charVal{color:var(--mut)}
@media(max-width:520px){
  .charRow{grid-template-columns:1fr;gap:4px}
  .charWhy{grid-column:1}
  .charVal{white-space:normal}
}



/* One quiet line instead of a row per absent fact: the block must not spend half a screen
   telling a rider what it does not know. */
.charNone{color:var(--dim);font-size:13px;margin:6px 0 16px;line-height:1.5}

/* The credit a licence requires, on the picture it belongs to. Small, legible, and a link to
   the file page - CC BY and CC BY-SA both want the creator named and the source reachable. */
.rotCred{position:absolute;left:0;right:0;bottom:0;padding:4px 8px;font-size:11px;
  background:linear-gradient(180deg,transparent,rgba(0,0,0,.72));color:#d8d5cd;
  text-overflow:ellipsis;overflow:hidden;white-space:nowrap}
.rotCred a{color:#d8d5cd;text-decoration:none}
.rotCred a:hover{text-decoration:underline}

/* ---- THE ROAD BETWEEN TWO STOPS ----
   A stretch card sits between the checkpoint it leaves and the next one, indented so the
   sequence still reads as a chain. Scenic stretches carry a photograph; a transfer does not,
   because a picture of a dual carriageway helps nobody. */
.rbStretch{display:flex;gap:14px;margin:2px 0 14px 34px;padding:12px 14px;
  border-left:2px solid #3a3d44;background:rgba(255,255,255,.018);border-radius:0 10px 10px 0}
.rbStretch.scenic{border-left-color:#e11b2b}
.rbStretch .stBody{flex:1;min-width:0}
.rbStretch h5{margin:0 0 5px;font-size:12px;letter-spacing:.06em;text-transform:uppercase;
  color:#9a978f;display:flex;gap:10px;align-items:baseline}
.rbStretch .stKm{color:#8f8c84;font-size:11px;letter-spacing:0}
.rbStretch p{margin:0;font-size:13px;line-height:1.55;color:#cfcbc2}
.stThumb{position:relative;flex:0 0 200px;border-radius:8px;overflow:hidden;background:#15171b}
.stThumb .stProf{width:200px;height:80px;display:block}
@media(max-width:620px){.stThumb{flex:none;width:100%}.stThumb .stProf{width:100%;height:92px}}
.stThumb .rhPh{font-size:22px;opacity:.4}
.stThumb img.rot{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;
  transition:opacity .5s}
.stThumb img.rot.on{opacity:1}
@media(max-width:620px){
  .rbStretch{margin-left:14px;flex-direction:column}
  .stThumb{flex:none;width:100%;height:150px}
}

/* ---- SCENIC CHAPTER ----
   A sibling of the leg block, in riding position. Photograph side on desktop, above on mobile;
   the media is a drawn profile of this stretch, not a fetched picture, so nothing here can
   arrive unscreened or carry a face. */
.rbScene{display:flex;gap:16px;margin:6px 0 18px 34px;padding:14px 16px;
  border-left:3px solid #e11b2b;background:linear-gradient(90deg,rgba(225,27,43,.055),transparent 60%);
  border-radius:0 12px 12px 0}
.rbSceneMedia{flex:0 0 132px}
.rbSceneMedia svg{width:132px;height:72px;display:block;border-radius:8px;background:#15171b}
.rbSceneBody{flex:1;min-width:0}
.rbSceneType{font-size:11px;letter-spacing:.09em;text-transform:uppercase;color:#e07a83;margin-bottom:4px}
.rbSceneTitle{margin:0 0 7px;font-size:15px;line-height:1.25;color:#efece5}
.rbSceneText{margin:0 0 8px;font-size:15px;line-height:1.6;color:#cfcbc2}
.rbSceneNote{margin:0 0 8px;font-size:13px;color:#e6b3b8}
.rbSceneFacts{display:flex;flex-wrap:wrap;gap:6px 14px;margin-bottom:10px}
.rbSceneFact{font-size:12px;color:#9a978f}
.rbSceneFact b{color:#cfcbc2;font-weight:600}
.rbSceneMapAction{min-height:44px;padding:0 16px;border-radius:22px;border:1px solid #3a3d44;
  background:transparent;color:#7fd8c8;font-size:16px;cursor:pointer}
.rbSceneMapAction:hover{border-color:#7fd8c8}
.rbScene.on{background:linear-gradient(90deg,rgba(225,27,43,.14),transparent 70%)}
@media(max-width:620px){
  .rbScene{margin-left:14px;flex-direction:column;padding:13px 14px}
  .rbSceneMedia{flex:none}
  .rbSceneMedia svg{width:100%;height:96px}
}

/* The stretch, as a map. Nine tiles in a clipped frame - a picture of the place that cannot
   contain a face, from the endpoint already approved and already credited. */
.rbSceneMedia{flex:0 0 200px}
.scMap{position:relative;width:200px;height:132px;overflow:hidden;border-radius:9px;
  background:#1b1d22;isolation:isolate}
.scMap img.scTile{position:absolute;width:96px;height:96px;image-rendering:auto;
  filter:saturate(.72) brightness(.86) contrast(1.05)}
.scPin{position:absolute;left:50%;top:50%;width:12px;height:12px;margin:-6px 0 0 -6px;
  /* ---- NO HALO ----
     A ring in the brand red is exactly the glow he asked three times to have removed, and my
     pin reintroduced it. A solid outline does the same job - it separates the pin from the
     tiles underneath - without the product looking like it is lit from inside. */
  border-radius:50%;background:#e11b2b;border:2px solid #15171b;z-index:2}
.scCred{position:absolute;right:4px;bottom:3px;font-size:11px;color:#e8e5de;z-index:2;
  background:rgba(0,0,0,.45);padding:1px 5px;border-radius:6px}
.rbSceneGrade{margin-top:6px}
.rbSceneGrade svg{width:200px;height:44px;display:block;border-radius:7px;background:#15171b}
@media(max-width:620px){
  .rbSceneMedia{flex:none;width:100%}
  .scMap{width:100%;height:170px}
  .rbSceneGrade svg{width:100%;height:52px}
}

/* ---- WHAT THIS PAGE KNOWS ----
   Collapsed by default: a rider who does not care never sees it, and one who does gets a
   straight answer per row. UNKNOWN is grey and plain - it is not styled as a warning, because
   not having a figure is normal and pretending otherwise would be the fault. */
.rbConf{margin:0 0 16px;border:1px solid #2b2e34;border-radius:10px;background:rgba(255,255,255,.014)}
.rbConf summary{padding:11px 14px;cursor:pointer;font-size:12px;letter-spacing:.05em;
  text-transform:uppercase;color:#9a978f;list-style:none;min-height:44px;display:flex;
  align-items:center;gap:10px}
.rbConf summary::-webkit-details-marker{display:none}
.rbConf summary::after{content:'▾';margin-left:auto;color:#8f8c84}
.rbConf[open] summary::after{content:'▴'}
.rbConfTier{color:#cfcbc2;text-transform:none;letter-spacing:0;font-size:12px}
.rbConfT{width:100%;border-collapse:collapse;font-size:13px}
.rbConfT th{text-align:left;font-weight:500;color:#9a978f;padding:6px 14px;width:34%;
  vertical-align:top}
.rbConfT td{padding:6px 10px;color:#cfcbc2;vertical-align:top}
.rbConfT tr+tr th,.rbConfT tr+tr td{border-top:1px solid #23262b}
.rbSt{display:inline-block;padding:1px 7px;border-radius:5px;font-size:11px;letter-spacing:.05em;
  border:1px solid #3a3d44;color:#cfcbc2;white-space:nowrap}
.rbSt.s-verified,.rbSt.s-routed,.rbSt.s-measured{border-color:#4b7f63;color:#8fd3ae}
.rbSt.s-curated{border-color:#7d6a3f;color:#e0c281}
.rbSt.s-corridor,.rbSt.s-inferred,.rbSt.s-seasonal{border-color:#4a5b73;color:#9fc0e0}
.rbSt.s-unknown{border-color:#3a3d44;color:#8d8a83}
@media(max-width:620px){.rbConfT th{width:42%}.rbConfT,.rbConfT th,.rbConfT td{font-size:12px}}

/* The map standing in for a photograph. Fills its slot exactly, so a card is never an empty
   rectangle; the placeholder glyph sits on top and is hidden once the tiles arrive. */
.scMap.plc{position:absolute;inset:0;width:100%;height:100%;border-radius:inherit;display:block}
.scMap.plc .scTile{opacity:.92}
.scMap.plc .scCred{font-size:11px;padding:0 4px}
.rotBox .scMap.plc ~ .rhPh{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  z-index:3;opacity:.55;font-size:19px;filter:drop-shadow(0 1px 3px rgba(0,0,0,.8))}
.rotBox img.rot.on ~ .scMap.plc{display:none}

/* The ground around a place, where a photograph of it cannot be shown. Fills the slot it is
   given, muted so it reads as context rather than competing with the text, and credited. */
.csMapFill{position:absolute;inset:0;overflow:hidden;background:#1b1d22}
.csMapFill img.csTile{position:absolute;width:256px;height:256px;
  filter:saturate(.6) brightness(.78) contrast(1.06)}
.csPin{position:absolute;left:50%;top:50%;width:10px;height:10px;margin:-5px 0 0 -5px;
  border-radius:50%;background:#e11b2b;border:2px solid #15171b;z-index:2}
.csCred{position:absolute;right:4px;bottom:3px;z-index:2;font-size:11px;color:#e8e5de;
  background:rgba(0,0,0,.45);padding:1px 5px;border-radius:6px}
.rotBox,.exPic,.swPic,.rideHero,.stThumb{position:relative;overflow:hidden}

/* A map with no backdrop is a map with no backdrop, not a broken product. The route, the
   markers and the controls stay exactly where they are; only the tiles are missing, and the
   note says why rather than leaving a rider looking at a wall of refusal images. */
.leaflet-container.tilesBlocked{background:#1b1d22}
.leaflet-container.tilesBlocked .leaflet-tile-pane{display:none}
.tileNote{position:absolute;left:50%;top:14px;transform:translateX(-50%);z-index:600;
  max-width:min(94%,420px);padding:10px 14px;border-radius:10px;border:1px solid #3a3d44;
  background:rgba(21,23,27,.94);color:#cfcbc2;font-size:12px;line-height:1.45;
  pointer-events:none;text-align:center}
.tileNote b{display:block;color:#efece5;margin-bottom:3px;font-size:13px}

/* The stretch graphic is the point of the card, not a decoration beside it: wide enough that
   the numbers on it can be read, and full width on a phone. */
.rbSceneMedia{flex:0 0 260px}
.rbSceneMedia .stProf{width:260px;height:96px;display:block;border-radius:9px;background:#15171b}
@media(max-width:620px){
  .rbSceneMedia{flex:none;width:100%}
  .rbSceneMedia .stProf{width:100%;height:112px}
}

/* Follow block: an icon for every channel, live ones linked, the rest plainly marked as not
   there yet. Nothing loads from a platform until a rider clicks a real link. */
.footSocialHead{font-size:11px;letter-spacing:.11em;text-transform:uppercase;color:#8f8c84;
  margin-bottom:9px}
.social{display:flex;flex-wrap:wrap;gap:9px}
.social svg{width:19px;height:19px;fill:currentColor}
.social a,.social span.soon{min-width:var(--tapMin,44px);min-height:var(--tapMin,44px)}

/* Service and sight dots on the route map. Small enough that thirty of them do not bury the
   road, and the same words appear on hover and on tap because a finger cannot hover. */
.svcTip{background:#15171b!important;border:1px solid #3a3d44!important;color:#efece5!important;
  border-radius:8px!important;padding:7px 10px!important;font-size:12px!important;
  max-width:230px!important;box-shadow:0 6px 20px rgba(0,0,0,.5)!important}
.svcTip:before{border-top-color:#3a3d44!important}
.svcPopKind{color:#9a978f;font-size:11px;margin-top:2px}
.svcPopWhy{color:#cfcbc2;font-size:12px;margin-top:5px;line-height:1.45}
.leaflet-popup-content .svcPopWhy{max-width:220px}

/* The fuel gate: a resolved forecourt, or an honest statement that none was found. It is not a
   generic checkpoint box, because the question it answers is different. */
.fuelBox{margin:9px 0 4px;padding:11px 13px;border-radius:10px;border:1px solid #3a3d44;
  background:rgba(255,138,61,.06);border-left:3px solid #ff8a3d}
.fuelBox b{display:block;color:#efece5;font-size:15px;margin-bottom:3px}
.fuelLine{color:#cfcbc2;font-size:13px;line-height:1.5}
.fuelAlt{color:#9a978f;font-size:12px;margin-top:5px}
.fuelWarn{color:#e0b070;font-size:12px;margin-top:7px;line-height:1.45}
.fuelUnres{border-left-color:#7b8794;background:rgba(123,135,148,.07)}
.fuelUnres b{color:#cfcbc2}
.fuelUnres div{color:#9a978f;font-size:12px;line-height:1.5}
.fuelBox .wpLinks{margin-top:8px}

/* The name a place carries where it is: quieter than the heading, never competing with it. */
.locName{color:#9a978f;font-weight:400;font-size:13px;white-space:nowrap}
h4 .locName,h3 .locName{margin-left:2px}
@media(max-width:620px){.locName{display:inline-block;white-space:normal}}

/* The hour a rider will actually be there, and the two either side. Emphasis, not hiding:
   the rest of the strip stays fully legible - a forecast with columns dimmed away is a
   forecast somebody will distrust. */
/* ---- I REACHED FOR A RED GLOW, WHICH HE HAS ASKED TO BE RID OF THREE TIMES ----
   box-shadow with rgba(225,27,43) is exactly the halo the register forbids, and the check
   caught it the moment I built. Emphasis does not need a glow: a solid border, a filled
   background and a label do the job and read as deliberate rather than lit up. */
.wxCell.wxNow{background:rgba(225,27,43,.16);border:1px solid #e11b2b}
.wxCell.wxNow .wxHr{color:#ff6b74;font-weight:700}
.wxCell.wxNow:after{content:"you";position:absolute;left:0;right:0;bottom:2px;
  font:700 11px/1 var(--display);letter-spacing:.06em;text-transform:uppercase;
  color:#ff6b74;text-align:center}
.wxCell.wxNow{position:relative;padding-bottom:14px}
.wxCell.wxNear{background:rgba(225,27,43,.06);border-color:#5a3d42}

/* An approximate profile says so in its own colour: the same grey as the rest would read as a
   footnote nobody sees, and this is the line that stops a rider trusting a shape too much. */
.pfSrc.pfApprox{color:#c8a15a}

/* A link between checkpoints, not a road. It must not read as something you can ride. */
.chordNote span{display:inline-block;transform:translate(-50%,-50%);white-space:nowrap;
  background:rgba(11,12,14,.82);border:1px solid #3a3d44;border-radius:8px;padding:4px 9px;
  color:#cfcbc2;font:600 11px/1.2 var(--display);letter-spacing:.04em;text-transform:uppercase}

/* What is left where the card grid was: a count and a pointer to the map. The dots carry the
   detail now, so this must not grow back into a second list. */
.stopSummary{display:flex;flex-direction:column;gap:4px;padding:11px 13px;border-radius:10px;
  background:rgba(255,255,255,.03);border:1px solid var(--edge)}
.stopSummary b{color:var(--ink);font-size:15px}
.stopSummary span{color:var(--mut);font-size:13px;line-height:1.5}
.stopSummary .stopHint{color:#8a867e;font-size:12px}

/* No vector style loaded: neutral ground, route and labels intact. Never a raster tile from a
   service we are not entitled to use. */
.csNoBase .leaflet-tile-pane{background:#e7e4dd}
.csNoBase.leaflet-container{background:#e7e4dd}
/* MapLibre's canvas sits in Leaflet's tile pane; the overlay pane must stay above it */
.leaflet-maplibre-gl-layer{z-index:1}

/* ---- THE BASEMAP MUST NOT EAT POINTER EVENTS ----
   The raster rule was `leaflet-tile-pane img{pointer-events:none}` - markers sit above the
   tiles and a tile that captures clicks makes every hover and tap die. MapLibre draws to a
   canvas in the same pane, so it needs the same treatment or the migration reintroduces the
   exact bug those rules were written for. */
/* MapLibre's own controls are not used; Leaflet owns zoom, attribution and fullscreen */
.maplibregl-control-container{display:none!important}

/* The card knows the summit and nothing else. Said as a figure, legibly, on the card's own
   background - not drawn as a chart that implies a shape, nor a control that implies a drag.
   Two previous attempts here were a slider nobody could use and a silhouette nobody could see. */
.altOnly{display:flex;align-items:baseline;gap:9px;padding:12px 2px 2px}
.altOnly b{font-family:var(--display);font-size:22px;font-weight:700;color:var(--ink);
  letter-spacing:.01em}
.altOnly span{color:var(--mut);font-size:12px;line-height:1.4}

/* The honest empty state: quieter than a recorded altitude, but never an unexplained hole. */
.altOnly.none{padding:10px 2px 2px}
.altOnly.none span{color:#8f8c84;font-size:12px;font-style:italic}

/* The route's own terrain card. It fills the hero exactly as a photograph did, so no layout
   changed - only what is in the frame, which is now the ride itself. */
.rideHero .heroCard{width:100%;height:100%;object-fit:cover;display:block;opacity:0;
  transition:opacity .35s ease}
.rideHero .heroCard.in{opacity:1}

/* The mini topo: this route's own line across its own ground, in the slot the profile uses.
   Same height as a sparkline so a card with a measured profile and one without stay aligned. */
.miniTopo{width:100%;height:auto;display:block;border-radius:8px;opacity:.95}

/* An approved photograph fills the hero exactly as the old runtime one did, so the card
   geometry is unchanged - only where the picture comes from. */
.rideHero .heroShot{width:100%;height:100%;object-fit:cover;display:block;opacity:0;
  transition:opacity .35s ease}
.rideHero .heroShot.in{opacity:1}

/* the offline/rejected hero: the route line filling the photo slot exactly */
.csMapFill{position:absolute;inset:0}
.csMapFill .heroShape{width:100%;height:100%;display:block}

/* Edge labels in the card graphics. .skTx centres text, and a CSS property overrides the SVG
   text-anchor attribute, so labels meant to start or end at an edge were centred on it and
   half of each hung outside the card. Two classes out-rank the one-class rule. */
.skTx.l{text-anchor:start}
.skTx.r{text-anchor:end}

/* Roadbook stop photo: a thumbnail beside the stop's heading, so each stop is listed once, with
   its picture, in the roadbook. Rows without a known place have no slot. */
.rbPic{float:right;width:132px;height:88px;margin:2px 0 8px 14px;border-radius:10px;overflow:hidden;
  position:relative;background:#15181d;flex:none}
.rbPic img{width:100%;height:100%;object-fit:cover;display:block}
.rbPic .rhPh{position:absolute;inset:0;display:grid;place-items:center;font-size:22px;opacity:.5}
.rbPic .exCred{font-size:11px;padding:2px 5px}
@media (max-width:520px){.rbPic{width:96px;height:66px;margin-left:10px}}
/* hidden means hidden: the class display rules below overrode the attribute and brought back the
   duplicate service section that was agreed away in favour of the map dots */
.svcList[hidden],.svcChips[hidden],.atrGrid[hidden]{display:none}

/* ---- THE ADD LIST, FULL WIDTH, READING TOP TO BOTTOM ----
   The sights wrapper (#atrSights) is not a cell of the sight grid: its children are, as they were
   before the wrapper existed. Without this the note took one column and the add list another,
   squeezing each row until its button landed in the middle. The add list spans the whole grid
   and lays its rows out as cards: name, type, why, distance and cost, then the button. */
#atrSights{display:contents}
.atrGrid > #addStopList{grid-column:1 / -1;display:grid;grid-template-columns:repeat(auto-fill,minmax(290px,1fr));
  gap:12px;align-items:stretch}
#addStopList .addRow{flex-direction:column;align-items:flex-start;gap:6px;height:100%}
#addStopList .addRow b{order:0;font-size:15px}
#addStopList .addRow .addKind{order:1;flex-basis:auto}
#addStopList .addRow .addWhy{order:2;flex-basis:auto}
#addStopList .addRow .addCost{order:3}
#addStopList .addRow .addStopBtn{order:4;margin-top:auto;align-self:flex-end}
#addStopList .addRow .addState{order:5}
#addStopList .addRow.addNone{grid-column:1 / -1}

/* Card chip rows back in line with the text: their margin shorthand (8px 0 0 and the like) zeroed
   the horizontal inset every other row keeps, so the pass warning, the live badges and the tag
   chips started at the card's border - visible on the owner's own screenshot. */
.ride .cardVerdict,.ride .liveTags,.ride .rTags{margin-left:16px;margin-right:16px}

/* Footer: Road of the Week, Email, Follow - side by side, stacking on a phone */
.footSocial{display:flex;flex-wrap:wrap;gap:22px 48px;align-items:flex-start}
.footGroup{min-width:200px}
.footLinks{display:flex;flex-wrap:wrap;gap:8px 16px;align-items:center;margin-top:6px}
.footLinks a,.footLead{color:var(--ink);font-size:15px;text-decoration:underline;text-underline-offset:3px}
.footLead{background:none;border:0;padding:0;cursor:pointer;font:inherit;color:var(--red-hot,#ff3b47);text-decoration:none;font-weight:700}

/* ---- ONE LABEL STYLE, NOTHING UNDER 12 PX (route page) ----
   Measured on the Lukmanier page: 41 distinct text styles, including seven variants of the small
   uppercase label (11-15 px, weights 400-700) and text at 10-11 px. The labels now share one style,
   and nothing that carries information is smaller than 12 px. */
.addRow .addKind,.rbSceneType,.rbSceneType .num,.stBody h5,.stat span,.rbi .kind,.rbConf summary,
.blLinks > span,.stKm,.lgdMore,.val small{
  font-family:system-ui,-apple-system,"Segoe UI",sans-serif;font-size:12px;font-weight:600;
  text-transform:uppercase;letter-spacing:.06em;font-style:normal}
.rbSt,.provConf,.provTag,.whTags i,.isPass b.lgAlt,.psBig b,.addRow .addStopBtn{font-size:16px}

/* every place in the add list carries its picture across the top of its card */
#addStopList .addRow .addPic{order:-1;align-self:stretch;height:150px;margin:-11px -13px 4px;border-radius:10px 10px 0 0;
  overflow:hidden;position:relative;background:#15181d}
#addStopList .addRow .addPic img{width:100%;height:100%;object-fit:cover;display:block}
#addStopList .addRow .addPic .rhPh{position:absolute;inset:0;display:grid;place-items:center;font-size:34px;opacity:.45}
#addStopList .addRow .addPic .exCred,#addStopList .addRow .addPic .rotCred{font-size:11px;padding:2px 6px}

/* Atlas list: the selected trip is marked; a second click opens it */
.atlasRow.sel{outline:2px solid var(--red-hot,#ff3b47);outline-offset:-2px;background:rgba(255,59,71,.08)}

/* This week's road: approved hero, live map, photographs of the passes */
#csLead .csStoryHero{height:min(52vh,460px);border-radius:14px;overflow:hidden;margin:20px 0;position:relative;background:#15181d}
#csLead .csStoryHero img{width:100%;height:100%;object-fit:cover;display:block}
#csLead .csStoryMap{height:460px;border-radius:14px;overflow:hidden;margin:20px 0;background:#e8e3da}
#csLead .csStoryPics{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px;margin:22px 0}
#csLead .csStoryPic{margin:0}
#csLead .csStoryPic .rotBox{height:210px;border-radius:12px;overflow:hidden;position:relative;background:#15181d}
#csLead .csStoryPic img{width:100%;height:100%;object-fit:cover;display:block}
#csLead .csStoryPic .rhPh{position:absolute;inset:0;display:grid;place-items:center;font-size:34px;opacity:.45}
#csLead .csStoryPic figcaption{font-size:13px;color:#a9a69d;margin-top:6px}
.csStoryTip{font:600 12px/1.2 system-ui,sans-serif;background:#fff;color:#111;border:0;border-radius:6px;padding:3px 7px}

#csLead .csSpotFig{margin:22px 0}
#csLead .csSpotFig .rotBox{height:min(46vh,380px)}

/* What can be seen at a stop */
.rbSees{display:flex;flex-wrap:wrap;gap:6px;margin:6px 0 10px}
.rbSees .see{display:inline-flex;align-items:center;gap:6px;background:#191c22;border:1px solid #23262e;
  border-radius:999px;padding:4px 10px;font-size:12px;color:#c8ccd2;line-height:1.3}
.rbSees .seeTx{white-space:nowrap}
@media (max-width:520px){.rbSees .seeTx{display:none}.rbSees .see{padding:4px 8px}}

/* ---- VERDICT FIRST ON A PHONE ----
   On a phone the first screen answered "what is this road" and hid "should I ride it today".
   Same blocks, same content, reordered for a phone only: title, verdict, the ways to take the
   ride with you, then the numbers and everything else. Desktop keeps its layout. */
@media (max-width:767px){
  div:has(> .dHead):has(> #butlerBox){display:flex;flex-direction:column}
  div:has(> .dHead):has(> #butlerBox) > *{order:20}
  div:has(> .dHead):has(> #butlerBox) > :has(#undoAdded){order:0}
  div:has(> .dHead):has(> #butlerBox) > .dHead{order:1}
  div:has(> .dHead):has(> #butlerBox) > #butlerBox{order:2}
  div:has(> .dHead):has(> #butlerBox) > .actionBar{order:3}
  div:has(> .dHead):has(> #butlerBox) > .statRow{order:4}
}

/* Scout Crew guide callout - subordinate to the verdict, the map and the photographs */
.csGuide{display:flex;gap:12px;align-items:flex-start;margin:10px 0 14px;padding:12px 14px;border-radius:12px;
  background:#121418;border:1px solid #23262e;border-left:3px solid var(--csg,#c9a227)}
.csGuide .csgFace{width:72px;height:72px;flex:none;border-radius:12px;object-fit:contain;object-position:bottom center}
.csGuide .csgIcon{display:grid;place-items:center;font-size:22px;background:#1a1d23;border:1px solid #2a2e36}
.csGuide .csgHead{font-size:13px;color:#c8ccd2;display:flex;flex-wrap:wrap;gap:6px;align-items:baseline}
.csGuide .csgHead b{color:#f4f2ec}.csGuide .csgRole{color:var(--csg,#c9a227)}
.csGuide .csgLabel{font-style:normal;font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:#7d828b}
.csGuide p{margin:4px 0 0;color:#e2e0da;font-size:13px;line-height:1.5}
.csGuide small{display:block;margin-top:4px;color:#8d9199;font-size:12px}
@media (max-width:767px){ div:has(> .dHead):has(> #butlerBox) > #csGuideRoute{order:2} }

/* Read this ride */
.csReadBtn{display:inline-flex;align-items:center;gap:8px;margin:8px 0 4px;padding:10px 16px;border-radius:999px;
  background:#1a1d23;color:#f4f2ec;border:1px solid #2a2e36;font-weight:700;cursor:pointer}
.csReadBtn:hover{background:#22262e}
.csRead{position:fixed;inset:0;z-index:70;background:rgba(6,7,9,.82);display:grid;place-items:center;padding:18px;overflow:auto}
.csReadIn{background:#0f1116;border:1px solid #262a31;border-radius:16px;max-width:680px;width:100%;padding:18px 20px 22px}
.csReadHead{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:10px}
.csReadHead b{font-size:19px}.csReadHead span{color:#9aa0a8;font-size:13px;flex:1}
.csReadListen,.csReadX{background:#1a1d23;color:#f4f2ec;border:1px solid #2a2e36;border-radius:999px;padding:8px 14px;cursor:pointer}
.csReadX{padding:6px 12px;font-size:19px;line-height:1}
.csReadV{display:flex;gap:12px;align-items:flex-start;padding:12px 0;border-top:1px solid #1e222a}
/* the reading panel is a feature surface: a portrait belongs at reading size, not as a bullet */
.csReadV .csgFace{width:140px;height:140px;flex:none;border-radius:14px;display:grid;place-items:center;
  font-size:34px;background:#171a20;border:1px solid #2a2e36;object-fit:contain;object-position:bottom center}
.csReadV img.csgFace{background:linear-gradient(180deg,#1b1f26,#12151a)}
@media (max-width:640px){.csReadV .csgFace{width:104px;height:104px;font-size:34px}}
.csReadV p{margin:4px 0 0;color:#e2e0da;line-height:1.55}
.csReadOpen{display:inline-block;margin-top:14px;background:#e11b2b;color:#fff;font-weight:700;padding:11px 20px;border-radius:999px;text-decoration:none}
@media (max-width:520px){.csReadIn{padding:14px}.csReadV .csgFace{width:40px;height:40px;font-size:19px}}

/* Scout portraits: contained, never cropped, never larger than the pack allows */
.csGuide .csgFace,.csReadV .csgFace{object-fit:contain;object-position:bottom center;background:transparent}
.csgFace-card{width:64px;height:64px}
.csgFace-roadbook{width:72px;height:72px}
.csgFace-feature{width:160px;height:160px;border-radius:14px}
@media (max-width:767px){.csgFace-feature{width:116px;height:116px}}
.csGuide img.csgFace,.csReadV img.csgFace{border-radius:12px}

/* A guide with no portrait yet: a monogram in their own colour, never a cartoon */
.csgMono{display:grid;place-items:center;font:700 22px/1 ui-serif,Georgia,serif;letter-spacing:.02em;
  color:var(--csg,#c9a227);background:#14171c;border:1px solid #262a31;border-radius:50%}
.csgFace-feature.csgMono{font-size:34px;border-radius:16px}
.csgFace-roadbook.csgMono{font-size:22px}

/* the reading panel owns its portrait size on every width */
#csRead .csReadV img.csgFace,#csRead .csReadV .csgMono{width:140px;height:140px;border-radius:14px}


/* A presenter: a real portrait beside copy that is already on the page. Large enough to read a
   face, quiet enough that the words stay the point. */
.csPresenter{display:inline-flex;align-items:center;gap:10px;margin:2px 0 8px;padding:6px 12px 6px 6px;
  border-radius:999px;background:#14171c;border:1px solid #23262e;box-shadow:inset 3px 0 0 var(--csg,#c9a227)}
.csPresenter img{width:56px;height:56px;border-radius:50%;object-fit:cover;object-position:top center;
  background:linear-gradient(180deg,#1b1f26,#12151a)}
.csPresenter b{font-size:13px;color:#f4f2ec}
.csPresenter i{font-style:normal;font-size:12px;color:var(--csg,#c9a227)}
/* the callouts and the reading panel: bigger portraits, this is a design element */
.csGuide .csgFace{width:96px;height:96px}
.csgFace-feature{width:200px;height:200px}
@media (max-width:767px){.csgFace-feature{width:132px;height:132px}.csGuide .csgFace{width:76px;height:76px}}
.csReadV .csgFace,#csRead .csReadV img.csgFace,#csRead .csReadV .csgMono{width:180px;height:180px}


/* Presenters are a design element: a real face, large enough to recognise, with the copy beside it */
.csPresenter{gap:14px;padding:8px 18px 8px 8px;margin:6px 0 12px}
.csPresenter img{width:88px;height:88px;border-radius:50%}
.csPresenter b{font-size:15px}
.csPresenter i{font-size:13px}
@media (max-width:640px){.csPresenter img{width:64px;height:64px}.csPresenter{gap:10px;padding:6px 14px 6px 6px}}
.actGroup .csPresenter,.bbCountry .csPresenter{background:#161a20}
.swCard .csPresenter{margin:8px 0 6px}

/* On a phone the first screen is spoken for: the verdict, then the buttons a rider actually taps.
   A presenter badge in the action group pushed the GPX button below the fold, so it stands down
   there and keeps its place on wider screens. */
@media (max-width:767px){ .actGroup .csPresenter{display:none} }

/* ---- PRESENTERS SIT BESIDE THE TEXT, NOT ABOVE IT ----
   A badge stacked over a paragraph costs a whole row of vertical space and pushes the useful part
   down the page. The portrait floats into the margin the prose already leaves empty and the text
   wraps around it: bigger face, no extra height. */
.csPresenter{float:right;margin:0 0 10px 18px;flex-direction:column;align-items:center;gap:6px;
  padding:10px;border-radius:16px;box-shadow:none;border:1px solid #23262e;background:#12151a;
  shape-outside:inset(0 round 16px);max-width:180px;text-align:center}
.csPresenter img{width:132px;height:132px;border-radius:14px;object-fit:cover;object-position:top center}
.csPresenter b{font-size:15px;display:block}
.csPresenter i{font-size:12px;display:block;line-height:1.3}
.story,.actGroup,.bbCountry,.rbi{overflow:hidden}          /* contain the float with its block */
.swCard .csPresenter{float:left;margin:0 14px 8px 0;max-width:132px}
.swCard .csPresenter img{width:96px;height:96px}
@media (max-width:767px){
  .csPresenter{float:none;margin:8px 0;flex-direction:row;max-width:none;text-align:left;gap:12px}
  .csPresenter img{width:72px;height:72px}
}
/* a callout is an expert speaking: the portrait is large and the words sit beside it */
.csGuide{align-items:flex-start;gap:16px;padding:14px 18px}
.csGuide .csgFace{width:132px;height:132px;border-radius:14px}
.csGuide p{font-size:15px;line-height:1.6}
@media (max-width:767px){.csGuide{gap:12px;padding:12px}.csGuide .csgFace{width:84px;height:84px}}

/* ---- ONE TYPE SCALE FOR THE RIDE PAGE ----
   The page computed 72 distinct type styles across 22 sizes, most of them differing by half a
   pixel because they were set in em on top of another em. Seven sizes carry everything: the ride
   title, a section head, a lead figure, body copy, the small print and two label sizes. Nothing is
   restyled here - only snapped to the nearest step of the scale, so the page reads as one piece. */
:root{
  --t-title:34px; --t-h2:22px; --t-figure:19px; --t-body:15px; --t-meta:13px;
  --t-label:12px; --t-fine:11px;
}
#view-ride h1{font-size:var(--t-title)}
#view-ride h2,#view-ride .chev h2{font-size:var(--t-h2)}
#view-ride h3,#view-ride h4{font-size:var(--t-figure)}
#view-ride p,#view-ride li,#view-ride td,#view-ride .story,#view-ride .rbMore,#view-ride .csGuide p{font-size:var(--t-body)}
#view-ride small,#view-ride .fine,#view-ride .seedNote,#view-ride .charWhy{font-size:var(--t-fine)}
#view-ride .charLbl,#view-ride .actGroupHead,#view-ride .rbKind,#view-ride .pill,
#view-ride .tag,#view-ride .chip,#view-ride th{font-size:var(--t-label);letter-spacing:.08em}
#view-ride .charVal,#view-ride .rbMeta,#view-ride .csgHead,#view-ride .csPresenter i{font-size:var(--t-meta)}
/* one condensed face for headings and labels, one for reading; nothing else */
#view-ride h1,#view-ride h2,#view-ride h3,#view-ride h4,
#view-ride .actGroupHead,#view-ride .charLbl,#view-ride .rbKind{font-family:'Barlow Condensed',system-ui,sans-serif}
#view-ride p,#view-ride li,#view-ride .story,#view-ride .rbMore{font-family:system-ui,-apple-system,'Segoe UI',sans-serif}

/* The scale has a phone step: the same seven roles, two steps smaller at the top, so the verdict
   and the buttons a rider taps still fit the first screen. */
@media (max-width:767px){
  :root{--t-title:26px;--t-h2:19px;--t-figure:15px}
  #view-ride h1{font-size:var(--t-title);line-height:1.15;margin-bottom:6px}
  #view-ride h2{font-size:var(--t-h2)}
  #view-ride .butler{padding:10px 12px}
  #view-ride .actGroup{margin-top:8px}
}
@media (max-width:767px){
  /* four pixels decided whether the GPX button sat on the first screen: the verdict block gives
     them up rather than the type scale. */
  #view-ride .butler{padding:8px 12px;margin-bottom:6px}
  #view-ride .actGroup{gap:6px}
}
@media (max-width:767px){
  /* the roadbook heading starts below the fold anyway: its top margin is dead space above it */
  #view-ride h1{margin-top:4px}
  #view-ride .dHead{margin-bottom:4px}
  #view-ride .actGroupHead{margin-bottom:4px}
}
@media (max-width:767px){ :root{--t-body:13px} #view-ride p{font-size:var(--t-body)} }


/* ---- PORTRAIT SIZES, BY SURFACE AND WIDTH ----
   No visible portrait renders below 64 px. The feature surfaces keep a face big enough to read at
   every width; the card surfaces step down but never become an avatar. */
.csGuide .csgFace,.csPresenter img,.csReadV img.csgFace{min-width:64px;min-height:64px}
.csGuide.csRouteLead .csgFace{width:160px;height:160px}
.csPresenter img{width:144px;height:144px}
.ride .csGuide .csgFace,.exCard .csGuide .csgFace{width:88px;height:88px}
.swCard .csGuide .csgFace,.swCard .csPresenter img{width:112px;height:112px}
.atCard .csGuide .csgFace,.atrCard .csGuide .csgFace{width:80px;height:80px}
.rbi .csGuide .csgFace,.rbi .csPresenter img{width:88px;height:88px}
#csRead .csReadV img.csgFace{width:220px;height:220px}
@media (max-width:1024px){
  .csGuide.csRouteLead .csgFace{width:144px;height:144px}
  .csPresenter img{width:128px;height:128px}
  .ride .csGuide .csgFace,.exCard .csGuide .csgFace{width:76px;height:76px}
  .swCard .csGuide .csgFace,.swCard .csPresenter img{width:104px;height:104px}
  .atCard .csGuide .csgFace,.atrCard .csGuide .csgFace{width:72px;height:72px}
  .rbi .csGuide .csgFace,.rbi .csPresenter img{width:76px;height:76px}
  #csRead .csReadV img.csgFace{width:180px;height:180px}
}
@media (max-width:767px){
  .csGuide.csRouteLead .csgFace{width:112px;height:112px}
  .csPresenter img{width:104px;height:104px}
  .ride .csGuide .csgFace,.exCard .csGuide .csgFace{width:64px;height:64px}
  .swCard .csGuide .csgFace,.swCard .csPresenter img{width:88px;height:88px}
  .atCard .csGuide .csgFace,.atrCard .csGuide .csgFace{width:64px;height:64px}
  .rbi .csGuide .csgFace,.rbi .csPresenter img{width:64px;height:64px}
  #csRead .csReadV img.csgFace{width:136px;height:136px}
}

/* Read this ride: tabs across the top, one voice showing */
.csReadTabs{display:flex;flex-wrap:wrap;gap:8px;margin:6px 0 12px}
.csReadTab{background:#14171c;border:1px solid #23262e;color:#c8ccd2;border-radius:999px;
  padding:7px 14px;cursor:pointer;font-size:13px}
.csReadTab span{color:#7d828b;margin-left:4px}
.csReadTab.on{background:#1f242c;color:#f4f2ec;border-color:#3a3f49}
.csReadTab.on span{color:#c9a227}
.csReadV{display:none}
.csReadV.on{display:flex}

/* the board's one-line pick summary, in place of three teaser cards on a phone */
.boardPicks{margin:8px 0;padding:10px 12px;background:#12151a;border:1px solid #23262e;border-radius:12px;font-size:13px}
.boardPicks b{color:#f4f2ec}
.boardSwipe{margin-left:8px;background:#e11b2b;color:#fff;border:0;border-radius:999px;padding:6px 12px;font-weight:700;cursor:pointer}
@media (max-width:767px){ #pvFilter{display:none} }

@media (max-width:767px){
  /* Swipe is one tap away in the header, so the three-card teaser block does not need to stand
     between a rider and the first route. */
  #swTeaser{display:none}
  .ownFold{margin:8px 0;border:1px solid #23262e;border-radius:12px;background:#12151a}
  .ownFold>summary{padding:11px 14px;cursor:pointer;font-weight:700;font-size:13px;list-style:none}
  .ownFold>summary::-webkit-details-marker{display:none}
  .ownFold .ownRoute{border:0;background:transparent;margin:0}
}

/* A folded roadbook stop: one line you can scan, the whole detail one tap away */
.rbFold{border-top:1px solid #1e222a}
.rbFold>summary{list-style:none;cursor:pointer;padding:12px 0;display:flex;gap:12px;align-items:baseline;flex-wrap:wrap}
.rbFold>summary::-webkit-details-marker{display:none}
.rbFold>summary b{font-size:15px;color:#f4f2ec}
.rbFold>summary span{font-size:13px;color:#9aa0a8}
.rbFold>summary::after{content:'open';margin-left:auto;font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:#7d828b}
.rbFold[open]>summary::after{content:'close'}

@media (max-width:767px){
  .moreFold{margin:10px 0;border:1px solid #23262e;border-radius:12px;background:#101318}
  .moreFold>summary{padding:13px 14px;cursor:pointer;font-weight:700;font-size:15px;list-style:none;
    font-family:'Barlow Condensed',system-ui,sans-serif;letter-spacing:.02em}
  .moreFold>summary::-webkit-details-marker{display:none}
  .moreFold>summary::after{content:'open';float:right;font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:#7d828b}
  .moreFold[open]>summary::after{content:'close'}
  .moreFold>*:not(summary){padding:0 12px 12px}
}

/* An explainer: a large portrait and a proper paragraph, so the section has someone behind it */
.csExplain{align-items:flex-start;gap:18px;padding:16px 20px;margin:12px 0 16px}
.csExplain .csgFace{width:180px;height:180px;border-radius:16px}
.csExplain p{font-size:15px;line-height:1.62}
@media (max-width:1024px){.csExplain .csgFace{width:150px;height:150px}}
@media (max-width:767px){.csExplain{gap:12px;padding:12px}.csExplain .csgFace{width:104px;height:104px}}

/* One grouped place to change the ride, instead of four unlabelled boxes around the fuel module */
.addGroup{margin:18px 0;padding:14px 16px;border:1px solid #23262e;border-radius:14px;background:#0f1116}
.addGroup>h2{margin:0 0 4px}
.addGroup>.fine{margin:0 0 10px;color:#9aa0a8}
.addGroup>*+*{margin-top:10px}
#fuelHead{margin:18px 0 6px}

/* A card teaser: a small face and one useful sentence, inside the card, never a card of its own */
.csTeaser{display:flex;gap:12px;align-items:flex-start;margin:8px 0 2px;padding:8px 10px;
  border-left:3px solid var(--csg,#c9a227);background:#12151a;border-radius:10px}
.csTeaser img{width:64px;height:64px;border-radius:9px;object-fit:cover;object-position:top center;flex:0 0 auto}
.csTeaser p{margin:0;font-size:13px;line-height:1.5;color:#c8ccd2}
.csTeaser b{color:#f4f2ec}
.csTeaser span{color:var(--csg,#c9a227);font-size:12px}
.csTeaser-swipe img{width:112px;height:112px}
.csTeaser-swipe p{font-size:14px}
@media (max-width:767px){.csTeaser img{width:56px;height:56px}.csTeaser-swipe img{width:92px;height:92px}}

/* ---- A READABLE FLOOR ----
   The type scale was set by role, and every role sat below the size a rider can read on a moving
   phone: narrative, guide text, buttons and inputs measured 13–15 px, credits 11. The scale keeps
   its proportions; the floor is raised. Core reading and anything you tap is at least 16 px,
   secondary metadata and credits at least 14. */
:root{ --t-body:16px; --t-meta:14px; --t-label:14px; --t-fine:14px; }
.story p, .csGuide p, .csTeaser p, .csPresenter i, .rbLead, .rbMore,
#view-ride p, #view-ride li, #view-ride td { font-size:16px; line-height:1.6 }
button, .btn, .tbtn, input, select, textarea, .addStopBtn, .swBtn { font-size:16px }
.fine, small, .pfSrc, .seedNote, .charWhy, figcaption,
.leaflet-control-attribution, .leaflet-control-attribution a { font-size:14px }
/* headings keep their own steps, a size above the body */
#view-ride h1{font-size:34px} #view-ride h2{font-size:24px} #view-ride h3,#view-ride h4{font-size:19px}
@media (max-width:767px){
  #view-ride h1{font-size:26px} #view-ride h2{font-size:20px}
  .story p, .csGuide p, .csTeaser p, .rbLead, .rbMore, #view-ride p, #view-ride li { font-size:16px }
}
/* the map's own controls and the Leaflet attribution carry their own sizes and were missed by the
   role selectors above; a control you tap is a core action, and the credit is secondary metadata */
.tbtn, .mapBtn, .leaflet-bar a, .leaflet-control button, .mapTool, .layerBtn,
.swWhy b, .pill, .chip, .tag { font-size:16px }
.leaflet-control-attribution, .leaflet-control-attribution *, .attrib, .credit { font-size:14px }
/* these sit inside more specific selectors further up (header .tbtn, .leaflet-control-attribution),
   so the floor is restated at the same specificity rather than with !important */
header .tbtn, header button, header a.tbtn { font-size:16px }
.leaflet-container .leaflet-control-attribution,
.leaflet-container .leaflet-control-attribution a { font-size:14px }
@media (max-width:767px){
  /* the larger, readable type pushed the GPX button 21 px past the first screen. The type floor
     stays; the space around the verdict and the action row gives way instead. */
  #view-ride .butler{padding:6px 12px;margin-bottom:4px}
  #view-ride h1{margin:2px 0 4px}
  #view-ride .actGroup{gap:6px;margin-top:6px}
  #view-ride .actGroupHead{margin-bottom:2px}
  #view-ride .statRow{margin:4px 0}
}
/* `.top .tbtn` and its neighbours set 15 px from a rule declared later in the sheet than the floor
   above, so the floor is restated here, last, at the same specificity. The scale is unchanged. */
.top .tbtn, .top button, .top .btn { font-size:16px }
.mapTools .tbtn, .mapBar .tbtn, .mapWrap button, .mapWrap .tbtn { font-size:16px }
.leaflet-container .leaflet-control-attribution,
.leaflet-container .leaflet-control-attribution a,
.leaflet-control-attribution, .leaflet-control-attribution a { font-size:14px }
/* Leaflet sets its attribution with a `font` shorthand from its own sheet, and the map tool buttons
   carry sizes from the map bar. Both are restated with enough specificity to win, and nothing else
   about them changes. */
.leaflet-container .leaflet-bottom .leaflet-control-attribution,
.leaflet-container .leaflet-bottom .leaflet-control-attribution a,
.leaflet-container .leaflet-control-attribution span { font-size:14px; line-height:1.5 }
#map .mapExpand, #map .mapHome, #map button, .mapShell button, .mapShell .tbtn,
.rideMap button, .rideMap .tbtn, .mapRow button, .mapRow .tbtn,
button.mapExpand, button.mapHome, button.on { font-size:16px }
/* the map bar and the jump list carry real labels a rider taps - "Set start", "Whole route", the
   checkpoint names - and they were at 12 and 15 px. They are labels, so they meet the floor. */
.mapBarRight button, .mapBarRight .tbtn, .mapBarLeft button, .mapBarLeft .tbtn,
.mapBar button, .mapBar .tbtn, .pinStart, button.pinStart,
.mapJump button, .mapJump select, .mapJump option, .mapJump .tbtn { font-size:16px }
@media (max-width:767px){
  /* the readable floor costs vertical space; the first screen keeps the verdict and the buttons by
     tightening what sits between them, not by shrinking the words */
  #view-ride .statRow{margin:2px 0;gap:4px}
  #view-ride .butler{padding:5px 10px;margin:0 0 4px}
  #view-ride .dHead{margin:2px 0}
  #view-ride .actGroup{margin-top:4px;gap:5px}
  #view-ride .actGroup .tbtn,#view-ride .actGroup button{padding:9px 10px}
}

/* Atlas: what is in view, introduced before anything is chosen */
.atlasPicks{margin:10px 0 14px;padding:12px;border:1px solid #23262e;border-radius:14px;background:#0f1116}
.atlasPicksIntro{display:flex;gap:14px;align-items:flex-start;margin-bottom:10px}
.atlasPicksIntro img{width:96px;height:96px;border-radius:12px;object-fit:cover;object-position:top center}
.atlasPicksIntro b{font-size:16px;color:#f4f2ec}
.atlasPicksIntro span{color:#c9a227;font-size:14px;margin-left:6px}
.atlasPicksIntro p{margin:4px 0 0;font-size:16px;line-height:1.55;color:#c8ccd2}
.atlasPick{padding:10px 0;border-top:1px solid #1e222a}
.atlasPick b{font-size:16px;color:#f4f2ec}
.atlasPick p{margin:3px 0 7px;font-size:16px;line-height:1.5;color:#c8ccd2}
.atlasPickActs{display:flex;gap:8px;flex-wrap:wrap}
.atlasPickActs button{font-size:16px;padding:8px 14px;border-radius:999px;border:1px solid #2a2f39;background:#14171c;color:#f4f2ec;cursor:pointer}
@media (max-width:767px){.atlasPicksIntro img{width:80px;height:80px}}

/* ---- GUIDE PANELS: THE FRAME FOLLOWS THE CONTENT ----
   A badge is a name and a role, so it gets a small portrait and sits on one line. A short fact is a
   compact note. A full explanation keeps the large portrait it earns. The artwork has transparent
   margins, so object-fit stays contain and nothing is cropped. */
.csGuide img, .csTeaser img, .csPresenter img { object-fit:contain; object-position:top center }
.csPresenter { align-items:center }
.csPresenter img, .csPresenter.gSmall img { width:64px; height:64px }
.csGuide.gSmall img, .csTeaser.gSmall img { width:76px; height:76px }
.csGuide.gMid img, .csTeaser.gMid img { width:96px; height:96px }
.csGuide.gFull img, .csTeaser.gFull img { width:132px; height:132px }
.csGuide.gSmall, .csTeaser.gSmall { padding:8px 10px }
.csGuide p, .csTeaser p { min-width:0 }
@media (max-width:767px){
  .csPresenter img, .csPresenter.gSmall img { width:56px; height:56px }
  .csGuide.gSmall img, .csTeaser.gSmall img { width:64px; height:64px }
  .csGuide.gMid img, .csTeaser.gMid img { width:76px; height:76px }
  .csGuide.gFull img, .csTeaser.gFull img { width:92px; height:92px }
}

/* Leon's contribution: one module in normal flow, portrait and name in a row, the passage below
   at full width - never a label floating beside unrelated paragraphs */
.csContrib{margin:18px 0;padding:14px 16px;border:1px solid var(--edge);border-radius:14px;background:var(--card)}
.csContribHead{display:flex;align-items:center;gap:12px;margin-bottom:8px}
.csContribHead img{width:72px;height:72px;object-fit:contain;flex:0 0 auto}
.csContribHead b{display:block;font-size:16px}
.csContribHead span{display:block;font-size:14px;color:var(--dim)}
.csContrib p{font-size:16px;line-height:1.6;margin:0}
.csContrib .csContribSrc{font-size:14px;color:var(--dim);margin-top:8px}

/* UI03: a row of tags in the route page's list did not wrap, so on a 390 px phone the row grew to
   542 px and the whole page widened to 575 px; two profile drawings were a fixed 420 px. The tags
   wrap, the rows are bounded by their column, and drawings scale to it. */
.whRow{min-width:0;max-width:100%}
.whTags{flex-wrap:wrap;min-width:0;max-width:100%}
.whRow b,.whRow i{min-width:0;max-width:100%;overflow-wrap:anywhere}
#view-ride svg{max-width:100%}

/* a badge's contribution: one readable sentence under the name, full width of the badge */
.csPresenter{flex-wrap:wrap}
.csPresenterFact{display:block;flex:1 1 100%;font-style:normal;font-size:16px;line-height:1.5;color:#c8ccd2;margin-top:6px}

/* ---- MOTION: THE ROAD THAT DRAWS ITSELF ----
   One orchestrated moment on the home page. Only stroke, opacity and an SVG motion path move; the
   layout never shifts. Reduced motion shows the finished road, still. */
.heroRoad{position:absolute;inset:0;width:100%;height:100%;z-index:1;pointer-events:none;overflow:visible}
.heroRoad path{fill:none;stroke-linecap:round;stroke-linejoin:round}
.hrGlow{stroke:rgba(225,27,43,.45);stroke-width:18;filter:blur(7px)}
.hrLine{stroke:rgba(255,246,226,.92);stroke-width:4.5}
.hrDash{stroke:#e11b2b;stroke-width:1.6;stroke-dasharray:9 15;opacity:.9}
.hrHalo{fill:rgba(255,236,190,.28);filter:blur(5px)}
.hrCore{fill:#fff8e6}
@media (prefers-reduced-motion:no-preference){
  .heroRoad:not(.still) .hrGlow,.heroRoad:not(.still) .hrLine{stroke-dasharray:var(--len);stroke-dashoffset:var(--len);
    animation:hrDraw 2.7s cubic-bezier(.62,.04,.24,1) .35s forwards}
  .heroRoad:not(.still) .hrDash{opacity:0;animation:hrFade .9s ease 2.9s forwards}
  .heroRoad:not(.still) .hrLight{opacity:0;animation:hrFade .6s ease 3.1s forwards}
  .heroIn>*{animation:hrRise .8s cubic-bezier(.2,.7,.2,1) backwards}
  .heroIn>*:nth-child(2){animation-delay:.12s}.heroIn>*:nth-child(3){animation-delay:.24s}.heroIn>*:nth-child(n+4){animation-delay:.36s}
}
@keyframes hrDraw{to{stroke-dashoffset:0}}
@keyframes hrFade{to{opacity:.9}}
@keyframes hrRise{from{opacity:0;transform:translateY(14px)}}

/* ---- MOTION: ANSWERING THE RIDER ----
   Checkpoints arrive in riding order as the line reaches them (the delay is set per pin), and the
   elevation profile traces from left to right when it first appears. The pin animation uses the
   marker's inner content only, so Leaflet's own positioning transform is never touched. */
@media (prefers-reduced-motion:no-preference){
  .leaflet-marker-icon.csPinIn > *{animation:csPin .5s cubic-bezier(.3,1.6,.5,1) var(--d,0ms) backwards}
  svg.spark .skLine{stroke-dasharray:1;stroke-dashoffset:1;animation:skTrace 1.4s cubic-bezier(.5,.05,.3,1) .15s forwards}
  svg.spark .skArea{animation:skArea 1s ease .9s backwards}
}
@keyframes csPin{from{opacity:0;transform:scale(.3) translateY(10px)}}
@keyframes skTrace{to{stroke-dashoffset:0}}
@keyframes skArea{from{opacity:0}}

/* ---- OWNER TYPE RULE (app) ----
   Completion order: 16 CSS px for core text, labels, inputs and actions; 14 px for secondary text and
   credits; measured on the element that carries the text. Generated from the measured undersized
   elements on Home, Board, a ride page and Leads at 1440 and 390 px (tools/test-type-floor.mjs). */
button.vmBtn,
p.heroSub,
button.primary,
button.ghost2,
p.heroWhy,
.fRow > label,
.geoTxt > b,
p.privacyLine,
.csgHead > b,
.reveal > span,
p.statNote,
.whyCard > h3,
.whyCard > p,
li.reveal,
.reveal > b,
b,
span,
.friend > strong,
footer,
div.footSocialHead,
button.footLead,
.footLinks > a,
.legalRow > a,
.legalRow > span,
.srcRow > a,
.srcRow > span,
button,
div,
p,
span.est,
button.edit,
.swTz > b,
.swTz > span,
.swTz > em,
button.swipeCta,
.sortRow > span,
.ownRoute > b,
.ownRoute > span,
label.ownBtn,
button.pvChip,
span.pvTag,
span.shTag,
.row1 > h3,
span.rTag,
span.apChip,
.apChip > b,
.why > span,
p.sl,
span.cvWarm,
span.icTag,
span.legendTag,
span.goodChip,
span.warnChip,
span.cvAlt,
.tierHead > p,
span.recTag,
span.crumb,
div.b,
span.blTag,
.blLinks > span,
.blLinks > a,
span.charLabel,
span.charVal,
span.charWhy,
.bbHead > b,
.bbHead > span,
.bbLeg > b,
i,
.bbCountry > b,
.fmRoad > b,
span.fmMeta,
.leaflet-marker-icon > span,
span.lgdMore,
.speedKey > b,
.speedKey > span,
span.pinKey,
.pinKey > i,
span.pfSrc,
.pfRead > b,
.pfRead > span,
.profLegend > span,
span.rhPh,
em.csName,
.csItem > i,
b.actGroupHead,
.recBox > span,
.csPresenter > b,
.csPresenter > i,
.rbTop > label,
span.rbArrive,
.rbArrive > b,
th,
span.rbIco,
span.kind,
span.rbWay,
.wpLinks > a,
span.rbLegTag,
.rbLeg > b,
.stBody > h5,
div.rbSceneType,
span.rbSceneFact,
.rbSceneFact > b,
span.seeTx,
.see > span,
.dayWarn > b,
.camHead > b,
.camHead > span,
.whRow > b,
span.whParts,
span.whWhy,
span.whCost,
.whCost > b,
.lgHead > b,
.lgHead > span,
div.spSugHead,
.addRow > b,
span.addWhy,
span.addCost,
.fcHead > b,
.fcHead > span,
i.fcGuess,
i.fcRate,
.fcRow > label,
.miniHead > b,
span.miBand,
span.miWp,
a.word,
.word > b,
.view > button,
.cur > span,
.whShot > em{font-size:16px !important}
span.csgRole,
em.csgLabel,
.stat > span,
span.provTag,
span.provConf,
i.provMore,
span.rideClock,
.markFold > summary,
.rbConf > summary,
span.rbConfTier,
span.stKm,
span.num{font-size:14px !important}

/* ---- CHANGE THIS RIDE: KENJI INTRODUCES THE GRID, HE DOES NOT FLOAT OVER IT ----
   Owner: the section looked sloppy - an empty framed "Worth adding" label and Kenji's card hanging
   over the photo grid. Kenji's explanation is the section's opening row: portrait, then what the
   places are and how adding works; the photographed grid follows underneath. */
#addGroup .csPresenter{position:static !important;float:none !important;display:grid !important;
  grid-template-columns:76px 1fr;column-gap:14px;row-gap:2px;align-items:start;width:auto !important;
  max-width:none !important;margin:6px 0 14px !important;padding:12px 14px !important;text-align:left !important}
#addGroup .csPresenter img{grid-row:1 / span 3;width:76px !important;height:76px !important;object-fit:contain}
#addGroup .csPresenter b,#addGroup .csPresenter i,#addGroup .csPresenter .csPresenterFact{grid-column:2;text-align:left !important}
#addGroup .csPresenter .csPresenterFact{line-height:1.5}
#addGroup #spurBox{border:0 !important;padding:0 !important;background:none !important}

/* story map: phone key band below 600 px (owner type rule) - tools/figures.mjs */
svg.cs-map .cs-lbl-m{display:none}@media (max-width:600px){svg.cs-map .cs-lbl-d{display:none}svg.cs-map .cs-lbl-m{display:inline}}

/* Remove stop (owner 2026-10-05): visible on every stop between start and finish */
.rbi .rbRemove{float:right;position:relative;z-index:2;width:auto;white-space:nowrap;margin:0 0 8px 10px;min-height:44px;padding:8px 14px;border-radius:999px;border:1px solid rgba(255,255,255,.28);background:transparent;color:inherit;font-size:16px;cursor:pointer}
.rbi .rbRemove:hover,.rbi .rbRemove:focus-visible{border-color:#e11b2b;color:#fff;background:rgba(225,27,43,.18)}

/* How to use the roadbook - compact disclosure (audit 2493adc) */
.rbHowTo{margin:8px 0 14px;border:1px solid rgba(255,255,255,.14);border-radius:12px;padding:0 14px}
.rbHowTo summary{font-size:16px;min-height:44px;display:flex;align-items:center;cursor:pointer;color:inherit}
.rbHowTo p{font-size:16px;line-height:1.55;margin:0 0 12px}

/* ---- MOBILE MAP: COMPACT CONTROLS (owner 2026-10-07: "much smaller buttons, it is so convoluted you cannot
   use it") - on phones the overlay controls shrink to one compact line so the road stays visible.
   Text stays 16 px (owner type rule R21); height, padding and layout shrink. ---- */
@media (max-width: 600px) {
  #lineMode, .lineMode { display: flex !important; flex-wrap: nowrap !important; gap: 4px !important; overflow-x: auto !important;
    max-width: calc(100% - 16px) !important; padding: 2px !important; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
  #lineMode::-webkit-scrollbar { display: none; }
  #lineMode button, .lineMode button { flex: 0 0 auto !important; width: auto !important; min-width: 0 !important; height: auto !important;
    min-height: 32px !important; padding: 2px 10px !important; line-height: 1.1 !important; white-space: nowrap !important; border-radius: 999px !important; }
  .mapBarRight { gap: 6px !important; }
  .mapBarRight button, #pinStart, #rideBtn, #baseBtn { height: auto !important; min-height: 32px !important; padding: 2px 10px !important;
    line-height: 1.1 !important; white-space: nowrap !important; width: auto !important; min-width: 0 !important; }
  .mapBase { gap: 4px !important; }
}

/* ---- owner 2026-10-07 ---- */
header.top .mark { cursor: pointer; }
/* start page: photographs and nothing else */
/* ---- the cold open (owner 2026-10-07: "start like a Hollywood movie") ----
   black, cinemascope bars, the photograph pushes in out of the dark, a red road draws itself,
   the title pulls focus, the bars open and the welcome screen is already there. Nothing glows. */
#csIntro { position: fixed; inset: 0; z-index: 10000; background: #000; overflow: hidden; cursor: pointer; transition: opacity .9s ease; }
#csIntro.out { opacity: 0; pointer-events: none; }
#csIntro .ciPic { position: absolute; inset: 0; opacity: 0; transition: opacity 1.6s ease 1.5s; }
#csIntro.pic.go .ciPic { opacity: 1; }
#csIntro .ciPic img { width: 100%; height: 100%; object-fit: cover; display: block; transform: scale(1.22); transition: transform 5s cubic-bezier(.2,.6,.3,1); }
#csIntro.go .ciPic img { transform: scale(1.04); }
#csIntro .ciShade { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(0,0,0,.55) 0%, rgba(0,0,0,.15) 40%, rgba(0,0,0,.25) 60%, rgba(0,0,0,.8) 100%); }
#csIntro .ciBar { position: absolute; left: 0; right: 0; height: 13vh; background: #000; transition: height .9s cubic-bezier(.7,0,.3,1) 2.6s; z-index: 3; }
#csIntro .ciTop { top: 0; } #csIntro .ciBot { bottom: 0; }
#csIntro.go .ciBar { height: 0; }
#csIntro .ciRoad { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1; transition: opacity 1.1s ease 1.7s; }
#csIntro.go .ciRoad { opacity: 0; }
#csIntro .ciRev { fill: none; stroke: #fff; stroke-width: 760; stroke-dasharray: 1; stroke-dashoffset: 1; transition: stroke-dashoffset 1.7s cubic-bezier(.45,0,.2,1) .2s; }
#csIntro.go .ciRev { stroke-dashoffset: 0; }
#csIntro .ciEdge { fill: none; stroke: #e11b2b; stroke-width: 2.5; vector-effect: non-scaling-stroke; stroke-linejoin: round; }
#csIntro .ciMid { fill: none; stroke: #f4f2ec; stroke-width: 2; stroke-dasharray: 16 20; vector-effect: non-scaling-stroke; opacity: .85; }
#csIntro .ciPresents { position: absolute; left: 0; right: 0; top: 34%; text-align: center; z-index: 2; color: #e9e6df;
  font: 600 14px/1 var(--display); letter-spacing: .55em; text-transform: uppercase; opacity: 0; animation: ciPresents 1.5s ease .15s forwards; }
#csIntro .ciTitle { position: absolute; left: 0; right: 0; top: 40%; text-align: center; z-index: 2; color: #fff;
  font: 800 italic clamp(48px, 12vw, 132px)/1 var(--display); text-transform: uppercase; letter-spacing: .6em; opacity: 0; filter: blur(6px);
  transition: letter-spacing 2.2s cubic-bezier(.2,.7,.2,1) 1.25s, opacity 1.2s ease 1.25s, filter 1.4s ease 1.25s; }
#csIntro .ciTitle b { color: #e11b2b; font-weight: 800; }
#csIntro.go .ciTitle { letter-spacing: .04em; opacity: 1; filter: none; }
#csIntro .ciTag { position: absolute; left: 0; right: 0; top: calc(40% + clamp(56px, 13vw, 142px)); text-align: center; z-index: 2; color: #e9e6df;
  font: 600 clamp(16px, 2.2vw, 22px)/1.2 var(--display); letter-spacing: .32em; text-transform: uppercase; opacity: 0; transform: translateY(10px);
  transition: opacity .8s ease 2.1s, transform .8s ease 2.1s; }
#csIntro.go .ciTag { opacity: 1; transform: none; }
#csIntro .ciTitle { font-size: clamp(52px, 14vw, 150px) !important; line-height: 1 !important; }
#csIntro .ciTag { font-size: clamp(16px, 2.2vw, 22px) !important; }
#csIntro .ciPresents { font-size: 14px !important; }
#csIntro .ciTitle b { font-size: inherit !important; font-style: inherit; }
@keyframes ciPresents { 0% { opacity: 0; } 30% { opacity: .9; } 70% { opacity: .9; } 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { #csIntro *, #csWall * { transition-duration: .01s !important; transition-delay: 0s !important; animation: none !important; } }
/* ---- the welcome screen: one photograph at a time, Ken Burns drift, a line of copy, two ways in ---- */
#view-home.csWallOn > :not(#csWall) { display: none !important; }
body.csWelcome #viewModes { display: none !important; }
body.csWelcome #view-home.csWallOn { padding: 0 !important; margin-top: 0 !important; max-width: none !important; }
#view-home:not(.csWallOn) > #csWall { display: none !important; }
#csWall { position: relative; width: 100vw; margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw); height: calc(100dvh - 140px); min-height: 420px; overflow: hidden; background: #050506; }
#csWall .csSlide { position: absolute; inset: 0; margin: 0; opacity: 0; transition: opacity 1.8s ease; overflow: hidden; }
#csWall .csSlide.on { opacity: 1; }
#csWall .csSlide img { width: 100%; height: 100%; object-fit: cover; display: block; transform-origin: 50% 50%; }
#csWall .csSlide.kb0 img { animation: csKb0 9s linear forwards; }
#csWall .csSlide.kb1 img { animation: csKb1 9s linear forwards; }
#csWall .csSlide.kb2 img { animation: csKb2 9s linear forwards; }
#csWall .csSlide.kb3 img { animation: csKb3 9s linear forwards; }
@keyframes csKb0 { from { transform: scale(1.04) translate(0, 0); } to { transform: scale(1.16) translate(-2%, -1%); } }
@keyframes csKb1 { from { transform: scale(1.16) translate(2%, 0); } to { transform: scale(1.04) translate(0, 1%); } }
@keyframes csKb2 { from { transform: scale(1.06) translate(-2%, 1%); } to { transform: scale(1.18) translate(1.5%, -1%); } }
@keyframes csKb3 { from { transform: scale(1.18) translate(0, -1.5%); } to { transform: scale(1.05) translate(-1%, 0); } }
#csWall .csSlide figcaption { position: absolute; right: 10px; bottom: 8px; z-index: 3; color: rgba(255,255,255,.75); }
#csWall .csHeroShade { position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg, rgba(0,0,0,.35) 0%, rgba(0,0,0,0) 28%, rgba(0,0,0,0) 45%, rgba(0,0,0,.72) 82%, rgba(0,0,0,.88) 100%); }
#csWall .csHeroText { position: absolute; z-index: 2; left: clamp(18px, 5vw, 72px); right: clamp(18px, 5vw, 72px); bottom: clamp(40px, 9vh, 96px); max-width: 860px;
  animation: csHeroIn 1.2s cubic-bezier(.2,.7,.2,1) both; }
#csWall .csHeroKicker { color: #e9e6df; font: 600 14px/1 var(--display); letter-spacing: .28em; text-transform: uppercase; display: flex; align-items: center; gap: 12px; }
#csWall .csHeroKicker::before { content: ''; width: 34px; height: 3px; background: #e11b2b; display: inline-block; }
#csWall .csHeroH { margin: 14px 0 12px; color: #fff; font: 800 italic clamp(44px, 8.4vw, 104px)/.92 var(--display); text-transform: uppercase; letter-spacing: .01em; }
#csWall .csHeroP { margin: 0 0 22px; color: #e9e6df; font-size: clamp(16px, 1.6vw, 20px); line-height: 1.45; max-width: 560px; }
#csWall .csHeroCta { display: flex; gap: 12px; flex-wrap: wrap; }
#csWall .csHeroCta button { font: 700 16px/1 var(--display); letter-spacing: .12em; text-transform: uppercase; border-radius: 999px; padding: 16px 28px; cursor: pointer; min-height: 48px; }
#csWall .csHeroGo { background: #e11b2b; color: #fff; border: 0; }
#csWall .csHeroAlt { background: rgba(0,0,0,.35); color: #fff; border: 1.5px solid rgba(255,255,255,.7); }
#csWall .csHeroDots { position: absolute; z-index: 2; top: 14px; left: clamp(18px, 5vw, 72px); right: clamp(18px, 5vw, 72px); display: flex; gap: 6px; }
#csWall .csHeroDots i { flex: 1; height: 2px; background: rgba(255,255,255,.28); border-radius: 2px; transition: background .6s; }
#csWall .csHeroDots i.on { background: #fff; }
@keyframes csHeroIn { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
@media (max-width: 600px) { #csWall .csHeroCta button { flex: 1 1 auto; padding: 15px 18px; } #csWall .csHeroH { font-size: clamp(42px, 13vw, 64px); } }
/* every photo source line at half its size */
.credit, .rotCred, .exCred, figcaption.credit, .csSlide figcaption, .cgCredit, .csStoryPic figcaption { font-size: 7px !important; line-height: 1.2 !important; }
@media (max-width: 600px) {
  /* mobile map: the bar and the note go BELOW the map; corner buttons stay small at the edges; nothing is cut */
  .mapBox .mapBar, .mapBox .mapNote { position: static !important; inset: auto !important; transform: none !important; width: auto !important; max-width: none !important; margin: 6px 0 0 !important; }
  #lineMode, .lineMode { flex-wrap: wrap !important; overflow: visible !important; max-width: none !important; }
  #lineMode button, .lineMode button { white-space: normal !important; }
  .mapBox .mapBase, .mapBox .mapExpand, .mapBox .mapHome { transform: scale(0.82); transform-origin: top right; }
  /* height profile: readable at a fixed drawing width, swipe sideways */
  #pfHost { overflow-x: auto !important; }
  #pfHost svg { min-width: 760px !important; height: auto !important; }
}

/* ---- owner 2026-10-07: mobile redesign ---- */
html { touch-action: manipulation; }
nav a:active, nav button:active, .bnav a:active, .bnav button:active, button:active { transform: scale(0.96); filter: brightness(1.2); transition: transform 60ms; }
@media (max-width: 600px) {
  /* the map: route, numbered stops and the bike only - nothing else on it */
  .mapBox { display: flex !important; flex-wrap: wrap; gap: 6px; align-items: center; }
  .mapBox > #map, .mapBox > .leaflet-container { flex: 0 0 100%; }
  .mapBox .mapNote, .mapBox .mapBar { flex: 0 0 100%; }
  .mapBox .mapEdit, .mapBox .mapLayers, .mapBox .mapBase, .mapBox .mapExpand, .mapBox .mapHome { position: static !important; inset: auto !important; transform: none !important; margin: 0 !important; }
  .mapBox .passPin, .mapBox .legendPin, .mapBox .restPin, .mapBox .whPin, .mapBox .leaflet-control-zoom, .mapBox .leaflet-control-attribution { display: none !important; }
  .mapBox .csMapCredit { flex: 0 0 100%; font-size: 14px; color: #8d8d8d; }
  .mapBox .csMapCredit a { color: inherit; }
}
@media (max-width: 600px) {
}

/* ---- owner 2026-10-07: on the phone no text overlaps and nothing is cut short (tools/audit-mobile-layout.mjs) ---- */
/* swipe: the ride's short lines show in full; the info panel already scrolls inside the card, so the
   card and the Pass/Keep buttons keep their place */
.swInfo > p { display: block !important; -webkit-line-clamp: unset !important; overflow: visible !important; }
.heroIn h1 .l1, .heroIn h1 .l2 { line-height: 1.1 !important; }
@media (max-width: 600px) {
  /* the last line of every page clears the bottom bar */
  body { padding-bottom: calc(78px + env(safe-area-inset-bottom)) !important; }
  /* section heads wrap instead of ending in "..." */
  .chev { flex-wrap: wrap; row-gap: 4px; }
  .chev h2, .chev small { white-space: normal !important; overflow: visible !important; text-overflow: clip !important; }
  /* scenic-road tags on cards wrap instead of being cut */
  span.icTag { white-space: normal !important; max-width: 100% !important; overflow: visible !important; text-overflow: clip !important; line-height: 1.3 !important; }
  /* "Yes, go" keeps its full label */
  #wbGo { flex: none !important; white-space: nowrap !important; overflow: visible !important; text-overflow: clip !important; }
}
@media (max-width: 600px) {
  /* card badges in one row at the top (score left, shape next to it, tier right), so neither covers the
     card's own title lines underneath */
  .rideHero .shTag { right: auto !important; left: 62px !important; top: 10px !important; }
}
@media (max-width: 600px) {
  /* roadbook direction chips show the whole direction, on two lines if needed */
  .rbWayChip { white-space: normal !important; overflow: visible !important; text-overflow: clip !important; line-height: 1.3 !important; }
  /* "What this page knows" fits the phone: the table wraps inside the screen */
  .rbConfT { table-layout: fixed !important; width: 100% !important; }
  .rbConfT th, .rbConfT td { overflow-wrap: anywhere; word-break: break-word; white-space: normal !important; }
  /* stop names under the route strip: whole name, wrapped */
  .csName { white-space: normal !important; overflow: visible !important; text-overflow: clip !important; max-width: 70px !important; overflow-wrap: anywhere; line-height: 1.15 !important; }
}

/* ---- owner 2026-10-07: "testimonials a little bigger; buttons, pills, boxes and texts aligned to use the space optimally;
   mobile crazy amazing and pro". One grid for everything: pills 36 px, buttons 52 px, gaps 8 px, boxes 16 px padding. ---- */
/* the guides: bigger faces and readable text everywhere */
.csGuide { gap: 14px; padding: 14px 16px; align-items: center; }
.csGuide .csgFace, .csgFace-card { width: 84px !important; height: 84px !important; }
.csgFace-roadbook { width: 92px !important; height: 92px !important; }
.csGuide .csgHead { font-size: 15px; }
.csGuide .csgLabel { font-size: 13px; }
.csGuide p { font-size: 16px; line-height: 1.55; }
.csGuide small { font-size: 14px; }
@media (max-width: 600px) {
  .csGuide { align-items: flex-start; }
  .csGuide .csgFace, .csgFace-card { width: 76px !important; height: 76px !important; }
  .csReadV .csgFace { width: 76px !important; height: 76px !important; }

  /* pills: one height, centred text, even gaps */
  .apChip, .rTags > span, .blLinks a, .srcRow a, .filterBar .chip, .why > span {
    display: inline-block !important; padding: 8px 14px !important; line-height: 20px !important;
    border-radius: 999px; font-size: 16px !important; box-sizing: border-box; text-align: left; }
  .rTags > span, .apChip { white-space: normal; }
  .why, .rTags, .blLinks, .srcRow { display: flex !important; flex-wrap: wrap; gap: 8px !important; }
  .filterBar { gap: 8px !important; }
  .filterBar .chip { min-height: 40px; }

  /* plain buttons in heads and on the map: same height and shape */
  #editSearch, .mapExpand, .mapBase button, #pinStart, #rideBtn { min-height: 44px !important; border-radius: 12px !important; }

  /* map bar: the three views as an even segmented control, the two ride controls side by side, the clock on its own line */
  #lineMode { display: grid !important; grid-template-columns: repeat(3, 1fr); gap: 6px; width: 100%; }
  #lineMode button { min-height: 44px; padding: 6px 8px !important; white-space: normal !important; line-height: 1.15; text-align: center; border-radius: 12px !important; }
  .mapBarRight { display: grid !important; grid-template-columns: 1fr 1fr; gap: 6px; width: 100%; }
  .mapBarRight button { width: 100%; justify-content: center; }
  .mapBarRight #rideClock { grid-column: 1 / -1; justify-self: center; }

  /* the action groups: a clean two-column grid, every button the same height, nothing squeezed */
  .actionBar .actGroup { grid-template-columns: 1fr 1fr !important; gap: 8px !important; }
  .actionBar .actGroup > * { grid-column: auto !important; }
  .actionBar .actGroup > .actGroupHead, .actionBar .actGroup > .recBox, .actionBar .actGroup > .beBack,
  .actionBar .actGroup > .backByOut { grid-column: 1 / -1 !important; }
  .actionBar .abtn { min-height: 52px !important; border-radius: 12px !important; padding: 8px 12px !important; font-size: 16px !important; width: 100%; box-sizing: border-box; }
  .actionBar .abtn.icon { font-size: 20px !important; }
  .actionBar .beBack { justify-content: space-between !important; padding: 6px 8px 6px 16px !important; }
  /* no orphan half-width buttons: Google Maps takes the full row so star and share pair up;
     Reverse and The way back sit together above Be back by */
  .actionBar #gmapA { grid-column: 1 / -1 !important; }
  .actionBar .actGroup > .actGroupHead { order: 0; }
  .actionBar #revBtn { order: 1; } .actionBar #wayHomeBtn { order: 2; } .actionBar #capBtn { order: 3; }
  .actionBar .actGroup > .beBack { order: 4; } .actionBar .actGroup > .backByOut { order: 5; }
  /* the highest-point line: the number never breaks from its unit */
  .altOnly > b { white-space: nowrap; flex: none; }
  /* ride stats: an even 2 x 2 instead of three and an orphan */
  #view-ride .statRow { grid-template-columns: 1fr 1fr !important; gap: 8px !important; }
  #view-ride .statRow .stat { border-radius: 14px !important; }

  /* boxes: same radius and breathing room */
  .ownRoute, .recBox, .csGuide { border-radius: 14px !important; }
  .ownRoute { padding: 16px !important; }
}

/* ---- owner 2026-10-08: Swipe on the phone - the whole card is readable (picture, guide, the trip, the numbers),
   the page scrolls instead of a tiny box inside the card, and Pass / Keep stay in reach at the bottom ---- */
.swStats { display: grid; grid-template-columns: repeat(auto-fit, minmax(90px, 1fr)); gap: 8px; margin: 10px 0 2px; }
.swStats span { background: #0d0f12; border: 1px solid var(--edge); border-radius: 12px; padding: 8px 10px; font-size: 14px; color: var(--mut); line-height: 1.2; display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.swStats b { color: #f4f2ec; font-size: 18px; font-weight: 700; }
@media (max-width: 600px) {
  #view-swipe .swHead { padding-top: 12px; gap: 10px; flex-wrap: wrap; }
  #view-swipe .swHead h2 { font-size: 20px; }
  #view-swipe .swHead p { font-size: 14px; }
  #view-swipe .swScope { margin-left: auto; }
  #view-swipe .swScope .scBtn { min-height: 40px; padding: 6px 12px; font-size: 14px; line-height: 1.15; }
  #view-swipe .swStack { height: auto !important; min-height: 0 !important; margin-top: 12px !important; margin-bottom: 0 !important; padding-bottom: 104px; perspective: none; }
  #view-swipe .swCard { display: none !important; }
  #view-swipe .swCard.top { display: flex !important; position: relative !important; inset: auto !important; height: auto !important; max-height: none !important; touch-action: pan-y !important; }
  #view-swipe .swCard.top .swMedia { height: 210px !important; flex: none !important; }
  #view-swipe .swCard.top .swInfo { max-height: none !important; overflow: visible !important; flex: none !important; }
  #view-swipe .swCard.top .csTeaser-swipe img { width: 84px !important; height: 84px !important; }
  /* the decision bar floats above the bottom menu, always reachable */
  #view-swipe .swBar { position: fixed !important; left: 0; right: 0; bottom: calc(59px + env(safe-area-inset-bottom)); z-index: 60; margin: 0 !important;
    padding: 18px 16px 10px; background: linear-gradient(180deg, rgba(11,12,14,0), rgba(11,12,14,.94) 40%); }
  #view-swipe .swBar .swBtn { width: 60px; height: 60px; }
  #view-swipe .swBar .swBtn.sm { width: 48px; height: 48px; }
}
@media (max-width: 600px) {
  /* on Swipe the back-to-top button sits above the decision bar, not on top of Undo */
  body:has(#view-swipe.on) #toTop { bottom: calc(150px + env(safe-area-inset-bottom)) !important; }
}
@media (max-width: 600px) {
  /* heritage tags under a place wrap instead of ending in "..." */
  .whTags i { white-space: normal !important; overflow: visible !important; text-overflow: clip !important; max-width: 100% !important; }
}

/* ---- owner 2026-10-08: avoid motorways / tolls, and the motorway / toll key on the Conditions map ---- */
.csAvoid { display: flex; flex-wrap: wrap; gap: 8px; width: 100%; margin: 6px 0 2px; }
.csAvoid button { min-height: 40px; padding: 6px 14px; border-radius: 12px; border: 1px solid var(--edge); background: #14161a; color: #e9e6df;
  font: 700 14px/1.1 var(--display); letter-spacing: .06em; text-transform: uppercase; cursor: pointer; }
.csAvoid button.on { background: #e11b2b; border-color: #e11b2b; color: #fff; }
.csAvoidNote { flex: 1 1 100%; margin: 4px 0 0; color: #c9c6bf; font-size: 14px; line-height: 1.45; }
.csRoadKey { display: flex; flex-wrap: wrap; gap: 8px 16px; width: 100%; margin-top: 6px; font-size: 14px; color: #e9e6df; }
.csRoadKey span { display: inline-flex; align-items: center; gap: 8px; }
.csRoadKey i { width: 22px; height: 6px; border-radius: 3px; display: inline-block; }
.csRoadKey i.toll { background: repeating-linear-gradient(90deg, #f2b134 0 8px, transparent 8px 13px); }
.csRoadKey .mut { color: #8d9199; }
@media (max-width: 600px) { .csAvoid { display: grid; grid-template-columns: 1fr 1fr; } .csAvoid button { min-height: 44px; } }
.csAvoid .csAvoidNote { grid-column: 1 / -1; }
@media (max-width: 600px) {
  /* the end-of-deck panel takes its own space in the scrolling page instead of floating over the header */
  #view-swipe .swDone { position: relative !important; inset: auto !important; padding: 28px 16px 24px; min-height: 0; }
}

/* ---- owner 2026-10-10: Trips - weekend planner and holiday planner ---- */
.tripWrap { max-width: 1180px; margin: 0 auto; padding: 18px 0 40px; }
.tripForm { background: linear-gradient(180deg, #16181d, #111316); border: 1px solid var(--edge); border-radius: 18px; padding: 20px 20px 16px; display: grid; gap: 14px; }
.tripH { margin: 0; font: 800 italic clamp(30px, 5vw, 46px)/1 var(--display); text-transform: uppercase; color: #fff; }
.tripLead { margin: -4px 0 4px; color: #c9c6bf; font-size: 16px; line-height: 1.5; max-width: 720px; }
.tripL { display: grid; gap: 8px; color: #e9e6df; font: 700 14px/1.2 var(--display); letter-spacing: .08em; text-transform: uppercase; }
.tripOpt { color: #8d9199; font-weight: 600; letter-spacing: .04em; }
.tripRow { display: flex; gap: 8px; flex-wrap: wrap; }
.tripRow input { flex: 1 1 180px; min-height: 46px; border-radius: 12px; border: 1px solid var(--edge); background: #0d0f12; color: #f4f2ec; padding: 0 14px; font: 500 16px/1.2 system-ui, sans-serif; text-transform: none; letter-spacing: 0; }
.tripRow .ghost2 { min-height: 46px; border-radius: 12px; }
.tripForm .chips { display: flex; flex-wrap: wrap; gap: 8px; }
.tripForm .chip { text-transform: none; letter-spacing: 0; font-size: 16px; }
.tripGo { min-height: 52px; border-radius: 14px; font-size: 18px; margin-top: 4px; }
.tripNote { color: #c9c6bf; font-size: 15px; line-height: 1.5; margin: 6px 0; text-transform: none; letter-spacing: 0; font-weight: 400; }
.tripFine { color: #8d9199; font-size: 14px; line-height: 1.5; margin: 10px 0 0; }
.tripWarn { background: rgba(242,177,52,.12); border: 1px solid rgba(242,177,52,.5); color: #f6d58b; border-radius: 12px; padding: 10px 14px; font-size: 15px; }
.tripEmpty { margin-top: 18px; background: #14161a; border: 1px solid var(--edge); border-radius: 16px; padding: 18px; }
.tripRes { margin-top: 22px; }
.tripH2 { margin: 0 0 6px; font: 800 italic clamp(26px, 4vw, 38px)/1 var(--display); text-transform: uppercase; color: #fff; }
.tripSum { color: #e9e6df; font-size: 16px; margin: 0 0 12px; }
.tripMap { height: 380px; border-radius: 16px; overflow: hidden; border: 1px solid var(--edge); background: #0d0f12; }
.tripPin { width: 24px; height: 24px; border-radius: 50%; color: #fff; font: 800 13px/24px var(--display); text-align: center; border: 2px solid #fff; }
.tripBed { width: 22px; height: 22px; border-radius: 6px; background: #15171b; border: 1.5px solid #fff; font-size: 13px; line-height: 20px; text-align: center; }
.tripDays { display: grid; gap: 12px; margin-top: 14px; }
.tripDay { background: #14161a; border: 1px solid var(--edge); border-radius: 16px; padding: 16px; }
.tripDayHead { display: flex; gap: 12px; align-items: flex-start; }
.tripNum { flex: none; width: 36px; height: 36px; border-radius: 50%; color: #fff; font: 800 18px/36px var(--display); text-align: center; }
.tripDay h3 { margin: 0; font: 700 20px/1.15 var(--display); color: #fff; }
.tripDate { display: block; color: #ff6a4d; font-size: 14px; letter-spacing: .08em; text-transform: uppercase; margin-bottom: 2px; }
.tripMeta { margin: 6px 0 0; color: #c9c6bf; font-size: 15px; }
.tripMeta b { color: #f4f2ec; }
.tripSl { color: #e2e0da; font-size: 16px; line-height: 1.5; margin: 10px 0 0; }
.tripRoads { margin: 10px 0 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: 8px; }
.tripRoads li { background: #0d0f12; border: 1px solid #2a2e36; border-radius: 999px; padding: 6px 12px; font-size: 14px; color: #c9c6bf; }
.tripRoads b { color: #ffd23f; }
.tripWhy, .tripApp { color: #a9a69d; font-size: 15px; line-height: 1.5; margin: 8px 0 0; }
.tripBtns { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 12px; }
.tripBtns .ghost2 { min-height: 44px; border-radius: 12px; display: inline-flex; align-items: center; justify-content: center; text-decoration: none; font-size: 15px; padding: 6px 10px; text-align: center; }
.tripAlt { margin-top: 10px; display: grid; gap: 8px; }
.tripAltBtn { text-align: left; background: #0d0f12; border: 1px solid var(--edge); color: #f4f2ec; border-radius: 12px; padding: 10px 12px; cursor: pointer; display: grid; gap: 2px; font-size: 16px; }
.tripAltBtn span { color: #a9a69d; font-size: 14px; }
.tripStay { margin-top: 12px; border-top: 1px solid #23262d; padding-top: 10px; }
.tripStay summary { cursor: pointer; color: #e9e6df; font: 700 15px/1.3 var(--display); letter-spacing: .04em; text-transform: uppercase; min-height: 32px; }
.tripStay h4 { margin: 10px 0 4px; font: 700 14px/1.2 var(--display); text-transform: uppercase; letter-spacing: .08em; color: #8d9199; }
.tripList { margin: 0; padding-left: 18px; display: grid; gap: 6px; color: #e2e0da; font-size: 15px; }
.tripK { color: #8d9199; font-size: 14px; }
.tripList a, .tripNote a { color: #ff6a4d; }
.tripActs { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.tripActs .primary, .tripActs .ghost2 { min-height: 48px; border-radius: 12px; padding: 0 18px; }
@media (min-width: 980px) {
  .tripRes { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 0 18px; align-items: start; }
  .tripRes > .tripH2, .tripRes > .tripSum, .tripRes > .tripWarn, .tripRes > .tripActs, .tripRes > .tripFine { grid-column: 1 / -1; }
  .tripMap { position: sticky; top: 80px; height: 620px; }
  .tripDays { margin-top: 0; }
}
@media (max-width: 600px) {
  .tripWrap { padding-top: 10px; }
  .tripForm { padding: 16px 14px; border-radius: 16px; }
  .tripMap { height: 300px; }
  .tripBtns { grid-template-columns: 1fr 1fr; }
  .tripBtns .ghost2:first-child { grid-column: 1 / -1; }
  .tripActs .primary, .tripActs .ghost2 { flex: 1 1 100%; }
}
.tripBtns .ghost2, .tripActs .ghost2, #tripGeo { border: 1px solid var(--edge) !important; background: #14161a !important; color: #e9e6df !important; font: 700 15px/1.1 var(--display); letter-spacing: .06em; text-transform: uppercase; cursor: pointer; }
.tripBtns .ghost2:hover, .tripActs .ghost2:hover { border-color: #e11b2b !important; }
#tripGeo { padding: 0 16px; }

/* ---- owner 2026-10-10: Trips, second step - trip at a glance, day ribbon, Play trip, night choice, saved trips ---- */
.tripStats { display: grid; grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); gap: 8px; margin: 4px 0 12px; }
.tripStat { background: #14161a; border: 1px solid var(--edge); border-radius: 14px; padding: 10px 12px; display: grid; gap: 2px; min-width: 0; }
.tripStat b { font-family: var(--display) !important; font-weight: 800 !important; font-style: italic; font-size: 26px !important; line-height: 1.05 !important; color: #fff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tripStat span { color: #a9a69d; font-size: 14px; }
.tripRibbon { display: flex; gap: 6px; margin: 0 0 12px; }
.tripSeg { flex: 1 1 0; min-width: 0; background: #14161a; border: 1px solid var(--edge); border-radius: 12px; padding: 8px 10px 9px; color: #e9e6df; text-align: left; cursor: pointer; display: grid; gap: 4px; font: inherit; }
.tripSeg:hover { border-color: var(--c); }
.tripSeg.on { border-color: var(--c); background: #1b1e24; }
.tripSegBar { display: block; height: 6px; border-radius: 3px; background: color-mix(in srgb, var(--c) 30%, #0d0f12); overflow: hidden; }
.tripSegFill { display: block; height: 100%; width: 0; background: var(--c); border-radius: 3px; }
.tripSeg.on .tripSegFill { width: 100%; }
.tripSegT { font: 700 14px/1.15 var(--display); letter-spacing: .05em; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tripSegK { color: #a9a69d; font-size: 14px; white-space: nowrap; }
.tripMapWrap { position: relative; }
.tripCap[hidden] { display: none; }
.tripMove .chip .tripK { margin-left: 6px; }
.tripPlay { position: absolute; z-index: 500; right: 10px; top: 10px; min-height: 44px; padding: 0 16px; border-radius: 999px; border: 1px solid rgba(255,255,255,.35); background: #e11b2b; color: #fff; font: 800 15px/1 var(--display); letter-spacing: .08em; text-transform: uppercase; cursor: pointer; }
.tripPlay.on { background: #15171b; }
.tripCap { position: absolute; z-index: 500; left: 10px; right: 10px; bottom: 10px; display: flex; gap: 10px; align-items: center; background: rgba(12,13,16,.92); border: 1px solid #2a2e36; border-radius: 14px; padding: 10px 12px; pointer-events: none; }
.tripCapN { flex: none; width: 30px; height: 30px; border-radius: 50%; color: #fff; font: 800 16px/30px var(--display); text-align: center; }
.tripCapT { display: grid; gap: 2px; min-width: 0; }
.tripCapT b { color: #fff; font: 700 16px/1.2 var(--display); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tripCapT span { color: #c9c6bf; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tripBike { width: 30px; height: 30px; border-radius: 50%; background: #15171b; border: 2.5px solid #fff; font-size: 16px; line-height: 25px; text-align: center; }
.tripNum { cursor: pointer; }
.tripDay.focus { border-color: #4a505b; }
.tripMove { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin: 8px 0 4px; }
.tripMove .chip { text-transform: none; letter-spacing: 0; font-size: 15px; min-height: 36px; }
.tripSaved { border-top: 1px solid #23262d; padding-top: 12px; display: grid; gap: 8px; }
.tripSavedList { display: flex; flex-wrap: wrap; gap: 8px; }
.tripSavedItem { display: inline-flex; align-items: center; background: #0d0f12; border: 1px solid var(--edge); border-radius: 999px; padding-left: 14px; min-height: 40px; }
.tripSavedItem a { color: #f4f2ec; text-decoration: none; font-size: 15px; }
.tripSavedX { background: none; border: 0; color: #8d9199; font-size: 20px; width: 40px; height: 40px; cursor: pointer; }
@media (min-width: 980px) {
  .tripRes > .tripStats, .tripRes > .tripRibbon { grid-column: 1 / -1; }
  .tripMap { position: relative; top: auto; }
  .tripMapWrap { position: sticky; top: 80px; }
}
@media (max-width: 600px) {
  .tripStats { display: flex; flex-wrap: wrap; gap: 6px; }
  .tripStat { flex: 1 1 calc(33.333% - 6px); }
  .tripStats[data-n="4"] .tripStat { flex-basis: calc(50% - 6px); }
  .tripStat { padding: 8px 9px; }
  .tripStat b { font-size: 20px !important; }
  .tripRibbon { overflow-x: auto; scrollbar-width: none; padding-bottom: 2px; }
  .tripRibbon::-webkit-scrollbar { display: none; }
  .tripSeg { min-width: 92px; }
  .tripPlay { right: 8px; top: 8px; min-height: 40px; padding: 0 14px; font-size: 14px; }
  .tripCap { left: 8px; right: 8px; bottom: 8px; padding: 8px 10px; }
}
@media (prefers-reduced-motion: reduce) { .tripSegFill { transition: none; } }

/* ---- owner 2026-10-10: Trips, third step - first-time-rider fixes ---- */
.tripL[hidden] { display: none !important; }
.tripGo { background: #e11b2b !important; color: #fff !important; border: 0 !important; font-family: var(--display) !important; font-weight: 800 !important; font-size: 18px !important; letter-spacing: .08em; text-transform: uppercase; cursor: pointer; }
.tripGo:hover { background: #c8121f !important; }
.tripOpt { text-transform: none; letter-spacing: 0; font-weight: 500; font-family: system-ui, sans-serif; font-size: 14px; color: #8d9199; }
.tripDates { flex-wrap: nowrap; }
.tripDL { flex: 1 1 0; min-width: 0; display: grid; gap: 4px; color: #a9a69d; font: 600 14px/1.2 system-ui, sans-serif; text-transform: none; letter-spacing: 0; }
.tripDL input { width: 100%; min-width: 0; box-sizing: border-box; }
.tripWith { margin: 0; display: flex; flex-wrap: wrap; gap: 6px 10px; align-items: center; background: #0d0f12; border: 1px solid var(--edge); border-radius: 12px; padding: 10px 12px; color: #e9e6df; font-size: 15px; }
.tripWithX { background: none; border: 0; color: #ff6a4d; font-size: 15px; cursor: pointer; min-height: 32px; padding: 0 4px; }
.tripNear { display: grid; gap: 8px; margin: 10px 0; }
.footWeek { background: none; border: 0; padding: 0; color: inherit; font: inherit; cursor: pointer; text-align: left; text-decoration: underline; text-underline-offset: 3px; }
.tripActs .primary { background: #e11b2b !important; color: #fff !important; border: 0 !important; font-family: var(--display) !important; font-weight: 800 !important; font-size: 15px !important; letter-spacing: .06em; text-transform: uppercase; cursor: pointer; }
.tripActs .primary:hover { background: #c8121f !important; }
/* the trip button takes its own full row on the ride page, so star and share still pair up */
.actionBar #tripWithA { grid-column: 1 / -1 !important; text-decoration: none; display: flex; align-items: center; justify-content: center; }
/* desktop: the "take it with you" row fills its twelve columns - GPX 4, GeoJSON 2, Google Maps 4, star 1, share 1 -
   so share no longer drops to a row of its own (it did since GeoJSON joined the row) */
@media (min-width: 641px) {
  .actionBar .actGroup #gpxBtn { grid-column: span 4 !important; }
  .actionBar .actGroup #geojsonBtn { grid-column: span 2 !important; }
  .actionBar .actGroup #gmapA { grid-column: span 4 !important; }
  .actionBar .actGroup #favBtn, .actionBar .actGroup #shareBtn { grid-column: span 1 !important; }
}
.tripSeason { margin: 8px 0 0; color: #f6d58b; font-size: 15px; line-height: 1.5; }
.tripWarnBtn { margin-left: 6px; background: #14161a; border: 1px solid rgba(242,177,52,.6); color: #f6d58b; border-radius: 999px; padding: 4px 12px; min-height: 34px; font: 600 14px/1.1 system-ui, sans-serif; cursor: pointer; }
.tripLinkBox { margin-top: 10px; display: grid; gap: 6px; }
.tripLinkBox input { min-height: 44px; border-radius: 12px; border: 1px solid var(--edge); background: #0d0f12; color: #f4f2ec; padding: 0 12px; font-size: 15px; width: 100%; box-sizing: border-box; }
/* owner 2026-10-12: a photograph per day, and the email composer with the trip picture */
.tripPic { margin: 10px 0 4px; border-radius: 12px; overflow: hidden; background: #0d0f12; }
.tripPic img { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }
.tripPic figcaption { font-size: 12px; color: #8f8b84; padding: 6px 10px; line-height: 1.35; }
.tripPic figcaption a { color: #b9b5ad; }
body.tmbOpen { overflow: hidden; }
.tripMailBox { position: fixed; inset: 0; z-index: 3000; background: rgba(5,6,8,.78); display: flex; align-items: flex-start; justify-content: center; overflow-y: auto; padding: 24px 12px; box-sizing: border-box; }
.tripMailBox[hidden] { display: none; }
.tmbIn { position: relative; width: min(560px, 100%); background: #14161a; border: 1px solid var(--edge); border-radius: 18px; padding: 20px 18px 16px; box-sizing: border-box; }
.tmbIn h3 { margin: 0 40px 6px 0; font-size: 22px; }
.tmbLead { margin: 0 0 12px; color: #c9c5bd; font-size: 15px; }
.tmbX { position: absolute; top: 10px; right: 10px; width: 44px; height: 44px; border-radius: 22px; border: 1px solid var(--edge); background: #0d0f12; color: #fff; font-size: 24px; line-height: 1; cursor: pointer; }
.tmbPrev { border-radius: 12px; overflow: hidden; background: #0d0f12; min-height: 120px; display: grid; place-items: center; }
.tmbPrev img { display: block; width: 100%; height: auto; }
.tmbWait { color: #9a968e; font-size: 14px; padding: 24px; text-align: center; }
.tmbActs { display: grid; gap: 8px; margin-top: 14px; }
.tmbActs > * { min-height: 48px; border-radius: 12px; padding: 0 18px; display: flex; align-items: center; justify-content: center; text-align: center; box-sizing: border-box; text-decoration: none; }
.tmbActs .primary { background: #e11b2b; color: #fff; border: 0; font-weight: 700; }
.tmbActs .ghost2 { background: transparent; border: 1px solid var(--edge); color: #f4f2ec; }
.tmbFine { margin: 12px 0 0; text-align: center; font-size: 14px; }
.tmbFine a { color: #b9b5ad; }
/* the email composer is a full-screen overlay: on a phone it starts at the top with a small margin */
@media(max-width:767px){
.tripMailBox { padding: 10px 8px; }
.tmbIn { padding: 16px 12px 12px; }
}
@media (max-width: 600px) {
  .tripSeg { min-width: 0; padding: 7px 8px 8px; }
  .tripRibbon[data-n="6"] .tripSegK, .tripRibbon[data-n="7"] .tripSegK, .tripRibbon[data-n="8"] .tripSegK, .tripRibbon[data-n="9"] .tripSegK, .tripRibbon[data-n="10"] .tripSegK { display: none; }
  .tripRibbon { overflow-x: visible; }
}
@media (max-width: 370px) { .tripDL input { font-size: 14px !important; padding: 0 6px !important; } }
/* the sticky map lives in its own block with the day cards, so it stops before Share / GPX / Save and the small print */
@media (min-width: 980px) {
  .tripRes { display: block !important; }
  .tripBody { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 0 18px; align-items: start; margin-top: 2px; }
  .tripBody .tripDays { margin-top: 0; }
}
/* eight days and more on a phone: the ribbon takes two rows instead of shrinking the labels away */
@media (max-width: 600px) {
  .tripRibbon[data-n="8"], .tripRibbon[data-n="9"], .tripRibbon[data-n="10"] { flex-wrap: wrap; }
  .tripRibbon[data-n="8"] .tripSeg, .tripRibbon[data-n="9"] .tripSeg, .tripRibbon[data-n="10"] .tripSeg { flex: 1 1 calc(20% - 6px) !important; }
  .tripRibbon[data-n="8"] .tripSegK, .tripRibbon[data-n="9"] .tripSegK, .tripRibbon[data-n="10"] .tripSegK { display: block; }
}
/* phones: every day gets the same width in the ribbon, so "149 km" is never cut (length by distance stays on desktop) */
@media (max-width: 600px) { .tripRibbon .tripSeg { flex: 1 1 0 !important; } }
/* ---- owner 2026-10-10: road status on each planned day, email a trip ---- */
.tripRoadSt { margin: 8px 0 0; font-size: 14px; color: #a9a69d; }
.tripRoadSt.ok { color: #7fd6a3; }
.tripRoadSt.bad { color: #f6d58b; }
.tripRetry { margin-left: 6px; background: #14161a; border: 1px solid rgba(242,177,52,.6); color: #f6d58b; border-radius: 999px; padding: 3px 12px; min-height: 32px; font: 600 14px/1.1 system-ui, sans-serif; cursor: pointer; }
.tripActs #tripMail { display: inline-flex; align-items: center; justify-content: center; text-decoration: none; }
/* the road is not loaded: said on the map, with a way to try again */
.csRoadBan { position: static; margin: 0 0 10px; background: rgba(12,13,16,.94); border: 1px solid rgba(242,177,52,.6); color: #f6d58b; border-radius: 12px; padding: 10px 12px; font-size: 15px; line-height: 1.4; }
.csRoadBan b { color: #fff; }
.csRoadBan button { margin-left: 6px; background: #e11b2b; color: #fff; border: 0; border-radius: 999px; padding: 4px 12px; min-height: 32px; font: 700 14px/1 var(--display); letter-spacing: .06em; text-transform: uppercase; cursor: pointer; }
/* ride page: jump to the briefing and the roadbook (they sat far down a phone page) */
.jumpRow { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 4px; }
.jumpRow a, .jumpRow button { cursor: pointer; font-family: inherit; display: inline-flex; align-items: center; min-height: 40px; padding: 0 14px; border-radius: 999px; border: 1px solid var(--edge); background: #14161a; color: #e9e6df; text-decoration: none; font-size: 16px !important; }
.jumpRow a:hover, .jumpRow button:hover { border-color: #e11b2b; }
.savedTrips a { color: #ff6a4d; }
/* legal tables never push the page sideways on a phone (QA 2026-10-10) */
.lgTable { display: block; overflow-x: auto; max-width: 100%; }
.lgTable td, .lgTable th { overflow-wrap: anywhere; }
/* the map legend's one-line summary stays on one line on a phone (it wrapped into "mostly / straight - / · 93") */
.lgdToggle { display: flex !important; align-items: center; gap: 6px; flex-wrap: nowrap; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.lgdToggle b { overflow: hidden; text-overflow: ellipsis; }
.lgdToggle .lgdMore { margin-left: auto; flex: none; }

/* ---- 2026-10-11 first-time-user audit: Saved is its own page ---- */
body.savedMode #filterBar, body.savedMode .sortRow, body.savedMode #pvFilter, body.savedMode #swTeaser,
body.savedMode .boardPicks, body.savedMode .ownFold, body.savedMode #ownRoute, body.savedMode .boardSwipe { display: none !important; }
.savedTripList { display: flex; flex-direction: column; gap: 8px; margin: 12px 0 4px; }
.savedTripRow { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 48px; padding: 10px 14px;
  border: 1px solid var(--line, #2a2d33); border-radius: 12px; background: var(--card, #15171b); color: var(--ink, #f2efe8); text-decoration: none; }
.savedTripRow b { font-weight: 600; }
.savedTripRow span { color: var(--red, #e11b2b); font-size: 14px; white-space: nowrap; }
.emptyGo { display: inline-block; margin-top: 10px; min-height: 44px; line-height: 44px; }
/* the phone's one-line board picks: label and road kept apart */
.boardPicks { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; }
.boardPicks .bpItem { display: inline; }
.boardPicks .bpItem b { margin-right: 4px; }
/* audit 2026-10-11: the decision bar's fade let card text show through behind the buttons */
@media (max-width: 767px) {
  #view-swipe .swBar { background: linear-gradient(180deg, rgba(11,12,14,0), rgba(11,12,14,.98) 34%) !important; }
  #view-swipe .swBar.swBarDone { background: none !important; pointer-events: none; }
  #view-swipe .swBar.swBarDone .swBtn { pointer-events: auto; }
  /* the view switch (Cards / Atlas map / Swipe) repeats the bottom bar on a phone */
  #viewModes { display: none !important; }
}
/* ---- audit 2026-10-11: ONE landing page ----
   The photo welcome is the start page. "Find a ride" then opened a second full-screen landing ("We scout the
   curves", a glowing button) before the search. Behind the welcome, the home view is the search: a short
   heading and the form in the first screen. Nothing glows. */
body:not(.csWelcome) #view-home .hero { min-height: 0 !important; }
body:not(.csWelcome) #view-home .heroIn { min-height: 0 !important; padding: 26px 20px 10px !important; }
body:not(.csWelcome) #view-home .heroIn .big,
body:not(.csWelcome) #view-home .heroIn .tag,
body:not(.csWelcome) #view-home .heroWhy,
body:not(.csWelcome) #view-home .heroScroll,
body:not(.csWelcome) #view-home .heroDots,
body:not(.csWelcome) #view-home .heroCred { display: none !important; }
body:not(.csWelcome) #view-home .heroIn h1 { font-size: clamp(30px, 8vw, 46px) !important; margin: 0 0 8px !important; }
body:not(.csWelcome) #view-home .heroSub { margin: 0 0 14px !important; }
.heroCta .primary { box-shadow: none !important; }
.heroCta .primary:after { display: none !important; }
/* audit 2026-10-11: nothing glows - the hovered roadbook stop and the focus dot are marked by a ring, not a halo */
.leaflet-marker-icon.pulse { filter: brightness(1.2) !important; outline: 3px solid #ffd43b; outline-offset: 2px; border-radius: 50%; }
.miFocus { animation: none !important; box-shadow: 0 0 0 3px #0b0c0e, 0 0 0 5px #ffe066 !important; }
.exMoreRow { grid-column: 1 / -1; display: flex; justify-content: center; padding: 18px 0 8px; }
.exMore { min-height: 48px; padding: 0 26px; border-radius: 99px; border: 1px solid var(--edge2, #31363f); background: #12151a; color: var(--ink, #f4f2ec);
  font-family: var(--display); font-weight: 700; letter-spacing: .04em; text-transform: uppercase; }
#cmpClear { min-height: 40px; padding: 0 16px; border-radius: 99px; border: 1px solid var(--edge2, #31363f); background: transparent; color: var(--ink, #f4f2ec); font: inherit; cursor: pointer; }
/* audit 2026-10-11: on a phone the Atlas legend stood 288 px tall and left ~170 px of map. One line of keys;
   the explanation sits behind "What the lines mean". The "← Board" button repeats the bottom bar. */
@media (max-width: 767px) {
  #view-atlas .atlasLegend { display: flex !important; flex-wrap: nowrap !important; overflow-x: auto; gap: 14px !important; padding: 6px 2px !important;
    font-size: 14px !important; white-space: nowrap; scrollbar-width: none; }
  #view-atlas .atlasLegend::-webkit-scrollbar { display: none; }
  #view-atlas .atlasLegend .lgNote { display: none !important; }
  #view-atlas .atlasLegend.open .lgNote { display: block !important; white-space: normal; flex: 0 0 100%; }
  #view-atlas .atlasLegend.open { flex-wrap: wrap !important; }
  #view-atlas #atlasBack { display: none !important; }
  #view-atlas .atlasMap { height: calc(100svh - 230px) !important; min-height: 360px; }
}
.atlasLegend .lgMoreBtn { background: none; border: 0; color: var(--mut, #a9a69d); text-decoration: underline; font: inherit; cursor: pointer; padding: 0; min-height: 32px; }
@media (min-width: 768px) { .atlasLegend .lgMoreBtn { display: none; } }
/* audit 2026-10-11: on a tablet (768-1100 px) the header ran out of room - "NEW SEARCH" was cut off and the logo read
   "CURVESC…". The brand never shrinks; the destinations scroll sideways when they do not fit, and "New search"
   (also reachable from the board) steps aside first. */
@media (min-width: 768px) and (max-width: 1100px) {
  header .word { flex: 0 0 auto !important; white-space: nowrap; }
  header .navScroll { display: flex !important; flex: 1 1 auto; min-width: 0; overflow-x: auto; scrollbar-width: none; gap: 6px; justify-content: flex-end; }
  header .navScroll::-webkit-scrollbar { display: none; }
  header .navScroll .tbtn { flex: 0 0 auto; padding-left: 12px; padding-right: 12px; }
  header #newSearchBtn { display: none !important; }
  header .spacer { flex: 0 0 8px !important; }
}
#buildBadge.inFoot { position: static !important; display: inline-block !important; width: auto !important; height: auto !important; margin: 10px 0 0;
  color: #8f8c84 !important; background: none !important; border: 0 !important; padding: 0 !important; opacity: 1 !important; font-size: 14px !important; }
/* ---- audit 2026-10-11: a phone card was 1,000-1,270 px tall ----
   The owner's rule stands: no text is cut short (tools/audit-mobile-layout.mjs), so the guide's note keeps every word.
   The card is shortened around it: a lower picture, a smaller portrait, chips that share lines. */
@media (max-width: 767px) {
  #rideList .ride .rideHero { max-height: 190px; }
  #rideList .ride .csTeaser { gap: 10px; padding: 8px 10px; }
  #rideList .ride .csTeaser img { width: 44px !important; height: 44px !important; }
}
.welcomeBack[hidden] { display: none !important; }
body:not(.csWelcome) #view-home .heroIn h1 .l1, body:not(.csWelcome) #view-home .heroIn h1 .l2 { font-size: clamp(26px, 7vw, 44px) !important; line-height: 1.05; }
@media (max-width: 767px) { #rideList .ride .why { display: flex; flex-wrap: wrap; gap: 6px; } #rideList .ride .why > span { margin: 0 !important; } }
/* audit 2026-10-11 re-check */
.swBtn[hidden] { display: none !important; }
body.savedMode #editSearch, body.savedMode #viewModes { display: none !important; }
body:not(.csWelcome) #view-home .heroIn h1 b { font-size: inherit !important; }
@media (max-width: 767px) {
  #view-atlas .atlasLegend .lgMoreBtn { order: -1; flex: 0 0 auto; }
  #view-atlas .atlasMap { margin-bottom: 70px; }
}

/* ---- About: the founder interview (owner 2026-10-11) ---- */
#view-about .abWrap { max-width: 720px; margin: 0 auto; padding: 28px 16px 56px; color: var(--ink, #f4f2ec); }
#view-about .abKicker { margin: 0 0 10px; color: var(--red-hot, #ff4d57); font-family: var(--display); font-weight: 700; letter-spacing: .12em; text-transform: uppercase; font-size: 14px; }
#view-about .abTitle { margin: 0 0 14px; font-family: var(--display); font-size: clamp(30px, 6.4vw, 48px); line-height: 1.06; letter-spacing: -.01em; text-transform: none; }
#view-about .abStand { margin: 0 0 22px; font-size: 19px; line-height: 1.5; color: var(--mut, #a9a69d); }
#view-about .abIntro { margin: 0 0 16px; font-size: 17px; line-height: 1.7; }
#view-about .abIntro:first-of-type::first-letter { float: left; font-family: var(--display); font-size: 58px; line-height: .9; padding: 6px 10px 0 0; color: var(--red-hot, #ff4d57); }
#view-about .abQ { margin: 34px 0 10px; font-family: var(--display); font-size: 21px; line-height: 1.3; letter-spacing: .01em; text-transform: none; color: #fff; padding-left: 14px; border-left: 3px solid var(--red, #e11b2b); }
#view-about .abA { margin: 0 0 14px; font-size: 17px; line-height: 1.72; color: #dcd9d1; }
#view-about .abA a { color: var(--ink, #f4f2ec); text-decoration: underline; text-underline-offset: 3px; }
#view-about .abFig { margin: 30px -16px; }
#view-about .abFig img { display: block; width: 100%; height: auto; background: #12151a; }
#view-about .abFig figcaption { padding: 10px 16px 0; font-size: 14px; line-height: 1.5; color: var(--mut, #a9a69d); }
#view-about .abFig2 img { max-height: 78vh; width: auto; max-width: 100%; margin: 0 auto; object-fit: contain; }
@media (min-width: 1100px) {
  #view-about .abWrap { padding-top: 44px; }
  #view-about .abFig { margin: 38px -90px; }
  #view-about .abFig img { border-radius: 14px; }
  #view-about .abFig figcaption { padding-left: 0; padding-right: 0; }
  #view-about .abFig2 { float: right; width: 300px; margin: 6px -110px 18px 28px; }
  #view-about .abFig2 img { max-height: none; width: 100%; }
}
#view-about .abEnd { clear: both; margin-top: 40px; padding: 22px 18px; border: 1px solid var(--edge, #262a31); border-radius: 14px; background: #12151a; }
#view-about .abEnd p { margin: 0 0 14px; font-size: 17px; line-height: 1.6; }
#view-about .abCta { display: flex; flex-wrap: wrap; gap: 10px; }
#view-about .abCta a { display: inline-flex; align-items: center; min-height: 48px; padding: 0 20px; border-radius: 99px; font-family: var(--display); font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase; font-size: 15px; text-decoration: none; }
#view-about .abGo { background: var(--red, #e11b2b); color: #fff; }
#view-about .abAlt { border: 1px solid var(--edge2, #31363f); color: var(--ink, #f4f2ec); }
.csHeroAbout { display: inline-block; margin-top: 14px; min-height: 44px; line-height: 44px; color: #f4f2ec; font-size: 16px; text-decoration: underline; text-underline-offset: 4px; opacity: .92; }

/* ---- owner 2026-10-12: the phone has three tabs; Rides switches between List, Map and Swipe ---- */
.mModes{display:none}
@media(max-width:767px){
  .mModes:not([hidden]){display:flex;gap:6px;margin:10px 14px 0;padding:4px;background:var(--card);border:1px solid var(--edge);border-radius:999px}
  .mmBtn{flex:1 1 0;min-height:44px;border:0;border-radius:999px;background:none;color:var(--mut);font-family:var(--display);text-transform:uppercase;letter-spacing:.04em;font-size:15px}
  .mmBtn.on{background:var(--red);color:#fff}
  .exChips{display:flex;gap:8px;overflow-x:auto;padding:2px 0 8px;scrollbar-width:thin}
  .exChips .chip{flex:0 0 auto;min-height:44px}
  .exSortRow{display:flex;align-items:center;gap:10px;margin:4px 0 10px}
  .exSortRow select{min-height:44px;flex:1 1 auto}
  .exPicks{margin:0 0 12px}
  #view-explore .ownFold{margin:16px 0}
}
@media(max-width:767px){
  #exFilters details.exMore{grid-column:1/-1}
  #exFilters details.exMore summary{min-height:44px;display:flex;align-items:center;color:var(--mut);cursor:pointer}
  #exFilters details.exMore[open]{display:grid;grid-template-columns:1fr 1fr;gap:8px}
  #exFilters details.exMore[open] summary{grid-column:1/-1}
  #exFilters details.exMore select,#exFilters details.exMore button{min-height:44px}
}
/* audit: the Maps / Street View / OSM / Weather link rows were under the 44 px tap minimum on a phone */
@media(max-width:767px){
  .wpLinks a,.atrLinks a,.svcLinks a{min-height:44px;display:inline-flex;align-items:center;padding:0 12px;box-sizing:border-box}
  .wpLinks,.atrLinks,.svcLinks{display:flex;flex-wrap:wrap;gap:8px}
}
/* the phone's Rides list is the board now, so its card titles follow the 16 px core text rule (R21) */
@media(max-width:767px){ .exTop h3{font-size:17px} }
@media(max-width:767px){ #view-explore details > summary{font-size:16px} }
.mapNote[hidden]{display:none !important}

/* ================= r22 (owner 2026-10-13) =================
   Pins instead of chords, trips A to B with transfers, place suggestions, What's here at every stop,
   the phone atlas card below the map, and My Road Atlas. Type floor: 16 px core, 14 px secondary. */
.lgPin{display:inline-block;width:11px;height:11px;border-radius:50%;background:#ffa62b;border:2px solid #0b0c0e;box-shadow:0 0 0 1px #9aa4b2;vertical-align:middle;margin-right:4px}
.lgRid{background:#ffd166}.lgWant{background:#6cb8ff}
/* place suggestions */
.csSug{position:absolute;left:0;right:0;top:100%;z-index:60;margin:4px 0 0;padding:4px;list-style:none;background:#14161a;border:1px solid var(--edge2);border-radius:12px;box-shadow:0 12px 30px rgba(0,0,0,.45);max-height:min(60vh,380px);overflow:auto}
.csSugRow{display:flex;align-items:center;gap:10px;padding:9px 10px;border-radius:9px;cursor:pointer;min-height:44px}
.csSugRow:hover,.csSugRow.on{background:#22262d}
.csSugF{font-size:20px;line-height:1;flex:0 0 auto}
.csSugT{display:flex;flex-direction:column;min-width:0}
.csSugT b{font-size:16px;color:var(--ink);font-weight:600}
.csSugT small{font-size:14px;color:var(--mut);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.csSugNote,.csSugCredit{padding:8px 10px;font-size:14px;color:var(--mut)}
.csSugCredit{font-size:14px;color:var(--dim);border-top:1px solid var(--edge);margin-top:4px}
/* trips: kinds, schedule, destination */
.tripKind .chip{font-size:16px}
.tripKindHelp{margin:6px 0 0;font-size:14px;color:var(--mut);max-width:60ch}
.tripSched{list-style:none;margin:10px 0;padding:0 0 0 2px;border-left:2px solid var(--edge2)}
.tripSched li{display:flex;gap:10px;align-items:baseline;padding:5px 0 5px 12px;position:relative;font-size:16px;line-height:1.4}
.tripSched li::before{content:'';position:absolute;left:-6px;top:12px;width:10px;height:10px;border-radius:50%;background:#5f6875;border:2px solid var(--card)}
.tripSched li.tsR::before{background:var(--red)}.tripSched li.tsN::before{background:#ffd166}
.tripSched time{font-variant-numeric:tabular-nums;color:var(--mut);font-size:14px;min-width:44px}
.tripSched .tsKm{font-weight:600;color:var(--ink)}
.tripSched li.tsX span{color:#c9cdd3}
.tripDest{width:26px;height:26px;border-radius:50%;background:#0b0c0e;color:#ffd166;border:2px solid #ffd166;font:800 14px/22px var(--display);text-align:center}
/* What's here at every stop */
.wh{margin:10px 0 6px;padding:12px 14px;border:1px solid var(--edge);border-radius:12px;background:rgba(255,255,255,.025)}
.whLead{margin:0 0 8px;font-size:16px;color:var(--ink);font-weight:600}
.whList{list-style:none;margin:0;padding:0;display:grid;gap:6px}
.whList li{display:grid;grid-template-columns:24px 52px 1fr;gap:6px;align-items:baseline;font-size:16px;line-height:1.45}
.whIc{font-size:16px}.whK{font-size:14px;color:var(--mut);text-transform:uppercase;letter-spacing:.04em;font-family:var(--display)}
.whV{color:#d9dce1}.whV b{color:var(--ink);font-weight:600}.whV a{color:#7cc4ff}
.whWarn{color:#ffb35c}
@media(max-width:767px){.whList li{grid-template-columns:22px 1fr}.whK{grid-column:2}.whV{grid-column:2}}
/* the phone atlas card: below the map, short */
@media(max-width:767px){
  #view-atlas > .atHover{position:static;max-width:none;margin:10px 0 80px;pointer-events:auto;backdrop-filter:none;background:var(--card)}
  #view-atlas > .atHover b{font-size:17px}
  #view-atlas > .atHover span{font-size:14px}
  #view-atlas > .atHover em{font-size:14px}
}
/* My Road Atlas */
.raStrip{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin:10px 0 12px}
.raB{min-height:44px;padding:9px 14px;border-radius:999px;border:1px solid var(--edge2);background:#16191e;color:var(--ink);font-size:16px;cursor:pointer}
.raB.on{background:#2a2414;border-color:#ffd166;color:#ffd166}
.raB[data-ras="w"].on{background:#14212d;border-color:#6cb8ff;color:#9fd2ff}
.raB[data-raf].on{background:#2a1416;border-color:var(--red);color:#ff8a92}
.raSm .raB{font-size:14px;padding:7px 11px;min-height:40px}
.raLink{font-size:16px;color:#7cc4ff;margin-left:4px}
.raToast{position:fixed;left:50%;bottom:88px;transform:translate(-50%,30px);opacity:0;transition:opacity .25s,transform .25s;z-index:3000;background:#14161a;border:1px solid #ffd166;border-radius:999px;padding:10px 18px;box-shadow:0 10px 30px rgba(0,0,0,.5);pointer-events:none;max-width:calc(100vw - 32px)}
.raToast.on{opacity:1;transform:translate(-50%,0);pointer-events:auto}
.raToast a{color:#ffd166;font-size:16px;text-decoration:none}
.raSavedLink{display:flex;flex-direction:column;gap:2px;margin:0 0 10px;padding:12px 14px;border:1px solid #ffd166;border-radius:12px;background:#1c1a12;text-decoration:none}
.raSavedLink b{color:#ffd166;font-size:16px}.raSavedLink span{color:var(--mut);font-size:14px}
.raWrap{max-width:1040px;margin:0 auto;padding:18px 16px 110px}
.raWrap h2{font-family:var(--display);text-transform:uppercase;letter-spacing:.04em;font-size:22px;margin:26px 0 10px}
.raHead h1{font-family:var(--display);font-style:italic;text-transform:uppercase;font-size:44px;margin:2px 0 8px}
.raKick{margin:0;color:#ffd166;font-family:var(--display);text-transform:uppercase;letter-spacing:.08em;font-size:15px}
.raXp span{font-size:15px;color:var(--mut)}
.raXpBar,.raBar{height:10px;border-radius:99px;background:#22262d;overflow:hidden;margin:6px 0}
.raXpBar i,.raBar i{display:block;height:100%;background:linear-gradient(90deg,#e11b2b,#ffd166);border-radius:99px}
.raEmpty{font-size:16px;line-height:1.5;padding:14px;border:1px dashed var(--edge2);border-radius:12px;color:#d9dce1}
.raEmpty a{color:#7cc4ff}
.raTiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:10px}
.raTile{background:var(--card);border:1px solid var(--edge);border-radius:12px;padding:12px 14px}
.raTile b{display:block;font-family:var(--display);font-size:32px;color:var(--ink)}.raTile span{font-size:14px;color:var(--mut)}
.raFlags{font-size:28px;margin:12px 0 4px}
.raPassList{font-size:16px;line-height:1.5;color:#d9dce1}
.raCols{display:grid;grid-template-columns:repeat(auto-fill,minmax(290px,1fr));gap:12px}
.raCol{background:var(--card);border:1px solid var(--edge);border-radius:14px;padding:14px}
.raCol.done{border-color:#ffd166}
.raCol h3{margin:0 0 4px;font-family:var(--display);text-transform:uppercase;letter-spacing:.03em;font-size:19px}
.raCol p{margin:0 0 8px;font-size:14px;color:var(--mut)}
.raOf{font-size:14px;color:var(--mut)}
.raCol ul{list-style:none;margin:8px 0 0;padding:0;display:grid;gap:4px}
.raCol li{display:flex;align-items:center;gap:8px;font-size:16px;min-height:40px}
.raCol li span{width:18px;color:var(--dim)}.raCol li.r span{color:#ffd166}.raCol li.w span{color:#6cb8ff}
.raPassB{margin-left:auto;font-size:14px;background:none;border:1px solid var(--edge2);color:var(--mut);border-radius:999px;padding:6px 11px;min-height:36px;cursor:pointer}
.raBadges{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px}
.raBadge{background:var(--card);border:1px solid var(--edge);border-radius:12px;padding:12px;opacity:.55;filter:grayscale(1)}
.raBadge.got{opacity:1;filter:none;border-color:#5a4c22}
.raBadge i{display:block;font-style:normal;font-size:28px}.raBadge b{display:block;font-size:16px;margin:4px 0 2px}.raBadge span{font-size:14px;color:var(--mut)}
.raLists{display:grid;grid-template-columns:1fr 1fr;gap:16px}
@media(max-width:767px){.raLists{grid-template-columns:1fr}.raHead h1{font-size:36px}}
.raList{list-style:none;margin:0;padding:0;display:grid;gap:6px}
.raList a{display:flex;flex-direction:column;padding:10px 12px;border:1px solid var(--edge);border-radius:10px;background:var(--card);text-decoration:none;min-height:44px}
.raList b{color:var(--ink);font-size:16px}.raList span{color:var(--mut);font-size:14px}
.raMut{font-size:14px;color:var(--mut);line-height:1.5}
.raBtns{display:flex;flex-wrap:wrap;gap:8px}
.raCodeBox{display:block;width:100%;margin:8px 0;background:#0f1114;color:var(--ink);border:1px solid var(--edge2);border-radius:10px;padding:10px;font-size:14px;font-family:ui-monospace,monospace}
.raCardImg{display:block;max-width:360px;width:100%;border-radius:12px;margin:10px 0}
@media(max-width:767px){
.raToast{bottom:calc(76px + env(safe-area-inset-bottom,0px));max-width:calc(100vw - 32px);white-space:normal;text-align:center}
}
/* map UI cleanup (owner 2026-10-13: "clean up the map ui"): the legend explanation folds on every screen behind
   "What the lines mean", so the map starts right under the key */
#view-atlas .atlasLegend .lgNote{display:none}
#view-atlas .atlasLegend.open .lgNote{display:block;flex:0 0 100%;white-space:normal}
@media(min-width:768px){.atlasLegend .lgMoreBtn{display:inline-block}}
/* ---- trip day cards, rewritten (owner 2026-10-17: "clean and neat ... much more great text per waypoint ... less
   redundancies and crisper, especially on the mobile") ---- */
.tripDayT{min-width:0;flex:1}
.tripKick small{font-size:14px}
.tripKick{margin:0 0 2px;color:#a9a69d;font:700 14px/1.2 var(--display);letter-spacing:.08em;text-transform:uppercase}
.tripDay h3{overflow-wrap:anywhere}
.tripLead{color:#e2e0da;font-size:16px;line-height:1.5;margin:10px 0 0}
.tripPath{margin:8px 0 0;color:#ffd23f;font:700 15px/1.45 var(--display);overflow-wrap:anywhere}
.tripPath i{color:#6b7280;font-style:normal;margin:0 2px}
.tripPath small{color:#c9c6bf;font-weight:600;font-size:14px}
.tripBook{margin-top:12px;border-top:1px solid #23262d;padding-top:4px}
.tripBook>summary{cursor:pointer;list-style:none;display:flex;justify-content:space-between;align-items:center;gap:10px;min-height:44px;color:#f4f2ec}
.tripBook>summary::-webkit-details-marker{display:none}
.tripBook>summary .tbT{font:700 15px/1.2 var(--display);letter-spacing:.04em;text-transform:uppercase}
.tripBook>summary .tbT::before{content:'▸';display:inline-block;width:16px;color:#e11b2b;transition:transform .15s}
.tripBook[open]>summary .tbT::before{transform:rotate(90deg)}
.tripBook>summary .tbS{color:#a9a69d;font-size:14px;font-variant-numeric:tabular-nums;white-space:nowrap}
.tripSched li{align-items:flex-start}
.tripSched time{padding-top:1px}
.tripSched .tsB{min-width:0;flex:1}
.tripSched .tsH,.tripSched .tsT,.tripSched .tsTags,.tripSched .tsKmL{margin:0}
.tripSched .tsH{color:#f4f2ec;overflow-wrap:anywhere}
.tripSched .tsT{color:#c9c6bf;font-size:16px;line-height:1.5;margin-top:3px}
.tripSched .tsT b{color:#f4f2ec;font-weight:700}
.tripSched .tsI{display:inline-block;min-width:18px;color:#e11b2b;font-size:14px}
.tripSched .tsAlt{color:#ffd23f;font-weight:700;font-size:16px;white-space:nowrap}
.tripSched .tsMk{color:#8d9199;font-size:14px;white-space:nowrap}
.tripSched .tsTags{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}
.tripSched .tsTag{background:#0d0f12;border:1px solid #2a2e36;border-radius:999px;padding:3px 10px;font-size:14px;line-height:1.35;color:#d7d4cd;overflow-wrap:anywhere}
.tripSched .tsTag.warn{border-color:#6b5320;color:#f6d58b}
.tripSched .tsTag.meal{border-color:#2f5e45;color:#9ee0b9}
.tripSched .tsTag.ev{border-color:#5b2f63;color:#e5b8f0}
.tripSched li.tsW{padding-top:8px;padding-bottom:8px}
.tripSched li.tsW::before{background:#e11b2b}
.tripSched li.tsW.k-pass::before,.tripSched li.tsW.k-high::before{background:#ffd23f}
.tripSched .tsWait{color:#8d9199}
.tripRoads{margin:6px 0 0 14px;color:#a9a69d;font-size:14px;line-height:1.45}
.tripRoads b{color:#e9e6df}
.tripFineD{margin-top:12px;grid-column:1/-1}
.tripFineD>summary{cursor:pointer;color:#a9a69d;font-size:14px;min-height:32px}
@media (max-width:600px){
  .tripDay{padding:14px 12px}
  .tripDay h3{font-size:18px}
  .tripDayHead{gap:10px}
  .tripNum{width:30px;height:30px;line-height:30px;font-size:16px}
  .tripSched li{gap:8px;padding-left:10px}
  .tripSched time{min-width:42px}
  .tripBtns{grid-template-columns:repeat(3,1fr)!important}
  .tripBtns .ghost2:first-child{grid-column:auto!important}
  .tripBtns .ghost2{font-size:15px;padding:6px 4px;min-height:44px}
  .tripPic img{aspect-ratio:2/1}
}
.tripSched .tsWiki{margin:6px 0 0;color:#c9c6bf;font-size:16px;line-height:1.5;overflow:hidden}
.tripSched .tsWiki a{color:#f4f2ec;font-weight:700;text-decoration:underline;text-decoration-color:#4a505b;text-underline-offset:2px}
.tripSched .tsWiki .tsPic{float:right;width:84px;height:84px;object-fit:cover;border-radius:10px;margin:2px 0 4px 10px;background:#0d0f12}
.tripSched .tsWiki .tsSrc{color:#8d9199;font-size:14px}
.tripSched .tsNext{margin:6px 0 0;color:#8d9199}
.tripSched .tsNext small{font-size:14px}
@media (max-width:600px){
  .tripActs{display:grid!important;grid-template-columns:1fr 1fr;gap:8px}
  .tripActs>*{margin:0!important;width:auto!important;min-width:0;padding:0 8px!important}
  .tripActs #tripShare{grid-column:1/-1}
}
