/* coffeewalks
   Palette taken from an Old Barracks Roastery cup: deep slate navy and warm
   cream, thin cream line-art on navy, nothing else. Two colours carry the
   whole interface; the only other colour is a verdict - never decoration.
   Shape rule: surfaces 16, controls 12, chips and pills full round. */

:root{
  /* the cup: cream ground, navy ink.
     Four tones of cream carry depth, in the order the eye reads it:
     --sunk is pressed into a surface, --card is the surface, --raise sits
     on it, --paper is the ground everything floats over. Nothing is
     outlined to say where it ends; the tone and the shadow say it. */
  --paper:#E6DECD;
  --card:#F8F4EC;
  --raise:#FDFBF6;
  --sunk:#ECE5D7;
  --ink:#1E2833;
  --ink-2:#3A4653;
  --muted:#55626D;        /* 5.1:1 on the card, 4.7:1 on the paper */
  --faint:#7E8993;        /* icons and 12px+ decoration only */
  --line:#E3DCCC;
  --rule:#D6CDBA;
  --line-2:#EAE3D5;
  --hot:#D9A441;          /* muted gold, not a highlighter */
  --hot-soft:rgba(217,164,65,.18);
  --on-hot:#1E2833;
  --yes:#3B6B52;          /* the green of a wet field, not a traffic light */
  --maybe:#8A5E24;
  --no:#A2483E;
  --yes-bg:#DDE8DC;
  --maybe-bg:#F5EBD9;
  --no-bg:#F0DCD6;
  --coffee:#A5572F;       /* roasted terracotta */
  /* Shadows are tinted with the ink, never black on cream. Three steps:
     resting, raised, floating. */
  --sh-1:0 1px 2px rgba(30,40,51,.05),0 2px 6px rgba(30,40,51,.05);
  --sh-2:0 1px 2px rgba(30,40,51,.06),0 6px 16px -4px rgba(30,40,51,.14),0 14px 32px -14px rgba(30,40,51,.22);
  --sh-3:0 2px 6px rgba(30,40,51,.08),0 12px 28px -8px rgba(30,40,51,.22),0 32px 64px -20px rgba(30,40,51,.32);
  --sh-up:0 -2px 6px rgba(30,40,51,.04),0 -12px 28px -8px rgba(30,40,51,.18);
  --sh-gold:0 1px 0 rgba(255,255,255,.28) inset,0 2px 3px rgba(30,40,51,.10),0 8px 18px -6px rgba(176,120,30,.45);
  --hard:var(--sh-1);
  --lift:var(--sh-2);
  --lift-lg:var(--sh-3);
  --tile:saturate(.16) brightness(1.02) contrast(.95) sepia(.10);
}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    /* the cup itself: navy ground, cream ink */
    --paper:#151D26;
    --card:#202B36;
    --raise:#283442;
    --sunk:#1A232D;
    --ink:#F1EBE0;
    --ink-2:#D3CCBF;
    --muted:#A7B0B9;
    --faint:#7B8792;
    --line:#2F3B48;
    --rule:#3A4756;
    --line-2:#2A3541;
    --hot:#E3B65A;
    --hot-soft:rgba(227,182,90,.16);
    --on-hot:#1E2833;
    --yes:#7FB292;
    --maybe:#D8A362;
    --no:#D98A7E;
    --yes-bg:#1E2E28;
    --maybe-bg:#2E2820;
    --no-bg:#2F2321;
    --coffee:#DC8B5E;
    --sh-1:0 1px 2px rgba(0,0,0,.25),0 2px 6px rgba(0,0,0,.18);
    --sh-2:0 1px 2px rgba(0,0,0,.3),0 6px 16px -4px rgba(0,0,0,.45),0 14px 32px -14px rgba(0,0,0,.6);
    --sh-3:0 2px 6px rgba(0,0,0,.35),0 12px 28px -8px rgba(0,0,0,.55),0 32px 64px -20px rgba(0,0,0,.7);
    --sh-up:0 -2px 6px rgba(0,0,0,.2),0 -12px 28px -8px rgba(0,0,0,.5);
    --sh-gold:0 1px 0 rgba(255,255,255,.22) inset,0 2px 3px rgba(0,0,0,.3),0 8px 18px -6px rgba(0,0,0,.5);
    --hard:var(--sh-1);
    --lift:var(--sh-2);
    --lift-lg:var(--sh-3);
    --tile:saturate(.12) brightness(.62) contrast(1.05) invert(.9) hue-rotate(175deg);
  }
}

/* An explicit dark choice has to win on a light OS too. */
:root[data-theme="dark"]{
    /* the cup itself: navy ground, cream ink */
    --paper:#151D26;
    --card:#202B36;
    --raise:#283442;
    --sunk:#1A232D;
    --ink:#F1EBE0;
    --ink-2:#D3CCBF;
    --muted:#A7B0B9;
    --faint:#7B8792;
    --line:#2F3B48;
    --rule:#3A4756;
    --line-2:#2A3541;
    --hot:#E3B65A;
    --hot-soft:rgba(227,182,90,.16);
    --on-hot:#1E2833;
    --yes:#7FB292;
    --maybe:#D8A362;
    --no:#D98A7E;
    --yes-bg:#1E2E28;
    --maybe-bg:#2E2820;
    --no-bg:#2F2321;
    --coffee:#DC8B5E;
    --sh-1:0 1px 2px rgba(0,0,0,.25),0 2px 6px rgba(0,0,0,.18);
    --sh-2:0 1px 2px rgba(0,0,0,.3),0 6px 16px -4px rgba(0,0,0,.45),0 14px 32px -14px rgba(0,0,0,.6);
    --sh-3:0 2px 6px rgba(0,0,0,.35),0 12px 28px -8px rgba(0,0,0,.55),0 32px 64px -20px rgba(0,0,0,.7);
    --sh-up:0 -2px 6px rgba(0,0,0,.2),0 -12px 28px -8px rgba(0,0,0,.5);
    --sh-gold:0 1px 0 rgba(255,255,255,.22) inset,0 2px 3px rgba(0,0,0,.3),0 8px 18px -6px rgba(0,0,0,.5);
    --hard:var(--sh-1);
    --lift:var(--sh-2);
    --lift-lg:var(--sh-3);
    --tile:saturate(.12) brightness(.62) contrast(1.05) invert(.9) hue-rotate(175deg);
  }

*{box-sizing:border-box}
[hidden]{display:none !important}
/* The map is a fixed, full-bleed layer and the chrome floats over it. If the
   document is ever able to scroll sideways - one row a few pixels too wide is
   enough - the two part company: the chrome travels with the scroll and the
   map does not, and the screen looks sliced down the left edge. Nothing here
   is meant to scroll horizontally, so nothing is allowed to. */
html,body{height:100%;margin:0;overflow-x:hidden;overscroll-behavior:none}
body{
  background:var(--paper);color:var(--ink);overflow:hidden;
  /* Chrome on Android fires pull-to-refresh when a sheet is dragged down at
     the top of its scroll. Safari has no such gesture, so this only ever
     showed up on Android. */
  overscroll-behavior:none;
  font:500 15px/1.5 Gabarito,system-ui,-apple-system,sans-serif;
  -webkit-font-smoothing:antialiased;
}
button,input{font:inherit;color:inherit}
/* Safari zooms the whole page when a text field under 16px takes focus, and
   does not zoom back out. Everything else here can stay at the design size. */
input[type=search],input[type=text],input[type=date],input[type=number],
input:not([type]),select,textarea{font-size:16px}
:focus-visible{outline:2.5px solid var(--ink);outline-offset:2px;border-radius:8px}
.mono,.d,.od,.bd,.away,.conf,.lbl,.stat span,.seg em{
  font-family:"JetBrains Mono",ui-monospace,monospace;font-variant-numeric:tabular-nums;
}

/* ---------- map ---------- */
#map{position:fixed;inset:0;background:var(--paper)}
.leaflet-tile-pane{filter:var(--tile)}
.leaflet-container{font:inherit;background:var(--paper)}
.leaflet-control-zoom{display:none}
.leaflet-popup-content-wrapper{border-radius:12px;box-shadow:var(--lift);
  border:1px solid var(--rule);background:var(--card);color:var(--ink)}
.leaflet-popup-tip{background:var(--card);border:1px solid var(--rule)}
.leaflet-popup-content{margin:11px 14px;font-size:13.5px}

/* ---------- chrome ---------- */
/* The status bar, once the app is an app.

   On the web nothing sits above the page, so the chrome could start at a flat
   16px. In a store build the webview runs edge to edge under the status bar -
   which is right for a map - and the clock landed on top of "Search walks".
   env() is 0 everywhere it does not apply, so the web is unchanged. */
:root{--safe-top:env(safe-area-inset-top,0px)}
#chrome{position:fixed;top:calc(16px + var(--safe-top));left:16px;right:16px;z-index:800;
  display:flex;flex-direction:column;gap:10px;pointer-events:none}
#chrome>*{pointer-events:auto}

/* ---- the chrome card ----

   One object holding two questions. The top row asks which walks - type a
   town, or narrow by who is coming. The row under it says where you are
   setting off from, which is what every drive time on the screen is
   measured from and was visible nowhere.

   They were two floating pills, and a crosshair inside the search box did
   the same job as the lower one. Two controls for one decision, in two
   separate objects, is how somebody comes to believe that searching a town
   moved their starting point.

   The card keeps the 16px radius the app uses for surfaces; the controls
   inside keep the pill the app uses for controls. That is the existing
   rule, not a new one. */
.bar{display:flex;flex-direction:column;gap:0;max-width:520px;
  background:var(--card);border:1px solid var(--rule);border-radius:16px;
  box-shadow:var(--hard);padding:0;overflow:hidden}
.bar-row{display:flex;align-items:center;gap:8px;flex-wrap:nowrap;padding:7px}

/* The hairline is the only thing separating the two questions, which is as
   much separation as they need. */
.fromrow{
  display:flex; align-items:center; gap:8px; width:100%;
  padding:9px 12px 10px; cursor:pointer; text-align:left;
  background:var(--sunk); border:0; border-top:1px solid var(--line);
  color:var(--ink); font:600 12.5px Gabarito,system-ui,sans-serif;
  transition:background .14s ease;
}
/* --muted on --sunk measures 3.07:1, which is under AA for 12.5px text.
   The quiet half of this row still has to be readable: --ink-2 is the
   colour the log sheet was moved to for exactly this reason. */
.fromrow > i{font-size:15px; color:var(--ink-2); flex:none}
.fromrow .fc-k{color:var(--ink-2); flex:none}
/* A long start name - "Carrigaline to Crosshaven Greenway Walking Trail" is
   one somebody can genuinely set - has to give way rather than push the
   card off a 412px phone. */
.fromrow b{min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.fromrow .fc-go{margin-left:auto; font-size:13px; color:var(--ink-2)}
.fromrow:hover{background:var(--line)}
.fromrow:active{background:var(--line)}
.fromrow:focus-visible{outline:2px solid var(--hot); outline-offset:-2px}
/* Not set is a state worth seeing, because every distance on the screen
   depends on it - but the words carry it, not the colour. --coffee at
   3.09:1 is fine for the pin, which is a graphic, and would fail for the
   text beside it. The text stays at full contrast and says "not set",
   which is the clearer signal anyway. */
/* The pin, not the chevron - "> i" caught both and left the chevron at
   3.09:1 in a row where everything else had been fixed. */
.fromrow.unset > i:first-child{color:var(--coffee)}
.fromrow.unset b{color:var(--ink)}

@media (prefers-reduced-motion:reduce){
  .fromrow{transition:none}
}
/* The badge's cream ground is nearly the colour of the card it sits on, so at
   34px it dissolved. Bigger, and ringed in ink like every other control here,
   so it reads as the mark rather than a smudge. */
.brand{flex:none;width:42px;height:42px;border-radius:50%;display:block;
  object-fit:cover;margin:0 2px;background:#FEFDF8;
  border:1px solid var(--rule);box-shadow:0 1px 0 var(--ink)}

.search{flex:1 1 190px;display:flex;align-items:center;gap:8px;min-width:0;
  background:var(--sunk);border-radius:12px;padding:0 12px}
.search i{color:var(--faint);font-size:17px;flex:none}
.search input{flex:1;min-width:0;border:0;background:none;padding:9px 0;
  outline:none;font-weight:500}
.search input::placeholder{color:var(--faint)}

.btn{display:inline-flex;align-items:center;gap:7px;flex:none;cursor:pointer;
  border:1px solid var(--rule);background:var(--card);color:var(--ink);
  border-radius:12px;padding:8px 13px;font-weight:600;
  transition:transform .08s,background .15s}
.btn i{font-size:17px}
/* ---- one button family -------------------------------------------------

   Measured across the walk sheet and the preview, the same two screens
   carried five corner radii (10, 11, 12, 13 and a 999 pill), heights of
   30, 41, 42, 46 and 69, and three different fills - so every row read
   as a kit from somewhere else. One scale now: 12px corners, 46px for
   an action, 44px for a tool, and one filled button per surface, which
   is the gold one and is the thing the screen is for.

   Chips stay pills on purpose. A chip is a choice among several, not an
   action, and rounding them like buttons would turn a row of options
   into a row of equal verbs. */
.btn{min-height:46px; border-radius:12px; padding:11px 14px;
     font:700 14.5px Gabarito,system-ui,sans-serif}
/* The compact ones opt out by name rather than by accident. */
.btn.tiny{min-height:0}
.btn:hover{background:var(--sunk)}
.btn:active{transform:translate(1px,1px)}
.btn.ghost{border-color:var(--line)}
.btn.ghost:hover{border-color:var(--ink)}
.btn.solid,.btn.on{background:var(--ink);color:var(--paper)}
.btn.solid:hover,.btn.on:hover{background:var(--ink)}
.btn b{min-width:20px;height:20px;border-radius:999px;background:var(--hot);
  color:var(--ink);font:700 12px/20px Gabarito;text-align:center;padding:0 6px}

/* ---------- cards ---------- */
#panel,#detail{position:fixed;left:16px;top:calc(var(--safe-top) + var(--chrome-h,112px) + 26px);
  bottom:16px;width:380px;z-index:750;
  display:flex;flex-direction:column;background:var(--card);
  border:1px solid var(--rule);border-radius:16px;box-shadow:var(--lift-lg);overflow:hidden}
#detail{z-index:760}

/* A sheet at its middle detent stops wherever its height runs out, which is
   usually halfway through a row - a name sliced across the middle reads as a
   rendering fault rather than as "there is more below". The fade says the
   second thing.

   On the sheet rather than on the scrolling body, so it stays put while the
   content moves under it, and not when peeked, where the body is hidden and
   there is nothing to continue. */
#panel::after, #detail::after{
  content:''; position:absolute; left:0; right:0; bottom:0; height:26px;
  background:linear-gradient(to top, var(--card), rgba(0,0,0,0));
  pointer-events:none; z-index:3;
}
#panel.peeked::after, #detail.peeked::after,
#panel.min::after{display:none}

#panel.min{bottom:auto;height:auto}
#panel.min #results,#panel.min #credits,#panel.min #landing,#panel.min #today{display:none}
.grip{display:none}

.cardhead{display:flex;align-items:center;gap:10px;padding:12px 14px;
  border-bottom:1px solid var(--rule);flex:none;background:var(--card)}
.cardhead #count{margin:0;flex:1;font-size:13px;color:var(--muted);font-weight:500}
.suit{flex:1;font-weight:700;font-size:15px;letter-spacing:-.015em}
.icon{width:32px;height:32px;flex:none;display:grid;place-items:center;cursor:pointer;
  border:1px solid var(--rule);background:var(--card);border-radius:12px;
  transition:transform .08s,background .15s}
.icon:hover{background:var(--sunk)}
.icon:active{transform:translate(1px,1px)}
.icon i{font-size:16px}

/* Every panel that scrolls has to stop its own overscroll here rather than
   letting it chain to the page. Dragging a card down from its top used to
   reach the root, where Chrome reads it as pull-to-refresh: the whole app
   reloaded, and every choice on it went with it. Explore was fine only
   because its drag handle swallows the gesture first; Saved, My walks and
   Profile had nothing in the way. `contain` keeps the scroll here and still
   lets the sheet drag work.

   `overscroll-behavior` also had to move to html - it was on body, and body
   is not the scrolling element in a fixed layout like this one, so the root
   never got the message. */
#results{list-style:none;margin:0;padding:8px;overflow-y:auto;flex:1;min-height:0;
  overscroll-behavior-y:contain}
#results li{padding:0;border-radius:14px;cursor:pointer;border:2px solid transparent}
#results li .rmeta{padding:12px 14px}
#results li:hover{background:var(--sunk)}
#results li.sel{background:var(--sunk);border-color:var(--ink)}
.bar-i{width:4px;border-radius:4px;align-self:stretch;min-height:32px}
.bar-i.yes{background:var(--yes)} .bar-i.maybe{background:var(--maybe)} .bar-i.no{background:var(--no)}
.rname{font-weight:700;font-size:15px;line-height:1.25;letter-spacing:-.02em}
.away{float:right;font-size:11.5px;color:var(--muted);margin-left:8px;font-weight:500}
.rmeta{font-size:12.5px;color:var(--muted);margin-top:3px}
.rchips{display:flex;gap:5px;margin-top:8px;flex-wrap:wrap}
.chip{display:inline-flex;align-items:center;gap:4px;font-size:11.5px;font-weight:600;
  padding:3px 9px;border-radius:999px;background:var(--sunk);color:var(--muted);white-space:nowrap}
.chip i{font-size:12px}
.chip.cafe1{color:var(--coffee);background:var(--maybe-bg)}
.goodfor{display:flex;flex-wrap:wrap;gap:5px;margin-top:8px}
.gf{font-size:11.5px;font-weight:600;padding:3px 9px;border-radius:999px;
  background:var(--yes-bg);color:var(--yes)}
.gf.none{background:var(--sunk);color:var(--faint)}

#credits{margin:0;padding:10px 14px;border-top:2px solid var(--line-2);
  font-size:11px;color:var(--faint);flex:none}

/* ---------- detail ---------- */
#detailBody{overflow-y:auto;padding:22px 20px 20px;flex:1;min-height:0;
  overscroll-behavior-y:contain}
#detailBody h2{margin:0 0 4px;font-size:23px;line-height:1.1;letter-spacing:-.035em;font-weight:800}
.dcounty{margin:0 0 16px;font-size:12.5px;color:var(--muted)}

.verdict{border:1px solid var(--rule);border-radius:14px;padding:13px 14px;margin-bottom:14px}
.verdict.yes{background:var(--yes-bg)}
.verdict.maybe{background:var(--maybe-bg)}
.verdict.no{background:var(--no-bg)}
.vhead{display:flex;align-items:baseline;gap:8px;font-weight:800;font-size:16px;
  letter-spacing:-.02em}
.verdict.yes .vhead{color:var(--yes)}
.verdict.maybe .vhead{color:var(--maybe)}
.verdict.no .vhead{color:var(--no)}
.conf{margin-left:auto;font-size:10px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--muted);font-weight:500}
.verdict ul{margin:8px 0 0;padding-left:16px;font-size:13px;color:var(--ink-2);font-weight:500}
.verdict li{margin-bottom:2px}

.matrix{border:1px solid var(--rule);border-radius:14px;overflow:hidden;margin-bottom:16px}
.mrow{display:grid;grid-template-columns:9px 1fr auto;gap:10px;align-items:center;
  padding:9px 13px;font-size:13.5px;cursor:pointer;border-top:1px solid var(--line-2)}
.mrow:first-child{border-top:0}
.mrow:hover{background:var(--sunk)}
.mrow.sel{background:var(--sunk)}
.mrow .who-l{font-weight:600;display:flex;align-items:center;gap:8px}
.mrow .who-l i{font-size:15px;color:var(--muted)}
.mrow .why{color:var(--muted);font-size:12px;text-align:right;font-weight:500;
  line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;max-width:180px}
.mrow{align-items:start}
.mrow .dot{margin-top:5px}
.mrow .who-l{align-items:flex-start;padding-top:1px}
.dot{width:9px;height:9px;border-radius:999px}
.dot.yes{background:var(--yes)} .dot.maybe{background:var(--maybe)} .dot.no{background:var(--no)}

.stats{display:grid;grid-template-columns:1fr 1fr;border:1px solid var(--rule);
  border-radius:14px;overflow:hidden;margin-bottom:16px}
.stat{padding:10px 13px;border-top:1px solid var(--line-2);border-left:1px solid var(--line-2)}
.stat:nth-child(-n+2){border-top:0}
.stat:nth-child(odd){border-left:0}
.stat span{display:block;font-size:9.5px;letter-spacing:.07em;text-transform:uppercase;
  color:var(--faint);margin-bottom:3px;font-weight:500}
.stat b{font-size:17px;font-weight:800;letter-spacing:-.02em}

.dsec{margin-bottom:18px}
.dsec h3{display:flex;justify-content:space-between;align-items:baseline;gap:10px;
  font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--faint);
  margin:0 0 8px;font-weight:700}
.dsec h3 span,.dsec h3 .muted{font-weight:500;color:var(--faint)}
.poi{display:flex;gap:11px;align-items:baseline;padding:9px 0;
  border-bottom:1px solid var(--line-2);font-size:13.5px;cursor:pointer}
.poi:last-child{border-bottom:0}
.poi:hover .pname{color:var(--coffee)}
.poi .d{font-size:11.5px;color:var(--muted);min-width:54px;flex:none}
.pname{font-weight:600}
.poi.t2 .pname{color:var(--ink-2);font-weight:500}
.ptags{font-size:11.5px;color:var(--faint);margin-top:2px;font-weight:500}
.none{font-size:12.5px;color:var(--faint);margin:0;font-weight:500}
.desc{font-size:13px;color:var(--ink-2);line-height:1.55;margin:0;font-weight:500}
.dlink{display:inline-block;margin-top:8px;font-size:13px;font-weight:600;color:var(--ink)}
.row1{display:flex;align-items:center;gap:8px;justify-content:space-between}

.bundle{display:flex;flex-direction:column;gap:3px;margin-top:8px}
.brow{display:flex;align-items:baseline;gap:7px;font-size:12.5px;color:var(--ink-2)}
.brow b{font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--faint);min-width:48px}
.brow.miss{color:var(--faint);font-weight:500}
.bd{margin-left:auto;font-size:11.5px;color:var(--muted);white-space:nowrap;flex:none}
.tierlabel{font-size:9.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--maybe);background:var(--maybe-bg);border-radius:999px;padding:1px 6px}

/* ---------- sheets: the scrim ---------- */
#scrim{position:fixed;inset:0;z-index:900;background:rgba(16,16,16,.34);animation:fade .16s ease}
@keyframes fade{from{opacity:0}}
.sheethead{display:flex;align-items:center;justify-content:space-between;
  padding:13px 16px;border-bottom:1px solid var(--rule);flex:none}
.sheethead h2{margin:0;font-size:18px;font-weight:800;letter-spacing:-.03em}
.sheetbody{overflow-y:auto;padding:20px;flex:1;min-height:0;
  overscroll-behavior-y:contain}
.sheetfoot{display:flex;gap:8px;padding:12px 16px;border-top:1px solid var(--rule);flex:none}
.sheetfoot .btn{flex:1;justify-content:center}

.field{margin-bottom:22px}
.field:last-child{margin-bottom:0}
/* These were --faint on the card: 2.3:1, against the 4.5:1 that ten-pixel
   uppercase text needs to be read at all. "WHEN DID YOU WALK IT?" was
   effectively invisible and the form looked like a row of controls with
   nothing to say what they were for. --ink-2 is 7.9:1. */
.lbl{display:flex;justify-content:space-between;align-items:baseline;
  font-size:10px;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-2);
  margin-bottom:9px;font-weight:500}
.lbl b{font-family:Gabarito;font-size:12.5px;letter-spacing:0;text-transform:none;
  color:var(--ink);font-weight:700}

.seg{display:flex;gap:6px}
.seg.wrap{flex-wrap:wrap}
.seg button{flex:1 1 0;min-width:78px;display:flex;flex-direction:column;align-items:center;
  gap:3px;padding:8px 6px;border:1px solid var(--rule);background:var(--card);
  border-radius:12px;cursor:pointer;color:var(--muted);font-size:11.5px;font-weight:600;
  transition:border-color .15s,color .15s}
.seg.wrap button{flex:1 1 calc(33.333% - 4px)}
.seg button em{font-style:normal;font-size:13px;font-weight:700}
.seg button i{width:100%;height:3px;border-radius:3px;background:var(--line)}
.seg button:hover{border-color:var(--muted)}
.seg button.on{color:var(--ink);border-color:var(--ink);
  box-shadow:inset 0 0 0 1px var(--ink)}

input[type=range]{width:100%;accent-color:var(--ink)}
.checks{display:flex;flex-direction:column;gap:11px}
.checks label{display:flex;gap:10px;align-items:flex-start;font-size:13.5px;
  cursor:pointer;line-height:1.35;font-weight:500}
.checks label.sub{margin-left:26px;margin-top:-5px;color:var(--muted);font-size:12.5px}
.checks input{accent-color:var(--ink);width:16px;height:16px;margin:1px 0 0;flex:none}

/* ---------- map pins ---------- */
.pin{display:grid;place-items:center;border-radius:999px;border:2px solid var(--card);
  box-shadow:0 1px 4px rgba(0,0,0,.4);font-weight:700;color:#fff}
.pin-cafe{display:grid;place-items:center;border-radius:999px;background:var(--coffee);
  color:#fff;border:2.5px solid var(--card);font-weight:800;font-size:12px;
  box-shadow:0 1px 5px rgba(0,0,0,.45)}
.pin-cafe-maybe{border-radius:999px;background:var(--card);border:2.5px solid var(--coffee);
  opacity:.8;box-shadow:0 1px 3px rgba(0,0,0,.3)}

/* ---------- phone ---------- */
/* Mid-width windows: drop the button words before anything wraps. */
@media (max-width:1080px){
  .btn .lbl{display:none}
}
@media (max-width:820px){
  #chrome{top:calc(10px + var(--safe-top));left:10px;right:10px;gap:8px}
  .bar{box-shadow:none}
  .bar-row{padding:6px}
  /* One row of chrome. The second row was 46px of map. */
  .brand{display:none}
  .btn .lbl{display:none}
  #panel,#detail{left:0;right:0;width:auto;top:auto;bottom:0;max-height:25dvh;
    border-radius:18px 18px 0 0;border-bottom:0;
    transition:max-height .24s cubic-bezier(.16,1,.3,1)}
  #panel.tall{max-height:86dvh}
  /* Three heights for a walk, opening on the middle one. A sheet that opens
     full turns a map app into a list app.

     The middle one is the fold, and the fold has to hold the name, the
     verdict, the three plan rows and the go bar - that is the whole
     answer, and it was measured at 456px on a 390x844 screen. 25dvh held
     the photo and the name and put the verdict under the fold; 58dvh
     holds the answer and leaves the walk itself on the map above it. */
  #detail{max-height:58dvh}
  #detail.tall{max-height:86dvh}
  #panel.min{max-height:none;height:auto}
  /* A 44x12 target is a dot you have to aim at. The handle is the whole top
     of the card - the bar is just what tells you it is draggable. */
  .grip{display:block;flex:none;cursor:grab;padding:11px 0 7px;
    touch-action:none;position:relative}
  .grip::before{content:'';display:block;width:44px;height:5px;border-radius:5px;
    background:var(--line);margin:0 auto}
  .grip::after{content:'';position:absolute;left:0;right:0;top:0;height:52px}
  #panel .cardhead,#detail .cardhead{touch-action:none}
  .seg.wrap button{flex:1 1 calc(50% - 3px)}
  .rchips .chip{font-size:11px}
}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms !important;transition-duration:.01ms !important}
}

/* the two remaining chip variants */
.chip.cafe2{background:var(--sunk);color:var(--faint)}
.chip.chal{background:var(--sunk);color:var(--ink-2)}

/* map style switcher */
/* Gray Canvas is already a data backdrop, so leave it alone. */
body[data-base="gray"] .leaflet-tile-pane{filter:none}

/* While the journey plays, the ground steps back.

   The dashed lines reading as strays are the basemap's county boundaries -
   Esri draws COUNTY CLARE / COUNTY LIMERICK as a dashed grey line, and at
   these zooms it looks exactly like a route wandering off. It is not ours to
   remove, but it does not need to be as loud as the thing you are watching.

   Faded for the duration, so one dark line is unmistakably the route and
   everything else is context. This is what the delivery maps do, and it is
   why their route reads at a glance.

   Opacity, and not the filter this used to be.

   A filter on the tile pane is a filter on a full-screen element, which
   makes the whole map one composited layer that has to be re-rasterised
   every time any part of it changes - and animating the filter re-rasterises
   it on every frame of the transition. Chrome rasterises a layer it is
   animating at a reduced scale and is supposed to redraw it at full
   resolution when the animation settles. When that redraw is missed, what
   stays on screen is the small raster stretched back up: a full-width band
   of blurry magnified map, a city label four times the size it should be,
   and the route and pins still perfectly sharp on top of it because they
   are in other panes. Reported from the live site, and it cleared on the
   next pan, which is a stale layer and not bad map data - the byte ranges
   behind it were all answered.

   Opacity does not have the problem. It is applied when the layer is
   composited rather than when it is drawn, so transitioning it never
   invalidates the raster underneath.

   What is lost is grayscale(1), and it is close to nothing: --tile already
   holds the basemap at saturate(.16), so there was very little colour left
   in it to remove. */
body.previewing .leaflet-tile-pane{opacity:.62}
.leaflet-tile-pane{transition:opacity .3s ease}
@media (prefers-reduced-motion:reduce){
  .leaflet-tile-pane{transition:none}
}
/* difficulty band: its own visual language, so it never reads as suitability */
.chal-band{border:1px solid var(--rule);border-radius:14px;padding:11px 13px;margin-bottom:14px}
.chal-top{display:flex;align-items:center;justify-content:space-between;gap:12px}
.chal-top b{font-size:17px;font-weight:800;letter-spacing:-.02em}
.meter{display:flex;gap:4px}
.meter i{width:16px;height:6px;border-radius:6px;background:var(--line);display:block}
.meter i.on{background:var(--ink)}
.chal-band p{margin:5px 0 0;font-size:13px;color:var(--ink-2);font-weight:500;line-height:1.45}

/* a provider rating sits beside your own, quieter */

/* Google requires visible attribution wherever its content is shown */
.attrib{margin:-10px 0 16px;font-size:11px;color:var(--faint);font-weight:500}
.attrib b{color:var(--ink-2);font-weight:700}

.btn.share{width:100%;justify-content:center;margin-top:14px}

.sharerow{display:flex;gap:8px;margin-top:16px}
.sharerow .btn{flex:1;justify-content:center;margin:0}
.shairnote{margin:8px 0 0;font-size:11.5px;color:var(--faint);font-weight:500;text-align:center}

.photonote{margin:6px 0 0;font-size:12px;font-weight:600;text-align:center}
.photonote:empty{display:none}
.photonote.ok{color:var(--yes)}
.photonote.off{color:var(--maybe)}
.photonote.unknown{color:var(--faint)}

/* tapping a place drops the sheet so the map is visible underneath */
@media (max-width:820px){
  #detail.peeked{max-height:30dvh}
}

/* ---------- bottom navigation ---------- */
/* The tab bar owns the bottom of the screen, so the cards stop above it. */
:root{--tabh:64px}
#tabs{position:fixed;z-index:820;display:flex;background:var(--card);
  border:1px solid var(--rule);box-shadow:var(--lift-lg);
  left:16px;bottom:16px;width:380px;border-radius:14px;padding:5px;gap:4px}
#panel,#detail{bottom:calc(var(--tabh) + 18px)}

/* "How was it?" - sits above the tab bar, on the same visual footing as the
   rest of the chrome. Not a toast: a toast disappears while you are reading
   it, and this one is asking a question. */
#tripAsk{position:fixed;z-index:900;left:16px;bottom:calc(var(--tabh) + 26px);
  width:380px;max-width:calc(100vw - 32px);display:flex;align-items:center;gap:10px;
  background:var(--card);border:2px solid var(--ink);border-radius:14px;
  padding:10px 10px 10px 14px;box-shadow:var(--lift-lg);
  animation:riseIn .24s cubic-bezier(.16,1,.3,1)}
#tripAsk .tabody{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
#tripAsk b{font:700 13.5px/1.2 Gabarito,system-ui,sans-serif}
#tripAsk span{font:500 12px/1.3 Gabarito,system-ui,sans-serif;color:var(--muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#tripAsk .btn{flex:0 0 auto;padding:8px 11px;font-size:12.5px;white-space:nowrap}
/* Three targets on a 390px screen. The name is the part that gives, because
   it is the one thing already on screen a moment ago. */
#tripAsk .tabody{min-width:0}
.tadismiss{flex:0 0 auto;width:32px;height:32px;border:0;background:none;
  color:var(--faint);cursor:pointer;border-radius:9px}
.tadismiss:hover{background:var(--sunk);color:var(--ink)}
@media (max-width:820px){#tripAsk{left:12px;right:12px;width:auto}}
@media (prefers-reduced-motion:reduce){#tripAsk{animation:none}}

.tab{position:relative;flex:1;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:3px;padding:7px 4px;border:2px solid transparent;
  border-radius:10px;background:none;cursor:pointer;color:var(--faint);
  font:600 10.5px/1 Gabarito,system-ui,sans-serif;letter-spacing:-.01em;
  transition:background .15s,color .15s,transform .08s}
.tab i{font-size:19px}
.tab:hover{background:var(--sunk);color:var(--ink-2)}
.tab:active{transform:translateY(1px)}
.tab.on{background:transparent;color:var(--ink)}
.tab.on::after{content:"";position:absolute;left:50%;bottom:2px;width:16px;height:2px;
  transform:translateX(-50%);background:var(--hot);border-radius:2px}
.tab:focus-visible{outline:2px solid var(--hot);outline-offset:2px}
.tab b{position:absolute;top:3px;right:calc(50% - 22px);min-width:15px;height:15px;
  border-radius:999px;background:var(--hot);color:var(--ink);
  font:700 9.5px/15px JetBrains Mono,monospace;text-align:center;padding:0 3px}

@media (max-width:820px){
  #tabs{left:0;right:0;bottom:0;width:auto;border-radius:0;border-left:0;border-right:0;
    border-bottom:0;padding:5px 6px calc(5px + env(safe-area-inset-bottom));gap:2px}
  #panel,#detail{bottom:calc(var(--tabh) + env(safe-area-inset-bottom))}
  #detail.peeked{max-height:30dvh}
  .tab{font-size:10px}
}

/* ---------- tab views (my walks / the cabinet / you) ---------- */
#tabBody{overflow-y:auto;flex:1;min-height:0;padding:14px;
  overscroll-behavior-y:contain}
#tabBody h3{margin:0 0 3px;font-size:17px;font-weight:800;letter-spacing:-.03em}
#tabBody .sub{margin:0 0 16px;font-size:12.5px;color:var(--muted);line-height:1.5}
#tabBody .empty{text-align:center;padding:34px 18px;color:var(--muted)}
#tabBody .empty i{font-size:34px;color:var(--line);display:block;margin-bottom:10px}
#tabBody .empty b{display:block;font-size:15px;color:var(--ink);margin-bottom:5px}
#tabBody .empty p{margin:0;font-size:12.5px;line-height:1.5}

.mystats{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:16px}
.mystat{border:1px solid var(--rule);border-radius:12px;padding:10px}
.mystat b{display:block;font:700 20px/1 JetBrains Mono,monospace;letter-spacing:-.04em}
.mystat span{display:block;font-size:10.5px;color:var(--muted);margin-top:4px;font-weight:600}

.logrow{display:flex;align-items:center;gap:10px;padding:11px 4px;
  border-bottom:2px solid var(--line-2);cursor:pointer}
.logrow:last-child{border-bottom:0}
.logrow .when{margin-left:auto;font:500 11px JetBrains Mono,monospace;color:var(--faint);
  flex:none;text-align:right}
.logrow .nm{font-weight:700;font-size:14px;letter-spacing:-.02em}
.logrow .mt{font-size:12px;color:var(--muted);margin-top:2px}
.logrow:hover .nm{text-decoration:underline}
.logrow .drop{flex:none;border:0;background:none;color:var(--faint);cursor:pointer;font-size:15px;
  padding:4px}
.logrow .drop:hover{color:var(--no)}

.prow{display:flex;align-items:center;gap:10px;padding:12px 0;
  border-bottom:2px solid var(--line-2);font-size:13.5px}
.prow:last-child{border-bottom:0}
.prow .k{font-weight:600}
.prow .v{margin-left:auto;color:var(--muted);font-size:12.5px}
.prow select{border:1px solid var(--rule);border-radius:10px;background:var(--card);
  color:var(--ink);font:600 12.5px Gabarito,system-ui,sans-serif;padding:6px 8px;
  margin-left:auto;cursor:pointer}
#tabBody .btn{width:100%;justify-content:center;margin-top:14px}

#saveWalk.on{background:var(--ink);color:var(--card)}

/* The sheet slid up under the floating chrome on tall phones, putting the
   rail on top of the back and save buttons. Measure the gap instead of
   guessing at a dvh fraction.
   The sheet stands on the tab bar and the home indicator under it, so both
   come off - without the indicator an iPhone ran the sheet 30px up under
   the search card. */
@media (max-width:820px){
  #panel.tall,#detail.tall{
    max-height:calc(100dvh - var(--safe-top) - var(--chrome-h,112px) - var(--tabh) - env(safe-area-inset-bottom) - 26px)}
  #detail{max-height:62dvh}
  #detail.peeked{max-height:16dvh}
  #panel.peeked{max-height:16dvh}
  /* keep Leaflet's own controls clear of the full-width tab bar */
  .leaflet-bottom{bottom:calc(var(--tabh) + env(safe-area-inset-bottom))}
}
/* the tab bar only covers the left column on desktop, so the bottom-right
   zoom and attribution stay where they are */
#panel[data-tab]:not([data-tab=explore]) .cardhead{display:none}

/* ---------- landing state ---------- */
/* Before the user picks an area, a list of walks is a list of nowhere in
   particular. Offer the two ways to pick one instead. */
#landing{padding:18px 16px 16px;overflow-y:auto;flex:1;min-height:0}
#landing .lead{margin:0 0 16px;font-size:14.5px;line-height:1.5;color:var(--ink-2)}
#landing .btn{width:100%;justify-content:center;margin-bottom:8px;padding:12px}
#landing .landnote{margin:12px 0 0;font-size:12px;line-height:1.5;color:var(--faint)}
#panel[data-landing] #credits{display:none}

/* ---------- persona rail overflow ---------- */
/* The rail scrolls, but a hard cut mid-pill reads as a broken layout. Fade
   the edge that still has content behind it. */

@media (max-width:820px){
  /* smaller pills fit more of the rail on screen before it needs scrolling */
      .brand{width:38px;height:38px}
  .search{padding:0 10px}
  .btn{padding:8px 10px}
}

/* One card at a time on a phone: the list header used to peek out above an
   open walk, so the screen showed three stacked card edges. */
@media (max-width:820px){
  body.detail-open #panel{display:none}
}
/* When the sheet is peeked its heading names the place you tapped. */
.suit.focused{font-size:14px;letter-spacing:-.01em}
/* Popups must not run off a narrow screen. */
@media (max-width:520px){
  .leaflet-popup-content{margin:11px 13px;font-size:13px}
  .leaflet-popup-content-wrapper{max-width:76vw}
}

/* A peeked sheet showing a sliver of mid-scrolled content reads as broken.
   Collapse it to a clean bar - the heading already names what you tapped. */
@media (max-width:820px){
  #detail.peeked{max-height:none;height:auto}
  #detail.peeked #detailBody{display:none}
  #detail.peeked .grip{cursor:pointer}
  /* Lifting the bar has to show the walk under the finger. Hidden, the bar
     stayed its own height however far it was pulled, and on letting go it
     measured that and snapped back down - only a flick or a tap lifted it. */
  #detail.peeked.dragging #detailBody{display:block}
}

/* ---------- chrome: one bar, two chips ---------- */
/* Every secondary control sits behind a sheet, so the top of the screen is a
   search field and two chips that always fit — nothing scrolls sideways. */
.chips{display:flex;gap:8px;flex-wrap:wrap}
.chipctl{display:inline-flex;align-items:center;gap:7px;flex:none;cursor:pointer;
  background:var(--card);border:1px solid var(--rule);border-radius:999px;
  padding:8px 14px;color:var(--ink);font-weight:600;font-size:14px;
  letter-spacing:-.015em;box-shadow:var(--hard);
  transition:transform .08s,background .15s}
.chipctl i{font-size:16px;color:var(--muted)}
.chipctl .car{font-size:13px;margin-left:-2px}
.chipctl:hover{background:var(--sunk)}
.chipctl:active{transform:translate(1px,1px)}
.chipctl.on{background:transparent;color:var(--ink);border-color:var(--ink);
  box-shadow:inset 0 0 0 1px var(--ink)}
.chipctl.on i{color:var(--hot)}
.chipctl b{min-width:19px;height:19px;border-radius:999px;background:var(--hot);
  color:var(--ink);font:700 11.5px/19px JetBrains Mono,monospace;text-align:center;padding:0 5px}
.chipctl:focus-visible{outline:2px solid var(--hot);outline-offset:2px}

/* map controls float over the map, clear of the cards */
#mapctl .mbtn{position:relative}
#mapctl .mbtn b{position:absolute;top:-4px;right:-4px;min-width:18px;height:18px;
  border-radius:999px;background:var(--hot);color:var(--ink);
  font:700 11px/18px Gabarito,system-ui,sans-serif;text-align:center;padding:0 4px}
#mapctl{position:fixed;z-index:790;right:16px;display:flex;flex-direction:column;gap:8px;
  bottom:calc(var(--tabh) + 34px)}
.mbtn{width:46px;height:46px;display:grid;place-items:center;cursor:pointer;
  background:var(--card);border:1px solid var(--rule);border-radius:14px;
  box-shadow:var(--hard);color:var(--ink);transition:transform .08s,background .15s}
.mbtn i{font-size:20px}
.mbtn:hover{background:var(--sunk)}
.mbtn:active{transform:translate(1px,1px)}
.mbtn.on{background:var(--ink);color:var(--hot)}

@media (max-width:820px){
  #mapctl{bottom:calc(var(--tabh) + env(safe-area-inset-bottom) + 12px);right:12px}
  .chipctl{font-size:13.5px;padding:7px 12px}
  .mbtn{width:44px;height:44px}
}

/* ---------- route direction ---------- */
/* A static dotted line says "there is a path"; a moving one says "walk this
   way". Each offset is a whole number of dash periods so the loop is seamless:
   1+9=10, 2+7=9, 7+7=14. The stored line runs walk -> destination, and a
   negative offset marches the dashes along that direction. */
@keyframes routeflow-a{to{stroke-dashoffset:-20}}
@keyframes routeflow-b{to{stroke-dashoffset:-18}}
@keyframes routeflow-c{to{stroke-dashoffset:-28}}
.flow-a{animation:routeflow-a 1.1s linear infinite}
.flow-b{animation:routeflow-b 1.3s linear infinite}
.flow-c{animation:routeflow-c 1.5s linear infinite}
/* an infinite 0.01ms loop is still a running animation; stop it outright */
@media (prefers-reduced-motion:reduce){
  .flow-a,.flow-b,.flow-c{animation:none !important}
}

/* ---------- log a walk ---------- */
/* 680px was a cap for its own sake. On a tall screen it left the dialog
   scrolling 915px of content through a 554px window with a metre of empty
   desk either side, and the cut landed mid-sentence - which reads as
   broken rather than as "there is more below". */
/* Same furniture as the log sheet it follows. */
#shareSheet{position:fixed;z-index:910;top:50%;left:50%;transform:translate(-50%,-50%);
  width:min(440px,calc(100vw - 32px));max-height:min(1000px,calc(100dvh - 72px));
  display:flex;flex-direction:column;background:var(--card);
  border:1px solid var(--rule);border-radius:18px;box-shadow:var(--lift-lg);overflow:hidden}
#shareSheet .btn{margin-bottom:9px}
/* The card as it will arrive, before it goes anywhere. Tall, because
   what it is previewing is a story. */
.shareprev{display:flex;justify-content:center;margin:0 0 16px}
.shareprev img{width:auto;max-width:62%;max-height:46dvh;border-radius:12px;
  border:1px solid var(--rule);box-shadow:var(--hard);display:block}
@media (max-width:820px){
  #shareSheet{top:auto;bottom:0;left:0;right:0;transform:none;width:auto;
    border-radius:18px 18px 0 0;border-bottom:0;max-height:86dvh}
}

#logSheet{position:fixed;z-index:910;top:50%;left:50%;transform:translate(-50%,-50%);
  width:min(440px,calc(100vw - 32px));max-height:min(1000px,calc(100dvh - 72px));
  display:flex;flex-direction:column;background:var(--card);
  border:1px solid var(--rule);border-radius:18px;box-shadow:var(--lift-lg);overflow:hidden}
/* Logging a walk without one already open: the sheet asks which, and
   everything it would otherwise ask about a walk it does not have yet
   stands down until it does. */
#logSheet.choosing .sheetbody > *:not(#logPick){display:none}
/* And the footer, which saves a walk the sheet has not been given yet.
   Picking one is the whole step; there is nothing to confirm. */
#logSheet.choosing .sheetfoot{display:none}
.logpickq{margin:0 0 14px;font-size:15px;font-weight:700;letter-spacing:-.02em}
.logpickrow{display:flex;flex-direction:column;gap:2px;width:100%;
  text-align:left;padding:11px 12px;margin-bottom:8px;cursor:pointer;
  border:1px solid var(--rule);border-radius:12px;
  background:var(--card);color:var(--ink);
  transition:background .18s,border-color .18s,transform .12s}
.logpickrow:hover{border-color:var(--ink);background:var(--sunk)}
.logpickrow:active{transform:translateY(1px)}
.logpickrow .lpname{font-size:14px;font-weight:700;letter-spacing:-.01em}
.logpickrow .lpwhere{font-size:12.5px;color:var(--muted)}
/* The way in for somebody who is back from a walk rather than planning
   one. It is the first thing on the tab because for them it is the only
   thing on it. */

.logwalk{margin:0 0 18px;font-size:15px;font-weight:700;letter-spacing:-.02em;line-height:1.3}
.when{flex:1}
/* Five answers rather than three. `.seg button` carries min-width:78px,
   which is right for three and overflows the sheet at five - 414px of
   buttons in 372px of room, and "Twice" fell off the edge. */
#logDone .done{flex:1 1 0;min-width:0;padding:8px 2px}
#logDate,#logSteps{margin-top:8px;width:100%;border:1px solid var(--rule);border-radius:10px;
  background:var(--card);color:var(--ink);padding:9px 11px;
  /* 16px, or Safari zooms the page on focus. The shorthand has to carry it -
     a font-size longhand above this line loses to it. */
  font:600 16px Gabarito,system-ui,sans-serif}
#logCoffee label{display:flex;align-items:center;gap:9px;padding:9px 0;
  border-bottom:1px solid var(--line-2);font-size:13.5px;cursor:pointer}
#logCoffee label:last-child{border-bottom:0}
#logCoffee .m{margin-left:auto;font:500 11.5px JetBrains Mono,monospace;color:var(--faint)}
.stars{display:flex;gap:6px;margin-top:4px}
.star{flex:1;display:grid;place-items:center;padding:11px 0;cursor:pointer;
  border:1px solid var(--rule);border-radius:12px;background:var(--card);
  color:var(--faint);transition:transform .08s,background .15s,border-color .15s}
.star i{font-size:21px}
.star:hover{border-color:var(--ink);background:var(--sunk)}
.star:active{transform:translate(1px,1px)}
.star.lit{border-color:var(--ink);background:var(--ink);color:var(--hot)}
.ratenote{margin:12px 0 0;font-size:11.5px;line-height:1.5;color:var(--faint)}

@media (max-width:820px){
  #logSheet{top:auto;bottom:0;left:0;right:0;transform:none;width:auto;
    border-radius:18px 18px 0 0;border-bottom:0;max-height:86dvh}
}

/* ================= detail sheet: fewer containers =====================
   Five stacked bordered cards plus a solid black header bar meant the eye
   had to cross six frames before reaching any actual content. Only the
   verdict earns a container — it is the answer to "can I do this walk".
   Everything else groups with hairlines and space, per the same house
   rules the results list already follows. ==================================== */

/* the walk title gets room to be the title */
#detailBody h2{font-size:26px;margin-bottom:5px;text-wrap:balance}
.dcounty{margin-bottom:20px}

/* difficulty: a line of type, not a box */
.chal-band{border:0;border-radius:0;padding:0 0 16px;margin:0 0 16px;
  border-bottom:1px solid var(--line-2)}
.chal-top b{font-size:19px}
.chal-band p{margin-top:6px}

/* the verdict keeps its frame — it is the one thing that is a card */
.verdict{border-width:2px;border-radius:16px;padding:14px 15px;margin-bottom:20px}

/* who it suits: rows, not a table in a box */
.matrix{border:0;border-radius:0;margin-bottom:20px}
.mrow{padding:10px 8px;border-radius:8px;margin:0 -8px;border-top:1px solid var(--line-2)}
.mrow:first-child{border-top:0}

/* four numbers do not need four cells and a frame */
.stats{border:0;border-radius:0;grid-template-columns:1fr 1fr;
  gap:16px 12px;margin-bottom:20px;overflow:visible}
.stat{padding:0;border:0}
.stat:nth-child(-n+2),.stat:nth-child(odd){border:0}
.stat b{font-size:19px;font-variant-numeric:tabular-nums}

/* section headings sit on a rule so sections read without being boxed */
.dsec{margin-bottom:30px}
.dsec h3{padding-bottom:7px;border-bottom:1px solid var(--ink);margin-bottom:2px}

/* One primary action on its own row, then the two share options. Three equal
   flex items in one row squeezed "I walked this" onto three lines and pushed
   the text link off the edge - a button label must never wrap. */
.sharerow{display:flex;flex-direction:column;gap:8px;margin-top:22px}
.sharerow .btn{width:100%;justify-content:center;margin:0;white-space:nowrap}
.sharerow .btn.tertiary{border:0;background:none;color:var(--muted);
  text-decoration:underline;padding:6px 0;box-shadow:none;
  font-size:12.5px;font-weight:500}
.sharerow .btn.tertiary:hover{color:var(--ink);background:none}
.shairnote{text-align:left;margin-top:10px}
.none.more{padding-top:9px;font-size:12px}

/* walker tags: structured notes, so they aggregate without moderation */
.tagpick{display:flex;flex-wrap:wrap;gap:7px}
.tagpick button{cursor:pointer;background:var(--card);border:1px solid var(--rule);
  border-radius:999px;padding:7px 13px;color:var(--ink-2);
  font:600 12.5px Gabarito,system-ui,sans-serif;letter-spacing:-.01em;
  transition:transform .08s,background .15s,border-color .15s,color .15s}
.tagpick button:hover{border-color:var(--ink);background:var(--sunk)}
.tagpick button:active{transform:translate(1px,1px)}
.tagpick button.on{background:transparent;border-color:var(--ink);color:var(--ink);
  box-shadow:inset 0 0 0 1px var(--ink)}
.tagpick button:focus-visible{outline:2px solid var(--hot);outline-offset:2px}
.lbl .opt{font-weight:500;color:var(--faint);text-transform:none;letter-spacing:0}

/* what you said about a walk, shown back on the walk */
.yours{display:flex;align-items:center;gap:9px;flex-wrap:wrap;padding:2px 0 0}
.yours .sc{font:700 14px JetBrains Mono,monospace;color:var(--ink)}
.yours .st{color:var(--hot);-webkit-text-stroke:.5px var(--ink);font-size:14px;letter-spacing:1px}
.yours .tg{font-size:11.5px;font-weight:600;padding:3px 9px;border-radius:999px;
  background:var(--sunk);color:var(--muted)}

/* ---------- weekly tracking ---------- */
/* Participation, not performance: the headline is how often you got out,
   which is the number parkrun's retention rests on. */
.thisweek{border-bottom:1px solid var(--ink);padding-bottom:12px;margin-bottom:14px}
.tw-k{margin:0;font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--faint);font-weight:700}
.tw-v{margin:5px 0 0;font-size:21px;font-weight:800;letter-spacing:-.03em;
  font-variant-numeric:tabular-nums}
.tw-v i{font-style:normal;color:var(--line);margin:0 3px}
.tw-s{margin:4px 0 0;font-size:12.5px;font-weight:600;color:var(--coffee)}

/* Clear of the rule under "this week": that block ends in a solid
   border, and a dashed target line immediately under it reads as a
   second rule rather than as part of the chart. */
.weeks{display:flex;align-items:flex-end;gap:4px;height:48px;
  margin:16px 0 6px}
/* The week's target, drawn across the twelve bars.

   The number was chosen in the onboarding and then never seen again, so
   the chart was a record of what happened with nothing to measure it
   against - which is the difference between a log and a goal. The line
   sits at --goal, a percentage of the same scale the bars use, and the
   scale is stretched to include the target so one that has never been
   reached still has somewhere to sit instead of clipping to the top.

   A week that met it is filled rather than outlined, because the useful
   question is not how tall the bar is but whether it got there. */
.weeks.aiming{position:relative}
.wkgoal{
  position:absolute; left:0; right:0; bottom:var(--goal); height:0;
  border-top:1.5px dashed var(--coffee); opacity:.75; pointer-events:none;
}
.wkgoal b{
  position:absolute; right:0; bottom:2px;
  font:700 9.5px Gabarito,system-ui,sans-serif; color:var(--coffee);
  font-variant-numeric:tabular-nums; letter-spacing:.04em;
}
.wk{flex:1;min-height:3px;height:max(3px,var(--h));border-radius:3px;
  background:var(--line);transition:background .15s}
.wk.has{background:var(--ink)}
.wk.met{background:var(--moss)}
.wk.now.has{background:var(--coffee)}
.wk.now:not(.has){background:var(--line);outline:1px dashed var(--line);outline-offset:1px}
.wkaxis{display:flex;justify-content:space-between;margin:0 0 18px;
  font-size:10.5px;color:var(--faint);font-weight:500}

/* The desktop collapse rule sets bottom:auto, which on a phone — where top is
   already auto — left the card with no anchor at all, so it fell to y=0 behind
   the search bar and took the locate button's gap calculation with it. */
@media (max-width:820px){
  #panel.min{top:auto;bottom:calc(var(--tabh) + env(safe-area-inset-bottom));
    max-height:none;height:auto}
}

/* The popup covers the route it is describing, so let the lines read through
   it. Blur keeps the text legible over busy map detail; without backdrop-filter
   support the same rule would just be a washed-out box, so it is gated. */
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .leaflet-popup-content-wrapper,
  .leaflet-popup-tip{
    background:color-mix(in srgb, var(--card) 78%, transparent);
    -webkit-backdrop-filter:blur(7px) saturate(1.4);
    backdrop-filter:blur(7px) saturate(1.4)}
}
/* Some people turn transparency off at the OS level; honour that. */
@media (prefers-reduced-transparency:reduce){
  .leaflet-popup-content-wrapper,
  .leaflet-popup-tip{background:var(--card);-webkit-backdrop-filter:none;backdrop-filter:none}
}

/* choosing the coffee this walk is for */
.pick{flex:none;display:grid;place-items:center;width:28px;height:28px;padding:0;
  border:0;background:none;cursor:pointer;color:var(--line);
  transition:color .15s,transform .08s}
.pick i{font-size:20px}
.pick:hover{color:var(--ink-2)}
.pick:active{transform:translateY(1px)}
.pick.on{color:var(--coffee)}
.pick:focus-visible{outline:2px solid var(--hot);outline-offset:1px;border-radius:999px}
.poi.picked .pname{color:var(--coffee)}
.row1{gap:6px}

/* the drive handoff sits above the on-foot actions */
.btn.nav{flex-direction:column;gap:2px;text-decoration:none;padding:11px 14px;
  background:var(--sunk);border-color:var(--ink)}
.btn.nav .navmain{display:flex;align-items:center;gap:7px;font-weight:600}
.btn.nav em{font-style:normal;font-size:11.5px;font-weight:500;color:var(--muted);
  letter-spacing:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.btn.nav:hover{background:var(--card)}
/* the content column has to fill the row, or space-between puts the pick
   control right after a short name instead of at the edge */
.poi > span:last-child{flex:1;min-width:0}
.row1{justify-content:space-between}

/* coffee before or after the walk */
.seg.ord{margin-top:2px}
.ord-b{flex:1}

/* ---------- starting point ---------- */
.originnow{margin:0 0 9px;font-size:13px;font-weight:600;letter-spacing:-.01em}
.originnow.unset{font-weight:500;color:var(--faint)}
.btn.small{flex:1;justify-content:center;padding:8px 10px;font-size:13px}
.plainsearch{margin-top:9px;border:1px solid var(--rule);border-radius:12px;
  background:var(--card);flex:none}
.plainsearch input{font-size:16px}   /* 16px or Safari zooms on focus */
.hits{margin-top:8px;border:1px solid var(--rule);border-radius:12px;overflow:hidden}
.hit{display:block;width:100%;text-align:left;border:0;background:none;cursor:pointer;
  padding:10px 12px;font:500 12.5px/1.4 Gabarito,system-ui,sans-serif;color:var(--ink);
  border-bottom:1px solid var(--line-2)}
.hit:last-of-type{border-bottom:0}
.hit:hover{background:var(--sunk)}
.hits .none{padding:10px 12px;margin:0}
.hits .attrib{border-top:1px solid var(--line-2);font-size:10.5px}

/* explicit pick-on-map mode */
body.picking #map{cursor:crosshair}
body.picking::after{content:"Tap the map to set your starting point";
  position:fixed;left:50%;transform:translateX(-50%);z-index:850;
  top:calc(var(--safe-top) + var(--chrome-h,112px) + 24px);
  background:var(--ink);color:var(--card);border-radius:999px;
  padding:9px 16px;font:600 13px Gabarito,system-ui,sans-serif;
  box-shadow:var(--lift-lg);pointer-events:none}
.btn.wide{width:100%;flex-direction:column;gap:3px;padding:12px;justify-content:center}
.btn.wide em{font-style:normal;font-size:11.5px;font-weight:500;color:var(--muted)}
/* straight-line connector: period 11, so a whole number of dashes per loop */
@keyframes routeflow-d{to{stroke-dashoffset:-22}}
.flow-d{animation:routeflow-d 1.6s linear infinite}
@media (prefers-reduced-motion:reduce){ .flow-d{animation:none !important} }

/* ================= motion ==============================================
   The app used to swap states instantly, which reads as a redraw rather than
   a move. Everything below is entrance-only and short — 200-320ms — so it
   feels responsive, not padded. Nothing loops except the route dashes. */
@keyframes riseIn{from{transform:translateY(10px);opacity:0}}
@keyframes sheetUp{from{transform:translateY(26px);opacity:0}}
@keyframes popIn{from{transform:scale(.9);opacity:0}}
@keyframes fadeIn{from{opacity:0}}
/* A sheet that opens on top of another one must not fade.
   Fading means transparent, and transparent over the walk sheet showed
   the map, the verdict and the car parks straight through "Log this
   walk" for the length of the animation - which on a phone reads as two
   screens fighting rather than one arriving. It slides instead, from
   below the fold, opaque the whole way. */
@keyframes sheetSlide{from{transform:translateY(100%)}}
/* The same arrival for the centred desktop dialog, which cannot borrow
   riseIn: that keyframe sets `transform` outright, and #logSheet is
   centred *with* a transform, so the first frame dropped the centring
   and the sheet flew in from the corner. */
@keyframes riseCentred{from{transform:translate(-50%,calc(-50% + 10px));opacity:0}}

#detail:not([hidden]){animation:riseIn .26s cubic-bezier(.16,1,.3,1)}

#logSheet:not([hidden]),#shareSheet:not([hidden]),#forSheet:not([hidden]),#pickSheet:not([hidden]){
  animation:riseCentred .24s cubic-bezier(.16,1,.3,1)}
#scrim:not([hidden]){animation:fadeIn .2s ease}
#landing:not([hidden]){animation:riseIn .24s cubic-bezier(.16,1,.3,1)}
/* A change of tab moves along the axis the tabs are arranged on, which
   is what makes a set of sections feel like one surface rather than
   four unrelated screens. Twenty-eight pixels and a fade: far enough
   to register as a direction, short enough that nobody is waiting for
   it. The transform is on an overflow-hidden box, so a slide never
   puts a sideways scrollbar on the page. */
/* Longer than it was, and further. At 28px over .28s the move was over
   before the eye had found it - technically a transition, practically a
   flicker. 38px over .46s is slow enough to read as one surface moving
   rather than two screens swapping, which is the whole point of it.

   The opacity runs ahead of the transform on purpose. Fading and moving
   on the same curve arrives twice, and the second arrival is the one
   that looks cheap; bringing the light up by 45% and letting the glide
   settle under it means the panel is readable while it is still coming
   to rest. The 70ms delay is the beat before it starts - small enough
   that nobody waits, long enough that the move reads as deliberate
   rather than as the page catching up - and it needs `backwards` or the
   panel sits at its final position through the delay and then jumps
   back to the start to animate. */
@keyframes tabFromRight{
  from{transform:translateX(38px);opacity:0}
  45%{opacity:1}
  to{transform:none;opacity:1}
}
@keyframes tabFromLeft{
  from{transform:translateX(-38px);opacity:0}
  45%{opacity:1}
  to{transform:none;opacity:1}
}
#tabBody{overflow-x:hidden}
#tabBody:not([hidden]){
  animation:tabFromRight .46s cubic-bezier(.16,1,.3,1) 70ms backwards}
#tabBody[data-slide="left"]:not([hidden]){
  animation:tabFromLeft .46s cubic-bezier(.16,1,.3,1) 70ms backwards}

@media (max-width:820px){
  #detail:not([hidden]){animation:sheetUp .3s cubic-bezier(.16,1,.3,1)}
  /* The modal sheets - the ones with a scrim, which are the ones that
     open over something else. */
  #forSheet:not([hidden]),#pickSheet:not([hidden]),#shareSheet:not([hidden]),
  #logSheet:not([hidden]){
    animation:sheetSlide .28s cubic-bezier(.16,1,.3,1)}
}

/* The route overlays redraw only when the walk or a pick changes, so they can
   fade without flickering on every pan. */
.rt-in{animation:fadeIn .32s ease both}
/* `animation` is one property, so a bare .rt-in would replace the dash flow
   rather than join it. Where both apply, declare them together. */
.flow-a.rt-in{animation:fadeIn .32s ease both, routeflow-a 1.1s linear infinite}
.flow-b.rt-in{animation:fadeIn .32s ease both, routeflow-b 1.3s linear infinite}
.flow-c.rt-in{animation:fadeIn .32s ease both, routeflow-c 1.5s linear infinite}
.flow-d.rt-in{animation:fadeIn .32s ease both, routeflow-d 1.6s linear infinite}
.leaflet-marker-icon.pop-in{animation:popIn .26s cubic-bezier(.34,1.4,.6,1) both}

/* Cards, chips and rows get a real transition rather than a hard swap. */
.chipctl,.tab,.mbtn,.pick,.star,.tagpick button,.seg button{
  transition:background .18s ease,color .18s ease,border-color .18s ease,
             transform .1s ease}
#results li{transition:background .16s ease,border-color .16s ease}
.poi,.logrow,.hit{transition:background .16s ease}
#panel,#detail{transition:max-height .3s cubic-bezier(.16,1,.3,1)}

@media (prefers-reduced-motion:reduce){
  #detail,#forSheet,#pickSheet,#logSheet,#scrim,#landing,#tabBody,
  .rt-in,.flow-a.rt-in,.flow-b.rt-in,.flow-c.rt-in,.flow-d.rt-in,
  .leaflet-marker-icon.pop-in{animation:none !important}
}

/* Where you actually are, as opposed to a starting point you picked. Red so it
   never reads as a walk, a cafe or a car park - none of which are red here. */
.medot{width:18px;height:18px;border-radius:50%;background:#E03131;
  border:3px solid #fff;box-shadow:0 0 0 2px rgba(224,49,49,.35),0 2px 6px rgba(0,0,0,.4)}
@media (prefers-reduced-motion:no-preference){
  .medot{animation:mepulse 2.4s ease-out infinite}
}
@keyframes mepulse{
  0%   {box-shadow:0 0 0 2px rgba(224,49,49,.45),0 2px 6px rgba(0,0,0,.4)}
  70%  {box-shadow:0 0 0 12px rgba(224,49,49,0),0 2px 6px rgba(0,0,0,.4)}
  100% {box-shadow:0 0 0 2px rgba(224,49,49,0),0 2px 6px rgba(0,0,0,.4)}
}
/* Reset stays put so the hand learns where it is; it just recedes when there
   is nothing filtered to clear. */
.chipctl.idle{border-color:var(--line);color:var(--muted);box-shadow:none}
.chipctl.idle i{color:var(--faint)}
.chipctl.idle:hover{border-color:var(--ink);color:var(--ink)}

/* Brand cup as the coffee marker. A drop-shadow rather than a border keeps the
   silhouette readable on the pale gray canvas and on streets alike. */
/* Top-rated coffee and walks: a gold star, the same one everywhere. */
.cupstar{position:relative;display:block}
.cupstar i{position:absolute;right:-7px;top:-6px;font-size:13px;color:var(--hot);
  filter:drop-shadow(0 0 1px #fff) drop-shadow(0 1px 1.5px rgba(0,0,0,.45))}
.tbadge i.fav{color:var(--hot)}
.crow .crate.top{color:var(--hot)}
.dscore{display:flex;align-items:center;gap:6px;margin:4px 0 10px;font-size:14px;color:var(--ink)}
.dscore i{font-size:16px;color:var(--hot)}
.dscore b{font:700 15px Gabarito,system-ui,sans-serif}
.dscore span{color:var(--muted)}
.dscore.none{font-size:13px}
.dscore.none i{color:var(--faint)}
.wscore{font-weight:700;color:var(--ink-2)}
.wscore.top{color:var(--maybe)}
/* A dark edge round every cup, so a coffee you can choose stands off the
   streets rather than sitting in them. */
.cupmark{display:block;filter:drop-shadow(0 0 .6px #1E2833) drop-shadow(0 0 .6px #1E2833)
                                drop-shadow(0 1px 2px rgba(0,0,0,.35))}

/* Failures that only live in a title attribute are invisible on a phone. */
#toast{position:fixed;z-index:960;left:50%;transform:translateX(-50%);
  top:calc(var(--safe-top) + var(--chrome-h,112px) + 26px);max-width:min(420px,calc(100vw - 32px));
  background:var(--ink);color:var(--card);border-radius:14px;padding:11px 16px;
  font:600 13.5px/1.45 Gabarito,system-ui,sans-serif;text-align:center;
  box-shadow:var(--lift-lg);animation:riseIn .22s cubic-bezier(.16,1,.3,1)}

/* Sheets are draggable by their grip. Without one they covered the map with no
   obvious way back to it, and the only exit was a small X in the corner. */
@media (max-width:820px){
  #forSheet .grip,#pickSheet .grip,#logSheet .grip{
    display:block;width:44px;height:5px;border-radius:5px;background:var(--line);
    margin:9px auto 2px;flex:none;cursor:grab;touch-action:none}
  #forSheet,#pickSheet,#logSheet{transition:transform .22s cubic-bezier(.16,1,.3,1)}
  .dragging{transition:none !important}
}

/* Walk badge: who it suits and how hard, right on the map. */
.tbadge{display:inline-flex;align-items:center;gap:4px;white-space:nowrap;
  background:var(--card);border:1px solid var(--rule);border-radius:999px;
  padding:2px 6px;box-shadow:0 1px 3px rgba(0,0,0,.28);transform:translate(6px,-50%)}
.tbadge i{font-size:12px;line-height:1;color:var(--ink)}
.tbadge.yes{border-color:var(--yes)}
.tbadge.maybe{border-color:var(--maybe)}
.tbadge.no{border-color:var(--no)}
.pips{display:inline-flex;gap:1.5px;align-items:center;margin-left:1px}
.pips b{width:3px;height:8px;border-radius:1px;background:var(--line)}
.pips b.on{background:var(--ink)}
.tbadge.yes .pips b.on{background:var(--yes)}
.tbadge.maybe .pips b.on{background:var(--maybe)}
.tbadge.no .pips b.on{background:var(--no)}

/* The dot colour is the app's answer, so it needs a key. Sits opposite the
   map buttons and tracks the top of whichever card is open. */
#legend{position:fixed;z-index:740;left:12px;bottom:16px;
  display:flex;flex-direction:column;gap:3px;
  background:var(--card);border:1px solid var(--rule);border-radius:12px;
  padding:8px 10px;box-shadow:var(--hard);pointer-events:none;
  font:600 11px/1.25 Gabarito,system-ui,sans-serif;letter-spacing:-.01em}
.lg-who{margin:0 0 3px;font-size:9.5px;letter-spacing:.07em;text-transform:uppercase;
  color:var(--faint);font-weight:700}
.lg-row{display:flex;align-items:center;gap:6px;color:var(--ink-2)}
.lg{width:9px;height:9px;border-radius:50%;flex:none;border:1.5px solid #fff;
  box-shadow:0 0 0 1px rgba(0,0,0,.18)}
.lg.yes{background:var(--yes)} .lg.maybe{background:var(--maybe)} .lg.no{background:var(--no)}
@media (max-width:820px){
  #legend{left:10px;padding:7px 9px;font-size:10.5px;
    bottom:calc(var(--tabh) + env(safe-area-inset-bottom) + 12px)}
}
@media (max-width:820px){
  #panel .grip{touch-action:none;padding:6px 0;margin:5px auto 0;
    width:44px;height:5px;background-clip:content-box}
  #panel{transition:max-height .26s cubic-bezier(.16,1,.3,1),
                    transform .22s cubic-bezier(.16,1,.3,1)}
}

/* A cafe you pass rather than detour to. */
.onway{margin-left:7px;font-size:9.5px;font-weight:700;letter-spacing:.05em;
  text-transform:uppercase;color:var(--yes);background:var(--yes-bg);
  border-radius:999px;padding:2px 7px;vertical-align:1px;white-space:nowrap}

.none.note{padding-top:10px;font-size:11.5px;line-height:1.5}

/* Choose a coffee stop straight from its map popup. */
.popbtn{display:block;width:100%;margin-top:9px;cursor:pointer;
  border:1px solid var(--rule);border-radius:10px;background:var(--card);
  color:var(--ink);padding:7px 10px;
  font:700 12.5px Gabarito,system-ui,sans-serif;letter-spacing:-.01em;
  transition:background .15s,transform .08s}
.popbtn:hover{background:var(--sunk)}
.popbtn:active{transform:translateY(1px)}
.popbtn.on{background:var(--coffee);border-color:var(--coffee);color:#fff}

/* Filter by what kind of place, and rank by rating. */

/* On-route coffee shown on the map with its rating, tappable to choose. */
.cupchoice{display:inline-flex;align-items:center;gap:3px;white-space:nowrap;
  background:var(--card);border:1.5px solid var(--ink);border-radius:999px;
  padding:1px 7px 1px 2px;box-shadow:0 1px 3px rgba(0,0,0,.3)}
.cupchoice img{display:block}
.cupchoice b{font:700 11px JetBrains Mono,monospace;letter-spacing:-.02em}
.cupchoice.on{background:var(--coffee);border-color:var(--coffee)}
.cupchoice.on b{color:#fff}
@media (max-width:820px){
  #detail .grip{touch-action:none;padding:6px 0;margin:5px auto 0;
    width:44px;height:5px;background-clip:content-box;cursor:grab}
  #detail{transition:max-height .26s cubic-bezier(.16,1,.3,1),
                     transform .22s cubic-bezier(.16,1,.3,1)}
}
/* Our route is the action; the maps handoff is the last step, not the headline. */
.sharerow .btn.nav{background:none;border-color:var(--line);box-shadow:none}
.sharerow .btn.nav .navmain{font-weight:600;font-size:13.5px}
.sharerow .btn.nav:hover{border-color:var(--ink);background:var(--sunk)}
/* ---------- what a popup says about a place ------------------------------
   It used to say everything in one sentence joined by middots, so the answer
   to "can I park" sat between the answer to "is it a chain" and a week of
   opening hours. Same facts, grouped: what it is, where the car goes, whether
   it is open now, and the links out - each with its own shape, so the eye
   goes to the one it came for. */
.popchips{display:flex;flex-wrap:wrap;gap:4px;margin-top:8px}
.popchips span{padding:3px 8px;border:1px solid var(--line);border-radius:999px;
  background:var(--card);color:var(--ink-2);white-space:nowrap;
  font:600 10.5px Gabarito,system-ui,sans-serif;letter-spacing:.02em}
.popfact{display:flex;align-items:center;gap:7px;margin-top:7px;
  font-size:12.5px;color:var(--ink-2);font-weight:600}
.popfact i{font-size:15px;color:var(--muted);flex:none}
.popfact.shut{color:var(--muted);font-weight:500}
/* Hours we could not read are shown as written rather than interpreted, so
   they wrap like the sentence they are. */
.popfact.raw{align-items:flex-start;font-size:11.5px;font-weight:500;color:var(--muted)}
.popfact.raw i{margin-top:1px}
.popnote{margin-top:7px;font:600 9.5px Gabarito,system-ui,sans-serif;
  letter-spacing:.06em;text-transform:uppercase;color:var(--faint)}
/* The links are a different kind of thing from the facts above them - they
   leave the app - so they sit below a line rather than in the same run. */
.leaflet-popup-content .plinks{margin-top:9px;padding-top:9px;
  border-top:1px solid var(--line-2)}

.poprate{display:inline-block;border:1.5px dashed var(--line);border-radius:999px;
  padding:1px 7px;font:700 11px JetBrains Mono,monospace;color:var(--muted);
  vertical-align:1px}
.tagpick.ents button{font-size:13px;padding:8px 14px}

/* Trail entrances, pickable on the map as well as in the list. */
.entpin{display:inline-flex;align-items:center;gap:4px;white-space:nowrap;
  background:var(--card);border:1px solid var(--rule);border-radius:999px;
  padding:2px 9px;font:700 11px Gabarito,system-ui,sans-serif;color:var(--muted);
  box-shadow:0 1px 3px rgba(0,0,0,.25);cursor:pointer;transform:translateY(-50%)}
.entpin:hover{border-color:var(--ink);color:var(--ink)}
.entpin.on{background:var(--ink);border-color:var(--ink);color:var(--card)}
.entpin.on i{font-size:12px;color:var(--hot)}

/* Entrances as a list of choices. As wrapping pills they broke across rows and
   read as tags rather than a decision. */
.entlist{display:flex;flex-direction:column;gap:0;margin-top:2px}
.entlist button{display:flex;align-items:center;gap:10px;width:100%;cursor:pointer;
  background:none;border:0;border-bottom:1px solid var(--line-2);
  padding:11px 2px;text-align:left;color:var(--ink);
  font:600 14px Gabarito,system-ui,sans-serif;letter-spacing:-.02em;
  transition:background .15s}
.entlist button:last-child{border-bottom:0}
.entlist button:hover{background:var(--sunk)}
.entlist button i{font-size:18px;color:var(--line);flex:none}
.entlist button.on i{color:var(--coffee)}
.entlist button.on span{color:var(--coffee)}
.entlist button span{flex:1;min-width:0}
.entlist button em{font-style:normal;font-size:11.5px;font-weight:500;
  color:var(--muted);font-family:JetBrains Mono,monospace;flex:none}
/* Say what each distance is measured from - the walk row is from you, the
   facility rows are from the walk, and one column made them look alike. */
.od i{display:block;font-style:normal;font-size:9.5px;font-weight:500;
  letter-spacing:.03em;text-transform:uppercase;color:var(--faint);margin-top:1px;
  text-align:right}

/* The button label must stay on one line, but its subtitle is a sentence and
   has to wrap. nowrap on the button was pushing the plan line out of both
   sides of it. */
.sharerow .btn{white-space:normal}
.sharerow .btn .navmain{white-space:nowrap}
.sharerow .btn em{display:block;white-space:normal;overflow-wrap:anywhere;
  max-width:100%;text-align:center;line-height:1.35;margin-top:2px}
/* Stack label over subtitle, matching the maps button underneath. */
#showRoute{flex-direction:column;gap:3px;padding:11px 14px}

/* A chosen stop is numbered and gold - it is part of the plan, not a
   suggestion. Everything unchosen stays quiet. */
.stoppin{display:inline-flex;align-items:center;gap:4px;white-space:nowrap;
  background:var(--hot);border:1px solid var(--rule);border-radius:999px;
  padding:2px 8px 2px 3px;box-shadow:0 2px 5px rgba(35,46,58,.35)}
.stoppin b{width:18px;height:18px;flex:none;display:grid;place-items:center;
  background:var(--ink);color:var(--hot);border-radius:50%;
  font:700 11px/1 JetBrains Mono,monospace}
.stoppin img{display:block}
.stoppin i{font-size:15px;color:var(--ink)}
.cupchoice.on{background:var(--hot);border-color:var(--ink)}
.cupchoice.on b{color:var(--ink)}
.stopno{width:17px;height:17px;flex:none;display:grid;place-items:center;
  background:var(--ink);color:var(--hot);border-radius:50%;
  font:700 10.5px/1 JetBrains Mono,monospace;margin-right:1px}
.popbtn.on{background:var(--hot);border-color:var(--ink);color:var(--ink)}

/* ---------- the cup, properly ----------
   Thin cream line on deep navy, generous space, almost nothing filled. The
   only solid areas left are the ones that mean "this is chosen". */
.tab{position:relative}
#chrome{gap:12px}
.bar{box-shadow:var(--hard)}
.search{background:transparent;border:1px solid var(--rule)}
.bar-row{padding:9px}
.chipctl{box-shadow:none}
.chipctl:hover{background:transparent;border-color:var(--ink)}
#tabs{box-shadow:0 -1px 0 var(--rule);border:0;border-top:1px solid var(--rule);
  border-radius:0;background:var(--card)}
.mbtn{box-shadow:var(--hard)}
#legend{box-shadow:var(--hard)}

/* Uppercase, letterspaced, small — the way the cup sets its secondary type. */
.dsec h3,.lbl,.ok,.tw-k,.lg-who,.tmain em,.tbody span{
  letter-spacing:.12em;font-weight:600}
#detailBody h2{letter-spacing:-.02em;font-weight:700}

/* Verdict and difficulty read as line, not as blocks of colour. */
.verdict{background:transparent;border-color:var(--rule)}
.verdict.yes{box-shadow:inset 3px 0 0 var(--yes)}
.verdict.maybe{box-shadow:inset 3px 0 0 var(--maybe)}
.verdict.no{box-shadow:inset 3px 0 0 var(--no)}
.chip,.gf{background:transparent;box-shadow:inset 0 0 0 1px var(--rule)}
.gf{color:var(--ink)}

/* The map is the one place colour is allowed to do work. */
.leaflet-container{background:var(--sunk)}
.stoppin em{font-style:normal;font:700 11px JetBrains Mono,monospace;
  color:var(--ink);padding-right:2px}

/* ---------- one selected state, everywhere ----------
   Gold ground, navy ink, navy rule. The map already says "chosen" this way
   with its numbered stops; every control now says it the same way, so
   selection is one thing you learn once rather than six variations. */
.chipctl.on,

.tagpick button.on,
.seg button.on,
.ord-b.on, .when.on,

.entlist button.on,
.tab.on{
  background:var(--hot);
  color:var(--ink);
  border-color:var(--ink);
  box-shadow:none;
}
.chipctl.on i,.tab.on i{color:var(--ink)}

.seg button.on em{color:var(--ink)}

/* The tab bar carries it as a rounded plate rather than a full-bleed block. */
.tab.on{border-radius:10px}
.tab.on::after{display:none}

/* A chosen row in a list is gold too, so lists and chips agree. */
.entlist button.on{border-radius:10px;padding-left:8px;padding-right:8px}
.entlist button.on i,.entlist button.on span{color:var(--ink)}
.mrow.sel{background:var(--hot)}
#results li.sel{background:var(--hot);border-color:var(--ink)}
.poi.picked .pname{color:var(--ink)}
.pick.on{color:var(--ink)}
.pick.on i{background:var(--hot);border-radius:50%}

/* Stars and the rating chip follow the same rule. */
.star.lit{background:var(--hot);border-color:var(--ink);color:var(--ink)}
/* Gold means chosen everywhere else in this app, so a rating that has not
   even been fetched must not wear it: the placeholder dot was rendering as a
   filled gold pill and every row looked selected. Gold only once there is a
   number in it. */

/* Starting point: a list of ways to answer one question, not two squashed
   buttons with their icons landing on the label. */
.startlist{display:flex;flex-direction:column;margin:2px 0 12px}
.startlist button{display:flex;align-items:center;gap:11px;width:100%;cursor:pointer;
  background:none;border:0;border-bottom:1px solid var(--rule);
  padding:12px 2px;text-align:left;color:var(--ink);
  font:600 14px Gabarito,system-ui,sans-serif;letter-spacing:-.01em;
  transition:background .15s}
.startlist button:last-child{border-bottom:0}
.startlist button:hover{background:var(--sunk)}
.startlist button i{font-size:18px;color:var(--muted);flex:none}
.startlist button span{flex:1;min-width:0}
.startlist button em{font-style:normal;font-size:11px;font-weight:600;
  letter-spacing:.08em;text-transform:uppercase;color:var(--faint);flex:none}
.originnow{margin:0 0 10px;font-size:15px;font-weight:700;letter-spacing:-.02em}
.plainsearch{margin-top:0}
.btn.wide2{width:100%;justify-content:center;margin-top:14px}
/* The way in for somebody back from a walk rather than planning one. It
   sits first on the tab because for them it is the only thing on it -
   and on wide2 rather than wide, which stacks its label under the icon
   for the sake of the "opens in Maps" line this button does not have. */
.btn.logadd{margin:0 0 18px}

.dsec h3{align-items:baseline;flex-wrap:nowrap;gap:12px}
.dsec h3 span{flex:0 1 auto;min-width:0;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;text-align:right}

/* ---------- walk photographs ---------- */
/* A short strip you swipe. Scroll-snap does the work, so a finger behaves
   natively and the whole thing survives with JavaScript doing nothing but
   moving the dots. Kept to a shallow band so the picture sets the place
   without pushing the grading - which is what the sheet is for - below the
   fold. */
.wphoto{
  position:relative; margin:0 0 14px; border-radius:14px; overflow:hidden;
  background:var(--sunk); border:1px solid var(--line);
}
.wtrack{
  display:flex; overflow-x:auto; scroll-snap-type:x mandatory;
  scrollbar-width:none; -webkit-overflow-scrolling:touch;
}
.wtrack::-webkit-scrollbar{display:none}
.wtrack:focus-visible{outline:2px solid var(--hot); outline-offset:-2px}
.wslide{margin:0; flex:0 0 100%; scroll-snap-align:center; position:relative}
.wslide img{
  display:block; width:100%; height:auto; aspect-ratio:3/2; max-height:340px;   /* the shape of a photo: it cut the bottom off (Oct 2026) */
  object-fit:cover; background:var(--sunk);
  /* Above the middle, because that is where the photograph is.

     A portrait phone photo in this letterbox keeps about a third of
     itself, and cover takes that third from the centre - which on a
     picture of a path is a band of tarmac and grass, with the trees,
     the horizon and whatever the place is known for all cropped off the
     top. Mungret Park led with a close-up of its own path surface.

     20%, measured against both shapes rather than picked: a fifth of
     the way down keeps the path underfoot while bringing the trees and
     the old college into frame. The 4:3 pictures from Commons already
     fill most of the window, so the same number moves them a little and
     crops nothing anybody would miss. */
  object-position:50% 45%;   /* near the middle now the frame is photo-shaped */
}
/* Credit sits in the corner of the picture: the licence requires it, the
   photograph should not have to carry a strip of small print for it. */
.wcredit{
  position:absolute; right:8px; bottom:8px; z-index:2;
  width:20px; height:20px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:rgba(35,46,58,.55); color:#F5F0E7; text-decoration:none;
  font:italic 700 11px Gabarito,system-ui,sans-serif;
  backdrop-filter:blur(3px); transition:background .15s ease;
}
.wcredit:hover{background:rgba(35,46,58,.85)}
.wcredit:focus-visible{outline:2px solid var(--hot); outline-offset:2px}

/* Dots sit on the image, above the caption strip. */
.wdots{
  position:absolute; left:0; right:0; top:calc(min(100cqw * 2 / 3, 340px) - 18px);
  display:flex; justify-content:center; gap:5px; pointer-events:none;
}
.wdots i{
  width:6px; height:6px; border-radius:50%; pointer-events:auto; cursor:pointer;
  background:rgba(245,240,231,.55); box-shadow:0 0 0 1px rgba(35,46,58,.25);
  transition:background .2s ease, transform .2s ease;
}
.wdots i.on{background:var(--hot); transform:scale(1.25)}
@media (prefers-reduced-motion:reduce){
  .wtrack{scroll-behavior:auto}
  .wdots i{transition:none}
}

/* ---------- walk summary ---------- */
/* Sits under the place line as the first thing read after the name. Sport
   Ireland's own writing gets room to breathe; a line assembled from the data
   is short by nature and needs none. */
.dsum{
  margin:-2px 0 16px; font-size:13.5px; line-height:1.55;
  color:var(--ink); opacity:.78; max-width:62ch;
}
.dsum.sourced{
  display:-webkit-box; -webkit-line-clamp:4; -webkit-box-orient:vertical;
  overflow:hidden;
}

/* ---------- hover preview ---------- */
/* The glow is a filter on the wide underlay only, so the bright line on top
   stays crisp instead of blurring with it. */
.glowline{filter:drop-shadow(0 0 6px rgba(217,164,65,.85))}
@media (prefers-reduced-motion:no-preference){
  .glowline{animation:glowpulse 1.8s ease-in-out infinite}
}
@keyframes glowpulse{
  0%,100%{opacity:.30}
  50%{opacity:.55}
}
/* Cup preview: a label, not a popup - no close button, no pointer capture. */
.cuptip.leaflet-tooltip{
  background:var(--card); color:var(--ink);
  border:1px solid var(--ink); border-radius:9px;
  padding:5px 9px; box-shadow:0 3px 10px rgba(35,46,58,.18);
  font:700 12px Gabarito,system-ui,sans-serif; white-space:nowrap;
}
.cuptip.leaflet-tooltip b{display:block; font-weight:800; letter-spacing:-.01em}
.cuptip.leaflet-tooltip i{
  display:block; font-style:normal; font-weight:600; font-size:10.5px;
  color:var(--ink); opacity:.6; margin-top:1px;
}
.cuptip.leaflet-tooltip::before{border-top-color:var(--ink)}

/* ---------- phone ergonomics ---------- */
/* Measured on a 390x844 screen. Everything you tap was between 32 and 41px,
   under the 44px that a thumb reliably hits, and the smallest text was 9.5px.
   Both are cheap to fix and neither changes the layout. */
@media (max-width:820px){
  .chipctl{min-height:44px}
  #collapse,.icon{min-width:44px;min-height:44px}
  .sheetfoot .btn,.btn.solid,.btn.ghost{min-height:46px}
  .tagpick button,.seg button{min-height:38px}
  /* 9.5px is a design detail on a desktop and unreadable on a phone. */
  .dsum,.ptags,.wslide figcaption,.landnote{font-size:11.5px}
  .lg-who,.dsec h3,.lbl{font-size:11px}
  .stat span{font-size:11px}
}

/* ---------- foldable reference sections ---------- */
.dsec.ref{padding:0}
.dsec.ref>summary{

  list-style:none; cursor:pointer; display:block;
  padding:11px 0; min-height:44px;
}
.dsec.ref>summary::-webkit-details-marker{display:none}

.dsec.ref>summary h3{margin:0; display:flex;

  align-items:baseline; justify-content:space-between; gap:10px}
/* A caret that turns, so the row reads as something that opens. */
.dsec.ref>summary h3::after{

  content:''; flex:none; width:7px; height:7px; margin-left:2px;
  border-right:1.5px solid currentColor; border-bottom:1.5px solid currentColor;
  transform:rotate(45deg) translateY(-2px); opacity:.45;
  transition:transform .18s ease;
}
.dsec.ref[open]>summary h3::after{transform:rotate(-135deg) translateY(-2px)}

.dsec.ref>summary:focus-visible{outline:2px solid var(--hot); outline-offset:-2px}

#detailBody{padding-bottom:26px}

/* ---------- adding a missing coffee shop ---------- */
/* ---------- waiting ------------------------------------------------------
   A shimmer is not decoration here. It says the shape of what is coming, so
   the list lands into a space that was already the right shape. */
@keyframes shimmer{to{background-position:-200% 0}}
.skel{list-style:none;padding:13px 14px;border-bottom:1px solid var(--line)}
.skel span{display:block;height:11px;border-radius:6px;
  background:linear-gradient(90deg,var(--sunk) 25%,var(--line) 37%,var(--sunk) 63%);
  background-size:200% 100%;animation:shimmer 1.5s linear infinite}
.skel .s1{width:58%;height:14px;margin-bottom:9px}
.skel .s2{width:82%}
.skel .s3{width:40%;margin-top:7px}

/* Rows arrive as a run rather than all at once. Capped at eight steps: a
   stagger that keeps counting to 120 stops being an entrance and becomes a
   wait. */
#results li:not(.skel){
  animation:riseIn .30s cubic-bezier(.2,.7,.3,1) both;
  animation-delay:calc(var(--i,0) * 26ms);
}
@media (prefers-reduced-motion:reduce){
  .skel span{animation:none}
  #results li:not(.skel){animation:none}
}

/* ---------- which buggy ---------------------------------------------------
   The row states the answer and opens the question. Folded shut by default:
   on most walks the answer is "any of them", and a picker on every walk is
   four buttons of noise between you and the verdict. */
.buggyrow{margin-top:11px;border:1px solid var(--line);border-radius:12px;
  background:var(--card);overflow:hidden}
.buggyrow > summary{display:flex;align-items:center;gap:10px;cursor:pointer;
  list-style:none;padding:10px 12px}
.buggyrow > summary::-webkit-details-marker{display:none}
.buggyrow > summary > i{font-size:20px;flex:none;color:var(--muted)}
.buggyrow summary span{min-width:0}
.buggyrow summary b{display:block;font-size:13px;font-weight:700;letter-spacing:-.01em}
.buggyrow summary em{display:block;font-style:normal;font-size:11.5px;
  font-weight:500;color:var(--muted);margin-top:2px}
.buggyrow.bg-ok > summary > i{color:var(--coffee)}
.buggyrow.bg-warn{border-style:dashed}
.buggyrow.bg-warn > summary > i{color:var(--muted)}
.buggyrow.bg-no{border-color:var(--ink);border-width:1.5px}
.buggyrow.bg-no > summary > i{color:var(--ink)}
.buggyrow.bg-unknown{border-style:dashed}
.buggyopts{display:flex;flex-direction:column;gap:7px;padding:2px 10px 11px}
.pickone.bg{align-items:flex-start}
.pickone.bg .bgeg{display:block;font-style:normal;font-size:10.5px;
  color:var(--faint);margin-top:3px;letter-spacing:.02em}
.pfnote{margin:0 0 9px;font-size:12px;color:var(--muted);line-height:1.45}

/* The drive-through toggle carries its own count, because there are 25 of
   these in the country and the honest thing is to say so before it is tapped
   rather than after it empties the list. */

/* Not gold, because it does not go anywhere yet - but not dead either: it is
   the way to the question it is waiting on. */
.btn.nav.locked{background:var(--sunk);border-color:var(--rule);color:var(--ink-2);
  box-shadow:none;cursor:pointer}
.btn.nav.locked:hover{border-color:var(--ink);color:var(--ink)}
.btn.nav.locked .navmain{color:inherit}
.btn.nav.locked em{color:var(--muted);opacity:1}

#map.picking{cursor:crosshair}
#toast a{color:var(--hot); text-decoration:underline; text-underline-offset:2px}
/* A way out of the toast, not a second sentence in it. */
.toastact{margin-left:12px;padding:0;border:0;background:none;cursor:pointer;
  font:inherit;font-weight:700;color:var(--hot);
  text-decoration:underline;text-underline-offset:2px}

/* The log sheet's photo row. The thumbnail is the reassurance: you see
   what the card will carry before anything leaves the phone. */
.logphoto{margin:0}
/* Offering the photograph for the walk itself. Opt in, and worded so
   that what happens to it is on the same line as the switch. */
.offer{display:flex;gap:10px;align-items:flex-start;margin:12px 0 0;
  padding:11px 12px;border:1px dashed var(--rule);border-radius:12px;
  cursor:pointer}
.offer input{margin:2px 0 0;flex:none;width:17px;height:17px;accent-color:var(--yes)}
.offer b{display:block;font-size:13px;font-weight:700}
.offer em{display:block;font-style:normal;font-size:11.5px;line-height:1.5;
  color:var(--muted);margin-top:2px}
.logshot{margin-top:10px;border-radius:12px;overflow:hidden;border:1px solid var(--rule);
  max-height:190px;display:flex;align-items:center;justify-content:center;
  background:var(--sunk)}
.logshot img{width:100%;height:auto;max-height:190px;object-fit:cover;display:block}

/* "Walked it already? Log it" - the quiet way into the log from a walk
   that is open, now that the pane is about going rather than having
   gone. */
/* The card, on a walk already logged. An icon because the row is a row
   and a second label would make it a form. */
.cardbtn{flex:none;margin-left:10px;width:34px;height:34px;display:flex;
  align-items:center;justify-content:center;cursor:pointer;
  border:1px solid var(--rule);border-radius:10px;
  background:var(--card);color:var(--ink)}
.cardbtn:hover{background:var(--sunk)}
.cardbtn.undo{margin-left:6px}
.cardbtn.undo:hover{border-color:var(--no);color:var(--no)}
.cardbtn i{font-size:16px}

/* Offered only to somebody who arrived on a walk from a friend's link
   and has never said who they walk with. The grades above are the app's
   whole argument and they are generic until this is answered. */
/* Four words and three badges on the payoff screen. Deliberately the
   quietest line on it - the walk is the offer, this is the reason to
   come back and say you did it. */
/* The marks on the "then it keeps count" screen. Round rather than the
   map-button square of the screen before it, because these are not
   buttons - nothing here is tappable, it is a list of what the app does
   once a walk is behind you. */
.obic{flex:none;width:38px;height:38px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:var(--sunk);color:var(--ink)}
.obic i{font-size:19px}

.ob-badges{display:flex;align-items:center;gap:10px;margin-top:12px;
  font-size:12.5px;font-weight:600;color:var(--muted);
  animation:riseIn .4s both;animation-delay:calc(.08s * var(--i, 0))}
.obbs{display:flex;gap:5px}
.obb{display:flex;align-items:center;justify-content:center;
  width:26px;height:26px;border-radius:50%;
  background:var(--sunk);color:var(--faint)}
.obb i{font-size:15px}
.obb.lit{background:var(--hot);color:var(--ink)}

/* The way back tomorrow, offered to somebody who arrived on a link.
   A bar at the foot of the map rather than a dialog over it: they came
   to look at a walk, not to install anything. */
#getapp{position:fixed;z-index:940;left:12px;right:12px;
  bottom:calc(var(--safe-bottom, 0px) + 74px);
  display:flex;align-items:center;gap:10px;
  padding:10px 10px 10px 14px;border-radius:14px;
  background:var(--ink);color:var(--card);
  font:600 13.5px/1.35 Gabarito,system-ui,sans-serif;
  box-shadow:var(--lift-lg);animation:riseIn .24s cubic-bezier(.16,1,.3,1)}
#getapp span{flex:1;min-width:0}
#getapp .ga-go{flex:none;cursor:pointer;font:inherit;font-weight:700;
  padding:7px 14px;border:0;border-radius:10px;
  background:var(--hot);color:var(--ink)}
#getapp .ga-no{flex:none;cursor:pointer;width:30px;height:30px;padding:0;
  display:flex;align-items:center;justify-content:center;
  border:0;border-radius:8px;background:none;color:var(--card);opacity:.7}
#getapp .ga-no:hover{opacity:1}

.whoprompt{margin:10px 0 0}
.whoprompt button{width:100%;padding:10px 12px;cursor:pointer;font:inherit;
  font-size:13px;font-weight:600;color:var(--ink);
  border:1px dashed var(--rule);border-radius:12px;background:none}
.whoprompt button:hover{background:var(--sunk)}

/* ---- logging the walk --------------------------------------------------

   It was an underlined line of muted 13px text at the very bottom of the
   sheet, which is where you put something you would rather nobody did.
   Logging is the one habit the app actually needs: the streak, the
   badges and the week's target all count logged walks and nothing else
   counts them, so a walk that is not logged is a walk the app cannot
   reward. Hiding the only way to do that under everything else was the
   app asking for the habit in a whisper.

   A real control now, and it says what it buys rather than what it is.
   Outlined rather than filled: "Let's go" is the filled one on this
   screen and there cannot be two. */
/* Not a .btn, deliberately. .btn b is the badge-count pill - 20px tall,
   gold, fully rounded - so the label inside this one came out as a thin
   gold strip with the subtitle under it, which is what "very thin" was.
   It has its own two lines and its own shape. */
.logit{
  display:flex; align-items:center; gap:11px; width:100%;
  min-height:60px; margin:16px 0 0; padding:12px 14px;
  border:1.5px solid var(--rule); border-radius:12px;
  background:var(--paper); color:var(--ink); cursor:pointer; text-align:left;
  font:inherit;
  transition:background .15s, border-color .15s, transform .1s;
}
.logit i{flex:none; font-size:21px; color:var(--moss)}
.logit b{display:block; font:700 14.5px Gabarito,system-ui,sans-serif}
.logit em{font-style:normal; font-size:12.5px; line-height:1.4; color:var(--muted)}
.logit:hover{background:var(--sunk); border-color:var(--ink-2)}
.logit:active{transform:scale(.995)}
.logit:focus-visible{outline:2px solid var(--hot); outline-offset:2px}
.logit[disabled]{opacity:.5; cursor:default}
.logit[disabled]:hover{background:var(--paper); border-color:var(--rule)}

.didline{margin:14px 0 0;text-align:center}
.didline button{border:0;background:none;padding:6px 10px;cursor:pointer;
  font:inherit;font-size:13px;font-weight:600;color:var(--muted);
  text-decoration:underline;text-underline-offset:3px}
.didline button:hover{color:var(--ink)}
.didline button[disabled]{text-decoration:none;color:var(--faint);cursor:default}

/* ---------- the map answering you ---------- */
/* While the map is moving the count is about to be wrong, so it steps back
   rather than asserting a stale number. */
#count{transition:opacity .18s ease, color .18s ease}
#count.settling{opacity:.4}
/* And when the number changes, it says so once, quietly. */
@media (prefers-reduced-motion:no-preference){
  #count.landed{animation:countland .5s ease}
}
@keyframes countland{
  0%{opacity:.4; transform:translateY(-2px)}
  40%{opacity:1; color:var(--hot)}
  100%{opacity:1; transform:none}
}

/* Starting point: one line once it is known. */
.originchange{
  background:none; border:0; padding:0; margin:-8px 0 0; cursor:pointer;
  color:var(--muted); font:600 12px Gabarito,system-ui,sans-serif;
  text-decoration:underline; text-underline-offset:3px; min-height:32px;
}
.originchange:hover{color:var(--ink)}
.originchange[hidden]{display:none}
#startList[hidden],#originSearch[hidden]{display:none}
/* A refusal makes the fallbacks the point, so it drops down the list. */
.startlist #originHere.demoted{order:9; opacity:.6}
.startlist{display:flex; flex-direction:column}

/* A stop that only might do coffee: dashed like every other provisional thing
   in this app, with a storefront instead of a cup. */
.cupchoice.maybe{
  border-style:dashed; border-color:var(--rule);
  background:var(--sunk); opacity:.9;
}
.cupchoice.maybe i{font-size:15px; color:var(--muted); margin:0 1px 0 3px}
.cupchoice.maybe b{color:var(--muted); font-weight:600}

/* How far away, under the place line where the question is asked. */
.dtravel{
  display:flex; align-items:center; gap:6px;
  margin:-10px 0 14px; font-size:12.5px; font-weight:600;
  color:var(--ink); opacity:.72;
}
.dtravel i{font-size:14px; opacity:.8}

/* Alternatives in the route view: readable, not loud. */
/* Smaller, but not faded: a faint cup read as part of the street map,
   not as something to tap. The ink ring is what says "choose me". */
.cupchoice.quiet{
  transform:scale(.86); transform-origin:left center;
}
.cupchoice.quiet:hover{opacity:1}

/* What people said: quotes, not another score to weigh. */
.rev{margin:0 0 12px; padding:0 0 0 12px; border-left:2px solid var(--line)}
.rev p{margin:0 0 4px; font-size:13px; line-height:1.5; color:var(--ink); opacity:.85}
.rev cite{font-style:normal; font-size:11px; color:var(--muted)}
.reviews summary h3 span{text-transform:none; letter-spacing:0; font-size:11.5px}

/* Stages: a list of walks inside a route. */
.stagelist{display:flex; flex-direction:column; gap:2px; margin-top:4px}
.stage{
  display:grid; grid-template-columns:26px minmax(0,1fr) auto;
  align-items:center; gap:9px; width:100%; min-height:44px;
  padding:7px 4px; cursor:pointer; text-align:left;
  background:none; border:0; border-bottom:1px solid var(--line);
  color:var(--ink); font:inherit;
}
.stage:last-child{border-bottom:0}
.stage:hover{background:var(--sunk)}
.stage.on{background:var(--hot)}
.stage .sn{
  display:flex; align-items:center; justify-content:center;
  width:22px; height:22px; border-radius:50%; background:var(--sunk);
  font:700 11px 'JetBrains Mono',ui-monospace,monospace;
}
.stage.on .sn{background:var(--card)}
.stage .sw{min-width:0}
.stage .sw b{
  display:block; font-size:13px; font-weight:700; letter-spacing:-.01em;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.stage .sw i{display:block; font-style:normal; font-size:10.5px; color:var(--muted)}
.stage.on .sw i{color:var(--ink); opacity:.7}
.stage .sk{
  font:600 12px 'JetBrains Mono',ui-monospace,monospace; white-space:nowrap;
}
.stages summary h3 span{text-transform:none; letter-spacing:0; font-size:11.5px}

/* A verdict that rests on somebody else's statement says so. */
.statednote{
  display:flex; gap:7px; align-items:flex-start;
  margin:0 0 14px; padding:9px 11px; border-radius:10px;
  background:var(--sunk); border:1px solid var(--line);
  font-size:12px; line-height:1.45; color:var(--ink); opacity:.85;
}
.statednote i{font-size:15px; flex:none; margin-top:1px; color:var(--yes)}

/* Find a coffee shop by name, inside the picker. */
.search.cafefind{margin:0 0 10px}
.search.cafefind input{font-size:13px}

/* ---------- first run --------------------------------------------------- */
/* Four questions, once, before the map. Everything it sets is a setting the
   app already had - this is a front door, not a second configuration. */
/* Nothing behind the onboarding is painted until the onboarding is up.
   visibility rather than display, so the map still sizes itself correctly
   and does not have to re-lay-out when it is let through. See the inline
   script in index.html for why this exists at all. */
html[data-onboarding] body > *:not(#onboard){visibility:hidden}
#onboard{position:fixed;inset:0;z-index:900;background:var(--card);
  display:flex;flex-direction:column}
#onboard[hidden]{display:none}
.obhead{flex:none;padding:calc(22px + env(safe-area-inset-top)) 22px 6px;
  max-width:560px;margin:0 auto;width:100%}
.obstep{font:700 10.5px Gabarito,system-ui,sans-serif;letter-spacing:.11em;
  text-transform:uppercase;color:var(--faint)}
.obhead h1{margin:7px 0 0;font-size:26px;font-weight:800;letter-spacing:-.035em;
  line-height:1.12;text-wrap:balance}
.obbody{flex:1;min-height:0;overflow-y:auto;padding:16px 22px 4px;
  max-width:560px;margin:0 auto;width:100%}
.obdots{display:flex;gap:5px;justify-content:center;padding:10px 0 0}
.obdots i{width:6px;height:6px;border-radius:50%;background:var(--line);
  transition:width .2s,background .2s}
.obdots i.on{background:var(--ink);width:18px;border-radius:999px}
/* Wraps, because the reassurance under the button is a second row and
   without this it fights the buttons for the same one. */
.obfoot{flex:none;display:flex;flex-wrap:wrap;gap:9px;
  padding:12px 22px calc(16px + env(safe-area-inset-bottom));
  max-width:560px;margin:0 auto;width:100%}
.obfoot .btn{flex:1;justify-content:center}
.obfoot .btn.solid{flex:2}

.obbrand{display:flex;flex-direction:column;align-items:center;padding:0 0 12px}
.obbrand img{width:60px;height:60px;border-radius:50%;border:1px solid var(--rule)}
.obbrand b{margin-top:11px;font:800 19px Gabarito,system-ui,sans-serif;
  letter-spacing:.3em;text-indent:.3em;text-transform:uppercase}
.obbrand em{margin-top:5px;font:600 9.5px Gabarito,system-ui,sans-serif;font-style:normal;
  letter-spacing:.34em;text-indent:.34em;color:var(--muted);text-transform:uppercase}

.pickone{display:flex;align-items:center;gap:12px;width:100%;text-align:left;
  cursor:pointer;background:var(--paper);border:1.5px solid transparent;
  border-radius:13px;padding:13px 14px;margin-bottom:8px;font:inherit;color:inherit}
.pickone.on{border-color:var(--ink);background:var(--sunk)}
.pickone > i:first-child{font-size:22px;color:var(--muted);flex:none}
.pickone.on > i:first-child{color:var(--ink)}
.pickone span{flex:1;min-width:0}
.pickone b{display:block;font-size:14.5px;font-weight:700}
.pickone em{font-style:normal;font-size:11.5px;color:var(--muted);line-height:1.35}
.pickone .box{width:22px;height:22px;border-radius:7px;border:1.5px solid var(--rule);
  flex:none;display:grid;place-items:center;font-size:13px}
.pickone.on .box{background:var(--ink);border-color:var(--ink);color:var(--card)}
.obnote{margin:10px 0 0;font-size:11.5px;color:var(--muted);line-height:1.5;
  background:var(--paper);border-radius:10px;padding:10px 12px}

.confirm{display:grid;grid-template-columns:1fr 1fr;gap:9px;margin:0 0 6px}
.ctile{display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:6px;padding:16px 10px;border-radius:14px;background:var(--sunk);
  border:1.5px solid var(--rule);text-align:center}
.ctile i{font-size:26px;color:var(--ink)}
.ctile b{font-size:13px;font-weight:700;line-height:1.2}
.ctile em{font-style:normal;font-size:10.5px;color:var(--muted);line-height:1.3}
.ctile.wide{grid-column:span 2;flex-direction:row;justify-content:flex-start;
  gap:11px;text-align:left;padding:13px 14px}
.ctile.wide i{font-size:21px;flex:none}
.ctile.wide span{display:block}
.ctile.wide b{display:block;margin-bottom:2px}
.ctile.soft{background:var(--paper);border-style:dashed}
.csec{margin:16px 0 7px;font:700 10.5px Gabarito,system-ui,sans-serif;
  letter-spacing:.1em;text-transform:uppercase;color:var(--faint)}
.csec:first-child{margin-top:0}
.chiprow{display:flex;flex-wrap:wrap;gap:7px}
.chiprow span{display:flex;align-items:center;gap:6px;padding:8px 12px;
  border-radius:999px;background:var(--sunk);border:1px solid var(--rule);
  font-size:12.5px;font-weight:700}
.chiprow span i{font-size:15px;color:var(--muted)}

/* ---------- route preview ----------------------------------------------- */
#steps{position:fixed;z-index:830;left:0;right:0;bottom:calc(var(--tabh) + env(safe-area-inset-bottom));
  background:var(--card);border-top:1px solid var(--rule);
  box-shadow:0 -6px 22px rgba(0,0,0,.14);padding:12px 14px 14px;
  transform:translateY(120%);transition:transform .28s cubic-bezier(.16,1,.3,1)}
#steps[hidden]{display:none}
#steps.up{transform:none}
/* Preview is the last screen before Maps: the walk, the plan tabs, the search
   bar and the tab bar all step out of the way, so what is left is the journey
   and two choices - go, or go back. */
body.previewing #panel,body.previewing #detail,
body.previewing #chrome,body.previewing #mapctl,body.previewing #legend,
body.previewing #tabs{
  opacity:0;pointer-events:none;transition:opacity .2s}
body.previewing #steps{bottom:0}
.strip{display:flex;align-items:center;gap:0;margin:0 0 11px}
.stp{flex:1;display:flex;flex-direction:column;align-items:center;gap:4px;
  background:none;border:0;cursor:pointer;color:var(--muted);padding:0}
.stp .bub{width:34px;height:34px;border-radius:50%;display:grid;place-items:center;
  border:1.5px solid var(--rule);background:var(--card);font-size:16px}
.stp b{font:700 10px Gabarito,system-ui,sans-serif;max-width:78px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.stp.on{color:var(--ink)}
.stp.on .bub{background:var(--hot);border-color:var(--ink);color:var(--ink);transform:scale(1.12)}
.stp.done .bub{border-color:var(--ink);color:var(--ink)}
.leg{flex:none;width:22px;height:2px;background:var(--rule);margin-top:-14px}
.leg.done{background:var(--ink)}
.stepnow{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;margin:0 0 11px;
  font-size:12.5px;color:var(--muted);line-height:1.35}
.stepnow b{font-size:14px;font-weight:800;color:var(--ink);letter-spacing:-.02em}
/* The "@" is punctuation, not emphasis - it should join the two words rather
   than compete with them. */
.stepnow b i{font-style:normal;font-weight:600;color:var(--muted);
  padding:0 1px;letter-spacing:.02em}

/* How long this leg takes, beside the name of the stop it ends at. While the
   journey is playing the question in your head is "how far is that", so it
   reads before the description, and it is a pill rather than more grey text
   because it is the number you are waiting for. */
.stepnow .leglen{display:inline-flex;align-items:center;gap:5px;font-style:normal;
  padding:3px 9px;border-radius:999px;background:var(--sunk);
  border:1px solid var(--line);color:var(--ink-2);
  font:700 11.5px 'JetBrains Mono',ui-monospace,monospace;
  font-variant-numeric:tabular-nums;white-space:nowrap}
.stepnow .leglen i{font-size:13px;color:var(--muted)}
/* Two rows: what you might do, then the thing the screen is for.
   Three buttons of three widths on one line read as three unrelated
   things - see the note over stepBtns in app.js.

   The row above this one needs air. "Leave now, back by 6.20" was sitting
   on the tools with 10px between them, so five controls read as one block
   of clutter. */
.stepbtns{display:flex;flex-direction:column;gap:10px;margin-top:16px}
.pvtools{display:flex;gap:8px}
.pvtool{
  flex:1 1 0; min-width:0;
  display:flex; align-items:center; justify-content:center;
  gap:6px; height:44px; padding:0 6px;
  border:1px solid var(--line); border-radius:12px;
  background:var(--paper); color:var(--ink-2); cursor:pointer;
  transition:border-color .15s, background .15s, transform .1s;
}
.pvtool i{font-size:16px; line-height:1}
.pvtool b{font:600 12.5px Gabarito,system-ui,sans-serif; letter-spacing:.01em}
.pvtool:hover{border-color:var(--rule); background:var(--sunk)}
.pvtool:active{transform:scale(.97)}
.pvtool:focus-visible{outline:2px solid var(--hot); outline-offset:2px}
.pvtool.on{border-color:var(--ink); background:var(--sunk); color:var(--ink)}
.stepbtns .btn.solid.wide{flex:none; width:100%; justify-content:center}
.pvpin{width:100%;height:100%;border-radius:50%;display:grid;place-items:center;
  background:var(--card);border:1.5px solid var(--ink);color:var(--ink);
  font-size:15px;box-shadow:0 2px 7px rgba(0,0,0,.3)}
.pvpin.on{background:var(--hot);font-size:18px}

/* ---------- phone list rows --------------------------------------------- */
/* One walk, one answer. The verdict is the line that matters, so it is the
   line under the name rather than the seventh chip. */
.rverdict{font-size:13px;font-weight:500;color:var(--muted);margin-top:2px;line-height:1.35}
.rverdict b{font-weight:700;color:var(--ink-2)}
@media (max-width:820px){
  #results li{padding:13px 12px;gap:11px}
  .rname{font-size:15.5px}
  .rmeta{font-size:12px;margin-top:3px;color:var(--faint)}
  /* The legend named three colours over a map that already labels itself,
     and it sat on top of the walks. */
  #legend{display:none}
}

/* The shuffle button is the only gold one on the map, because it is the only
   one that does something rather than showing something. */
/* Shuffle in ink: the one gold thing on the screen is Let's go. */
.mbtn.ink{background:var(--ink);color:var(--card);border-color:var(--ink)}
.mbtn.ink:hover{background:var(--ink)}

/* A stale cached app used to need site data cleared by hand. Now it says so. */
#updatebar{position:fixed;z-index:960;left:12px;right:12px;
  bottom:calc(var(--tabh) + env(safe-area-inset-bottom) + 12px);
  display:flex;align-items:center;gap:10px;
  background:var(--ink);color:var(--card);border-radius:12px;
  padding:11px 12px 11px 15px;box-shadow:var(--lift-lg);
  font:600 13px Gabarito,system-ui,sans-serif;
  transform:translateY(160%);transition:transform .3s cubic-bezier(.16,1,.3,1)}
#updatebar.up{transform:none}
#updatebar span{flex:1}
#updatebar button{flex:none;cursor:pointer;border:0;border-radius:9px;
  background:var(--hot);color:var(--ink);padding:8px 14px;
  font:800 13px Gabarito,system-ui,sans-serif}
@media (min-width:821px){ #updatebar{left:auto;width:340px;bottom:16px;right:16px} }

/* ---------- map responsiveness ------------------------------------------ */
/* Measured on a phone: a zoom took 266ms of Leaflet's animation, then a 90ms
   debounce, then 30ms of actual work - so the map sat still for a third of a
   second before the results caught up. The work was never the problem.
   Leaflet's default zoom transition is 250ms. At 150ms the gesture still
   reads as movement rather than a jump, and the whole map feels immediate. */
.leaflet-zoom-anim .leaflet-zoom-animated{
  transition:transform .15s cubic-bezier(0,0,.25,1)}

/* The preview's own pins arrive as the old markers leave, so the map crosses
   over rather than going briefly bare. */
@keyframes pvin{from{opacity:0;transform:scale(.86)}}
.pvpin{animation:pvin .24s cubic-bezier(.2,.8,.3,1) both}
@media (prefers-reduced-motion:reduce){.pvpin{animation:none}}

/* Lines must not fatten while the map zooms - but not from here.

   vector-effect:non-scaling-stroke used to live at this spot, scoped to
   .leaflet-zoom-anim, and it never worked. Two reasons, both measured.

   The class is set for a pinch or a zoom button and not for flyTo, which
   scales the same pane from its own frame loop: 217 samples across one
   preview, the class present in none of them, the pane transform peaking at
   31x. Unscoping it did not help either, because vector-effect exempts a
   stroke from transforms inside the SVG's own coordinate system, and this one
   is a CSS transform on the <svg> element from outside it. That scales the
   rendered picture, stroke included, and no SVG property reaches it.

   So the width is divided by the live scale factor in JS instead - see
   pinWidths() in app.js. Nothing to do here. */
.leaflet-fade-anim .leaflet-tile{transition:opacity .15s linear}
@media (prefers-reduced-motion:reduce){
  .leaflet-zoom-anim .leaflet-zoom-animated{transition:none}
}

/* The dot that runs the journey. */
.jdot{width:100%;height:100%;border-radius:50%;background:var(--hot);
  border:3px solid var(--card);box-shadow:0 0 0 2px rgba(35,46,58,.35),0 2px 8px rgba(0,0,0,.35)}

/* On a wide screen the step bar was full-bleed with a Next button the width
   of the window, sitting across the map and colliding with the tab column.
   It is a card, the same width as the results card, in the same place. */
@media (min-width:821px){
  #steps{left:16px;width:380px;right:auto;bottom:16px;border-radius:16px;
    border:1px solid var(--rule);box-shadow:var(--lift-lg);padding:14px}
}

/* ---------- place links --------------------------------------------------- */
.plinks{display:flex;flex-wrap:wrap;gap:6px;margin-top:9px}
.plink{display:inline-flex;align-items:center;gap:5px;text-decoration:none;
  padding:5px 9px;border-radius:999px;border:1px solid var(--rule);
  background:var(--card);color:var(--ink-2);
  font:700 11px Gabarito,system-ui,sans-serif}
.plink i{font-size:13px}
.plink:hover{background:var(--sunk);color:var(--ink)}
.plink.ig{border-color:var(--ink);color:var(--ink)}
.plink.fb{border-color:var(--ink);color:var(--ink)}
/* On a row it is one glyph: a place with an Instagram is worth a look, and
   that is all the row needs to say. */
/* A look at the place, from the row you are choosing in. */
/* Beside the name, not pushed to the far side of the row. flex:none so a
   long name ellipsises before the links are squeezed out of existence. */
.rowlinks{display:inline-flex;align-items:center;gap:4px;flex:none}
.rlink{display:grid;place-items:center;width:26px;height:26px;border-radius:8px;
  border:1px solid var(--line);color:var(--muted);text-decoration:none;background:var(--card)}
.rlink i{font-size:14px}
.rlink:hover{border-color:var(--ink);color:var(--ink)}
.rlink.ig{border-color:var(--ink);color:var(--ink)}
.rlink.fb{border-color:var(--ink);color:var(--ink)}

/* A gate fee is not a feature of the walk, it is a condition on it, so it
   reads as a caution rather than sitting among the amenities. */
.chip.fee{
  background:color-mix(in srgb, var(--warn, #A03A30) 12%, transparent);
  border-color:color-mix(in srgb, var(--warn, #A03A30) 35%, transparent);
  color:var(--warn, #A03A30);
}

/* A note that is a caution rather than an aside. Same size, warmer ground,
   so it reads as the app talking back rather than small print. */
.obnote.warn {
  background: var(--warm, #F3EDE3);
  border-left: 2px solid var(--ink, #2B2B2B);
  padding: .55rem .7rem;
  border-radius: 0 6px 6px 0;
}
.obnote.warn em { font-style: normal; font-weight: 700; }

/* "Walk from Toronto instead" - a one-tap move of the starting point, on the
   line that already says how many walks the search found. Quiet until it is
   relevant, which is only after you have searched somewhere you are not. */
.btn.tiny {
  font-size: .82rem;
  padding: .3rem .6rem;
  margin: .35rem 0 0;
  width: auto;
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  white-space: nowrap;
}

/* Three facts where there were fifteen rows. Each one is a sentence, so it
   is set as text rather than as a table of distances and names - the
   distance belongs inside the sentence, not in a column of its own. */
.facts {
  margin: .5rem 0 1rem;
  display: flex;
  flex-direction: column;
  gap: .4rem;
}
.facts .fact {
  margin: 0;
  font-size: .95rem;
  line-height: 1.35;
  display: flex;
  align-items: baseline;
  gap: .5rem;
  justify-content: space-between;
}
.facts .fact .more {
  font-size: .78rem;
  letter-spacing: .02em;
  opacity: .55;
  white-space: nowrap;
}
/* The full lists are a reference behind one line, not three open sections. */
.facts-all > summary h3 { opacity: .75; }
.facts-all .dsec { margin: .25rem 0; }

/* The how-to step. Not pickable, so it must not look pickable: no box, no
   check, just the icon the control actually wears and what it does. */
.obtip {
  display: flex;
  gap: .85rem;
  align-items: flex-start;
  padding: .75rem 0;
  border-bottom: 1px solid var(--line-2);
}
.obtip:last-of-type { border-bottom: 0; }
/* The icon carries the colour, because a page of grey line icons over grey
   text is what a book club signs up with. Gold for the one that gets you
   out the door, green for the ground you will cover, coffee for the rest. */
.obtip-i {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 12px;
  display: grid;
  place-items: center;
  font-size: 1.22rem;
}
.obtip[data-tone="gold"]   .obtip-i { background: rgba(217,164,65,.22); color: #8A6412; }
.obtip[data-tone="green"]  .obtip-i { background: rgba(59,107,82,.18);  color: var(--yes); }
.obtip[data-tone="coffee"] .obtip-i { background: rgba(180,98,58,.18);  color: var(--coffee); }
:root:not([data-theme="light"]) .obtip[data-tone="gold"] .obtip-i { color: var(--hot); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .obtip[data-tone="gold"] .obtip-i { color: var(--hot); }
}
:root[data-theme="dark"] .obtip[data-tone="gold"] .obtip-i { color: var(--hot); }
.obtip b { display: block; font-size: 1rem; }
.obtip em {
  display: block;
  font-style: normal;
  font-size: .88rem;
  line-height: 1.4;
  opacity: .72;
  margin-top: .15rem;
}

/* The morning band on the first onboarding screen. Full bleed of the card's
   padding so it reads as a scene rather than a picture sitting on a form. */
/* The picture is the offer on the first screen and the weather on every
   other, and it was too small to be either - a 2:1 strip 206px tall on a
   412px phone, with a paragraph of lead under it and then nothing at all
   for four hundred pixels. It takes the room the blank space was wasting. */
.obscene {
  /* Twenty animations inside one SVG, and SVG transforms are main-thread
     work in Chrome - every frame re-rasterises. contain tells the browser
     that nothing in here affects anything outside it, so the repaint stops
     at the picture's edge instead of taking the screen with it. It was 32
     animations before the firs and the ripples were grouped. */
  contain: paint;
  display: block;
  width: 100%;
  height: clamp(260px, 47vh, 460px);
  margin: .7rem 0 .4rem;
  border-radius: 14px;
}
/* On the first screen it is the offer and gets the room; after that the
   questions want the space, so it crops to a band - the bottom of the same
   scene, where the people are. */
/* Tall enough to keep their heads on. The crop takes the bottom of the
   scene, so too short a band decapitates the walkers. */
/* And the band on the question screens, which was 104px - enough to see a
   lake in but not enough to see anything move in it. */
.obscene.slim { height: clamp(128px, 19vh, 210px); margin: .5rem 0 0; }
/* On a short phone the band is the thing that can afford to give. At
   375x667 the controls screen ran 66px past the fold and the rewards
   screen 60, and a picture is the one element on either of them that
   nobody needs to read. 104px still shows the lake and the walkers,
   which is what the band is a picture of. */
@media (max-height: 700px){
  .obscene.slim { height: clamp(104px, 16vh, 150px); margin: .35rem 0 0; }
}
/* Both shapes are in the DOM from the start and the step turns one off.
   A class rather than [hidden], because `hidden` is an HTMLElement
   property and an <svg> is not one: setting it reflects to no attribute,
   matches no selector, and still reads back true - so the screen shows
   both pictures stacked while every check agrees it is fine. */
.obscene.off, .obbrand.off { display: none; }

/* Two columns, so eight choices are one screen rather than two and a half.
   The tile keeps the icon, the name and the line under it - what goes is
   the empty half of a full-width row. */
.obgrid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-bottom: 2px;
}
.obgrid .pickone.tile {
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  margin: 0;
  padding: 11px 12px 12px;
  position: relative;
  min-height: 92px;
}
.obgrid .pickone.tile > i:first-child { font-size: 20px; }
.obgrid .pickone.tile b { font-size: 13.5px; line-height: 1.25; }
.obgrid .pickone.tile em { font-size: 11px; line-height: 1.3; }
/* The check sits in the corner rather than taking a column of its own. */
.obgrid .pickone.tile .box {
  position: absolute;
  top: 9px;
  right: 9px;
  width: 18px;
  height: 18px;
  border-radius: 6px;
  font-size: 11px;
}
@media (max-width: 340px) { .obgrid { grid-template-columns: 1fr; } }

/* The crosshair that lived in here set the starting point, which is the
   job of the row under the box. One decision, one control. */
.search { position: relative; }

/* The one number the preview never gave you: whether you are back by one. */
.steptotal {
  margin: 8px 0 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 8px;
  font-size: 12.5px;
  line-height: 1.4;
}
.steptotal b { font-size: 13.5px; }
/* What the three hours buy, on its own line under what they cost. */
.tpaces{
  flex:1 0 100%; display:flex; align-items:center; gap:6px;
  margin-top:3px; color:var(--ink-2);
}
.tpaces i{font-size:15px; color:var(--moss)}
.tpaces b{font-size:13.5px}
.steptotal span { color: var(--muted); }

/* The paywall wears onboarding's clothes, because it is the same
   conversation continued rather than a different app putting its hand out. */
#paywall {
  position: fixed;
  inset: 0;
  z-index: 4000;
  background: var(--card);
  display: flex;
  flex-direction: column;
}
#paywall[hidden] { display: none; }
.pwwhy {
  margin: .8rem 0 0;
  font-size: .95rem;
  line-height: 1.45;
  color: var(--ink-2);
}
.pwgets { margin: .9rem 0 1.1rem; display: flex; flex-direction: column; gap: .7rem; }
.pwgets p { margin: 0; display: flex; gap: .7rem; align-items: flex-start; }
.pwgets i { font-size: 1.2rem; color: var(--coffee); flex: none; margin-top: .1rem; }
.pwgets b { display: block; font-size: .95rem; }
.pwgets span { font-size: .85rem; line-height: 1.4; color: var(--muted); }

/* Two plans, the annual one carrying the number that makes it the obvious
   pick. The badge sits on the border because a saving is a label on the
   thing, not another row of text under it. */
.pwplan {
  position: relative;
  width: 100%;
  display: flex;
  align-items: center;
  gap: 12px;
  text-align: left;
  margin-bottom: 10px;
  padding: 14px 15px;
  border-radius: 14px;
  border: 1.5px solid var(--line);
  background: var(--paper);
  font: inherit;
  color: inherit;
  cursor: pointer;
}
.pwplan.on { border-color: var(--ink); background: var(--sunk); }
.pwp-main { flex: 1; min-width: 0; }
.pwp-main b { display: block; font-size: 1rem; }
.pwp-main em { font-style: normal; font-size: .8rem; color: var(--muted); }
.pwp-price { text-align: right; flex: none; }
.pwp-price b { display: block; font-size: 1.05rem; font-variant-numeric: tabular-nums; }
.pwp-price em { font-style: normal; font-size: .75rem; color: var(--muted); }
.pwp-badge {
  position: absolute;
  top: -9px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--hot);
  color: #2B2214;
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: 999px;
}
/* The way off the screen, where a thumb looks for it first. */
#pwClose{
  position:absolute; z-index:3;
  top:calc(10px + env(safe-area-inset-top)); right:14px;
  width:34px; height:34px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  border:0; cursor:pointer; font-size:17px;
  background:var(--sunk); color:var(--ink-2);
}
#pwClose:hover{background:var(--line)}
#pwClose:focus-visible{outline:2px solid var(--hot); outline-offset:2px}

/* The one button, and under it the links a subscription screen is expected
   to carry - Apple rejects one without Restore, and Terms and Privacy are
   the two somebody is entitled to read before they tap. */
.btn.solid.wide{flex:1 0 100%}
/* The way past, small and plain. It has to be findable - a paywall with
   no visible way out is a trap and gets reported as one - and it has to
   be obviously the lesser of the two things on the screen, which is what
   a single underlined line under the button is. */
.pwskip{
  display:block; margin:13px auto 0; padding:4px 10px;
  background:none; border:0; cursor:pointer;
  font:600 12.5px Gabarito,system-ui,sans-serif; color:var(--muted);
  text-decoration:underline; text-underline-offset:3px;
}
.pwskip:hover{color:var(--ink-2)}
.pwskip:focus-visible{outline:2px solid var(--hot); outline-offset:2px; border-radius:6px}

.pwlinks{
  flex:1 0 100%; display:flex; justify-content:center; gap:1.4rem;
  margin:.2rem 0 0;
}
.pwlinks a, .pwlinks button{
  background:none; border:0; padding:.35rem 0; cursor:pointer;
  font:600 .78rem Gabarito,system-ui,sans-serif; color:var(--muted);
  text-decoration:none;
}
.pwlinks a:hover, .pwlinks button:hover{color:var(--ink-2); text-decoration:underline}
.pwlinks a:focus-visible, .pwlinks button:focus-visible{
  outline:2px solid var(--hot); outline-offset:2px; border-radius:6px}

/* No commitment, cancel any time, nothing charged today - the three
   questions somebody is actually asking at the moment they are asked to
   tap. Ticks rather than a paragraph, because nobody reads prose here. */
/* What it is for, in three lines. Not the feature list that was taken
   out of here - that was three things in two sentences each, above the
   prices, and nobody read it. Six words apiece, under the counts that
   say how much there is. */
.pwgets{list-style:none;margin:1rem 0 .2rem;padding:0;
  display:flex;flex-direction:column;gap:.55rem}
.pwgets li{display:flex;align-items:flex-start;gap:.5rem;
  font:600 .88rem/1.4 Gabarito,system-ui,sans-serif;color:var(--ink-2)}
.pwgets i{font-size:1rem;color:var(--moss);flex:none;margin-top:.05rem}

/* The plans start below the lead with room for the first badge. */
.pwplans{margin-top:1.6rem}
.pwfree{
  display:flex; align-items:center; justify-content:center; gap:.4rem;
  margin:1rem 0 1.3rem;
  font:600 .88rem Gabarito,system-ui,sans-serif; color:var(--ink-2);
}
.pwfree i{font-size:1rem; color:var(--moss)}
/* Said once more directly under the thumb that is about to tap. */
.pwunder{
  flex:1 0 100%; text-align:center; margin:.5rem 0 0;
  font-size:.72rem; color:var(--muted); letter-spacing:.01em;
}
.pwlegal {
  margin: .4rem 0 0;
  font-size: .75rem;
  line-height: 1.5;
  color: var(--muted);
}
.btn.ghost.quiet { flex: 0 0 auto; padding-left: .8rem; padding-right: .8rem; }

/* A scrollable body should look scrollable. Without this the content just
   stops, and a sentence cut in half reads as a bug rather than as a hint
   to keep going. */
#logSheet .sheetbody, #forSheet .sheetbody, #pickSheet .sheetbody {
  background:
    linear-gradient(var(--card) 30%, transparent) top / 100% 24px no-repeat,
    linear-gradient(transparent, var(--card) 70%) bottom / 100% 24px no-repeat,
    radial-gradient(farthest-side at 50% 0, rgba(35,46,58,.12), transparent)
      top / 100% 10px no-repeat,
    radial-gradient(farthest-side at 50% 100%, rgba(35,46,58,.12), transparent)
      bottom / 100% 10px no-repeat;
  background-attachment: local, local, scroll, scroll;
}
/* The faint label is still right where it is genuinely secondary - the
   word "optional" beside a heading is not the heading. */
.lbl .opt { color: var(--muted); }

/* Before you go. The facts that change whether you set off, gathered out
   of the descriptive paragraph they were buried in and ordered by what it
   costs to find out the hard way. */
.bygo {
  margin: 14px 0 4px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--paper);
}
.bygo h3 {
  margin: 0 0 9px;
  font: 700 11px Gabarito, system-ui, sans-serif;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.byg {
  margin: 0 0 7px;
  display: flex;
  gap: 9px;
  align-items: flex-start;
  font-size: 13px;
  line-height: 1.4;
}
.byg:last-child { margin-bottom: 0; }
.byg > i { font-size: 15px; flex: none; margin-top: 1px; color: var(--muted); }
/* Money, a locked gate, a walk back - the ones worth a second look. */
.byg.warn > i { color: var(--coffee); }
/* Somebody was actually there, which is a different kind of fact. */
.byg.said { color: var(--ink-2); }
.byg.said > i { color: var(--yes); }

/* ===== onboarding: autumn, greenery, warm coffee =========================
   The brand's own cream and navy stay; what is added is the season. Two
   illustration colours only - a turning-leaf rust and a low amber - and
   they never become interface. Gold remains the single accent anything
   clickable is allowed to use. */
:root{
  --leaf:#A8572F;        /* a turning leaf, warmer than the coffee terracotta */
  --leaf-2:#C98A3C;      /* the low autumn sun through it */
  --moss:#4A6B4F;        /* evergreen, against the deciduous */
}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    --leaf:#C9713F; --leaf-2:#DCA256; --moss:#6E9476;
  }
}
:root[data-theme="dark"]{ --leaf:#C9713F; --leaf-2:#DCA256; --moss:#6E9476; }

/* ---- the streak ----

   One number, said once, at the top of the only screen that is about
   coming back. The flame fills in at three because two is not yet a run
   and colouring it in would be flattery. */
.streak{
  display:flex; align-items:center; gap:12px;
  margin:12px 0 10px; padding:13px 14px;
  border:1.5px solid var(--rule); border-radius:14px; background:var(--card);
}
.streak > i{font-size:24px; color:var(--muted); flex:none}
.streak.hot{border-color:var(--hot); background:var(--sunk)}
.streak.hot > i{color:var(--hot)}

/* ---- two coffees, meeting ----

   The cups swing in from either side, tilt toward each other, touch, and
   settle back. 900ms end to end, which is long enough to be a gesture and
   short enough that nobody is waiting for the card underneath it.

   The clink is at 52% - 470ms - and that number is also in app.js, where
   the confetti is fired from. They have to agree: paper that goes up
   before the cups touch reads as two unrelated things happening at once.

   Each cup is one transform on one group. The spark strokes do not exist
   until the moment of contact, which is what makes it read as a hit
   rather than a glow. */
.cheers{display:block; margin:4px auto 2px; width:min(210px, 62%)}
.cheers svg{width:100%; height:auto; overflow:visible; display:block}
.cheers .cup{transform-box:fill-box; transform-origin:50% 100%}
.cheers .cup.l{animation:cheersL .9s cubic-bezier(.34,1.3,.56,1) both}
.cheers .cup.r{animation:cheersR .9s cubic-bezier(.34,1.3,.56,1) both}
/* Where they meet is arithmetic, not taste. The cup is cup.png at 27 units
   wide, so 41.6 tall, and it turns about its base - which puts the top
   outside corner at
     41.6*sin(18) + 13.5*cos(18) = 25.7
   units from the cup's own centre. Translating each one 26 units in brings
   those two corners together at the middle with the bases fifty-two apart,
   which is a clink. At rest they fall back to 30 and 14 degrees, where the
   corners are seven units either side of centre and there is daylight
   between them.

   The first attempt moved them to 13 and the bodies overlapped by twelve
   pixels - measured, not eyeballed - so it read as one wide shape rather
   than two cups touching. */
@keyframes cheersL{
  0%{opacity:0; transform:translate(-76px,12px) rotate(-30deg)}
  38%{opacity:1}
  52%{transform:translate(-26px,0) rotate(18deg)}      /* the clink */
  66%{transform:translate(-32px,0) rotate(12deg)}      /* the recoil */
  100%{opacity:1; transform:translate(-30px,0) rotate(14deg)}
}
@keyframes cheersR{
  0%{opacity:0; transform:translate(76px,12px) rotate(30deg)}
  38%{opacity:1}
  52%{transform:translate(26px,0) rotate(-18deg)}
  66%{transform:translate(32px,0) rotate(-12deg)}
  100%{opacity:1; transform:translate(30px,0) rotate(-14deg)}
}
/* Nothing until the hit, then out and gone. */
.cheers .clink{transform-box:fill-box; transform-origin:50% 50%;
  animation:clinkSpark .42s ease-out .44s both}
@keyframes clinkSpark{
  0%{opacity:0; transform:scale(.3)}
  28%{opacity:1; transform:scale(1)}
  100%{opacity:0; transform:scale(1.5)}
}
@media (prefers-reduced-motion:reduce){
  .cheers .cup.l{animation:none; transform:translate(-30px,0) rotate(14deg)}
  .cheers .cup.r{animation:none; transform:translate(30px,0) rotate(-14deg)}
  .cheers .clink{animation:none; opacity:0}
}

/* ---- the streak's fire ----

   Unlit it is the same grey shape the Phosphor icon was, so a card with
   no run going does not advertise one. Lit, three layers move on co-prime
   clocks - 1.7s, 1.1s, 0.83s - so the loops never come back into phase
   and it does not read as a short animation playing over and over.

   Each layer transforms its own path from the base of the flame, which is
   where a flame is anchored, and nothing but transform and opacity
   changes. fill-box because an SVG path's default transform origin is the
   viewport, not the shape, and rotating about that throws it off screen. */
.flame{width:26px; height:34px; flex:none; display:block}
.flame path{transform-box:fill-box; transform-origin:50% 100%}
.flame .fl-o{fill:var(--line)}
.flame .fl-m{fill:var(--rule)}
.flame .fl-c{fill:var(--card)}
.streak.hot .flame .fl-o{fill:#C0561F}
.streak.hot .flame .fl-m{fill:#E08A28}
.streak.hot .flame .fl-c{fill:#F6C94B}
.flame.lit .fl-o{fill:#C0561F}
.flame.lit .fl-m{fill:#E08A28}
.flame.lit .fl-c{fill:#F6C94B}
.flame.lit .fl-o{animation:flameO 1.7s ease-in-out infinite}
.flame.lit .fl-m{animation:flameM 1.1s ease-in-out infinite}
.flame.lit .fl-c{animation:flameC .83s ease-in-out infinite}
@keyframes flameO{
  0%,100%{transform:scale(1,1) translateX(0)}
  32%{transform:scale(.96,1.06) translateX(-.4px)}
  68%{transform:scale(1.04,.97) translateX(.3px)}
}
@keyframes flameM{
  0%,100%{transform:scale(1,1) translateX(0)}
  40%{transform:scale(1.05,.93) translateX(.5px)}
  74%{transform:scale(.95,1.05) translateX(-.3px)}
}
@keyframes flameC{
  0%,100%{transform:scaleY(1); opacity:.95}
  45%{transform:scaleY(.86); opacity:.7}
}

/* ---- and the day it grows ----

   The one moment the number means anything is the moment it goes up, and
   that happened in silence: the tab simply had a bigger figure in it the
   next time you looked. One flare, once, when the run is longer than the
   last time anybody was told - see streakGrew, which remembers rather
   than recomputes, because "it went up" is a comparison with what you
   were last shown and not a property of the log. */
.streak.grew .flame{animation:flareUp 1.1s cubic-bezier(.22,1,.36,1)}
.streak.grew{animation:streakGlow 1.4s ease-out}
@keyframes flareUp{
  0%{transform:scale(.6) translateY(6px)}
  45%{transform:scale(1.35) translateY(-3px)}
  70%{transform:scale(.94)}
  100%{transform:scale(1)}
}
@keyframes streakGlow{
  0%{box-shadow:0 0 0 0 rgba(224,138,40,.55)}
  60%{box-shadow:0 0 0 14px rgba(224,138,40,0)}
  100%{box-shadow:0 0 0 0 rgba(224,138,40,0)}
}
@media (prefers-reduced-motion:reduce){
  .flame.lit .fl-o, .flame.lit .fl-m, .flame.lit .fl-c,
  .streak.grew .flame, .streak.grew{animation:none}
}
.streak.none{border-style:dashed}
.streak b{display:block; font:800 17px Gabarito,system-ui,sans-serif;
  letter-spacing:-.02em}
.streak em{display:block; margin-top:2px; font-style:normal; font-size:12.5px;
  color:var(--muted); line-height:1.45}
/* The week count stays visible behind the day count, so a wet Tuesday
   does not look like it took everything. */
.streak-alt{
  margin-left:auto; flex:none; align-self:flex-start;
  font:700 11px Gabarito,system-ui,sans-serif; color:var(--muted);
  border:1px solid var(--line); border-radius:999px; padding:3px 9px;
}

/* ---- milestones ----

   Earned ones only. A grid of padlocks beside one earned badge reads as
   nine failures and turns a private record into a chore list the app is
   setting; the single "within reach" line does the same job the streak
   card's does, in the same voice. */
.miles{margin:14px 0 4px}
.miles-k{
  margin:0 0 7px; font:700 10.5px Gabarito,system-ui,sans-serif;
  letter-spacing:.11em; text-transform:uppercase; color:var(--muted);
}
/* ---- earning one ----------------------------------------------------
   The loudest screen in the app, and the only one. Rays, a hexagon at
   four times its cabinet size, and an arrival with a turn in it - none
   of which appear anywhere else, which is what makes it an event
   rather than another card. */
/* Above the celebration it belongs to, and never in the way of a tap. */
.confetti{position:fixed;inset:0;z-index:1000;pointer-events:none}

#hooray{position:fixed;inset:0;z-index:980;display:flex;
  align-items:center;justify-content:center;padding:24px;
  background:rgba(16,16,16,.52);animation:fadeIn .2s ease}
.hooray-card{position:relative;width:min(360px,100%);text-align:center;
  padding:30px 24px 20px;border-radius:22px;overflow:hidden;
  background:var(--card);box-shadow:var(--lift-lg);
  animation:popIn .34s cubic-bezier(.2,1.3,.4,1)}
.hooray-card .rays{position:absolute;left:50%;top:-56px;width:420px;height:420px;
  margin-left:-210px;pointer-events:none;opacity:.16;
  background:repeating-conic-gradient(var(--hot) 0deg 9deg,transparent 9deg 18deg);
  animation:rayspin 26s linear infinite}
@keyframes rayspin{to{transform:rotate(360deg)}}
#hoorayHex{position:relative;display:flex;justify-content:center;margin-bottom:14px}
#hoorayHex .hex{position:relative;width:104px;height:116px;display:flex;
  align-items:center;justify-content:center;background:var(--bh,var(--yes));
  clip-path:polygon(50% 0%,100% 25%,100% 75%,50% 100%,0% 75%,0% 25%);
  animation:badgepop .5s cubic-bezier(.2,1.4,.4,1) both}
#hoorayHex .hex i{font-size:48px;color:#FFF9EE}
#hoorayHex .times{position:absolute;right:2px;bottom:6px;
  min-width:26px;height:26px;padding:0 6px;border-radius:13px;
  display:flex;align-items:center;justify-content:center;
  background:var(--ink);color:var(--card);
  font:800 13px/1 Gabarito,system-ui,sans-serif;border:3px solid var(--card)}
@keyframes badgepop{from{transform:scale(.3) rotate(-24deg);opacity:0}}
.hooray-k{position:relative;margin:0 0 4px;font-size:11.5px;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;color:var(--hot)}
.hooray-card h2{position:relative;margin:0 0 6px;font-size:23px;font-weight:800;
  letter-spacing:-.03em;line-height:1.15;color:var(--ink)}
.hooray-card > p:not(.hooray-k){position:relative;margin:0 0 18px;
  font-size:13.5px;line-height:1.5;color:var(--muted)}
.hooray-more{position:relative;display:flex;align-items:center;justify-content:center;
  gap:6px;margin:0 0 16px;flex-wrap:wrap}
.hooray-more .hex{width:34px;height:38px;display:flex;align-items:center;
  justify-content:center;background:var(--bh,var(--yes));
  clip-path:polygon(50% 0%,100% 25%,100% 75%,50% 100%,0% 75%,0% 25%)}
.hooray-more .hex i{font-size:16px;color:#FFF9EE}
.hooray-more em{font-style:normal;font-size:12px;font-weight:600;color:var(--muted)}
.hooray-card .btn{position:relative;margin-bottom:8px}
@media (prefers-reduced-motion:reduce){
  .hooray-card,.hooray-card .rays,#hoorayHex .hex{animation:none}
}

/* ---- the trophy cabinet ---------------------------------------------
   A hexagon each, in its own colour, because twenty-four identical
   green seals in a column is a changelog and not a cabinet. The shape
   is a clip-path rather than an image: it scales, it takes the colour
   from one variable, and there is nothing to download. */
.cabinet{display:grid;grid-template-columns:repeat(4,1fr);gap:14px 8px;
  margin:4px 0 0;padding:0}
@media (max-width:360px){ .cabinet{grid-template-columns:repeat(3,1fr)} }
.badge{display:flex;flex-direction:column;align-items:center;gap:6px;
  border:0;background:none;padding:2px 0;cursor:pointer;color:inherit;
  font:inherit;min-width:0}
.badge .hex{position:relative;width:54px;height:60px;display:flex;
  align-items:center;justify-content:center;
  background:var(--bh,var(--yes));
  clip-path:polygon(50% 0%,100% 25%,100% 75%,50% 100%,0% 75%,0% 25%);
  transition:transform .14s}
.badge .hex i{font-size:25px;color:#FFF9EE}
.badge em{font-style:normal;font-size:10.5px;font-weight:600;line-height:1.25;
  text-align:center;color:var(--muted);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden}
.badge:hover .hex{transform:translateY(-2px) scale(1.04)}
.badge:active .hex{transform:scale(.96)}
.badge.open em{color:var(--ink)}
.badge.open .hex{box-shadow:0 0 0 3px var(--card),0 0 0 5px var(--bh,var(--yes))}
/* How many times, for the ones that happen again. */
.badge .times{position:absolute;right:-3px;bottom:2px;
  min-width:19px;height:19px;padding:0 4px;border-radius:10px;
  display:flex;align-items:center;justify-content:center;
  background:var(--ink);color:var(--card);
  font:800 10.5px/1 Gabarito,system-ui,sans-serif;
  border:2px solid var(--card)}
/* Not yet. Grey rather than hidden, and it keeps its own mark so the
   shape of what is coming is visible - a row of identical padlocks
   says there is something there without saying what. */
.badge.locked .hex{background:var(--sunk);
  box-shadow:inset 0 0 0 1px var(--line)}
.badge.locked .hex i{color:var(--faint)}
.badge.locked em{color:var(--faint)}
.badge.locked:hover .hex{transform:none}
.badge.locked.open .hex{box-shadow:inset 0 0 0 1px var(--line),
  0 0 0 3px var(--card),0 0 0 5px var(--line)}

.badgenote{margin:12px 0 0;font-size:12.5px;line-height:1.5;color:var(--muted)}
.badgenote b{color:var(--ink);font-weight:700}

/* The colours. Taken off the scene illustration rather than invented,
   so a cabinet full of them still looks like this app. */
.b-moss{--bh:#3B6B52}
.b-evergreen{--bh:#4A6B4F}
.b-terracotta{--bh:#A8572F}
.b-gold{--bh:#C08432}
.b-clay{--bh:#B07A34}
.b-rust{--bh:#A2483E}
.b-blue{--bh:#2F4A58}
.b-water{--bh:#5E8D9A}
.b-slate{--bh:#6F8894}
.b-heather{--bh:#6E5F7D}

.miles-next{
  margin:9px 0 0; font-size:12.5px; color:var(--ink-2);
  padding:9px 11px; background:var(--sunk); border-radius:11px;
}

/* The week's target, which was set in the onboarding and then read by
   nothing at all until this bar. */
.goalbar{
  margin:9px 0 5px; height:7px; border-radius:999px;
  background:var(--line); overflow:hidden;
}
.goalbar i{
  display:block; height:100%; border-radius:999px; background:var(--moss);
  transition:width .5s cubic-bezier(.16,1,.3,1);
}

/* ---- how it works ----

   The four controls are the real ones: same class, same size, same gold on
   the shuffle, so what is learnt here is recognised on the map rather than
   being a drawing of it. The badge rule is duplicated from #mapctl because
   that one is scoped to the map's own stack. */
/* Five rows now rather than four, and the smallest phone has to hold
   them: at 375x667 the extra one pushed the screen 60px past the fold. */
.ob-ctls{display:flex; flex-direction:column; gap:9px; margin:0 0 4px}
/* The instruction above the list needs a gap, or it reads as the first
   item's heading rather than as the thing the list is about. */
.ob-lead + .ob-ctls{margin-top:14px}
.ob-ctl{
  display:flex; align-items:center; gap:13px; margin:0;
  animation:obRise .5s cubic-bezier(.16,1,.3,1) backwards;
  animation-delay:calc(var(--i) * 110ms + 140ms);
}
.ob-ctl .mbtn{flex:none; position:relative; box-shadow:none}
.ob-ctl .mbtn b{
  position:absolute; top:-4px; right:-4px; min-width:18px; height:18px;
  border-radius:999px; background:var(--hot); color:var(--ink);
  font:700 11px/18px Gabarito,system-ui,sans-serif; text-align:center; padding:0 4px;
}
.ob-ctl > span:last-child{min-width:0}
.ob-ctl b{display:block; font:700 14.5px Gabarito,system-ui,sans-serif}
.ob-ctl em{font-style:normal; font-size:12.5px; color:var(--muted); line-height:1.45}

/* That they compose is the part nobody discovers on their own. */
.obnote.stack{
  background:var(--sunk); border-radius:12px; padding:10px 12px;
  font-size:12.5px; color:var(--ink-2);
}
.obnote.stack em{
  font-style:normal; font-weight:700; color:var(--ink);
  background:var(--paper); border:1px solid var(--line); border-radius:6px;
  padding:0 5px;
}

/* The same four stops the preview card shows, so the sequence is learnt
   once and met again where it matters. */
.ob-seq{
  display:flex; align-items:center; gap:4px; margin:4px 0 0;
  animation:obRise .5s cubic-bezier(.16,1,.3,1) backwards;
  animation-delay:calc(var(--i) * 110ms + 140ms);
}
.ob-stp{display:flex; flex-direction:column; align-items:center; gap:4px; flex:1}
.ob-stp .bub{
  width:36px; height:36px; border-radius:50%;
  display:grid; place-items:center;
  border:1.5px solid var(--rule); background:var(--paper); color:var(--ink-2);
}
.ob-stp .bub i{font-size:17px}
.ob-stp b{font:600 11px Gabarito,system-ui,sans-serif; color:var(--muted);
  white-space:nowrap}
.ob-stp.on .bub{background:var(--hot); border-color:var(--hot); color:var(--ink)}
.ob-stp.on b{color:var(--ink); font-weight:700}
.ob-leg{flex:none; width:14px; height:1.5px; background:var(--line); margin-bottom:17px}

/* One boxed note per screen. Two reads as a page of warnings. */
.ob-after{
  margin:9px 0 0; font-size:12.5px; color:var(--muted); line-height:1.5;
  animation:obRise .5s cubic-bezier(.16,1,.3,1) backwards;
  animation-delay:calc(var(--i) * 110ms + 140ms);
}
@media (prefers-reduced-motion:reduce){
  .ob-ctl, .ob-seq, .ob-after{animation:none}
}

/* Closed, on the row, before anybody opens it. Quiet rather than alarming
   - it is a fact about the hour, not a fault with the place - but dark
   enough to read at 10.5px, which --muted is not. */
.shutnow{
  flex:none; margin-left:6px; padding:1px 7px;
  border:1px solid var(--line); border-radius:999px;
  background:var(--paper); color:var(--coffee);
  font:700 10px Gabarito,system-ui,sans-serif; letter-spacing:.03em;
  text-transform:lowercase; white-space:nowrap;
}
.poi.isshut .pname{color:var(--ink-2)}
.popfact.shut span{color:var(--coffee); font-weight:700}
.popfact.quiet span{color:var(--ink-2)}

/* Leave now, and the time you get back.

   The duration above it answers "how long"; this answers "what time", which
   is the one somebody is holding while they decide whether to go today. It
   sits as a button rather than a line because tapping it turns an estimate
   into a fact. */
/* ---- the foot of the preview ------------------------------------------

   Three filled boxes of three different heights used to sit here: a
   bordered row for the leaving time, three bordered squares for the
   tools, and a gold block twice their height for the one that matters.
   Every one of them read as a button, so the screen had five buttons of
   four weights and no order to them.

   One order now. The leaving time is information, so it is a line with a
   rule above it and no box - it is still tappable, because re-stamping
   it is the usual reason to touch it, but it stops competing. The tools
   are a quiet row. The gold one is the only filled thing on the screen,
   which is what makes it the answer. */
.leaveby{
  display:flex; align-items:center; gap:9px; width:100%;
  margin:12px 0 16px; padding:11px 2px 0;
  border:0; border-top:1px solid var(--line); border-radius:0;
  background:none; cursor:pointer; text-align:left;
  font:inherit; color:inherit;
  transition:opacity .15s;
}
.leaveby:hover{opacity:.72}
.leaveby:active{transform:scale(.99)}
.leaveby:focus-visible{outline:2px solid var(--hot); outline-offset:2px}
.leaveby i{font-size:17px; color:var(--moss); flex:none}
.leaveby b{font:700 14px Gabarito,system-ui,sans-serif}
.leaveby em{
  margin-left:auto; font-style:normal; font-size:13px; color:var(--ink-2);
  font-variant-numeric:tabular-nums;
}
.leaveby.went{border-color:var(--moss); background:var(--sunk)}
.leaveby.went em{color:var(--ink); font-weight:700}

/* The CTA carries its destination underneath rather than in place of the
   thing it is actually doing. "Open in Maps" named the mechanism; this
   names the outing and lets the mechanism be the small print.

   Gold, not ink. The solid button is ink-on-cream everywhere else in the
   app and that is right for Preview and Keep, but this one is the last
   thing on the last screen before somebody drives - and the small print
   under it was cream at 72% on near-black, which measured 3.4:1 and was
   genuinely hard to read. Gold is the colour this app already uses for
   the thing it wants you to press: the shuffle button, the Explore tab,
   the done tick on a plan step. Ink on gold is 7.4:1, and the small print
   under it clears AA as well. */
/* One line, not three. Stacked, the icon sat over the label and the
   label over its own footnote, and the button came out nearly twice the
   height of everything near it - loud by size rather than by being the
   only filled thing, which it already is. */
#pvGo{
  /* .btn.wide stacks its children and is used by half the app, so the
     override belongs here rather than on the shared class. */
  flex-direction:row; flex-wrap:wrap;
  gap:9px; line-height:1.2; margin-top:9px;
  padding-top:13px; padding-bottom:13px;
  background:var(--hot); color:var(--ink); border:1.5px solid var(--ink);
}
/* It is an <a>, so both lines came out underlined. A button that looks
   like a link is neither. */
#pvGo, #pvGo:hover{text-decoration:none}
#pvGo:hover{background:var(--hot); filter:brightness(1.04)}
#pvGo .gomain{font-weight:800; font-size:15px}
/* --muted from .btn em, at 1.95:1 on gold. Opacity would only make it
   worse: fading ink towards gold is fading the contrast away. Solid ink,
   one size smaller and one weight lighter than the line above it, which
   is what makes it small print. */
#pvGo em{font-style:normal; font-size:12px; font-weight:600; color:var(--ink)}
#pvGo em::before{content:'\00b7'; margin-right:7px; opacity:.55}

#pvGo i{color:var(--ink)}

/* ---- the scene ----------------------------------------------------------

   The whole illustration is tokens, so one palette turns the lake over for
   dark mode rather than a second copy of the artwork. Depth is done the way
   flat landscape illustration does it: each band back is paler and a shade
   bluer than the one in front, which is what reads as distance without a
   single gradient between them.

   Autumn lives in the figures and in the deciduous warmth of the near
   grass. The firs stay evergreen, because they do. */
.obscene{
  --sc-sky-1:#BFD9DE; --sc-sky-2:#E4E6DC;
  --sc-cloud:rgba(255,255,255,.82);
  --sc-bird:#55616B;
  --sc-far:#9FB6BF;        /* the furthest range, nearly sky */
  --sc-mid:#7D9AA4;
  --sc-hill-1:#6E9476;     /* the far shore */
  --sc-hill-2:#4A6B4F;     /* the headlands, evergreen
                              - the same green as --moss */
  --sc-fir-far:#5C8266; --sc-fir-near:#375A42;
  --sc-water-1:#8FB6BE; --sc-water-2:#6E9AA6;
  --sc-ripple:rgba(255,255,255,.5);
  --sc-grass-1:#7FA667;    /* the hill underfoot, warmer than the far shore */
  --sc-grass-2:#95B972;
  --sc-grass-3:#C98A3C;    /* the turning of it */
  --sc-figure:#2B3440; --sc-coat:#A8572F; --sc-coat-2:#C98A3C;
  --sc-coat-3:#4A6B4F;     /* the third walker, in the evergreen */
  --sc-pack:#2F4A58; --sc-skin:#E7C4A3; --sc-hair:#3A2E28; --sc-hair-2:#5B4433;
  --sc-hair-3:#2F2622;
  --sc-cup:#F3EDE2; --sc-lid:#2B3440;
  --sc-pram:#2B3440;
  --sc-path:#C2B98F;       /* worn ground, lighter than the grass */
  --sc-path-2:#D6CEA6;
}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]) .obscene{
    --sc-sky-1:#2B3A47; --sc-sky-2:#3C4A47;
    --sc-cloud:rgba(226,232,228,.16);
    --sc-bird:#8FA0AC;
    --sc-far:#44596A; --sc-mid:#3A5160;
    --sc-hill-1:#3C5A47; --sc-hill-2:#2B4234;
    --sc-fir-far:#33503C; --sc-fir-near:#20362A;
    --sc-water-1:#3A5866; --sc-water-2:#2C4654;
    --sc-ripple:rgba(226,232,228,.22);
    --sc-grass-1:#415C3B; --sc-grass-2:#4E6C44; --sc-grass-3:#8A6230;
    --sc-skin:#C49B78;
    --sc-coat-3:#3C5A47; --sc-hair-3:#241D1A;
    --sc-path:#6E6A52; --sc-path-2:#7E7A60;
  }
}
:root[data-theme="dark"] .obscene{
  --sc-sky-1:#2B3A47; --sc-sky-2:#3C4A47;
  --sc-cloud:rgba(226,232,228,.16);
  --sc-bird:#8FA0AC;
  --sc-far:#44596A; --sc-mid:#3A5160;
  --sc-hill-1:#3C5A47; --sc-hill-2:#2B4234;
  --sc-fir-far:#33503C; --sc-fir-near:#20362A;
  --sc-water-1:#3A5866; --sc-water-2:#2C4654;
  --sc-ripple:rgba(226,232,228,.22);
  --sc-grass-1:#415C3B; --sc-grass-2:#4E6C44; --sc-grass-3:#8A6230;
  --sc-skin:#C49B78;
    --sc-coat-3:#3C5A47; --sc-hair-3:#241D1A;
    --sc-path:#6E6A52; --sc-path-2:#7E7A60;
}

/* The picture arrives as a picture.

   It used to assemble from the back forward - mountains at 40ms, hills
   at 120, the near bank at 200, the lake at 280, trees at 360, the
   foreground at 440, and the two of them last at 600 over 800ms. As a
   description of how a view appears when mist lifts that is lovely. As
   something to watch on a phone it is the screen building itself in
   front of you, a part at a time, for a second and a half before it is
   a picture at all.

   It showed on the first two screens and nowhere else, which is the
   tell: the scene is only rebuilt when its shape changes - once for the
   full scene on the opening screen, once more for the band on the
   second - and every screen after that reuses the SVG and never
   replays. So the entrance was the whole of the complaint.

   One fade, four tenths of a second, the whole thing at once. The
   parallax it used to carry is a real idea but it belongs to a picture
   that is arriving over a second; at this length nobody can read depth
   from differential travel, they can only see the parts. Depth here is
   done with colour and overlap, which is how a still picture does it,
   and the life comes from the ambient loops below rather than from the
   way it got here. */
.obscene{animation:scFade .4s ease-out backwards}
@keyframes scFade{from{opacity:0}}

/* ---- and then it keeps moving ----

   Not until it has arrived. The loops used to run underneath the
   entrance, so a fir was swaying about its own bounding box while the
   band holding it was still moving - two transforms, one of them
   recomputing its origin every frame. The `settled` class goes on when
   the entrance is over and the loops start then, which is now a much
   shorter wait than it was.

   A picture that settles and stops is an illustration; one that never
   quite settles is a place. Everything below is ambient - nothing waits
   for it, nothing changes because of it - and every duration is a
   different number of seconds so that no two things ever come back into
   step. That is the whole trick: the moment two trees sway together the
   eye sees a loop instead of a wood.

   Amplitudes were first set under what you would notice on purpose - half
   a degree of sway - on the theory that you should feel it rather than
   watch it. On a desk that was right. On a phone at arm's length, in a
   band 104 pixels tall, it was invisible, which is the same as not being
   there. They are two to three times that now: still nothing performs,
   but a tree that sways reads as a tree in wind rather than a tree. */

/* Wind through the trees, each on its own clock, the near ones quicker
   and wider because they are closer to it. */
.settled .scFirSway{
  transform-box:fill-box; transform-origin:50% 100%;
  will-change:transform;
  animation:scSway var(--t,7s) ease-in-out infinite alternate;
  animation-delay:var(--d,0s);
}
/* 1.6deg on a 32px fir was nine tenths of a pixel at the tip - a tree
   that fizzed rather than swayed. 3.6deg is two, which is a tree in
   wind. */
@keyframes scSway{
  from{transform:rotate(-3.6deg)}
  to{transform:rotate(3.6deg)}
}
.settled .scFirSway.near{animation-name:scSwayNear}
@keyframes scSwayNear{
  from{transform:rotate(-5deg) translateY(.5px)}
  to{transform:rotate(5deg) translateY(-.5px)}
}

/* The water. Five short strokes that drift and fade at five different
   rates, which is enough to read as a surface rather than as marks. */
.settled .scRipple{
  animation:scDrift2 var(--t,7s) ease-in-out infinite alternate;
  animation-delay:var(--d,0s);
}
@keyframes scDrift2{
  from{transform:translateX(-7px) scaleX(.8); opacity:.3}
  to{transform:translateX(9px) scaleX(1.15); opacity:1}
}

/* ---- the people, moving far enough to be moving ----

   These were animated below the threshold at which a screen can draw
   motion at all. Measured against their own boxes: the walker travelled
   1.10px over 1.9s, the standing adult 1.59px over 4.3s, the child
   2.11px over 2.6s, a fir 1.44px. Half a pixel a second is about a
   hundredth of a pixel per frame, and a vector shape displaced by a
   hundredth of a pixel does not move - it is re-rasterised with slightly
   different coverage along every antialiased edge. What you see is the
   edges fizzing in place. That is the flicker, and winding the duration
   up or the easing around makes no difference to it, because the problem
   is amplitude.

   Three rules from here on, and they are the ordinary ones:

   Move at least a few pixels or do not move. Everything below now
   travels 3px or more, which is the point where the eye reads
   displacement instead of noise.

   Prefer translation to small rotations. A degree of rotation on a 40px
   figure is two thirds of a pixel at the extremes - the least motion for
   the most edge recomputation, which is the worst trade available. The
   sub-degree leans are gone; what is left is a lean big enough to see.

   Say it is coming. will-change promotes these to their own layers, so
   the compositor moves a finished raster rather than redrawing curves
   every frame. They are tiny and there are not many, which is the case
   the hint exists for.

   The intent is unchanged: nobody should catch these happening. */
.settled .scBreathe{
  transform-box:fill-box; transform-origin:50% 100%;
  will-change:transform;
  animation:scBreathe 5.2s ease-in-out infinite;
}
.settled .scBreathe.child{animation-duration:3.1s; animation-delay:-.7s}
/* She is walking rather than standing, so she gets the rise and fall of
   a stride. Four pixels and a lean was too much of it - she bounced, and
   a figure bouncing on the spot is further from walking than one holding
   still. Two pixels, no lean, and slower: at 77px tall that is the rise
   of a step rather than a hop, and it is the compositing rather than the
   size that keeps it clean. */
.settled .scWalker{
  transform-box:fill-box; transform-origin:50% 100%;
  will-change:transform;
  animation:scStride 2.1s ease-in-out infinite;
}
@keyframes scStride{
  0%,100%{transform:translateY(0)}
  50%{transform:translateY(-2px)}
}
/* The child shifts about more than the adult, as children do: a weight
   change from one foot to the other, which is sideways and plainly
   visible, rather than a lean too small to render. */
.scBreathe.child{animation-name:scBreatheChild}
@keyframes scBreatheChild{
  0%,100%{transform:translateX(-1.6px) scaleY(1)}
  50%{transform:translateX(1.6px) scaleY(1.08)}
}
/* Breath: the chest rising, from the feet. 8% of a 46px figure is nearly
   four pixels at the shoulders and nothing at the ground, which is how
   breathing looks. */
@keyframes scBreathe{
  0%,100%{transform:scaleY(1)}
  50%{transform:scaleY(1.08)}
}

/* The child's arm, which is the one thing in the picture doing something
   rather than being something. Long pause, short wave: a gesture repeated
   without rest stops reading as a gesture. */
.settled .scWave{
  transform-box:fill-box; transform-origin:0% 100%;
  will-change:transform;
  animation:scWave 5s ease-in-out infinite;
}
@keyframes scWave{
  0%,48%,100%{transform:rotate(0)}
  56%{transform:rotate(-16deg)}
  64%{transform:rotate(13deg)}
  72%{transform:rotate(-10deg)}
  80%{transform:rotate(6deg)}
  88%{transform:rotate(0)}
}

/* Steam, which is the only thing on screen that says the coffee is hot.
   Rises, widens, fades - and the second wisp is offset so they never
   leave together. */
.settled .scSteam path{
  animation:scSteam 3.6s ease-out infinite;
  opacity:0;
}
.settled .scSteam .b{animation-duration:4.4s; animation-delay:-1.8s}
@keyframes scSteam{
  0%{opacity:0; transform:translateY(1px) scaleX(.6)}
  18%{opacity:.9}
  70%{opacity:.4}
  100%{opacity:0; transform:translateY(-8px) scaleX(1.5)}
}
/* Clouds at two speeds, because one speed is a slideshow. Slow enough that
   you notice it only if you stop and look, which is the point. */
.settled .scCloud{animation:scDrift linear infinite alternate}
.settled .scCloud.a{animation-duration:26s}
.settled .scCloud.b{animation-duration:34s; animation-direction:alternate-reverse}
.settled .scCloud.c{animation-duration:21s}
@keyframes scDrift{
  from{transform:translateX(-18px)}
  to{transform:translateX(22px)}
}
/* Birds glide the width of the sky and start again. */
.settled .scBird{animation:scGlide linear infinite; opacity:.75}
.settled .scBird.one{animation-duration:15s}
.settled .scBird.two{animation-duration:19s; animation-delay:-6s}
@keyframes scGlide{
  0%{transform:translate(-130px,6px); opacity:0}
  12%{opacity:.75}
  88%{opacity:.75}
  100%{transform:translate(210px,-10px); opacity:0}
}

/* A landscape is not worth a single frame of somebody's vestibular system.
   All of it, including the ambient loops - especially those, since they
   never stop. */
@media (prefers-reduced-motion:reduce){
  .scLayer, .scPeople, .scCloud, .scBird,
  .scFirSway, .scRipple, .scBreathe, .scWave, .scWalker,
  .scSteam path{animation:none}
  .scSteam path{opacity:.5}
}

/* ---- the running count ---- */
.obcount{
  margin:10px 0 0; display:flex; align-items:baseline; gap:9px;
}
.obcount b{
  font:800 34px/1 Gabarito,system-ui,sans-serif; letter-spacing:-.03em;
  font-variant-numeric:tabular-nums; color:var(--ink);
}
.obcount span{font-size:12.5px; color:var(--muted); line-height:1.3}
/* Falling, because an answer that rules walks out should feel like it. */
.obcount.down b{color:var(--leaf)}

/* ---- the body, entering ---- */
/* Longer and further than it was, because it is now the only thing
   moving. While the container rose too, each item travelled 28px -
   twice its own 14 - and the extra came from the group sliding under
   it rather than from anything designed. Taking that away left the
   entrance at half strength, so the item itself carries it: 18px over
   .52s, and 55ms between one and the next, which is far enough apart
   to read as a sequence rather than a block arriving slightly blurred. */
#obBody.in > *{
  animation:obRise .52s cubic-bezier(.16,1,.3,1) backwards;
  animation-delay:calc(var(--i,0) * 55ms + 40ms);
}
#obBody.in .obgrid > *{
  animation:obRise .4s cubic-bezier(.16,1,.3,1) backwards;
}
#obBody.in .obgrid > :nth-child(1){animation-delay:60ms}
#obBody.in .obgrid > :nth-child(2){animation-delay:95ms}
#obBody.in .obgrid > :nth-child(3){animation-delay:130ms}
#obBody.in .obgrid > :nth-child(4){animation-delay:165ms}
#obBody.in .obgrid > :nth-child(5){animation-delay:200ms}
#obBody.in .obgrid > :nth-child(6){animation-delay:235ms}
@keyframes obRise{
  from{opacity:0; transform:translateY(18px)}
  45%{opacity:1}
  to{opacity:1; transform:none}
}
#onboard[data-dir="back"] #obBody.in > *{animation-name:obRiseBack}
@keyframes obRiseBack{
  from{opacity:0; transform:translateY(-14px)}
  45%{opacity:1}
  to{opacity:1; transform:none}
}

/* ---- and the screen that is leaving ----

   The entrance above was the whole transition: the old body was replaced
   in one frame and the new one rose into the hole it left. An arrival with
   no departure reads as a reload with an animation on it.

   Forward is up. The old words rise away and the new ones rise in from
   below, which joins the two halves into one upward travel - the same
   direction the entrance already had, so nothing had to be redesigned to
   meet it. Accelerating out (ease-in) and decelerating in: things leave in
   a hurry and arrive gently, which is the whole of why it reads as
   deliberate rather than mechanical.

   One element, one transform, 140 ms - see obGo for why that number. The
   body is the only thing that moves; the picture above it is in .obhead
   and holds perfectly still, which is what sells it as one place being
   paged through rather than nine screens in a row. */
#obBody.out, #obTitle.out{
  animation:obExit .14s cubic-bezier(.4,0,1,1) forwards;
}
@keyframes obExit{to{opacity:0; transform:translateY(-14px)}}
#onboard[data-dir="back"] #obBody.out,
#onboard[data-dir="back"] #obTitle.out{animation-name:obExitBack}
@keyframes obExitBack{to{opacity:0; transform:translateY(14px)}}

/* The heading used to snap into place while everything beneath it rose -
   the largest, boldest thing on the screen, and the only one that did not
   move. 10px against the body's 18 because it is 26px type: the same
   optical speed needs less distance the bigger the object. */
#obTitle.in{
  animation:obRiseTitle .4s cubic-bezier(.16,1,.3,1) backwards;
  animation-delay:20ms;
}
@keyframes obRiseTitle{from{opacity:0; transform:translateY(10px)}}
#onboard[data-dir="back"] #obTitle.in{animation-name:obRiseTitleBack}
@keyframes obRiseTitleBack{from{opacity:0; transform:translateY(-8px)}}

/* ---- answering is worth something ----

   Ticking a tile used to redraw the whole grid, so all eight blinked out
   and rose again - including the one under the finger. The answer now
   lands on the tile that was tapped and nothing else moves, which leaves
   room for the tick itself to be the thing that happens.

   The back-out curve overshoots about 6%, which is the spring in every
   checkbox worth copying. Only on small discrete objects - a tick, a dot -
   never on prose, where an overshoot reads as a wobble. */
/* On the tap, not on the render. Scoping this to .on meant a tile that
   was already ticked popped its tick while the tile itself was rising in -
   two things moving at once inside each other, which is the one thing the
   rule above forbids and which the suite caught. The class is added by the
   handler and only ever by the handler. */
.pickone .box i.pop{animation:tickPop .28s cubic-bezier(.34,1.56,.64,1)}
@keyframes tickPop{from{transform:scale(.4); opacity:0}}

/* ---- and she walks up the path ----

   One group, one transform, and the compositor slides a raster that is
   already drawn - the forty-odd nodes inside her do not re-render to move.
   600 ms so she has finished before the eye has read the new heading, on a
   curve that leaves quickly and settles, which is how walking looks when
   you are not watching the feet. Reversing walks her back, which is honest.

   The position is the whole story under reduced motion too, so only the
   travel between positions is dropped there, not the positions. */
.obscene .scTravel{
  will-change:transform;
  transform:translate(var(--wx,0px), var(--wy,0px));
  transition:transform .6s cubic-bezier(.22,1,.36,1);
}
@media (prefers-reduced-motion:reduce){
  .obscene .scTravel{transition:none}
}

/* A step finished is worth a beat of its own. */
.obdots i.justdone{animation:dotDone .3s cubic-bezier(.34,1.56,.64,1)}
@keyframes dotDone{from{transform:scale(.3)}}

/* ---- one thing moves at a time ----

   The rule above rises every direct child of the body, and five of the
   eight steps put a container there whose own children also rise: the
   beats inside .ob-demo, the tiles inside .obgrid, the controls inside
   .ob-ctls, and the shot, lines and badges inside .ob-win. Transforms
   compose, so each of those items was being moved twice on two clocks
   that start at different moments and run for different lengths. The
   group stretched open and shut as the two timelines drifted past each
   other, which is the concertina - an entrance that reads as a fault.

   Where the container is only a box - a flex column, a grid - it has no
   edges of its own to arrive, and the stagger of its children is the
   entrance. It simply shows, and the children do the moving. */
#obBody.in > .ob-demo,
#obBody.in > .obgrid,
#obBody.in > .ob-ctls{animation:none}

/* Where the container is a card, the card is the thing that moves and
   its contents arrive by light alone. Same clocks, same stagger, one
   transform - so the sequence inside it still reads, and nothing is
   carried by two of them at once. */
@keyframes obLight{from{opacity:0}}
#obBody.in > .ob-win .ob-shot,
#obBody.in > .ob-win .ob-win-line,
#obBody.in > .ob-win .ob-badges,
#obBody.in > .ob-win .ob-more{animation-name:obLight}
#onboard[data-dir="back"] #obBody.in > .ob-win .ob-shot,
#onboard[data-dir="back"] #obBody.in > .ob-win .ob-win-line,
#onboard[data-dir="back"] #obBody.in > .ob-win .ob-badges,
#onboard[data-dir="back"] #obBody.in > .ob-win .ob-more{animation-name:obLight}

/* ---- screen one, which says almost nothing ---- */
/* The first screen holds a picture and one sentence, and the sentence was
   pinned under the picture with four hundred pixels of nothing beneath it.
   It sits in the middle of what is left instead, which reads as composed
   rather than as a page that stopped loading. */
/* And on anything tall that is every screen, not only the first. A 560px
   column pinned to the top of a 1400px window leaves half the page empty
   under it - six rows of choices and then nothing, which reads as a page
   that failed to finish rather than as a form that is short.

   The picture and the question travel together, so centring the body alone
   only moved the gap: the scene stayed at the top and the choices went to
   the middle, which is further apart than either of them started. Two auto
   margins centre the pair of them in the space above the footer, which
   stays where a footer belongs.

   Only when there is room. Below 760px the column is taller than the
   window and it scrolls from the top, which is correct. */
@media (min-height:760px){
  .obhead{margin-top:auto}
  .obbody{flex:0 1 auto; margin-bottom:auto}
}

/* With the picture at 47vh the lead is the only other thing on the first
   screen, so it may as well be read from across a room. */
/* Location is the recommended answer, and the row says so rather than
   leaving it to be inferred from the order. A tag rather than a sentence,
   because the sentence under it is already doing the explaining. */
.recotag{
  display:inline-block; margin-left:7px; padding:1px 7px; border-radius:999px;
  background:var(--hot); color:var(--ink); vertical-align:2px;
  font:700 9.5px/1.6 Gabarito,system-ui,sans-serif; font-style:normal;
  letter-spacing:.07em; text-transform:uppercase;
}
.pickone.reco{border-color:var(--hot)}

/* Why Next is not available yet. Shown only while nothing is chosen, so
   it reads as the next thing to do rather than as a warning. */
.ob-need{
  display:flex; gap:7px; align-items:flex-start;
  margin:11px 0 0; font-size:12.5px; line-height:1.45; color:var(--ink-2);
}
.ob-need i{flex:none; font-size:15px; color:var(--hot); margin-top:1px}

/* A step that cannot be taken yet. Dimmed rather than hidden: a button
   that disappears reads as a bug, one that is visibly not ready reads as
   something still to do. */
.obfoot .btn:disabled{
  opacity:.4; cursor:not-allowed; box-shadow:none;
}

/* The last screen: one number, the one that was counted from their own
   answers, and then what comes with every one of them. */
.ob-hook{
  display:flex; flex-direction:column; gap:3px; margin:0 0 15px;
  padding:0 0 15px; border-bottom:1px solid var(--line);
}
.ob-hook-n{
  font:800 40px/1 Gabarito,system-ui,sans-serif; color:var(--ink);
  font-variant-numeric:tabular-nums; letter-spacing:-.035em;
}
.ob-hook-l{
  font-size:14px; line-height:1.45; color:var(--ink-2); max-width:34ch;
}
/* What stops them, answered - the one line on the card that is about
   them rather than the walk, so it is set apart from both. */
.ob-answer{
  display:flex; gap:9px; align-items:flex-start; margin:-4px 0 14px;
  font-size:14.5px; line-height:1.45; font-weight:600; color:var(--ink);
  animation:obRise .5s cubic-bezier(.16,1,.3,1) .25s backwards;
}
.ob-answer .ph{flex:none; margin-top:2px; color:#B4632F}

.ob-lead{
  margin:0; font-size:17.5px; line-height:1.45; color:var(--ink-2);
  max-width:30ch; text-wrap:balance;
}

/* What the four beats are: one walk, not a summary of the app. Somebody
   on their second screen has no way to know which. */
.ob-sample{
  margin:0 0 10px; font:700 10.5px Gabarito,system-ui,sans-serif;
  letter-spacing:.11em; text-transform:uppercase; color:var(--muted);
}

/* The same evidence as the line below, read at a glance.

   Three figures across, because a sentence has to be parsed and a number
   does not, and the first screen is the one place where a reader has not
   yet decided to spend any effort. Tabular figures so the three sit on a
   grid rather than drifting, and the labels small enough that the numbers
   are the thing. A build that did not ship one of these draws two
   instead of three rather than a zero. */
.ob-proof{
  display:flex; gap:10px; margin:16px 0 0;
}
/* Nothing to show yet, on the second or two before the walks land. */
.ob-proof:empty{display:none}
.ob-pf{
  flex:1; min-width:0; display:flex; flex-direction:column; gap:2px;
  padding:10px 10px 11px; border-radius:12px;
  background:var(--sunk); border:1px solid var(--line);
}
.ob-pf b{
  font:800 19px/1.05 Gabarito,system-ui,sans-serif; color:var(--ink);
  font-variant-numeric:tabular-nums; letter-spacing:-.02em;
}
.ob-pf em{
  font-style:normal; font-size:11px; line-height:1.3; color:var(--muted);
}

/* The sentence under the numbers: who the grading is for, which is the
   part that is not obvious from a walk count. */
.ob-why{
  margin:12px 0 0; font-size:13px; line-height:1.55; color:var(--muted);
  max-width:40ch;
}

/* The ground the app covers, which is the honest kind of social proof:
   not how many people use it, which would be a claim, but how much is in
   it, which is a fact. Quiet, because it is evidence and not a headline. */
.ob-stat{
  margin:14px 0 0; font-size:13px; line-height:1.5; color:var(--ink-2);
  font-variant-numeric:tabular-nums;
}
.ob-stat:empty{display:none}

/* The same fact, on the screen where somebody is deciding to pay for it. */
.pwstat{
  margin:.9rem 0 0; font-size:.92rem; line-height:1.45; color:var(--ink-2);
  font-variant-numeric:tabular-nums;
}

/* ---- the demo, four beats in sequence ---- */
.ob-demo{display:flex; flex-direction:column; gap:2px}
.ob-demo .beat{
  display:flex; gap:12px; align-items:flex-start; margin:0; padding:11px 0;
  border-bottom:1px solid var(--line-2);
  animation:obBeat .5s cubic-bezier(.16,1,.3,1) backwards;
  animation-delay:calc(var(--i) * 520ms + 200ms);
}
.ob-demo .beat:last-child{border-bottom:0}
.ob-demo .beat i{font-size:20px; color:var(--moss); flex:none; margin-top:1px}
.ob-demo .beat:nth-child(2) i{color:var(--yes)}
.ob-demo .beat:nth-child(3) i{color:var(--leaf)}
.ob-demo .beat:nth-child(4) i{color:var(--leaf-2)}
.ob-demo .beat b{display:block; font-size:15px; line-height:1.25}
.ob-demo .beat em{
  display:block; font-style:normal; font-size:12.5px; color:var(--muted);
  line-height:1.4; margin-top:2px;
}
@keyframes obBeat{
  from{opacity:0; transform:translateX(-10px)}
  to{opacity:1; transform:none}
}

/* ---- the radius chips ---- */
.ob-q{margin:18px 0 8px; font-size:14px; font-weight:600}
.ob-row{display:flex; gap:7px; flex-wrap:wrap}
.chip{
  border:1.5px solid var(--line); border-radius:999px; padding:8px 14px;
  background:var(--paper); font:600 13px Gabarito,system-ui,sans-serif;
  color:var(--ink-2); cursor:pointer;
  transition:transform .14s, border-color .14s, background .14s;
}
.chip:hover{border-color:var(--rule)}
.chip:active{transform:scale(.96)}
.chip.on{border-color:var(--ink); background:var(--sunk); color:var(--ink)}

/* ---- the payoff ----

   The card is a photograph with a caption now, not a panel with a list in
   it. The picture is allowed to be the biggest thing on the screen because
   it is the only part of this app somebody can judge at a glance. */
.ob-win{
  border:1.5px solid var(--rule); border-radius:16px; overflow:hidden;
  background:var(--paper); margin:0 0 14px;
  padding:16px 17px;
}
.ob-win:has(.ob-shot){padding:0 0 14px}
.ob-shot{
  position:relative; margin:0 0 13px; overflow:hidden;
  background:var(--sunk);
  animation:obShotIn .62s cubic-bezier(.16,1,.3,1) backwards;
}
.ob-shot > img{
  display:block; width:100%; height:clamp(150px,34vw,215px);
  object-fit:cover;
}
/* A photograph is somebody's morning, not a swatch: it gets a soft foot so
   the name below it does not look stuck on. */
.ob-shot::after{
  content:''; position:absolute; inset:auto 0 0 0; height:40%;
  background:linear-gradient(transparent,rgba(26,22,20,.22)); pointer-events:none;
}
@keyframes obShotIn{
  from{opacity:0; transform:scale(1.04)}
  to{opacity:1; transform:none}
}
/* Somebody who has answered five questions and is shown one walk could
   reasonably think that is the answer rather than an example of one. */
.ob-win-tag{
  display:block; margin-bottom:3px;
  font:700 10px Gabarito,system-ui,sans-serif; letter-spacing:.12em;
  text-transform:uppercase; color:var(--muted);
}
.ob-win:has(.ob-shot) .ob-win-tag{padding-left:17px; padding-right:17px}
.ob-win-name{
  display:block; font:800 21px/1.15 Gabarito,system-ui,sans-serif;
  letter-spacing:-.025em; margin-bottom:8px;
}
.ob-win:has(.ob-shot) .ob-win-name,
.ob-win:has(.ob-shot) .ob-win-line{padding-left:17px; padding-right:17px}
.ob-win-line{
  display:flex; gap:8px; align-items:center; font-size:13.5px;
  color:var(--ink-2); padding:4px 0;
  animation:obRise .5s cubic-bezier(.16,1,.3,1) backwards;
  animation-delay:calc(var(--i) * 170ms + 260ms);
}
.ob-win-line i{font-size:16px; color:var(--leaf)}
.ob-more{
  margin:0; font-size:13px; color:var(--muted);
  animation:obRise .5s cubic-bezier(.16,1,.3,1) backwards;
  animation-delay:calc(var(--i) * 170ms + 260ms);
}

/* ---- the count of walks beside a buggy class ---- */
.pickone .cnt{
  font:700 13px/1 "JetBrains Mono",ui-monospace,monospace;
  font-variant-numeric:tabular-nums; color:var(--muted); flex:none;
  font-style:normal;
}
.pickone.on .cnt{color:var(--ink)}
.pickone.wide{width:100%}

/* ---- the dots, now with a done state ---- */
.obdots i.done{background:var(--moss)}

/* Everything above is decoration on a form somebody has to fill in while
   holding a baby. None of it is allowed to be the reason they cannot. */
@media (prefers-reduced-motion:reduce){
  #obBody.in > *, #obBody.in .obgrid > *, .ob-demo .beat,
  .ob-win-line, .ob-more, .ob-shot{animation:none}
  /* The exit is skipped in obGo rather than animated to nothing, so these
     are belt and braces for a preference that changes mid-flow. */
  #obBody.out, #obTitle.out, #obTitle.in,
  .pickone .box i.pop, .obdots i.justdone{animation:none}
  .chip:active{transform:none}
}

/* ---- the first walk, explained -----------------------------------------

   Over the map rather than over the walk: the sheet below is the thing
   being described, so covering it would leave the words pointing at
   nothing. It sits under the search bar and above the sheet, which is
   the band of map the landing has just filled with a route.

   Not modal. There is no scrim and the map stays live underneath,
   because the card's whole claim is that tapping things changes them -
   and a card that blocks tapping while saying so is an argument with
   itself. */
#firstTip,#locHelp{
  position:fixed; z-index:880;
  left:16px; right:16px;
  top:calc(var(--safe-top) + var(--chrome-h,112px) + 18px);
  display:flex; justify-content:center;
  pointer-events:none;
}
#firstTip[hidden],#locHelp[hidden]{display:none}
#locHelp{z-index:890}
#locHelp .btn+.btn{margin-top:8px}
.tipcard{
  pointer-events:auto;
  width:100%; max-width:420px;
  background:var(--paper); border:1.5px solid var(--rule); border-radius:16px;
  padding:15px 16px 14px;
  box-shadow:0 10px 30px rgba(35,46,58,.18);
  animation:sheetUp .34s cubic-bezier(.16,1,.3,1);
}
.tipcard h2{
  margin:0 0 6px; font:800 17px/1.2 Gabarito,system-ui,sans-serif;
  letter-spacing:-.02em; color:var(--ink);
}
.tipcard > p{
  margin:0 0 12px; font-size:13px; line-height:1.5; color:var(--ink-2);
}
.tiphow{list-style:none; margin:0 0 13px; padding:0;
  display:flex; flex-direction:column; gap:10px}
.tiphow li{display:flex; gap:11px; align-items:flex-start}
.tiphow b{display:block; font:700 13.5px Gabarito,system-ui,sans-serif; color:var(--ink)}
.tiphow em{font-style:normal; font-size:12.5px; line-height:1.4; color:var(--muted)}

/* The pins as they are drawn, at the size they are drawn, so the key is
   a picture of the map rather than a description of it. */
.tipic{
  flex:none; width:26px; height:26px; border-radius:50%;
  display:grid; place-items:center;
  background:var(--sunk); border:1px solid var(--line);
  font:700 13px Gabarito,system-ui,sans-serif; color:var(--ink);
}
.tipic img{display:block}
.tipp{background:#2B2B2B; border-color:#2B2B2B; color:#fff}
.tipt{background:#3D5A80; border-color:#3D5A80; color:#fff}
.tipb{background:#6D5A8C; border-color:#6D5A8C; color:#fff}
.tipy{background:#B0761A; border-color:#B0761A; color:#fff; font-size:10px}

.tipkey-h{
  margin:0 0 7px; font:700 10px Gabarito,system-ui,sans-serif;
  letter-spacing:.11em; text-transform:uppercase; color:var(--muted);
}
.tipkey{
  list-style:none; margin:0 0 14px; padding:0;
  display:flex; flex-wrap:wrap; gap:8px 13px;
}
.tipkey li{
  display:flex; align-items:center; gap:6px;
  font-size:12px; color:var(--ink-2);
}
.tipkey .tipic{width:21px; height:21px; font-size:11px}
/* The verdict colours, as the map draws them: a stroke, because that is
   what a route is, rather than a filled dot which is what a pin is. */
.tipsw{
  flex:none; width:20px; height:5px; border-radius:3px;
}
/* One per line: these labels are sentences, not words, so wrapping them
   across a row put "Possibly" and "Not suitable" on the same line and
   the long one on its own above them. */
.tipcol{flex-direction:column; gap:7px; margin-bottom:13px}
.tipcol li{gap:9px}

/* The same three on the screen where the crew is chosen. */
.obcol b{font-weight:700; color:var(--ink); white-space:nowrap}
.obcol b i{
  display:inline-block; width:15px; height:4px; border-radius:2px;
  margin-right:4px; vertical-align:middle;
}
.tipkey .tipy{font-size:8px}

@media (prefers-reduced-motion:reduce){ .tipcard{animation:none} }

/* ---- the map controls, named once --------------------------------------

   Anchored to each button's measured position rather than guessed from
   the stack's spacing, because the stack changes height: the stack has
   been two buttons and five, so anything laid out by counting rows
   points at the wrong thing half the time.

   Layered under the cards, not over them: the labels name buttons that
   float over the map, and the map is the only thing they may print on.
   showCtlTips hides them when a sheet opens; this is the same promise
   kept by the stylesheet, so a label that is on screen when a card
   rises is behind the card rather than across the walk on it. */
#ctlTips{position:fixed; inset:0; z-index:745; pointer-events:none}
#ctlTips[hidden]{display:none}
.ctltip{
  position:absolute; transform:translateY(-50%);
  padding:5px 10px; border-radius:999px;
  background:var(--ink); color:var(--paper);
  font:700 11.5px Gabarito,system-ui,sans-serif; white-space:nowrap;
  box-shadow:0 4px 14px rgba(35,46,58,.28);
  animation:ctlTipIn .34s cubic-bezier(.16,1,.3,1) backwards;
}
.ctltip::after{
  content:''; position:absolute; right:-4px; top:50%;
  width:8px; height:8px; margin-top:-4px; border-radius:1px;
  background:var(--ink); transform:rotate(45deg);
}
.ctltip:nth-child(1){animation-delay:.04s}
.ctltip:nth-child(2){animation-delay:.10s}
.ctltip:nth-child(3){animation-delay:.16s}
.ctltip:nth-child(4){animation-delay:.22s}
.ctltip:nth-child(5){animation-delay:.28s}
@keyframes ctlTipIn{from{opacity:0; transform:translateY(-50%) translateX(8px)}}
@media (prefers-reduced-motion:reduce){ .ctltip{animation:none} }

/* ---- how far, how long, how many steps --------------------------------

   A walk that does not loop has two honest answers and the screen used
   to carry one of each in three different places. One block, two
   columns, same rows: nothing to add up and nothing to reconcile.

   Figures are tabular so the two columns line up on the digit rather
   than drifting against each other, which is the whole reason for
   putting them side by side. */
.legs{
  /* Room under it as well as over it. The verdict box that follows has
     no top margin of its own, so at 12px 0 0 the two were touching and
     the figures read as the first line of the panel below them. */
  margin:14px 0 16px; padding:11px 13px 12px;
  border:1px solid var(--line); border-radius:12px; background:var(--sunk);
  font-variant-numeric:tabular-nums;
}
.legs.one{display:flex; gap:10px}
/* .legcell, not .leg: .leg is already the connector line between the
   preview's stepper dots - 22px wide, 2px tall, pulled 14px up with a
   negative margin. A class selector could override the flex properties
   and not the height or the margin, so the cells came out two pixels
   tall, their labels clipped away, bleeding into the section below. */
.legs.one .legcell{flex:1 1 0; min-width:0; display:flex;
  flex-direction:column; gap:2px}
.legs.one em{
  font-style:normal; font:600 10.5px Gabarito,system-ui,sans-serif;
  letter-spacing:.09em; text-transform:uppercase; color:var(--muted);
}
.legs.one b{font:700 15px Gabarito,system-ui,sans-serif; color:var(--ink)}

.legh, .legr{
  display:grid; grid-template-columns:minmax(0,1fr) auto auto;
  gap:8px 14px; align-items:baseline;
}
.legh{padding-bottom:7px; border-bottom:1px solid var(--line); margin-bottom:8px}
.legh em{
  font-style:normal; font:700 10.5px Gabarito,system-ui,sans-serif;
  letter-spacing:.08em; text-transform:uppercase; color:var(--muted);
  text-align:right; min-width:78px;
}
.legr + .legr{margin-top:7px}
.legr span{font-size:13px; color:var(--ink-2)}
.legr b{
  font:700 14.5px Gabarito,system-ui,sans-serif; color:var(--ink);
  text-align:right; min-width:78px;
}
/* The column somebody is actually deciding on. */
.legr b:last-child{color:var(--ink)}
.legr b:nth-child(2){color:var(--ink-2); font-weight:600}

/* ---- the streak, as days ----------------------------------------------

   "5 days in a row" is the count; this is the run. A square per day,
   newest on the right, so the next one to fill is the gap after it -
   which is the thing the card is really asking for.

   No month grid around them. A calendar of empty boxes is a record of
   what somebody did not do, and this is the one place in the app
   keeping score of what they did. */
.streakwrap{display:flex; flex-direction:column}
.sdays{
  display:flex; align-items:flex-end; gap:5px; flex-wrap:nowrap;
  margin:9px 2px 0; overflow-x:auto; scrollbar-width:none;
  padding-bottom:2px;
}
.sdays::-webkit-scrollbar{display:none}
.sday{
  flex:none; display:flex; flex-direction:column; align-items:center; gap:2px;
  min-width:30px; padding:5px 6px 6px; border-radius:9px;
  background:var(--hot); color:var(--ink);
  font-variant-numeric:tabular-nums;
}
.sday i{
  font-style:normal; font:700 8.5px Gabarito,system-ui,sans-serif;
  letter-spacing:.07em; text-transform:uppercase; opacity:.62; min-height:10px;
}
.sday b{font:800 14px Gabarito,system-ui,sans-serif; line-height:1}
/* The days before the ten shown, counted rather than drawn. */
.smore{
  flex:none; align-self:center; padding:4px 8px; border-radius:999px;
  background:var(--sunk); border:1px solid var(--line); color:var(--muted);
  font:700 11px Gabarito,system-ui,sans-serif; font-variant-numeric:tabular-nums;
}

/* ---- the ones that are not goals ---------------------------------------

   A locked target is motivating; a locked surprise is a spoiler. These
   six are the app noticing something rather than a thing anybody sets
   out to do, so they stay blank until they land - quieter than the other
   locked ones, because the point is that there is nothing to read. */
.badge.secret .hex{
  background:var(--sunk); border:1px dashed var(--line);
  color:var(--faint);
}
.badge.secret .hex i{font-size:21px}
/* Not italic: the label sits in a fixed cell beside the others and
   italic ran it past the edge - "Not yet foun". */
.badge.secret em{color:var(--faint)}

/* ---- where the coffee goes ---------------------------------------------

   Under the stops it reorders, because a control for moving step two
   belongs beside step two and not in a filter drawer three taps back.
   Quiet: it is an adjustment to a plan that is already made, not one of
   the decisions the screen is asking for. */
.pvorder{
  display:flex; align-items:center; gap:10px;
  margin:10px 0 2px; padding:0 2px;
}
.pvorder[hidden]{display:none}
.pvorder-k{
  display:flex; align-items:center; gap:5px; flex:none;
  font:700 11px Gabarito,system-ui,sans-serif;
  letter-spacing:.08em; text-transform:uppercase; color:var(--muted);
}
.pvorder-k i{font-size:14px}
.pvorder .seg{flex:1; min-width:0}

/* The last row of a capped list, which is a way on rather than a note.
   It reads as the list it ends, not as a button bolted to the bottom. */
button.none.more{
  display:block; width:100%; margin:0; padding:11px 4px;
  border:0; background:none; cursor:pointer;
  font:inherit; font-size:12.5px; color:var(--muted); text-align:center;
  text-decoration:underline; text-underline-offset:3px;
}
button.none.more:hover{color:var(--ink)}
button.none.more:focus-visible{outline:2px solid var(--hot); outline-offset:2px}

/* ---- on the walk ----
   Over the search card rather than under it: once you are on a trail the
   question is where you are on it, not which walk to look for. */
.onwalkbar{position:fixed;z-index:810;top:calc(16px + var(--safe-top));left:16px;right:16px;
  display:flex;align-items:center;gap:12px;padding:12px 10px 12px 16px;
  background:var(--ink);color:var(--card);border-radius:16px;box-shadow:var(--hard);
  font:500 15px/1.35 Gabarito,system-ui,sans-serif}
.onwalkbar>i{color:var(--hot);font-size:20px;flex:none}
.onwalkbar p{margin:0;flex:1;min-width:0}
.onwalkbar b{font-weight:700}
.onwalkbar .icon{flex:none;width:36px;height:36px;display:grid;place-items:center;
  background:none;border:0;color:inherit;cursor:pointer;border-radius:10px}
.onwalkbar .icon:hover{background:rgba(255,255,255,.08)}
@media (min-width:821px){ .onwalkbar{left:auto;width:min(480px,calc(100vw - 32px))} }

/* Under the walk's name: the one button for when you are standing on it,
   and whether its map will still be there when the signal is not. */
.onwalk{display:grid;grid-template-columns:auto 1fr;align-items:start;gap:10px 12px;
  margin:12px 0 6px;padding:12px 14px;border-radius:14px;background:var(--sunk)}
.onwalk .owi{width:34px;height:34px;border-radius:10px;display:grid;place-items:center;
  background:var(--card);color:var(--muted);font-size:18px}
.onwalk[data-state="saved"] .owi{color:var(--yes)}
.onwalk[data-state="failed"] .owi{color:var(--no)}
.onwalk .owt b{display:block;font:700 14.5px/1.3 Gabarito,system-ui,sans-serif;color:var(--ink)}
.onwalk .owt span{display:block;margin-top:2px;font-size:13px;line-height:1.35;color:var(--muted)}
.onwalk .owgo{grid-column:2;justify-self:start;display:inline-flex;align-items:center;gap:6px;
  padding:7px 12px;border:0;border-radius:999px;background:var(--card);color:var(--ink);
  font:700 13px Gabarito,system-ui,sans-serif;cursor:pointer;box-shadow:var(--sh-1)}
.onwalk .owgo i{color:var(--hot);font-size:15px}
.waitcard{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:12px 0 6px;
  padding:12px 14px;border-radius:14px;background:var(--hot);color:#232E3A;text-decoration:none;
  font-size:14px;line-height:1.35}
.waitcard b{display:block;font-size:15px;font-weight:800;letter-spacing:-.01em}
.waitcard i{font-size:20px;flex:none}
.offchip{display:inline-flex;align-items:center;gap:6px;color:var(--muted);
  font:500 13px/1.3 Gabarito,system-ui,sans-serif}
.offchip[data-state="saved"] i{color:#2b8a3e}
.offchip[data-state="failed"] i{color:#c92a2a}

/* The buggy question, under the pram tile that raised it. */
#obBuggyInline .ob-q{margin:16px 0 8px}
#obBuggyInline .ob-q em{font-style:normal;font-weight:600;color:var(--muted);font-size:.85em;margin-left:4px}
.ob-buggies{flex-wrap:wrap}
/* Another walk, under the first one: quiet, never the gold button. */
.ob-another{display:inline-flex;align-items:center;gap:8px;margin:2px 0 0;width:100%;justify-content:center}
/* The last screen is the walk; the picture can give up height so that
   "Show me another" is on screen without a scroll. */
#onboard[data-step="payoff"] .ob-shot > img{height:clamp(120px,26vw,170px)}
#onboard[data-step="payoff"] .ob-map{height:clamp(150px,36vw,190px)}
#onboard[data-step="payoff"] .ob-hook{margin-bottom:10px;padding-bottom:10px}
#onboard[data-step="payoff"] .ob-hook-n{font-size:32px}
#onboard[data-step="payoff"] .obscene{display:none}
/* The goal asked on its own, after a walk: no picture over it. Inside the
   run it is a screen like the others and keeps the band. */
#onboard[data-only="1"][data-step="goal"] .obscene{display:none}

/* ---------- the preview's controls: one row, one height ---------------- */
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.stepbtns{gap:6px}
.stepbtns .pvtools{display:flex;gap:8px;align-items:stretch}
.stepbtns .pvtool{flex:0 0 48px;width:48px;height:48px;padding:0;border-radius:12px}
.stepbtns .pvtool i{font-size:19px}
.stepbtns #pvGo{flex:1 1 auto;min-width:0;height:48px;padding:0 16px;border-radius:12px;
  display:flex;align-items:center;justify-content:center;gap:8px;font-size:16px}
.stepbtns #pvGo i{font-size:18px}
/* Replay carries its word: the only tool left beside Back, and an
   icon on its own there read as a second Back. Same height and corners
   as the square beside it. */
.stepbtns .pvtool.wide{flex:0 0 auto;width:auto;padding:0 14px;gap:7px}
.stepbtns .pvtool.wide b{font:700 13.5px Gabarito,system-ui,sans-serif;color:var(--ink)}
/* Before / After: two equal halves, the size of a label, not of a button. */
.pvorder .seg.ord.tight{flex:none;display:inline-grid;grid-template-columns:1fr 1fr;gap:0;
  padding:3px;border-radius:999px;background:var(--sunk);border:1px solid var(--line)}
.pvorder .seg.ord.tight button{min-width:68px;padding:5px 12px;border:0;border-radius:999px;
  background:none;font:700 12.5px Gabarito,system-ui,sans-serif;color:var(--ink-2);box-shadow:none}
.pvorder .seg.ord.tight button.on{background:var(--card);color:var(--ink);
  box-shadow:0 1px 2px rgba(35,46,58,.14)}

/* The last onboarding card: a swap, not a redraw. */
.ob-win{transition:opacity .14s ease, transform .14s ease}
.ob-win.swapping{opacity:0; transform:translateY(4px)}
.ob-win.swapped .ob-shot, .ob-win.swapped .ob-win-line{animation:none}
/* A walk without a photograph of ours shows its own outline. */
.ob-shot.ob-art{background:#2E3A48; margin:0 0 13px}
.ob-shot.ob-art::after{display:none}
.ob-shot.ob-art svg{display:block; width:100%; height:clamp(120px,26vw,170px)}
@media (prefers-reduced-motion:reduce){ .ob-win{transition:none} }
.ob-another:disabled{background:var(--paper);color:var(--ink-2);border-color:var(--line);opacity:.7;cursor:default}
.stepbtns #pvGo{margin:0;min-height:48px;box-sizing:border-box;align-self:stretch}
.stepbtns .pvtool{box-sizing:border-box;margin:0}
.pvorder .seg.ord.tight button{flex-direction:row;min-height:0;height:30px;line-height:1}

/* ================= the walk page: one scroll, one go bar ===============
   The two tabs are gone and the plan is three rows under the verdict. The
   go bar sits under the sheet's scroll, inside the card, so it is on
   screen at every height the sheet takes and nothing scrolls behind it.
   Gold is spent once on a walk, here. ===================================== */

/* -- the header, peeked -------------------------------------------------
   Peeked, the sheet is the header and the go bar. The header names the
   walk on one line and grades it on the next; at every other height the
   name line hides, because the heading under it says it bigger. */
.suitwrap{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.peekname{display:none;font-size:15px;font-weight:800;letter-spacing:-.02em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#detail.peeked .peekname{display:block}
#detail.peeked .suit{font-size:12.5px;font-weight:600;color:var(--muted);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#detail.peeked .suit.focused{color:var(--ink)}

/* -- the go bar ----------------------------------------------------------- */
.gobar{flex:none;display:flex;gap:10px;align-items:stretch;
  padding:10px 14px 12px;border-top:1px solid var(--rule);background:var(--card);
  box-shadow:0 -14px 22px -20px rgba(35,46,58,.45);position:relative;z-index:4}
.gobar[hidden]{display:none}
.pvbtn{flex:none;width:50px;min-height:50px;display:grid;place-items:center;cursor:pointer;
  border:1px solid var(--rule);border-radius:14px;background:var(--card);color:var(--ink);
  font-size:21px}
.pvbtn:hover{background:var(--sunk)}
.pvbtn:focus-visible{outline:2px solid var(--hot);outline-offset:2px}
/* Navy on gold in both themes. --ink goes pale in the dark theme, and pale
   on gold is the one pairing that cannot be read. */
.gogo{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:1px;min-height:50px;padding:7px 14px;
  background:var(--hot);color:#232E3A;text-decoration:none;border-radius:14px;
  border:1px solid rgba(35,46,58,.45);line-height:1.15;
  transition:transform .15s ease}
.gogo b{display:flex;align-items:center;gap:7px;font:800 16px Gabarito,system-ui,sans-serif;
  letter-spacing:-.01em}
.gogo b i{font-size:17px}
.gogo span{font:600 12px Gabarito,system-ui,sans-serif;opacity:.78;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.gogo span:empty{display:none}
.gogo:active{transform:scale(.985)}
.gogo:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
@media (max-width:820px){
  /* The bar keeps clear of the tab bar's own safe-area padding; the card
     stops above the tab bar, so this is just the bar's own breathing room. */
  .gobar{padding-bottom:12px}
  /* Peeked, the body is hidden but the bar is not: name, verdict, go. */
  #detail.peeked .gobar{display:flex}
}

/* -- the verdict band: verdict and difficulty on one row ----------------- */
.vtop{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}
.vtop .vhead{flex:1;min-width:0}
.vdiff{flex:none;display:flex;flex-direction:column;align-items:flex-end;gap:4px;padding-top:2px}
.vdiff b{font:700 11px Gabarito,system-ui,sans-serif;letter-spacing:.01em;color:var(--ink-2)}
.vdiff .meter i{width:13px;height:5px}
.vwhy{margin:6px 0 0;font-size:13px;line-height:1.45;color:var(--ink-2);font-weight:500}
/* Why it is graded the way it is, under the numbers rather than over the verdict. */
.chalwhy{margin:-6px 0 18px;font-size:13px;line-height:1.45;color:var(--ink-2);font-weight:500}
.chalwhy b{color:var(--ink)}

/* -- the plan rows -------------------------------------------------------- */
.plan{margin:14px 0 6px;border:1px solid var(--rule);border-radius:16px;
  background:var(--paper);overflow:hidden}
.prow{display:flex;align-items:center;gap:12px;width:100%;min-height:58px;
  padding:9px 12px;border:0;border-top:1px solid var(--line-2);background:none;
  color:var(--ink);text-align:left;font:inherit;cursor:default}
.prow:first-child{border-top:0}
button.prow{cursor:pointer}
button.prow:hover{background:var(--sunk)}
button.prow:focus-visible{outline:2px solid var(--hot);outline-offset:-2px}
.pico{flex:none;width:36px;height:36px;border-radius:11px;display:grid;place-items:center;
  background:var(--card);box-shadow:inset 0 0 0 1px var(--line);color:var(--ink);font-size:18px}
.pbody{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.plab{font-style:normal;font-size:11.5px;font-weight:600;color:var(--muted);line-height:1.2;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pval{font-size:15px;font-weight:700;letter-spacing:-.01em;line-height:1.25;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pval span{display:block;font-size:12px;font-weight:500;color:var(--muted);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pval i{font-style:normal;font-size:12px;font-weight:600;margin-left:6px}
.pval i.isopen{color:var(--yes)}
.pval i.prate{color:var(--ink-2);font-weight:700;margin:0 6px 0 0}
.pval i.prate.top{color:var(--maybe)}
.pval i.isshut{color:var(--no)}
/* Not known to be open: a holiday on weekday hours, or no hours at all.
   The amber of "maybe", not the red of shut. */
.pval i.ismaybe{color:var(--maybe)}
.pchg{flex:none;font:700 12.5px Gabarito,system-ui,sans-serif;color:var(--ink-2);
  background:var(--card);box-shadow:inset 0 0 0 1px var(--rule);border-radius:999px;
  padding:6px 11px}
button.prow:hover .pchg{color:var(--ink);box-shadow:inset 0 0 0 1px var(--ink)}

.changeplan>h3{margin-bottom:12px}
.changeplan .dsec{margin-bottom:14px}
.changeplan .entrance{margin-bottom:18px}

/* -- who it suits, the rest folded --------------------------------------- */
.mrest{margin-top:-8px}
.mrest>summary h3{white-space:nowrap}
.mrest>summary h3 span{text-transform:none;letter-spacing:0;min-width:0;flex:1;
  text-align:right;overflow:hidden;text-overflow:ellipsis}
.mrest .matrix{margin-top:6px}

/* -- the end of the page ------------------------------------------------- */
.sharerow{margin-top:8px;display:flex;flex-direction:column;gap:7px}
.sharerow .btn{width:100%;justify-content:center;margin:0}
.sharerow .keep.on{border-color:var(--ink);color:var(--ink);background:var(--sunk)}
.sharerow .keep.on i{color:var(--coffee)}

/* -- tighter above the fold ----------------------------------------------
   Everything above the plan rows is measured against the middle height of
   the sheet, so the gaps here are the gaps that fit. */
#detailBody h2{margin-bottom:3px}
.dcounty{margin-bottom:12px}
.verdict{padding:12px 14px;margin-bottom:12px}
.vwhy{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.vwhy.open{display:block;-webkit-line-clamp:unset;overflow:visible}
.vmore{display:inline-block;margin:4px 0 0;padding:2px 0;border:0;background:none;color:var(--ink);
  font:700 13px/1.3 Gabarito,system-ui,sans-serif;text-decoration:underline;text-underline-offset:3px;cursor:pointer}
.vmore[hidden]{display:none}
.buggyrow{margin-top:9px}
.buggyrow > summary{padding:8px 11px}
.bygo{margin:10px 0 0}
.plan{margin:10px 0 6px}
/* The buggy row is one line until it is opened: what it wants, and a
   caret. The why and the "tap to say what you push" are inside, where
   the picker is. A two-line card in the band pushed the plan rows under
   the fold on every walk with a pram in the crew. */
.buggyrow > summary{min-height:38px}
.buggyrow summary span{flex:1}
.buggyrow summary b{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.buggyrow summary em{display:none}
.buggyrow[open] summary em{display:block}
.buggyrow[open] summary b{white-space:normal}
.buggyrow > summary::after{content:'';flex:none;width:7px;height:7px;margin-right:3px;
  border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;
  transform:rotate(45deg) translateY(-2px);opacity:.45;transition:transform .18s ease}
.buggyrow[open] > summary::after{transform:rotate(-135deg) translateY(-2px)}
/* Before you go: the rows are the heading. Each carries its own icon, and
   the label above them cost a line the fold did not have. */
.bygo{padding:9px 12px}
.bygo h3{display:none}
.byg{font-size:12.5px}
/* The prompts under the verdict and the plan carry an icon; space it. */
.whoprompt button{display:inline-flex;align-items:center;justify-content:center;gap:7px}

/* Gold ground, navy ink - in the dark theme too. --ink goes pale there,
   and pale on gold is the one pairing nobody can read. */
:root{--on-hot:#232E3A}
.chipctl.on, .tagpick button.on, .seg button.on,
.ord-b.on, .when.on,
.entlist button.on, .tab.on,
.chipctl.on i, .tab.on i,
.seg button.on em{color:var(--on-hot)}
.chipctl.on, .tagpick button.on, .seg button.on,
.ord-b.on, .when.on,
.entlist button.on, .tab.on{border-color:var(--on-hot)}

/* ================= the home screen =====================================
   Explore with a starting point: the filter line in the header, today's
   walk, Let's go, four more in a row. Pulled up, the list - same card,
   smaller. One gold button on the screen. ================================ */

/* The line at the top of the card. A sentence that is also the way to
   change any word in it. */
.fline{flex:1;min-width:0;display:flex;align-items:center;gap:8px;
  padding:4px 0;border:0;background:none;cursor:pointer;text-align:left;
  color:var(--ink);font:600 13.5px/1.2 Gabarito,system-ui,sans-serif;letter-spacing:-.01em}
.fline[hidden]{display:none}
.fline > i:first-child{font-size:16px;color:var(--muted);flex:none}
.fline .fl-go{margin-left:auto;font-size:13px;color:var(--muted);flex:none}
.fline span{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fline span i{font-style:normal;color:var(--faint);margin:0 5px}
.fline:hover span{text-decoration:underline;text-underline-offset:2px}
.fline:focus-visible{outline:2px solid var(--hot);outline-offset:2px;border-radius:8px}

/* The verdict chip. The colour is the map's colour for the walk; the
   words are the heading the walk will open with. */
.vchip{display:inline-flex;align-items:center;gap:6px;max-width:100%;
  padding:3px 9px 3px 7px;border-radius:999px;
  font:700 11.5px/1.3 Gabarito,system-ui,sans-serif;letter-spacing:.005em;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.vchip i{width:7px;height:7px;border-radius:50%;flex:none;background:currentColor}
.vchip.yes{background:var(--yes-bg);color:var(--yes)}
.vchip.maybe{background:var(--maybe-bg);color:var(--maybe)}
.vchip.no{background:var(--no-bg);color:var(--no)}

/* The card: picture, name, chip, one line. */
.wcard{display:flex;gap:12px;align-items:center;min-width:0;cursor:pointer}
.wc-thumb{flex:none;width:76px;height:76px;border-radius:12px;object-fit:cover;
  background:var(--sunk);display:grid;place-items:center;color:var(--faint);
  font-size:22px;overflow:hidden}
/* Navy in both themes: the outline is drawn cream, and cream on the dark
   theme's pale ink is no outline at all. */
.wc-thumb.art{background:#232E3A}
.wc-thumb.art > svg{width:100%;height:100%;display:block}
.wc-body{flex:1;min-width:0}
.wc-k{font:700 11px/1.2 Gabarito,system-ui,sans-serif;letter-spacing:.02em;
  color:var(--maybe);margin-bottom:2px}
.wc-name{font:700 17px/1.15 Gabarito,system-ui,sans-serif;letter-spacing:-.02em;
  color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.wc-chip{margin-top:5px;display:flex;align-items:center;gap:8px;min-width:0}
.wc-chip:empty{display:none}
/* Two lines, not one: the coffee is the end of the line and the part
   worth reading, and one line cut it to "coffee at The Pavilio…". */
.wc-meta{margin-top:5px;font:500 12.5px/1.35 Gabarito,system-ui,sans-serif;color:var(--muted);
  overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;
  line-clamp:2;overflow-wrap:anywhere}
.wc-meta b{font-weight:600;color:var(--ink-2)}
.wc-go{flex:none;font-size:15px;color:var(--faint)}
.wcard.sm{padding:10px 12px}
.wcard.sm .wc-thumb{width:60px;height:60px;border-radius:10px}
.wcard.sm .wc-name{font-size:15.5px}

/* Today's walk: the card, then the three things to do with it. */
.today{flex:none;padding:12px 14px 10px;overflow:hidden}
.today[hidden]{display:none}
.td-head{display:flex;justify-content:space-between;align-items:baseline;gap:10px;
  margin-bottom:10px;white-space:nowrap}
.td-k{font:800 12px/1 Gabarito,system-ui,sans-serif;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink);flex:none}
.td-s{font:500 12px/1.2 Gabarito,system-ui,sans-serif;color:var(--muted);min-width:0;
  overflow:hidden;text-overflow:ellipsis}
.td-row{display:flex;gap:8px;align-items:stretch;margin-top:12px}
.td-row .gogo{flex:1.5;min-height:46px}
.td-row .gogo b{font-size:15.5px}
.td-none{margin:4px 0 10px;font-size:13.5px;line-height:1.5;color:var(--ink-2)}
/* A quiet button: the answer you give when the gold one is wrong. */
.btn.quiet{border-color:var(--rule);background:var(--card);color:var(--ink);
  justify-content:center;font-weight:700}
.btn.quiet:hover{background:var(--sunk)}
/* An icon button the height of the buttons beside it. */
.ibtn{flex:none;width:46px;min-height:46px;display:grid;place-items:center;cursor:pointer;
  border:1px solid var(--rule);border-radius:12px;background:var(--card);color:var(--ink);
  font-size:19px;transition:transform .08s,background .15s}
.ibtn:hover{background:var(--sunk)}
.ibtn:active{transform:translate(1px,1px)}
.ibtn:focus-visible{outline:2px solid var(--hot);outline-offset:2px}
/* The landing's one primary button, and the card's: gold, navy on it in
   both themes, same as the go bar on a walk. */
.btn.gold{background:var(--hot);color:#232E3A;border-color:rgba(35,46,58,.45);font-weight:800}
.btn.gold:hover{background:var(--hot)}
#landing .btn.quiet{border-color:transparent;color:var(--ink-2);margin-bottom:0}

/* The credits as the last row of the home list - see drawList - not a
   block pinned under it. */
#panel.home #credits{display:none}
#results li.rcredits{cursor:default;padding:12px 14px 6px;font-size:11px;line-height:1.5;
  color:var(--faint)}
#results li.rcredits:hover{background:none}

/* Four more, in a row that scrolls sideways under the thumb. */
.td-mini{display:flex;gap:8px;margin:12px -14px 0;padding:0 14px 8px;overflow-x:auto;
  scroll-snap-type:x proximity;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.td-mini::-webkit-scrollbar{display:none}
.mcard{flex:0 0 auto;width:188px;display:flex;align-items:center;gap:9px;text-align:left;
  padding:8px;border:1px solid var(--rule);border-radius:12px;background:var(--card);
  color:var(--ink);cursor:pointer;scroll-snap-align:start;
  transition:transform .08s,background .15s,border-color .15s}
.mcard:hover{background:var(--sunk);border-color:var(--ink)}
.mcard:active{transform:translate(1px,1px)}
.mcard .wc-thumb{width:46px;height:46px;border-radius:9px;font-size:16px}
.mc-body{min-width:0;display:flex;flex-direction:column;gap:1px}
.mc-k{font:700 10.5px/1.2 Gabarito,system-ui,sans-serif;letter-spacing:.02em;color:var(--maybe)}
.mc-name{font:700 13px/1.15 Gabarito,system-ui,sans-serif;letter-spacing:-.015em;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mc-meta{font:500 11.5px/1.2 Gabarito,system-ui,sans-serif;color:var(--muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* Where the screen is a phone: the middle height holds the card with the
   row of four; pulled up, the card gives way to the list; peeked, the
   filter line is all there is. The caret goes - the grip is the handle. */
@media (max-width:820px){
  #panel.home{max-height:54dvh}
  /* The fade that says "there is more below" has nothing to say here:
     the card ends where the row of four ends. */
  #panel.home:not(.tall)::after{display:none}
  #panel.home #collapse{display:none}
  /* The landing is two buttons and a line, and the plain list's height
     cut it at the first button. */
  /* Explore's landing only. Left on, it pinned My walks and You to the same
     44dvh in every state, so dragging changed nothing - the tab felt stuck. */
  #panel[data-landing]:not([data-tab]):not(.tall):not(.peeked),
  #panel[data-landing][data-tab=explore]:not(.tall):not(.peeked){max-height:min(44dvh,400px)}
  /* Pulled all the way up it is the explore screen: today's walk stays at
     the top and every other walk that fits runs on below it. The home
     card's own 54dvh used to win over .tall, so the sheet stopped halfway;
     86dvh fixed that and ran it up under the search card. It stops where
     every other tab's does - a gap below the chrome. */
  #panel.home.tall{
    max-height:calc(100dvh - var(--safe-top) - var(--chrome-h,112px) - var(--tabh) - env(safe-area-inset-bottom) - 26px)}
  /* Pulled up there is room for all four picks - nearest, best coffee, new
     to you, a bit further - as a grid, not a row that hid two off the edge. */
  #panel.home.tall .td-mini{display:grid;grid-template-columns:1fr 1fr;overflow:visible}
  #panel.home.tall .td-mini .mcard{width:auto;min-width:0}
  #panel.home:not(.tall) #results,#panel.home:not(.tall) #credits{display:none}
  /* While a finger lifts it the list has to be there to lift into - hidden,
     the sheet stayed the card's height however far it was pulled, and on
     letting go it measured that and dropped back. Only a flick worked. */
  #panel.home.dragging #results{display:block}
  #panel.home.peeked #today{display:none}
}
/* On a desktop the card and the list share one column: today's walk at
   the top, the rest under it. */
@media (min-width:821px){
  .today{border-bottom:1px solid var(--rule)}
}

/* ================= the two sheets ======================================
   "Walks for…" is the one sheet that narrows the walks - it replaced the
   filter sheet, the plan sheet and the who sheet - and the pick sheet is
   the coffee or the car park, opened by "change" on a plan row. Both are
   the log sheet's shape: centred on a desktop, a bottom sheet on a phone,
   over the scrim. */
#forSheet,#pickSheet{position:fixed;z-index:910;top:50%;left:50%;transform:translate(-50%,-50%);
  width:min(460px,calc(100vw - 32px));max-height:min(1000px,calc(100dvh - 72px));
  display:flex;flex-direction:column;background:var(--card);
  border:1px solid var(--rule);border-radius:18px;box-shadow:var(--lift-lg);overflow:hidden}
@media (max-width:820px){
  #forSheet,#pickSheet{top:auto;bottom:0;left:0;right:0;transform:none;width:auto;
    border-radius:18px 18px 0 0;border-bottom:0;max-height:88dvh}
  /* The footer sits above the home bar. */
  #forSheet .sheetfoot{padding-bottom:calc(12px + env(safe-area-inset-bottom))}
  #pickSheet .sheetbody{padding-bottom:calc(20px + env(safe-area-inset-bottom))}
}
/* Clear and close together in the corner. Clear is a word, not a button:
   it undoes, and an undo should not look like the thing it undoes. */
.headacts{display:flex;align-items:center;gap:6px}
.textbtn{background:none;border:0;padding:6px 8px;min-height:36px;cursor:pointer;
  color:var(--ink-2);font:700 13.5px Gabarito,system-ui,sans-serif;
  text-decoration:underline;text-underline-offset:3px;text-decoration-color:var(--line);
  border-radius:8px}
.textbtn:hover{color:var(--ink);text-decoration-color:var(--ink)}
.textbtn.on{color:var(--coffee);text-decoration-color:var(--coffee)}
.textbtn:focus-visible{outline:2px solid var(--hot);outline-offset:2px}
.sheettitle{min-width:0}
.sheettitle h2{margin:0;font-size:18px;font-weight:800;letter-spacing:-.03em}
.sheetsub{margin:1px 0 0;font-size:12px;color:var(--muted);font-weight:500;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* -- from -------------------------------------------------------------- */
/* Where you set off from, as one line once it is known, with "change" at
   the end of it. The list of ways to answer sits under it until then. */
.fromnow{display:flex;align-items:center;gap:10px;min-height:44px;padding:0 12px;
  border-radius:14px;background:var(--paper);border:1px solid var(--line-2)}
.fromnow > i{font-size:16px;color:var(--ink-2);flex:none}
.fromnow .originnow{flex:1;min-width:0;margin:0;font-size:14.5px;font-weight:700;
  letter-spacing:-.01em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fromnow .originnow.unset{font-weight:500;color:var(--ink-2);white-space:normal;
  font-size:13px;line-height:1.35;padding:8px 0}
.fromnow .originchange{margin:0;flex:none;min-height:32px}
.fromnow:has(.originnow.unset){background:transparent;border-style:dashed}
#forSheet .startlist{margin:8px 0 10px}

/* -- how far ----------------------------------------------------------- */
/* Four drives as one control. The base .seg button is a column with a
   78px floor, which four of cannot share a phone; these are a row each. */
.seg.radii{gap:6px}
.seg.radii button{min-width:0;flex-direction:row;padding:9px 4px;font-size:13px;
  font-weight:700;color:var(--ink-2)}
.fornote{margin:8px 0 0;font-size:11.5px;line-height:1.5;color:var(--faint)}
.fornote.warn{color:var(--maybe)}
.fornote:empty{display:none}

/* -- who --------------------------------------------------------------- */
/* The onboarding's tiles, three to a row where there is room: six of them
   two to a row stood taller than the map. */
.obgrid.forwho{grid-template-columns:repeat(3,1fr);gap:7px}
.obgrid.forwho .pickone.tile{min-height:74px;padding:10px 10px 10px;gap:5px;
  background:var(--paper)}
.obgrid.forwho .pickone.tile.on{background:var(--sunk)}
.obgrid.forwho .pickone.tile b{font-size:12.5px;line-height:1.2;padding-right:14px}
.obgrid.forwho .pickone.tile > i:first-child{font-size:19px}
.obgrid.forwho .pickone.tile .box{top:8px;right:8px;width:16px;height:16px;font-size:10px}
@media (max-width:360px){.obgrid.forwho{grid-template-columns:1fr 1fr}}
#forBuggy .ob-q{margin:12px 0 7px;font-size:13px}
#forBuggy:empty{display:none}
#forWhoNote{margin-top:10px}

/* -- more -------------------------------------------------------------- */
/* One line that opens into the rest. A dot on it says something inside is
   narrowing the list, so a short sheet never hides a filter. */
.formore{margin:4px 0 0}
.formore summary{display:flex;align-items:center;gap:8px;cursor:pointer;list-style:none;
  min-height:46px;padding:0 2px;border-top:1px solid var(--rule);
  font:700 15px Gabarito,system-ui,sans-serif;color:var(--ink)}
.formore summary::-webkit-details-marker{display:none}
.formore summary em{flex:1;min-width:0;font-style:normal;font-size:12px;font-weight:500;
  color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.formore summary i{font-size:14px;color:var(--muted);transition:transform .18s ease}
.formore[open] summary i{transform:rotate(180deg)}
.formore.on summary span::after{content:'';display:inline-block;width:7px;height:7px;
  border-radius:50%;background:var(--hot);margin-left:7px;vertical-align:2px}
.formore[open] summary{margin-bottom:14px}
.formore .field:last-child{margin-bottom:6px}
.formore summary:focus-visible{outline:2px solid var(--hot);outline-offset:-2px}

/* The gold button says the count. When nothing matches it says so, and
   is still a way out of the sheet. */
#forSheet .sheetfoot .btn.gold{flex:1.5}
#forSheet .sheetfoot .btn.quiet{flex:1}
#forGo.none{background:var(--sunk);color:var(--ink-2);border-color:var(--line)}

/* -- the coffee and the car park --------------------------------------- */
/* Ranked rows: a number, the name and its line, the one figure that
   matters at the right, and a tick on the chosen one. The whole row is
   the button. */
.crows{display:flex;flex-direction:column}
.crow{display:flex;align-items:center;gap:10px;width:100%;min-height:58px;
  padding:9px 2px;background:none;border:0;border-bottom:1px solid var(--line-2);
  text-align:left;color:var(--ink);cursor:pointer;border-radius:0;
  transition:background .15s}
.crow:last-child{border-bottom:0}
.crow:hover{background:var(--sunk)}
.crow:focus-visible{outline:2px solid var(--hot);outline-offset:-2px;border-radius:10px}
.crow .rk{flex:none;width:22px;height:22px;border-radius:50%;background:var(--sunk);
  display:grid;place-items:center;font:700 11px 'JetBrains Mono',ui-monospace,monospace;
  color:var(--ink-2)}
.crow.on .rk{background:var(--hot);color:#232E3A}
.crow .cbody{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.crow .nm{font-size:15px;font-weight:700;letter-spacing:-.01em;line-height:1.2;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.crow.t2 .nm{font-weight:600;color:var(--ink-2)}
.crow .mt{font-size:12px;color:var(--muted);line-height:1.3;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.crow .mt b{font-weight:700}
.crow .mt b.isopen{color:var(--yes)}
.crow .mt b.isshut{color:var(--no)}
.crow .mt b.ismaybe{color:var(--maybe)}
.crow .tagk{font-style:normal;font-weight:700;color:var(--coffee);margin-right:6px}
.crow .tagk::after{content:'·';color:var(--faint);margin-left:6px;font-weight:500}
.crow .crate{font-style:normal;font-size:12px;font-weight:700;color:var(--maybe);margin-left:4px}
.crow .rt{flex:none;max-width:34%;text-align:right;
  font:600 12px/1.25 'JetBrains Mono',ui-monospace,monospace;color:var(--ink-2)}
.crow .tick{flex:none;width:22px;font-size:20px;color:var(--coffee);display:grid;place-items:center}
.crow .tick:empty{opacity:0}
/* The way to the rest, as a row in the same list. */
.allrow{display:flex;align-items:center;gap:8px;width:100%;min-height:48px;padding:8px 2px;
  background:none;border:0;border-bottom:1px solid var(--line-2);text-align:left;
  color:var(--ink);cursor:pointer;font:700 15px Gabarito,system-ui,sans-serif}
.allrow em{flex:1;min-width:0;font-style:normal;font-size:12px;font-weight:500;color:var(--muted);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.allrow i{font-size:14px;color:var(--muted)}
.allrow:hover{background:var(--sunk)}
#pickSheet .seg.ord{margin:0 0 6px}
#pickSheet .search.cafefind{margin:14px 0 0}
#pickSheet .attrib{margin:10px 0 0}
.picklinks{display:flex;justify-content:space-between;gap:10px;margin:14px 0 0}
.picklinks .textbtn{padding:6px 0}
#pickSheet .none.note{margin-top:12px}

/* ---------- My walks, You, the cabinet page -----------------------------
   Three tabs. My walks has the one gold button on it; You has none,
   because nothing there is an outing. One radius for the cards (16px),
   one for the controls (12px), one height for a row (52px). */
.mwhead{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:2px}
.mwhead h3{margin:0}
#tabBody > h3{font-size:24px;margin-bottom:5px}
#tabBody .mwhead .btn{width:auto;margin:0;min-height:40px;padding:0 14px 0 12px;
  font-size:14px;border-radius:12px;gap:5px}
#tabBody .mwhead .btn i{font-size:16px}

/* The streak and the badges as one card: the number that is still
   running, and under a hairline the five hexagons that open the cabinet. */
.streakcard{margin:14px 0 16px;padding:0 14px;border:1.5px solid var(--rule);
  border-radius:16px;background:var(--card)}
.streakcard .streakwrap{display:contents}
/* The widget, offered: a small picture of it with their own number, and
   the three steps folded under Show me how. */
.wtip{margin:-4px 0 20px;padding:14px;border:1.5px solid var(--rule);border-radius:16px;background:var(--raise)}
.wtip .wtop{display:flex;gap:14px;align-items:center}
.wmini{flex:none;display:grid;place-items:center;align-content:center;gap:0;width:64px;height:64px;
  border-radius:15px;background:var(--card);box-shadow:var(--sh-1);color:var(--ink)}
.wmini i{font-size:15px;color:var(--hot)}
.wmini b{font-size:24px;font-weight:800;line-height:1}
.wmini span{font-size:10.5px;color:var(--muted)}
.wtip h4{margin:0 0 3px;font-size:15.5px;font-weight:700;letter-spacing:-.01em;line-height:1.25}
.wtip .wtxt p{margin:0;font-size:14px;color:var(--muted);line-height:1.4}
.wbtns{display:flex;gap:8px;margin-top:12px}
.wbtns .btn{flex:1 1 0;width:auto;min-width:0}
.wsteps{margin:14px 0 0;padding-left:20px;font-size:14.5px;line-height:1.45}
.wsteps li{margin-bottom:6px}
.wnote{margin:4px 0 0;font-size:13px;color:var(--muted);line-height:1.4}
.yfold .wsteps{margin-top:2px}
.streakcard .streak{margin:0;padding:13px 0;border:0;background:transparent}
.streakcard:has(.streak.hot){border-color:var(--hot);background:var(--sunk)}
.bstrip{display:flex;align-items:center;gap:7px;width:100%;padding:12px 0;
  border:0;border-top:1px solid var(--line-2);background:none;cursor:pointer;
  color:var(--ink);font:inherit;text-align:left}
.bstrip:hover .bcount{color:var(--ink)}
.bstrip:focus-visible{outline:2px solid var(--hot);outline-offset:2px;border-radius:8px}
.bhex{flex:none;width:36px;height:40px;display:grid;place-items:center;
  background:var(--bh,var(--yes));color:#FFF9EE;font-size:17px;
  clip-path:polygon(50% 0%,100% 25%,100% 75%,50% 100%,0% 75%,0% 25%)}
.bhex.locked{background:var(--sunk);color:var(--faint);
  box-shadow:inset 0 0 0 1px var(--line)}
.bhex.secret{font-size:14px}
.bcount{margin-left:auto;display:inline-flex;align-items:center;gap:3px;
  font:600 12.5px Gabarito,system-ui,sans-serif;color:var(--muted);white-space:nowrap}
.bcount i{font-size:12px}

/* This week: the label and the number on one line, the bar, the days. */
.tw-row{display:flex;justify-content:space-between;align-items:baseline;gap:10px}
.tw-row .tw-s{margin:0;color:var(--muted);font-weight:600;white-space:nowrap}
.tw-row .tw-s b{font:700 12.5px 'JetBrains Mono',ui-monospace,monospace;color:var(--ink-2)}
.thisweek .goalbar{margin:10px 0 0}
.days{display:flex;gap:6px;margin-top:10px}
.days span{flex:1;height:34px;border-radius:9px;display:grid;place-items:center;
  font:700 12px Gabarito,system-ui,sans-serif;background:var(--sunk);color:var(--faint)}
.days span.on{background:var(--moss);color:#FFF9EE}
/* Today: a gold ring standing off the square, the same size as the rest.
   It was .today, which is also the home panel's class - its padding
   made the day twice as wide as the others. */
.days span.now{color:var(--ink);box-shadow:0 0 0 2px var(--card),0 0 0 4px var(--hot)}
.days span.on.now{color:#FFF9EE}

/* Logged · Saved. A segmented control, one piece, the chosen half
   lifted - not the gold of a filter chip, because this is a view and
   not a choice that changes the answer. */
.segs{display:flex;padding:3px;margin:16px 0 4px;border-radius:12px;background:var(--sunk)}
.segs button{flex:1 1 0;min-height:38px;border:0;border-radius:9px;background:none;
  cursor:pointer;color:var(--muted);font:700 13.5px Gabarito,system-ui,sans-serif;
  transition:background .18s ease,color .18s ease}
.segs button.on{background:var(--card);color:var(--ink);box-shadow:var(--lift)}
.segs button:focus-visible{outline:2px solid var(--hot);outline-offset:-2px}
.segs.mini{flex:none;margin:0 0 0 auto;padding:2px}
.segs.mini button{flex:none;min-height:30px;padding:0 11px;font-size:12px}
#tabBody .segs + .logrow{margin-top:4px}
#tabBody .empty{padding:30px 18px}

/* The cabinet page: a row back to My walks above the heading. */
.backrow{display:inline-flex;align-items:center;gap:6px;margin:0 0 8px;padding:6px 8px 6px 0;
  border:0;background:none;cursor:pointer;color:var(--ink-2);
  font:700 13px Gabarito,system-ui,sans-serif;border-radius:8px}
.backrow i{font-size:15px}
.backrow:hover{color:var(--ink)}
.backrow:focus-visible{outline:2px solid var(--hot);outline-offset:2px}
#tabBody .csec{margin-top:22px}

/* You: the crew as pills in a card, then a list of rows. */
.crewcard{margin:14px 0 10px;padding:14px;border:1.5px solid var(--rule);
  border-radius:16px;background:var(--card)}
.cc-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}
.cc-head .tw-k{color:var(--ink)}
.cc-head .textbtn{min-height:28px;padding:2px 4px;font-size:13px}
.pills{display:flex;flex-wrap:wrap;gap:8px}
.pill{display:inline-flex;align-items:center;gap:7px;padding:8px 13px;border-radius:999px;
  background:var(--ink);color:var(--card);font:700 13px Gabarito,system-ui,sans-serif}
.pill i{font-size:15px}
.pill.off{background:var(--sunk);color:var(--muted)}
.crewcard .pfnote{margin:10px 0 0;font-size:12.5px;line-height:1.5}
/* Coffeewalks Pro: the crew card's frame, one line that says where you
   stand, one note, one button. */
.procard .pc-line{display:block;font-size:17px;font-weight:800;letter-spacing:-.02em}
.procard .pfnote{margin:4px 0 0}
.procard .pc-btn{display:flex;justify-content:center;width:100%;margin-top:12px;min-height:46px}
.procard .pc-restore{display:block;margin:6px auto 0;font-size:13px}
.pc-on{font:700 10.5px Gabarito,system-ui,sans-serif;letter-spacing:.06em;text-transform:uppercase;
  color:var(--moss)}
.crewcard .obgrid{margin-top:4px}
.crewcard .buggyopts{margin-top:4px}
.ylist{margin-top:6px}
.yrow{display:flex;align-items:center;gap:12px;width:100%;min-height:52px;padding:10px 2px;
  border:0;border-bottom:1px solid var(--line-2);background:none;text-align:left;
  font:inherit;color:var(--ink);cursor:pointer;text-decoration:none;border-radius:0}
.yrow > i:first-child{flex:none;width:22px;font-size:19px;color:var(--ink-2);text-align:center}
.yrow .yk{flex:none;font-weight:700;font-size:15px;letter-spacing:-.01em}
.yrow .yv{margin-left:auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-size:13px;color:var(--muted);text-align:right}
.yrow > i:last-child{flex:none;font-size:14px;color:var(--faint);transition:transform .18s ease}
.yrow[aria-expanded="true"] > i:last-child{transform:rotate(90deg)}
.yrow:hover{background:var(--sunk)}
.yrow:focus-visible{outline:2px solid var(--hot);outline-offset:-2px;border-radius:8px}
.yrow.still{cursor:default}
.yrow.still:hover{background:none}
.yrow.still select{margin-left:auto;border:1px solid var(--rule);border-radius:10px;
  background:var(--card);color:var(--ink);font:600 12.5px Gabarito,system-ui,sans-serif;
  padding:6px 8px;cursor:pointer}
.yrow.danger .yk,.yrow.danger > i:first-child{color:var(--no)}
.yfold{padding:6px 2px 14px 36px;border-bottom:1px solid var(--line-2);
  font-size:12.5px;line-height:1.5;color:var(--muted)}
.yfold p{margin:0 0 8px}
.yfold p:last-child{margin-bottom:0}
.yfold ul{margin:0;padding-left:16px}
.ycredit{margin:14px 0 0;font-size:11px;line-height:1.5;color:var(--faint)}

/* The paywall's proof: the walk just planned, as a card where the vista
   was. Same thumbnail the home card uses, so it is recognisably the one. */
.pwwalk{display:flex;align-items:center;gap:12px;margin:14px 0 4px;padding:12px;
  border-radius:16px;background:var(--sunk)}
.pwwalk .wc-thumb{width:64px;height:64px;border-radius:12px}
.pww-body{min-width:0}
.pww-body b{display:block;font-size:15px;font-weight:700;letter-spacing:-.01em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pww-body em{display:flex;align-items:center;gap:5px;margin-top:3px;font-style:normal;
  font-size:12.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pww-body em i{font-size:13px;color:var(--moss)}
#paywall .pwwhy{font-size:1rem}
/* The plans sit on the button, where the thumb is, and the picture takes
   whatever height is left above them - so no phone gets a band of empty
   cream between the last plan and the way in. On a short phone the
   picture gives way first, then the body scrolls. */
#pwBody{display:flex;flex-direction:column}
#pwBody > :first-child{margin-top:auto}
/* Not the onboarding's centring (min-height:760px below): that splits the
   spare height above the title and above the button, which is the gap. */
#paywall .obhead{margin-top:0}
#paywall .obbody{flex:1 1 auto;margin-bottom:0}
#paywall .obscene.pwscene{flex:1 1 0;height:auto;min-height:110px;max-height:340px;
  margin:.2rem 0 .2rem}
#paywall .pwwhy{flex:none;margin:.9rem 0 0}
#paywall .pwwhy.one{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#paywall .pwplans{flex:none;margin-top:1.3rem}
#paywall .pwwalk{flex:none}
/* A short phone has room for the plans or the picture, and it is not the
   picture. */
@media (max-height:740px){ #paywall .obscene.pwscene{display:none}
  #pwBody > .pwscene + *{margin-top:auto} }
/* The one gold on this screen is the way in. */
#paywall .btn.gold.wide{flex:1 0 100%;justify-content:center;border-color:rgba(35,46,58,.45)}

@media (prefers-reduced-motion:reduce){
  .segs button,.yrow > i:last-child{transition:none}
}

/* A walk across the county is a cut, not a glide: the map comes up from
   a little faded rather than flying past tiles that never load. */
.leaflet-container.cw-cut .leaflet-map-pane{animation:cwCut .28s ease-out}
@keyframes cwCut{from{opacity:.35}to{opacity:1}}
#goLabel{transition:opacity .2s ease}
#goLabel.pending{opacity:0}
/* Android paints its own blue over a tapped button; the shuffle flashed it
   on every press. The press is ours to show. */
.mbtn{-webkit-tap-highlight-color:transparent}
.mbtn.ink:active{filter:brightness(1.2);transform:scale(.94)}

/* ---- the onboarding card's map: the same picture on every card ---- */
.ob-map{height:clamp(160px,38vw,220px)}
.ob-map::after{display:none}
.ob-map .ob-ph,.ob-map .ob-mini{position:absolute; inset:0}
.ob-map .ob-ph{display:grid; place-items:center; background:var(--sunk)}
.ob-map .ob-ph svg{width:100%; height:100%}
.ob-map .ob-mini{background:transparent; opacity:0; transition:opacity .35s ease}
.ob-map.ready .ob-mini{opacity:1}
.ob-map .leaflet-control-attribution{font-size:8px; line-height:1.2; padding:0 4px;
  background:rgba(255,255,255,.6)}
.ob-map .leaflet-control-attribution a{color:inherit}
.ob-map img.ob-inset{
  position:absolute; right:12px; bottom:12px; z-index:500;
  width:92px; height:92px; object-fit:cover; border-radius:12px;
  border:3px solid var(--card); box-shadow:0 6px 18px rgba(26,22,20,.28);
}
.ob-stage{position:fixed; left:-10000px; top:0; visibility:hidden; pointer-events:none}
.ob-map .leaflet-bottom{bottom:0!important}
.ob-map .leaflet-right{right:0!important}

/* ---- the outing's three actions: one kind of button, icons only ---- */
.sharerow.iconrow{flex-direction:row; justify-content:center; gap:18px;
  margin:22px 0 6px; padding-top:18px; border-top:1px solid var(--rule)}
.iact{width:50px; height:50px; border-radius:50%; flex:none;
  display:grid; place-items:center; cursor:pointer;
  background:var(--card); color:var(--ink); border:1.5px solid var(--rule);
  -webkit-tap-highlight-color:transparent;
  transition:background .18s ease,border-color .18s ease,color .18s ease,transform .1s ease}
.iact i{font-size:21px}
.iact:hover{border-color:var(--ink)}
.iact:active{transform:scale(.93)}
.iact:focus-visible{outline:2px solid var(--hot); outline-offset:2px}
.iact.on,.iact.done{background:var(--ink); border-color:var(--ink); color:var(--hot)}
.sharerow .iact.keep.on{background:var(--ink); border-color:var(--ink); color:var(--hot)}
.sharerow .iact.keep.on i{color:var(--hot)}
a.iact{text-decoration:none}

/* ---- the sheet: how it moves ------------------------------------------
   Half the screen for a walk, so the map above it is a picture and not a
   strip. The curve is the one phones use for their own sheets - quick to
   leave, long to settle - instead of the snap of an ease-out. */
@media (max-width:820px){
  #detail{max-height:50dvh}
  #panel,#detail{
    transition:max-height .42s cubic-bezier(.32,.72,0,1),
               transform .22s cubic-bezier(.16,1,.3,1);
    border-radius:22px 22px 0 0;
    box-shadow:0 -1px 0 rgba(0,0,0,.04),0 -10px 34px rgba(26,22,20,.13)}
  #panel .grip,#detail .grip{width:38px;height:5px;padding:9px 30px;margin:0 auto -4px;
    background:var(--rule);background-clip:content-box;border-radius:9px;
    cursor:grab;touch-action:none;opacity:.85}
  #detailBody,#results,#tabBody{overscroll-behavior:contain}
  /* Pulled all the way up, the map steps back rather than competing. */
  #map::after{content:'';position:absolute;inset:0;z-index:690;pointer-events:none;
    background:rgba(20,24,30,.22);opacity:0;transition:opacity .42s cubic-bezier(.32,.72,0,1)}
  body.sheet-tall #map::after{opacity:1}
}
/* The badges on a phone: a size a thumb can read and hit. */
@media (max-width:820px){
  .tbadge{padding:4px 8px;gap:5px;cursor:pointer}
  .tbadge i{font-size:14px}
}

/* ---- the taste: the one ask a shared link makes ---- */
#joinSheet{position:fixed;inset:0;z-index:2000}
#joinSheet .js-scrim{position:absolute;inset:0;background:rgba(20,24,30,.42);
  opacity:0;transition:opacity .32s ease}
#joinSheet .js-card{position:absolute;left:0;right:0;bottom:0;margin:0 auto;max-width:520px;
  background:var(--card);color:var(--ink);border-radius:24px 24px 0 0;
  padding:10px 22px calc(22px + env(safe-area-inset-bottom));
  box-shadow:0 -12px 40px rgba(26,22,20,.22);
  transform:translateY(105%);transition:transform .42s cubic-bezier(.32,.72,0,1)}
#joinSheet.on .js-scrim{opacity:1}
#joinSheet.on .js-card{transform:none}
#joinSheet .js-grip{width:38px;height:5px;border-radius:9px;background:var(--rule);margin:0 auto 18px}
#joinSheet h2{font:800 24px/1.15 Gabarito,system-ui,sans-serif;letter-spacing:-.025em;margin:0 0 10px}
#joinSheet .js-lead{margin:0 0 18px;font-size:14.5px;line-height:1.5;color:var(--ink-2)}
#joinSheet .js-form{display:flex;flex-direction:column;gap:10px}
#joinSheet input{font:500 16px Gabarito,system-ui,sans-serif;padding:14px 16px;border-radius:14px;
  border:1.5px solid var(--rule);background:var(--paper);color:var(--ink)}
#joinSheet input:focus{outline:none;border-color:var(--ink)}
#joinSheet .btn.gold{width:100%;justify-content:center;padding:14px;font-size:15px}
#joinSheet .js-err{margin:0;font-size:13px;color:var(--no)}
#joinSheet .js-fine{margin:12px 0 4px;font-size:12px;color:var(--muted);text-align:center}
#joinSheet .js-fine a{color:inherit}
#joinSheet .js-back{display:block;margin:8px auto 0;background:none;border:0;padding:10px;
  font:600 14px Gabarito,system-ui,sans-serif;color:var(--ink);cursor:pointer;
  -webkit-tap-highlight-color:transparent}

/* ---- a map of the walk on every card without a photograph ---- */
.wc-thumb.art{position:relative;overflow:hidden}
.wc-thumb .wc-mini{position:absolute;inset:0;opacity:0;transition:opacity .35s ease;
  background:transparent;pointer-events:none}
.wc-thumb.mapped .wc-mini{opacity:1}
.wc-thumb.mapped > svg{opacity:0;transition:opacity .35s ease}

/* ======================================================================
   SURFACES, NOT OUTLINES
   ----------------------------------------------------------------------
   The app had been drawn with a pen: every card, button, field and sheet
   wore the same 1px beige rule, and the eye had to cross a fence to reach
   anything. Everything below replaces the fences with tone and light.

   Four creams in depth order, --sunk < --card < --raise, floating over
   --paper. Three shadows, --sh-1 resting, --sh-2 raised, --sh-3 floating,
   all tinted with the ink. A border now means one thing only: a thing is
   chosen, or it has focus.

   Type gets its spine back. Headings are large and tight, section titles
   are sentences in ink rather than grey caps on a rule, body copy is ink,
   and the numbers somebody decides on - minutes, kilometres, steps - are
   set big in the display face.

   One family of controls: tonal icon buttons, a tonal secondary button, an
   ink solid, and one gold primary with real weight. Pressing anything
   pushes it down a pixel and takes its shadow away.

   This block sits last on purpose. Earlier blocks are layered overrides
   of each other; this one is the system, and it wins. ================== */

/* ---- the ground ------------------------------------------------------ */
.leaflet-container{background:var(--paper)}

/* ---- type ------------------------------------------------------------ */
body{font-weight:500}
/* Section titles: a sentence in ink, not a label in grey caps on a rule.
   The text is authored in sentence case - "Who it suits", "About",
   "Every one of them" - so taking the transform away is all it needs. */
.dsec h3,.lbl,.tw-k,.lg-who,.td-k,.cbl,.csec,.miles-k,.rkicker,.obstep,
.tipkey-h,.ob-sample,.bygo h3,.legs.one em,.legh em,.stat span,
.tmain em,.tbody span,.pvorder-k,.rangerow .lbl,.ob-win-tag{
  text-transform:none;letter-spacing:-.01em;
}
.dsec h3{
  font:800 16.5px/1.2 Gabarito,system-ui,sans-serif;letter-spacing:-.02em;
  color:var(--ink);padding:0;border:0;margin:0 0 10px;
}
.dsec h3 span,.dsec h3 .muted{font:500 12.5px/1.3 Gabarito,system-ui,sans-serif;
  letter-spacing:0;color:var(--muted)}
.dsec{margin-bottom:26px}
.dsec.ref>summary,details.dsec.plan-step>summary{padding:10px 0}
.dsec.ref>summary h3::after,details.dsec.plan-step>summary h3::after{opacity:.55}
.lbl{font:800 15px/1.2 Gabarito,system-ui,sans-serif;letter-spacing:-.02em;
  color:var(--ink);margin-bottom:10px}
.lbl .opt,.lbl b{font:500 12.5px Gabarito,system-ui,sans-serif;color:var(--muted);
  text-transform:none;letter-spacing:0}
#matchSheet .lbl b{font-weight:700;color:var(--ink)}
.tw-k,.miles-k,.csec,.rkicker,.obstep,.tipkey-h,.ob-sample,.cbl{
  font:800 13px/1.2 Gabarito,system-ui,sans-serif;letter-spacing:-.01em;color:var(--ink)}
.obstep{color:var(--muted);font-weight:700}
.csec{font-size:15px;letter-spacing:-.02em}
.td-k{font:800 16px/1.1 Gabarito,system-ui,sans-serif;letter-spacing:-.02em;color:var(--ink)}
.td-s{font:500 12.5px/1.2 Gabarito,system-ui,sans-serif;color:var(--muted)}
.ob-win-tag{font:700 12.5px Gabarito,system-ui,sans-serif;color:var(--muted)}

/* Body copy reads in ink. Grey paragraphs were the "shy and retiring". */
.desc,.vwhy,.chalwhy,.rplan,.rverdict,.td-none,#landing .lead,.tipcard>p,
.pwwhy,.ob-lead,.ob-hook-l,.statednote,.byg,.pfnote,.rev p{color:var(--ink)}
.desc{font-size:14.5px;line-height:1.6;font-weight:500}
.vwhy,.chalwhy{font-size:13.5px;font-weight:500;color:var(--ink-2)}
.rverdict{font-weight:500;color:var(--ink-2)}
.rverdict b{color:var(--ink)}
.ratenote,.fornote,.whonote,.matchnote,.landnote,.badgenote,.ob-after,
.pwlegal,.shairnote{color:var(--muted)}

/* The walk's name: the biggest thing on the sheet, and tight. */
#detailBody h2{font-size:30px;line-height:1.02;letter-spacing:-.035em;font-weight:800;
  margin:0 0 6px;text-wrap:balance}
.dcounty{font-size:13px;font-weight:500;color:var(--muted);margin-bottom:14px}
.sheethead h2,.sheettitle h2{font-size:22px;letter-spacing:-.03em;font-weight:800}
.sheetsub{font-size:12.5px}
#tabBody > h3{font-size:28px;letter-spacing:-.035em;line-height:1.05;margin-bottom:6px}
.obhead h1{font-size:30px;letter-spacing:-.035em;line-height:1.05}
.tipcard h2{font-size:19px}

/* Numbers people decide on: the display face, big, tabular. The mono was
   a nice detail at 11px and a weak one at 20. */
.stat b,.mystat b,.tw-v,.legr b,.legs.one b,.crow .rt,.tdist,.poi .d,.away,
.logrow .when,.stage .sk,.cupchoice b,.stepnow .leglen{
  font-family:Gabarito,system-ui,sans-serif;font-variant-numeric:tabular-nums}
.stat b{font-size:26px;font-weight:800;letter-spacing:-.035em;line-height:1}
.stat span{font:600 12.5px/1.2 Gabarito,system-ui,sans-serif;color:var(--muted);margin-bottom:5px}
.stats{gap:18px 14px;margin:4px 0 22px}
.legs.one b{font-size:20px;font-weight:800;letter-spacing:-.03em;line-height:1.05}
.legs.one em{font:600 12px/1.2 Gabarito,system-ui,sans-serif;color:var(--muted)}
.legr b{font-size:16px;font-weight:800;letter-spacing:-.02em}
.legh em{font:700 12px Gabarito,system-ui,sans-serif;color:var(--muted)}
.mystat b{font:800 24px/1 Gabarito,system-ui,sans-serif;letter-spacing:-.035em}
.tw-v{font-size:26px;letter-spacing:-.035em}
.crow .rt{font:700 12.5px/1.25 Gabarito,system-ui,sans-serif;color:var(--ink-2)}
.away,.poi .d,.tdist{font-weight:600}
.obcount b{font-size:38px}
.ob-pf b{font-size:22px;letter-spacing:-.03em}
.ob-hook-n{font-size:44px}

/* ---- surfaces -------------------------------------------------------- */
/* The floating cards: no rule, a floating shadow, a slightly larger
   radius so the shadow has a curve to sit under. */
#panel,#detail,#sheet,#forSheet,#pickSheet,#logSheet,#shareSheet,#whoSheet,
#matchSheet,#tripAsk,.hooray-card,.tipcard{
  border:0;box-shadow:var(--sh-3);border-radius:22px}
.tipcard{background:var(--card)}
@media (max-width:820px){
  /* The same edge as the search card above it - no white highlight line
     on one and not the other - so the two read as one family. */
  #panel,#detail{border-radius:24px 24px 0 0;
    box-shadow:0 -2px 6px rgba(30,40,51,.08),0 -16px 44px -8px rgba(30,40,51,.28)}

  #sheet,#forSheet,#pickSheet,#logSheet,#shareSheet,#whoSheet,#matchSheet{
    border-radius:24px 24px 0 0;border:0}
  #panel .grip,#detail .grip{background-color:var(--rule);opacity:1}
  #whoSheet .grip,#matchSheet .grip,#logSheet .grip,#sheet .grip,
  #forSheet .grip,#pickSheet .grip{background:var(--rule)}
}
/* Heads and feet are part of the surface, not boxes stuck to it. The
   scroll fade on the body already says where the content goes. */
.cardhead{border-bottom:0;padding:12px 16px 10px;gap:12px}
#detail .cardhead{padding-bottom:8px}
.sheethead{border-bottom:0;padding:14px 18px 10px}
.sheetfoot{border-top:0;box-shadow:var(--sh-up);background:var(--card);
  position:relative;z-index:4;padding:12px 16px 14px;gap:10px}
#tabBody h3{margin-top:4px}
.suit{font-weight:800;font-size:15.5px;letter-spacing:-.02em;color:var(--ink)}
#detail.peeked .suit{color:var(--muted);font-weight:600}
.cardhead #count{font-weight:600;color:var(--ink-2)}
#credits{border-top:0;color:var(--muted)}
#panel.min{border-radius:22px}

/* Inner cards lift off the sheet in a brighter cream and a resting shadow.
   Inset things press into it in the darker one. */
.plan,.readycard,.streakcard,.crewcard,.logit,.mcard,.ob-win,
.streak,.logpickrow,.ctile,.tipcard .tiphow{
  border:0;background:var(--raise);box-shadow:var(--sh-1)}
.plan{border-radius:18px;margin:12px 0 8px}
.readycard{border-radius:18px}
.streakcard,.crewcard{border-radius:20px;padding:0 16px}
.crewcard{padding:16px}
.streakcard:has(.streak.hot){background:var(--raise);box-shadow:var(--sh-1),inset 0 0 0 2px var(--hot)}
.streak{box-shadow:none;background:transparent}
.streak.hot{background:transparent}
.streak b{font-size:18px}
.streak-alt{border:0;background:var(--sunk);color:var(--ink-2)}
.ctile{border-radius:16px}
.ctile.soft{background:var(--sunk);box-shadow:none}
.bygo,.legs,.statednote,.obnote,.miles-next,.fromnow,.ob-pf,.pwwalk{
  border:0;background:var(--sunk);border-radius:16px}
.bygo{padding:12px 14px;margin:12px 0 0}
.legs{padding:14px 16px 15px;border-radius:16px}
.statednote{padding:11px 13px;opacity:1;color:var(--ink-2)}
.obnote{padding:12px 14px}
.obnote.warn{background:var(--hot-soft);border-left:0;border-radius:14px;padding:12px 14px}
.ob-pf{border-radius:16px;padding:12px 12px 13px}
.offer{border:1.5px dashed var(--rule);background:transparent}
.fromnow{min-height:48px;border-radius:16px}
.fromnow:has(.originnow.unset){background:transparent;border:1.5px dashed var(--rule)}
.wphoto{border:0;border-radius:18px;box-shadow:var(--sh-1)}
.logshot,.shareprev img{border:0;border-radius:16px;box-shadow:var(--sh-1)}
.pwplan{border-radius:18px;background:var(--sunk);box-shadow:none;border:0;padding:16px 16px}
.pwplan.on{background:var(--raise);box-shadow:var(--sh-1),inset 0 0 0 2px var(--hot)}
.pwp-main b{font-size:17px;font-weight:800;letter-spacing:-.02em}
.pwp-price b{font-size:20px;font-weight:800;letter-spacing:-.02em}
.pwp-badge{color:var(--on-hot);box-shadow:var(--sh-1)}
.hits{border:0;background:var(--raise);box-shadow:var(--sh-2);border-radius:16px}
.hit{border-bottom:1px solid var(--line-2)}
.cmore summary{border:0;background:var(--sunk);border-radius:14px}
.cmore[open] > *:not(summary){border:0;background:var(--sunk)}
.cmore[open] summary{border-radius:14px 14px 0 0}
.cmore[open] > *:last-child{border-radius:0 0 14px 14px}
.buggyrow{border:0;background:var(--raise);box-shadow:var(--sh-1);border-radius:14px}
.buggyrow.bg-warn,.buggyrow.bg-unknown{border:1.5px dashed var(--rule);box-shadow:none;background:transparent}
.buggyrow.bg-no{border:0;box-shadow:var(--sh-1),inset 0 0 0 2px var(--ink)}
.verdict .buggyrow{background:var(--card)}

/* The verdict: a tonal band in its own colour, the one coloured surface on
   the page, with no fence and no stripe. The heading is large enough to
   count as large text, which is what the tint needs. */
.verdict{border:0;box-shadow:none;border-radius:18px;padding:15px 16px 14px;margin:0 0 12px}
.verdict.yes{background:var(--yes-bg)}
.verdict.maybe{background:var(--maybe-bg)}
.verdict.no{background:var(--no-bg)}
.vhead{font-size:19px;font-weight:800;letter-spacing:-.025em;line-height:1.15}
.vdiff b{font-size:12px;font-weight:700;color:var(--ink)}
.vdiff .meter i{background:rgba(30,40,51,.14)}
.verdict.yes .vdiff .meter i.on{background:var(--yes)}
.verdict.maybe .vdiff .meter i.on{background:var(--maybe)}
.verdict.no .vdiff .meter i.on{background:var(--no)}
.vwhy{margin-top:7px}
.chal-band{border:0}

/* The plan rows: one raised card, rows parted by a hairline that is the
   same cream as the sheet, so it reads as a crease rather than a line. */
.prow{border-top:1px solid var(--line-2);min-height:62px;padding:10px 14px}
.prow:first-child{border-top:0}
button.prow:hover{background:var(--sunk)}
.pico{width:40px;height:40px;border-radius:13px;background:var(--sunk);box-shadow:none;font-size:19px}
.plab{font-size:12px;font-weight:600;color:var(--muted)}
.pval{font-size:16px;font-weight:800;letter-spacing:-.02em}
.pval span{font-weight:500;color:var(--muted)}
.pchg{background:var(--sunk);box-shadow:none;color:var(--ink);font-weight:700;padding:8px 13px}
button.prow:hover .pchg{box-shadow:none;background:var(--hot);color:var(--on-hot)}

/* Who it suits: rows on the sheet, no table lines. */
.matrix{border:0}
.mrow{border-top:1px solid var(--line-2);font-size:14px}
.mrow .why{color:var(--muted)}
.mrow .who-l i{color:var(--ink-2)}
.mrow.sel{background:var(--hot-soft);border-color:transparent}

/* ---- the chrome: one surface, the front door ------------------------- */
#chrome{gap:10px}
.bar{border:0;box-shadow:var(--sh-3);border-radius:22px;background:var(--card)}
.bar-row{padding:10px 10px 6px 12px;gap:10px}
.brand{display:block;width:38px;height:38px;border:0;margin:0;
  box-shadow:0 1px 2px rgba(30,40,51,.18),0 0 0 2px var(--card)}
.search{background:var(--sunk);border:0;border-radius:15px;padding:0 13px;min-height:46px}
.search i{color:var(--ink-2);font-size:18px}
.search input{padding:11px 0;font-weight:600;color:var(--ink)}
.search input::placeholder{color:var(--muted);font-weight:500}
.search:focus-within{box-shadow:inset 0 0 0 2px var(--ink)}
.fromrow{background:transparent;border:0;padding:6px 16px 13px;gap:7px;
  font:600 13px Gabarito,system-ui,sans-serif;color:var(--muted)}
.fromrow > i{color:var(--hot);font-size:16px}
.fromrow > i:first-child{background:var(--hot);color:var(--on-hot);width:22px;height:22px;
  border-radius:50%;display:grid;place-items:center;font-size:13px;margin-right:2px;
  box-shadow:var(--sh-1)}
.fromrow .fc-k{color:var(--muted)}
.fromrow b{color:var(--ink);font-weight:800;font-size:13.5px;letter-spacing:-.01em}
.fromrow .fc-go{color:var(--muted);font-size:13px}
.fromrow:hover,.fromrow:active{background:var(--sunk)}
.fromrow.unset > i:first-child{background:var(--coffee);color:#fff}
@media (max-width:820px){
  .bar{box-shadow:var(--sh-3)}
  .bar-row{padding:9px 9px 5px 11px}
  .brand{display:block;width:36px;height:36px}
}

/* The line at the top of the home card. */
.fline{font-weight:700;font-size:14px}
.fline > i:first-child{color:var(--ink)}
.fline span i{color:var(--rule)}

/* ---- buttons: one family --------------------------------------------- */
/* Secondary: tonal, no fence. Solid: ink. Gold: the primary, with weight.
   Every one presses down a pixel and loses its shadow. */
.btn{border:0;background:var(--sunk);color:var(--ink);font-weight:700;
  border-radius:14px;padding:10px 15px;box-shadow:none;
  transition:transform .1s ease,background .15s ease,box-shadow .15s ease,filter .15s ease}
.btn:hover{background:var(--line)}
.btn:active{transform:translateY(1px);box-shadow:none}
.btn.ghost{border:0;background:var(--sunk);color:var(--ink)}
.btn.ghost:hover{border:0;background:var(--line)}
.btn.quiet{border:0;background:var(--sunk);color:var(--ink)}
.btn.quiet:hover{background:var(--line)}
.btn.solid,.btn.on{background:var(--ink);color:var(--card);box-shadow:var(--sh-2)}
.btn.solid:hover,.btn.on:hover{background:var(--ink);filter:brightness(1.12)}
.btn.solid:active{box-shadow:var(--sh-1)}
.btn.gold,#forGo,#pvGo,.gogo,.rrow .nav,.mbtn.hot,#getapp .ga-go,#updatebar button,
#landing .btn.gold,#paywall .btn.gold.wide,#joinSheet .btn.gold{
  background:var(--hot);color:var(--on-hot);border:0;box-shadow:var(--sh-gold);font-weight:800}
.btn.gold:hover,#pvGo:hover,.gogo:hover,.rrow .nav:hover,.mbtn.hot:hover{
  background:var(--hot);filter:brightness(1.04)}
.btn.gold:active,#pvGo:active,.gogo:active,.rrow .nav:active{
  transform:translateY(1px);box-shadow:0 1px 0 rgba(255,255,255,.2) inset,0 1px 2px rgba(30,40,51,.12)}
#pvGo{border:0}
#forGo.none{background:var(--sunk);color:var(--ink-2);box-shadow:none}
.btn.tertiary,.sharerow .btn.tertiary{background:none;box-shadow:none}
.btn.nav,.sharerow .btn.nav,.btn.nav.locked{border:0;background:var(--sunk)}
.btn.nav.locked{box-shadow:none}
.rrow .keep,.rrow #showRoute,.rrow #navMaps2{background:var(--sunk);border:0}
.rrow .keep.on{background:var(--hot-soft);box-shadow:inset 0 0 0 2px var(--hot)}
.btn.tiny{background:var(--sunk);padding:.35rem .7rem;border-radius:999px}
.btn b{box-shadow:none}
.obfoot .btn{min-height:50px;border-radius:16px;font-size:15.5px}
.obfoot .btn:disabled{opacity:.4;box-shadow:none}
.sheetfoot .btn{min-height:50px;border-radius:16px;font-size:15px}
#landing .btn{min-height:50px;border-radius:16px;font-size:15px}
#landing .btn.quiet{background:transparent;color:var(--ink-2)}
#landing .btn.quiet:hover{background:var(--sunk)}
#tabBody .mwhead .btn{box-shadow:var(--sh-gold);background:var(--hot);color:var(--on-hot);
  font-weight:800;border-radius:14px}
#tipGo,#hoorayGo{min-height:48px;border-radius:14px}
#saveWalk.on{background:var(--ink);color:var(--hot)}
.whoprompt button,.addcafe{border:1.5px dashed var(--rule);background:transparent;color:var(--ink-2)}
.nocoffee{border:0;background:var(--sunk)}
.nocoffee.on{background:var(--ink);color:var(--card)}
.previewbtn,.popbtn{border:0;background:var(--sunk);font-weight:700}
.popbtn.on{background:var(--hot);color:var(--on-hot)}
.textbtn{text-decoration-color:var(--rule)}
.didline button,.originchange{color:var(--ink-2)}

/* Icon buttons: a tonal plate, square for the chrome and round for the
   outing's three actions. Same ink icon, same press. */
.icon,.ibtn,.pvbtn,.cardbtn,.iact,.rlink,.tadismiss,#pwClose,.pvtool,.stepbtns .pvtool{
  border:0;background:var(--sunk);color:var(--ink);box-shadow:none;
  -webkit-tap-highlight-color:transparent;
  transition:transform .1s ease,background .15s ease,color .15s ease}
.icon{width:40px;height:40px;border-radius:13px}
.icon i{font-size:18px}
.icon:hover,.ibtn:hover,.pvbtn:hover,.cardbtn:hover,.iact:hover,.rlink:hover,.pvtool:hover{
  background:var(--line);border:0}
.icon:active,.ibtn:active,.pvbtn:active,.cardbtn:active,.pvtool:active{transform:scale(.95)}
.ibtn,.pvbtn{border-radius:15px;font-size:20px}
.iact{width:54px;height:54px;background:var(--sunk);border:0}
.iact i{font-size:22px}
.iact.on,.iact.done,.sharerow .iact.keep.on{background:var(--ink);color:var(--hot);border:0}
.sharerow.iconrow{border-top:0;padding-top:4px;margin:18px 0 4px;gap:16px}
.mbtn{border:0;background:var(--card);color:var(--ink);box-shadow:var(--sh-2);border-radius:16px;
  -webkit-tap-highlight-color:transparent}
.mbtn:hover{background:var(--card)}
.mbtn.ink{background:var(--ink);color:var(--card)}
.mbtn.ink:hover{background:var(--ink)}
.mbtn.on{background:var(--ink);color:var(--hot)}
.ob-ctl .mbtn{box-shadow:var(--sh-1)}
.rlink{width:28px;height:28px;border-radius:9px;color:var(--ink-2)}
.rlink.ig,.rlink.fb{border:0;color:var(--ink)}
.tadismiss{background:transparent}
#pwClose{background:var(--sunk);color:var(--ink)}
.onwalkbar .icon{background:transparent;color:inherit}
.onwalkbar .icon:hover{background:rgba(255,255,255,.1)}
.pvtool{background:var(--sunk);color:var(--ink);border:0}
.pvtool.on{background:var(--ink);color:var(--card)}
.pvtool.on b{color:var(--card)}
.stepbtns .pvtool.wide b{color:inherit}
@media (max-width:820px){
  #collapse,.icon{min-width:42px;min-height:42px}
}

/* ---- the go bar ------------------------------------------------------ */
.gobar{border-top:0;box-shadow:var(--sh-up);padding:10px 16px 12px;gap:10px;background:var(--card)}
.pvbtn{width:52px;min-height:52px}
.gogo{border:0;border-radius:16px;min-height:52px;box-shadow:var(--sh-gold)}
.gogo b{font-size:17px;letter-spacing:-.015em}
.gogo span{opacity:1;color:var(--on-hot);font-weight:600;font-size:12.5px}
.td-row .gogo{min-height:50px}
.td-row .gogo b{font-size:16px}
.td-row .btn.quiet{min-height:50px;border-radius:15px;padding:0 16px}
.ibtn{width:50px;min-height:50px}

/* ---- "I walked this" --------------------------------------------------- */
.logit{border:0;background:var(--raise);box-shadow:var(--sh-1);border-radius:18px;
  padding:13px 15px;gap:13px;min-height:64px}
.logit i{width:40px;height:40px;border-radius:50%;display:grid;place-items:center;
  background:color-mix(in srgb,var(--moss) 16%,transparent);color:var(--moss);font-size:20px}
.logit b{font-size:15.5px;font-weight:800;letter-spacing:-.02em}
.logit em{color:var(--muted)}
.logit:hover{background:var(--raise);box-shadow:var(--sh-2)}
.logit:active{transform:translateY(1px);box-shadow:var(--sh-1)}
.logit[disabled]:hover{background:var(--raise);box-shadow:var(--sh-1)}

/* ---- the home card ----------------------------------------------------- */
.today{padding:12px 16px 12px}
.td-head{margin-bottom:12px;align-items:baseline}
.wc-thumb{border-radius:16px;box-shadow:var(--sh-1);width:80px;height:80px}
.wc-name{font-size:19px;font-weight:800;letter-spacing:-.025em}
.wc-k{color:var(--maybe)}
.wc-meta{color:var(--muted);font-size:13px}
.wc-meta b{color:var(--ink);font-weight:700}
.wcard.sm{padding:12px 14px;border-radius:18px}
.wcard.sm .wc-thumb{width:62px;height:62px;border-radius:13px}
.td-mini{margin-top:12px;padding-bottom:10px}
.mcard{border:0;background:var(--raise);box-shadow:var(--sh-1);border-radius:16px;padding:9px}
.mcard:hover{background:var(--raise);box-shadow:var(--sh-2);border:0}
.mcard:active{transform:translateY(1px);box-shadow:var(--sh-1)}
.mcard .wc-thumb{border-radius:11px;box-shadow:none}
.mc-name{font-size:13.5px;font-weight:800}
.mc-meta{color:var(--muted)}
.vchip{font-size:12px;font-weight:800;padding:4px 10px 4px 8px}

/* List rows: the chosen one is gold, the rest are rows. */
#results li{border:0;border-radius:16px;padding:13px 14px;transition:background .16s ease}
#results li:hover{background:var(--sunk)}
#results li.sel{background:var(--hot-soft);border:0;box-shadow:inset 0 0 0 2px var(--hot)}
.rname{font-size:16px;font-weight:800;letter-spacing:-.025em}
.rmeta{color:var(--muted);font-weight:500}
@media (max-width:820px){.rmeta{color:var(--muted)}}
.chip,.gf{box-shadow:none;background:var(--sunk);color:var(--ink-2);font-weight:700}
.chip.cafe1{color:var(--coffee);background:var(--maybe-bg)}
.gf{background:var(--yes-bg);color:var(--yes)}
.gf.none{background:var(--sunk);color:var(--muted)}

/* ---- chips and choices: tonal, gold when chosen ------------------------ */
.chipctl{border:0;background:var(--card);box-shadow:var(--sh-2);font-weight:700;padding:9px 15px}
.chipctl:hover{border:0;background:var(--card)}
.chipctl.idle{border:0;box-shadow:var(--sh-1);color:var(--ink-2)}
.chipctl.idle:hover{border:0}
.tagpick button{border:0;background:var(--sunk);color:var(--ink);font-weight:700;padding:9px 15px}
.tagpick button:hover{border:0;background:var(--line)}
.cfilters button{border:0;background:var(--sunk);color:var(--ink-2);font-weight:700}
.cfilters button:hover{border:0;color:var(--ink);background:var(--line)}
.cfilters .csort.on{border:0}
.seg button{border:0;background:var(--sunk);color:var(--ink-2);border-radius:14px;font-weight:700}
.seg button:hover{border:0;background:var(--line)}
.seg button i{background:rgba(30,40,51,.14)}
.seg.radii button{font-weight:800;color:var(--ink);min-height:46px}
.seg.ord.tight button{border-radius:999px}
.who{border:0;background:var(--sunk);border-radius:16px}
.who:hover{border:0;background:var(--line)}
.star{border:0;background:var(--sunk);color:var(--muted);border-radius:14px}
.star:hover{border:0;background:var(--line)}
.chipctl.on,.who.on,.cfilters button.on,.tagpick button.on,.seg button.on,
.tier.on,.ch.on,.kind.on,.mc.on,.ord-b.on,.cm.on,.when.on,.bases .base.on,
.entlist button.on,.tab.on,.star.lit,.dtab.on,.cfilters .csort.on{
  background:var(--hot);color:var(--on-hot);border:0;box-shadow:none}
.pvorder .seg.ord.tight{border:0;background:var(--sunk);padding:3px}
.pvorder .seg.ord.tight button.on{background:var(--card);color:var(--ink);box-shadow:var(--sh-1)}
.chipctl.on i,.who.on i,.cm.on em,.tab.on i,.seg button.on em,.cfilters button.on em,
.who.on em,.entlist button.on i,.entlist button.on span{color:var(--on-hot)}
.chip{border:1.5px solid transparent;background:var(--sunk);color:var(--ink);font-weight:700}
.chip:hover{border-color:transparent;background:var(--line)}
.chip.on{border-color:transparent;background:var(--hot);color:var(--on-hot)}
.ob-row .chip,.chiprow span{border:0;background:var(--sunk);font-weight:700;padding:9px 15px}
.ob-row .chip.on{background:var(--hot);color:var(--on-hot)}

/* Tiles that pick a person: pressed into the sheet until chosen, then a
   gold ring and a gold check. A ring is a border that means something. */
.pickone{border:0;background:var(--sunk);border-radius:16px;box-shadow:none;
  transition:background .15s ease,box-shadow .15s ease,transform .1s ease}
.pickone:hover{background:var(--line)}
.pickone:active{transform:scale(.985)}
.pickone.on{background:var(--hot-soft);box-shadow:inset 0 0 0 2px var(--hot);border:0}
.pickone.on > i:first-child{color:var(--ink)}
.pickone .box{border:0;background:var(--card);box-shadow:var(--sh-1)}
.pickone.on .box{background:var(--hot);color:var(--on-hot);box-shadow:none}
.obgrid.forwho .pickone.tile{background:var(--sunk);border:0}
.obgrid.forwho .pickone.tile.on{background:var(--hot-soft);box-shadow:inset 0 0 0 2px var(--hot)}
.obgrid .pickone.tile b{font-weight:800}
.ob-another:disabled{border:0;background:var(--sunk)}

/* Segments and small plates. */
.segs{background:var(--sunk);border-radius:14px}
.segs button.on{background:var(--card);box-shadow:var(--sh-1);color:var(--ink)}
.rangerow{border-bottom:0}
.rangerow .km{border:0;background:var(--sunk)}
.rangerow .km button + button{border-left:0}
.rangerow .km button.on{background:var(--ink);color:var(--card)}
.days span{background:var(--sunk);color:var(--muted);border-radius:11px;font-weight:800}
.days span.on{background:var(--moss);color:#FFF9EE}
.thisweek{border-bottom:0;padding-bottom:4px}
.crow .rk{background:var(--sunk);font:800 12px Gabarito,system-ui,sans-serif;color:var(--ink-2)}
.crow.on .rk{background:var(--hot);color:var(--on-hot)}
.crow .nm{font-size:16px;font-weight:800;letter-spacing:-.02em}
.crow .mt{color:var(--muted)}
.crow .tick{color:var(--coffee)}
.allrow{font-weight:800}
.entlist button{border-bottom:1px solid var(--line-2)}
.entlist button i{color:var(--muted)}
.startlist button{border-bottom:1px solid var(--line-2)}
.startlist button em{text-transform:none;letter-spacing:0;font-size:12px;font-weight:600;color:var(--muted)}
.stp .bub,.ob-stp .bub{border:0;background:var(--sunk);box-shadow:var(--sh-1)}
.stp.on .bub,.ob-stp.on .bub{background:var(--hot);color:var(--on-hot)}
.stp.done .bub{background:var(--ink);color:var(--card)}
.leg{background:var(--line)}
.leg.done{background:var(--ink)}
.dtab{border:0;background:var(--sunk);opacity:1;color:var(--ink-2);border-radius:12px}
.dtab.on{background:var(--hot);color:var(--on-hot)}
.crow.chead .th{border:0;background:var(--sunk);color:var(--ink-2)}
.crow.chead .th.on{background:var(--ink);color:var(--card)}
.poi.crow.chead{border-bottom:0}
.rate{border:0;background:var(--sunk);color:var(--coffee);font-weight:800}
.rate.prov{background:var(--hot);color:var(--on-hot)}
.rate.prov.empty,.rate.prov.ask{background:var(--sunk);color:var(--muted);border:0}
.rate.demo{border:1.5px dashed var(--rule);background:transparent}
.rate.live.ask{border:1.5px dotted var(--rule);background:transparent}
.plink{border:0;background:var(--sunk);color:var(--ink-2);font-weight:700}
.plink.ig,.plink.fb{border:0;color:var(--ink)}
.plink:hover{background:var(--line)}
.popchips span{border:0;background:var(--sunk);color:var(--ink-2)}
.tadd{border:1.5px dashed var(--rule)}
.tnum{border:0;background:var(--sunk);color:var(--muted)}
.tstub{border:0;box-shadow:var(--sh-1)}
.pill{box-shadow:var(--sh-1)}
.pill.off{box-shadow:none}
.yrow.still select,.prow select,#logDate,#logSteps{border:0;background:var(--sunk);border-radius:12px;font-weight:700}
#logDate,#logSteps{padding:11px 13px}
.smore{border:0}
.shutnow{border:0;background:var(--maybe-bg)}
.stepnow .leglen{border:0;background:var(--sunk);font-weight:800}
.tipic{border:0;background:var(--sunk);box-shadow:var(--sh-1)}
/* The rule above greyed every key out, so P, T, B and the playground read
   white on beige - nothing like the pins they explain. The map's own
   colours, as the pins are drawn (drawPois). */
.tipic.tipp{background:#2B2B2B}
.tipic.tipt{background:#3D5A80}
.tipic.tipb{background:#6D5A8C}
.tipic.tipy{background:#B0761A}
.tiphow{padding:12px 14px;border-radius:16px}
.ob-pf{box-shadow:none}
.obb,.obic{background:var(--sunk)}
.obbrand img{border:0;box-shadow:var(--sh-2)}
.obbrand b{letter-spacing:.22em;text-indent:.22em;font-size:17px}
.obbrand em{letter-spacing:.26em;text-indent:.26em;color:var(--muted)}
.ob-win{border:0;background:var(--raise);box-shadow:var(--sh-2);border-radius:20px}
.ob-win-name{font-size:23px}
.ob-hook{border-bottom:0;padding-bottom:4px}
.ob-demo .beat{border-bottom:1px solid var(--line-2)}
.ob-demo .beat b{font-weight:800;letter-spacing:-.015em}
.obtip{border-bottom:1px solid var(--line-2)}
.obtip b{font-weight:800;letter-spacing:-.015em}
.obtip em{opacity:1;color:var(--muted)}
.obdots i{background:var(--rule)}
.obdots i.on{background:var(--ink)}
.obdots i.done{background:var(--moss)}
.pvpin{border:0;box-shadow:0 0 0 2px var(--ink),0 2px 7px rgba(0,0,0,.3)}
/* A box now, not a ruled line: the line's padding was all on top, and the
   words sat low in it. Even all round. */
.leaveby{border:0;background:var(--sunk);box-shadow:none;border-radius:14px;padding:11px 12px}
.leaveby.went{background:color-mix(in srgb,var(--moss) 14%,transparent);box-shadow:inset 0 0 0 2px var(--moss)}
.leaveby:hover{border:0}
.pwfree{color:var(--ink)}
.pwgets b{font-weight:800;letter-spacing:-.015em}
.pwgets span{color:var(--muted)}
.hooray-card{border-radius:24px}
.waitcard{box-shadow:var(--sh-gold)}
.readycard{background:var(--raise)}
.readycard .trow{border-bottom:1px dashed var(--line)}
.leaflet-popup-content-wrapper,.leaflet-popup-tip{border:0;box-shadow:var(--sh-3)}
.leaflet-popup-content-wrapper{border-radius:16px}
.cuptip.leaflet-tooltip{border:0;box-shadow:var(--sh-2);border-radius:12px}
.cuptip.leaflet-tooltip::before{border-top-color:var(--card)}
.tbadge,.cupchoice,.entpin,.stoppin{border:0;box-shadow:var(--sh-2)}
/* Except a coffee you can switch to: borderless, it read as part of the
   street map. The ink ring says it can be chosen. */
.cupchoice:not(.on):not(.maybe){border:1.5px solid #1E2833;background:#FBF8F2}
.tbadge.yes{box-shadow:var(--sh-2),inset 0 0 0 1.5px var(--yes)}
.tbadge.maybe{box-shadow:var(--sh-2),inset 0 0 0 1.5px var(--maybe)}
.tbadge.no{box-shadow:var(--sh-2),inset 0 0 0 1.5px var(--no)}
.cupchoice.on{background:var(--hot)}
.stoppin{background:var(--hot)}
#legend{border:0;box-shadow:var(--sh-2);border-radius:14px}
#legend .lg-row{color:var(--ink)}
.logrow,.yrow,.yfold,#logCoffee label,.poi{border-bottom-color:var(--line-2)}
.logrow{border-bottom-width:1px}
.logrow .nm{font-weight:800;letter-spacing:-.02em;font-size:15px}
.logrow .mt{color:var(--muted)}
.logrow .when{color:var(--muted)}
.yrow .yk{font-weight:800}
.yrow .yv{color:var(--muted)}
.yrow > i:first-child{color:var(--ink)}
.prow .v{color:var(--muted)}
.mystat{border:0;background:var(--raise);box-shadow:var(--sh-1);border-radius:16px;padding:12px}
.mystat span{color:var(--muted)}
.formore summary{border-top:1px solid var(--line-2);font-weight:800}
.formore summary em{color:var(--muted)}
.rev{border-left:2px solid var(--hot)}
.rev p{opacity:1;color:var(--ink-2)}
.rev cite{color:var(--muted)}
.stage{border-bottom:1px solid var(--line-2)}
.stage .sn{background:var(--sunk);font:800 11px Gabarito,system-ui,sans-serif}
.stage.on{background:var(--hot-soft);border-radius:12px}
.stage .sw i{color:var(--muted)}
.skel{border-bottom:0}
.skel span{background:linear-gradient(90deg,var(--sunk) 25%,var(--line) 37%,var(--sunk) 63%);
  background-size:200% 100%}
.chal-top b,.tw-v{letter-spacing:-.03em}
.dsum{opacity:1;color:var(--ink-2)}
.dtravel{opacity:1;color:var(--ink-2)}
.facts .fact .more{opacity:1;color:var(--muted)}
.facts .fact{font-weight:600}
.none,.ptags{color:var(--muted)}
.poi .d{color:var(--muted)}
.brow b,.od i,.popnote,.shutnow{letter-spacing:.02em}
.tw-s{color:var(--coffee)}
.mwhead{margin-bottom:6px}

/* ---- the tab bar ------------------------------------------------------- */
#tabs{border:0;box-shadow:var(--sh-up);background:var(--card);padding:6px 8px;gap:4px}
@media (max-width:820px){
  #tabs{border:0;padding:6px 8px calc(6px + env(safe-area-inset-bottom))}
}
.tab{border:0;border-radius:14px;color:var(--muted);font-weight:700;font-size:11px;gap:4px;padding:8px 4px}
.tab i{font-size:21px}
.tab:hover{background:var(--sunk);color:var(--ink)}
.tab.on{background:var(--hot);color:var(--on-hot);border-radius:14px;box-shadow:var(--sh-1)}
.tab:active{transform:scale(.97)}
.tab b{box-shadow:none}

/* ---- scrim, toast, bars ------------------------------------------------- */
#scrim{background:rgba(20,26,33,.42)}
#toast,#getapp,#updatebar,.ctltip,body.picking::after{box-shadow:var(--sh-3)}
#toast{border-radius:16px;font-weight:700}
#getapp,#updatebar{border-radius:18px}
.onwalkbar{box-shadow:var(--sh-3);border-radius:20px}
#steps{border-top:0;box-shadow:var(--sh-up)}
@media (min-width:821px){ #steps{border:0;box-shadow:var(--sh-3);border-radius:22px} }
#detail::after,#panel::after{background:linear-gradient(to top,var(--card),rgba(0,0,0,0))}

/* ---- focus: the one border that always means something ----------------- */
:focus-visible{outline:2.5px solid var(--ink);outline-offset:2px;border-radius:10px}
.btn.gold:focus-visible,.gogo:focus-visible,#pvGo:focus-visible,.tab.on:focus-visible{
  outline-color:var(--ink)}

/* ---- press, everywhere ------------------------------------------------- */
.chipctl:active,.tagpick button:active,.cfilters button:active,.seg button:active,
.who:active,.star:active,.pickone:active,.chip:active,.mcard:active,.mbtn:active,
.iact:active,.crow:active,.prow:active,.wcard:active{transform:translateY(1px) scale(.985)}
@media (prefers-reduced-motion:reduce){
  .btn,.icon,.ibtn,.pvbtn,.cardbtn,.iact,.mbtn,.rlink,.pvtool,.pickone,.logit,.mcard{transition:none}
}

/* ---- second pass, measured on a 390px screen --------------------------- */
/* The verdict's coloured stripe came from a block above; the tint is the
   whole statement now. */
.verdict.yes,.verdict.maybe,.verdict.no{box-shadow:none}
.vhead{font-size:18px}
/* The grading line in the header fits on one line beside two 38px plates. */
.cardhead{gap:10px}
.icon{width:38px;height:38px}
#detail .cardhead .suit{font-size:14.5px;letter-spacing:-.015em;line-height:1.2}
@media (max-width:820px){ #collapse,.icon{min-width:38px;min-height:38px} }
/* The modal sheets' grip was a 44x23 pill: the base .grip carries padding
   for the finger, and the sheet rule painted the whole box. Paint only
   the bar, keep the padding as the target. */
@media (max-width:820px){
  #whoSheet .grip,#matchSheet .grip,#logSheet .grip,#sheet .grip,
  #forSheet .grip,#pickSheet .grip,#shareSheet .grip{
    width:100px;height:25px;padding:10px 31px 10px;margin:4px auto 0;
    background:var(--rule);background-clip:content-box;border-radius:9px}
}
/* On a desktop the tab bar is a card in the column, so it gets the
   column's corners. */
@media (min-width:821px){ #tabs{border-radius:22px} }
/* The outline waits on a light ground, the colour of the map that replaces
   it, so the map arriving is a change of detail rather than dark to light. */
.wc-thumb.art{background:var(--sunk)}
.wc-thumb.art > svg path:first-child{stroke:rgba(30,40,51,.12)}
.wc-thumb.art > svg path:last-of-type{stroke:var(--ink-2)}
/* The strip at the foot is all handle: the browser must not take a swipe
   on it for a page scroll or a pull-to-refresh. And the handle itself is
   a full-width band a thumb can find, not a 5px line. */
@media (max-width:820px){
  #detail.peeked,#panel.peeked{touch-action:none;cursor:grab}
  #panel > .grip,#detail > .grip{padding:12px 46%;margin:0 auto -6px;width:100%;
    background-clip:content-box;box-sizing:border-box}
  /* The band is the handle; its reach stops there. The base 52px reach ran
     down over the header, and a tap on My walks' Log a walk went to the
     handle and toggled the sheet instead. */
  #panel > .grip::after,#detail > .grip::after{height:auto;bottom:0}
}

/* Over another place this site carries: the way to its walks. */
.regionhop{position:fixed;z-index:850;left:50%;transform:translateX(-50%);
  top:calc(var(--safe-top) + var(--chrome-h,112px) + 30px);
  display:inline-flex;align-items:center;gap:8px;padding:10px 16px;border:0;border-radius:999px;
  background:var(--ink);color:var(--card);font:700 14px Gabarito,system-ui,sans-serif;
  box-shadow:var(--sh-3);cursor:pointer;white-space:nowrap}
.regionhop i{color:var(--hot);font-size:17px}
.regionhop[hidden]{display:none}

/* The filter line as a chip of its own, with the handle above it clearly a
   separate band: the sheet is pulled by the handle (or by dragging the
   chip), and the chip is tapped to change the filters. One flat line of
   text read as both and was neither. */
#panel .fline{background:var(--sunk);border-radius:12px;padding:9px 12px;margin:2px 0 0}
#panel .fline:active{filter:brightness(.97)}
@media (max-width:860px){
  #panel > .grip{margin-top:6px;margin-bottom:0}
}
/* Today's walk's ring says what it is. */
.halotag{background:var(--hot);color:#232E3A;font:800 11.5px/1 Gabarito,system-ui,sans-serif;
  padding:5px 9px;border-radius:999px;white-space:nowrap;box-shadow:0 2px 6px rgba(0,0,0,.18);
  transform:translate(-50%,-50%);display:inline-block}

/* Wikipedia's account of the place, then its credit, then ours. */
.desc.wiki{margin-bottom:4px}
.wsrc{margin:0 0 12px;font-size:12px;color:var(--muted)}
.wsrc a{color:inherit;text-decoration:underline;text-underline-offset:2px}

/* The preview's dissolve between far-apart views (see camTo). */
.pvdissolve{transition:opacity .24s ease}
.pvdissolve.out{opacity:0}

/* ---- overview styles (see OVERVIEW in app.js) ---- */
.ovcanvas{position:absolute;left:0;top:0;pointer-events:none;transition:opacity .26s ease}
.ovcount{display:flex;align-items:center;justify-content:center;border-radius:50%;
  background:rgba(245,240,231,.94);color:#127a45;font:800 13px/1 Gabarito,system-ui,sans-serif;
  border:2px solid #127a45;box-shadow:0 3px 10px rgba(35,46,58,.18);letter-spacing:-.02em;cursor:pointer;
  transition:transform .15s ease}
.ovcount:hover{transform:scale(1.06)}
.ovglowtag{transform:translate(-50%,-50%);white-space:nowrap;padding:5px 10px;border-radius:999px;
  background:rgba(35,46,58,.86);color:#F0EADF;font:600 12px/1.1 Gabarito,system-ui,sans-serif;
  box-shadow:0 3px 10px rgba(0,0,0,.2);cursor:pointer;display:inline-block}
.ovglowtag b{color:#D9A441;font-weight:800;margin-right:3px}
.ovphoto{width:46px;height:46px;border-radius:50%;overflow:hidden;border:3px solid #F5F0E7;
  box-shadow:0 4px 12px rgba(35,46,58,.32);background:#cfd8cc;cursor:pointer;transition:transform .15s ease}
.ovphoto:hover{transform:scale(1.08)}
.ovphoto img{width:100%;height:100%;object-fit:cover;display:block}
.ovcounty{transform:translate(-50%,-50%);display:inline-flex;flex-direction:column;align-items:center;
  white-space:nowrap;cursor:pointer;text-shadow:0 1px 0 rgba(245,240,231,.9),0 0 8px rgba(245,240,231,.9)}
.ovcounty span{font:800 1em/1 Gabarito,system-ui,sans-serif;color:#232E3A;letter-spacing:-.02em}
.ovcounty b{font:700 .58em/1.3 Gabarito,system-ui,sans-serif;color:#127a45;margin-top:1px}
#ovSwitch{position:fixed;z-index:2000;left:50%;transform:translateX(-50%);
  top:calc(var(--safe-top,0px) + var(--chrome-h,112px) + 22px);
  display:flex;gap:4px;padding:4px;border-radius:999px;background:rgba(35,46,58,.9);box-shadow:0 6px 18px rgba(0,0,0,.25);
  max-width:calc(100vw - 24px);overflow-x:auto}
#ovSwitch button{border:0;border-radius:999px;padding:7px 10px;background:none;color:#F0EADF;
  font:700 12px/1 Gabarito,system-ui,sans-serif;white-space:nowrap;cursor:pointer}
#ovSwitch button.on{background:#D9A441;color:#232E3A}

/* The overview's marks arrive and leave softly, and step back while the map
   zooms rather than riding the zoom at the wrong size. */
@keyframes ovin{from{opacity:0;transform:scale(.86)}to{opacity:1;transform:none}}
.ovin{animation:ovin .32s cubic-bezier(.2,.8,.2,1) both}
.ovcounty.ovin{animation-name:ovinc}
@keyframes ovinc{from{opacity:0;transform:translate(-50%,-50%) scale(.9)}to{opacity:1;transform:translate(-50%,-50%)}}
.leaflet-marker-icon.ovgone,.ovgone{opacity:0!important;transition:opacity .2s ease}

/* Under the tiles, the colour of the land they draw. A tile fades in over
   whatever is beneath it, and the cream paper beneath turned every zoom
   and pan into a beige flash between grey tiles. Matched per style. */
body[data-base=streets] #map.leaflet-container{background:#e7e3dd}   /* measured, after --tile */
body[data-base=gray] #map.leaflet-container{background:#c9c9c9}
:root[data-theme=dark] body #map.leaflet-container{background:#1f1f1f}
@media (prefers-color-scheme:dark){:root:not([data-theme=light]) body #map.leaflet-container{background:#1f1f1f}}

/* ---- the streak, alive ----
   A medallion the size of a badge: a warm disc that breathes, the flame
   flickering harder than before, and embers lifting off it on their own
   clocks so it never loops visibly. */
.flamemedal{position:relative;flex:none;width:60px;height:60px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:radial-gradient(circle at 50% 62%,#FFF3DC 0%,#FBE3BF 45%,rgba(251,227,191,0) 72%)}
.flamemedal:not(.lit){background:var(--sunk)}
.flamemedal .flame{width:34px;height:45px;position:relative;z-index:1}
.fm-glow{position:absolute;inset:4px;border-radius:50%;
  background:radial-gradient(circle,rgba(246,170,60,.55) 0%,rgba(246,170,60,0) 70%);
  animation:fmGlow 2.3s ease-in-out infinite}
@keyframes fmGlow{0%,100%{transform:scale(.88);opacity:.65}50%{transform:scale(1.12);opacity:1}}
.fm-ember{position:absolute;left:50%;bottom:22px;width:4px;height:4px;border-radius:50%;
  background:#F6A93C;box-shadow:0 0 6px 1px rgba(246,169,60,.8);opacity:0;z-index:2;
  animation:fmEmber 2.6s ease-out infinite}
.fm-ember.e1{margin-left:-6px;animation-delay:.2s}
.fm-ember.e2{margin-left:3px;animation-delay:1.1s;width:3px;height:3px}
.fm-ember.e3{margin-left:-1px;animation-delay:1.9s}
@keyframes fmEmber{
  0%{transform:translate(0,0) scale(1);opacity:0}
  12%{opacity:1}
  100%{transform:translate(var(--dx,4px),-30px) scale(.3);opacity:0}}
.fm-ember.e1{--dx:-5px}.fm-ember.e3{--dx:6px}
/* Livelier flicker than the 26px one had. */
.flamemedal .flame.lit .fl-o{animation:flameO2 1.3s ease-in-out infinite}
.flamemedal .flame.lit .fl-m{animation:flameM2 .9s ease-in-out infinite}
.flamemedal .flame.lit .fl-c{animation:flameC2 .7s ease-in-out infinite}
@keyframes flameO2{0%,100%{transform:scale(1,1) skewX(0)}30%{transform:scale(.93,1.1) skewX(-3deg)}65%{transform:scale(1.06,.95) skewX(2deg)}}
@keyframes flameM2{0%,100%{transform:scale(1,1) translateX(0)}40%{transform:scale(1.08,.9) translateX(.7px)}75%{transform:scale(.92,1.08) translateX(-.5px)}}
@keyframes flameC2{0%,100%{transform:scaleY(1);opacity:1}45%{transform:scaleY(.8);opacity:.7}}
.streak .flamemedal{margin:-6px 4px -6px -4px}

/* ---- a badge earned more than once says so, clearly ----
   The count sat low on the hex's corner, dark on dark, and was easy to
   miss. Now a gold tag at the top right, standing off the hex. */
.badge{position:relative}
.badge .times{top:-6px;bottom:auto;right:auto;left:calc(50% + 12px);min-width:26px;height:22px;padding:0 6px;
  border-radius:11px;background:#D9A441;color:#232E3A;font:800 12.5px/1 Gabarito,system-ui,sans-serif;
  border:2px solid var(--card);box-shadow:0 2px 6px rgba(35,46,58,.25);z-index:2}
@media (prefers-reduced-motion:reduce){
  .fm-glow,.fm-ember,.flamemedal .flame.lit .fl-o,.flamemedal .flame.lit .fl-m,.flamemedal .flame.lit .fl-c{animation:none}
}

/* The streak's own moment in the popup: the medallion, large. */
.hoorayflame{display:flex;justify-content:center;margin:6px 0 2px}
.hoorayflame .flamemedal{width:112px;height:112px;margin:0}
.hoorayflame .flamemedal .flame{width:62px;height:82px}
.hoorayflame .fm-ember{bottom:42px;width:5px;height:5px}
.hoorayflame .fm-ember.e2{width:4px;height:4px}
@keyframes fmEmberBig{0%{transform:translate(0,0) scale(1);opacity:0}12%{opacity:1}100%{transform:translate(var(--dx,6px),-58px) scale(.3);opacity:0}}
.hoorayflame .fm-ember{animation-name:fmEmberBig}
#hooray.streaky .hooray-k{color:#C0561F}

/* Today's walk, as a label with a pointer to the walk's start. */
.halotag.pin{transform:translate(-50%,calc(-100% - 9px));position:relative}
.halotag.pin::after{content:'';position:absolute;left:50%;bottom:-6px;width:10px;height:10px;
  background:var(--hot);transform:translateX(-50%) rotate(45deg);border-radius:2px;z-index:-1}

/* ---- the home list, organised ---- */
#results .shelf{list-style:none;padding:14px 0 6px;border:0}
.sh-head{display:flex;align-items:baseline;gap:8px;padding:0 16px}
.sh-head h3{margin:0;font:800 17px/1.2 Gabarito,system-ui,sans-serif;letter-spacing:-.01em;color:var(--ink)}
.sh-head span{font:700 12.5px/1 Gabarito,system-ui,sans-serif;color:var(--muted)}
.sh-all{margin-left:auto;display:inline-flex;align-items:center;gap:2px;padding:6px 0 6px 8px;border:0;
  background:none;color:var(--ink);font:700 13px/1 Gabarito,system-ui,sans-serif;cursor:pointer}
.sh-all i{font-size:12px;color:var(--muted)}
.rc-more .rc-art{display:grid;place-items:center;align-content:center;gap:4px;background:var(--sunk);color:var(--ink)}
.rc-more .rc-art i{font-size:22px;color:var(--muted)}
.rc-more .rc-art b{font:800 14px/1 Gabarito,system-ui,sans-serif}
.shelfopen .sh-back{display:inline-flex;align-items:center;gap:4px;margin:0 0 10px;padding:6px 10px 6px 6px;
  border:1.5px solid var(--rule);border-radius:999px;background:var(--card);color:var(--ink);
  font:700 13px/1 Gabarito,system-ui,sans-serif;cursor:pointer}
.shelfopen h3 span{font-size:13px;font-weight:700;color:var(--muted);margin-left:4px}
#panel.home #results .shelfopen .sh-sub,#results .shelfopen .sh-sub{padding:0;margin:-4px 0 10px}
.sh-sub{margin:3px 16px 10px;font-size:12.5px;color:var(--muted)}
.sh-rail{display:flex;gap:10px;overflow-x:auto;padding:0 16px 6px;scroll-snap-type:x mandatory;
  scrollbar-width:none;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain}
.sh-rail::-webkit-scrollbar{display:none}
.rcard{flex:none;width:148px;scroll-snap-align:start;display:flex;flex-direction:column;gap:4px;
  padding:0;border:0;background:none;text-align:left;cursor:pointer;color:var(--ink)}
.rc-art{display:block;width:148px;height:104px;border-radius:14px;overflow:hidden;background:var(--sunk);
  box-shadow:0 2px 8px rgba(35,46,58,.10)}
.rc-art .wc-thumb{width:100%!important;height:100%!important;object-fit:cover;border-radius:0;display:block}
.rc-art .wc-thumb.art{display:flex;align-items:center;justify-content:center}
.rc-name{font:700 13.5px/1.25 Gabarito,system-ui,sans-serif;display:-webkit-box;-webkit-line-clamp:2;
  -webkit-box-orient:vertical;overflow:hidden;margin-top:2px}
.rc-meta{font-size:11.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rcard:active .rc-art{transform:scale(.98)}
#results .hl-head{list-style:none;padding:18px 16px 8px;border-top:1px solid var(--line);margin-top:8px}
/* The Coffee button (Nov 2026), beside the filter line and the same pill.
   On, the list of cafes in the same rows the coffee picker uses. The list
   is one block of buttons, so the block itself is not a tappable row. */
#panel .cbtn{flex:none;display:inline-flex;align-items:center;gap:6px;margin:2px 0 0;
  padding:9px 12px;border:0;border-radius:12px;background:var(--sunk);color:var(--ink);
  font:700 14px/1.2 Gabarito,system-ui,sans-serif;cursor:pointer;
  box-shadow:inset 0 0 0 1.5px transparent}
#panel .cbtn[hidden]{display:none}
#panel .cbtn i{font-size:16px;color:var(--coffee)}
#panel .cbtn.on{background:var(--hot-soft);box-shadow:inset 0 0 0 1.5px var(--hot)}
#panel .cbtn:active{filter:brightness(.97)}
#panel .cbtn:focus-visible{outline:2px solid var(--hot);outline-offset:2px}
#panel.home .cardhead{gap:8px}
/* A narrow phone: the line keeps its first words and the ellipsis, and
   loses its icon before the button loses its word. */
@media (max-width:359px){
  #panel .fline > i:first-child{display:none}
  #panel .fline{padding-left:10px;padding-right:10px;gap:6px}
  #panel .cbtn{padding-left:10px;padding-right:10px}
}
/* On, the middle height of the sheet shows the list - it keeps it for
   pulled up otherwise - and today's card steps aside for it. */
@media (max-width:820px){
  #panel.home.coffee:not(.tall) #results{display:block}
}
#panel.home.coffee #today{display:none}
#results li.coffeelist:hover{background:none}
#results li.coffeelist{cursor:default;padding:0 16px 8px}
#results .coffeeopen{border-top:0;margin-top:0}
#results .coffeeopen .sh-sub + .sh-sub{margin-top:-6px}
.crow.nowalk .nm{font-weight:600;color:var(--ink-2)}
@media (max-width:820px){
  #panel.home #results li.coffeelist{padding-left:8px;padding-right:8px}
}
.hl-head h3{margin:0 0 10px;font:800 17px/1.2 Gabarito,system-ui,sans-serif;letter-spacing:-.01em}
.hl-sort{display:flex;gap:6px;overflow-x:auto;scrollbar-width:none}
.hl-sort .chip{flex:none}
/* The four orders in one row that fits: "Top rated" was cut off the edge
   of a phone. Equal quarters, centred, nothing to scroll. */
.hl-sort{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;overflow:visible}
.hl-sort .chip{justify-content:center;min-width:0;padding:8px 4px;font-size:12.5px;white-space:nowrap}
/* One left edge for the whole explore list, the one today's walk sets
   (16 px): the shelf titles and the list heading sat at 24, the shelf
   pictures at 8 and the walk rows' thumbnails at 36. #results already
   gives 8, so everything in it adds 8 more. */
@media (max-width:820px){
  #panel.home #results .sh-head{padding:0 8px}
  #panel.home #results .sh-sub{margin-left:8px;margin-right:8px}
  #panel.home #results .sh-rail{padding:0 8px 6px;scroll-padding-inline:8px}
  #panel.home #results .hl-head{padding-left:8px;padding-right:8px}
  #panel.home #results li.wrow{padding-left:0;padding-right:0}
  #panel.home #results li.wrow .wcard.sm{padding-left:8px;padding-right:8px}
}
/* A tap leaves :hover on a touch screen, so the last walk opened kept a
   tinted box in the list as if it were chosen (Quincentennial Park). */
@media (hover:none){
  #results li:hover{background:none}
  #results li.sel:hover{background:var(--hot-soft)}
}

/* The first shelf whole on the first screen, top to bottom. Pulled up on a
   phone the sheet held today's walk, the four picks and only the heading and
   top of "Coffee at the gate" - the names were under the tab bar, so nobody
   saw what the shelf was without scrolling. The room comes from spacing and
   from a shorter card, not from anything taken away. */
#results li.shelf:hover{background:none}
@media (max-width:820px){
  #panel.home.tall #results{padding-top:0}
  #panel.home.tall .td-mini{gap:7px;padding-bottom:2px;margin-top:10px}
  #panel.home.tall .mcard{padding:7px}
  #panel.home.tall .mcard .wc-thumb{width:40px;height:40px}
  #panel.home.tall .today{padding-bottom:6px}
  #panel.home.tall .td-head{margin-bottom:8px}
  #panel.home.tall .td-row{margin-top:10px}
  #results .shelf{padding:4px 0 2px}
  .sh-sub{margin:2px 16px 7px}
  .rcard{width:138px;gap:2px}
  .rc-art{width:138px;height:80px;border-radius:13px}
  .rc-name{font-size:13px;line-height:1.2}
}

/* The bookmark, said in words: "Save for later", then "Saved". */
#saveWalk{width:auto;display:inline-flex;align-items:center;gap:6px;padding:0 12px;
  font:700 13px Gabarito,system-ui,sans-serif;white-space:nowrap}
#saveWalk i{font-size:17px}

/* The home card after Today's walk: the question, and saving for later. */
.td-plan h3{margin:2px 0 6px;font-size:19px;font-weight:800;letter-spacing:-.02em;color:var(--ink)}
.td-plan p{margin:0;font-size:14.5px;line-height:1.5;color:var(--ink-2)}
.td-save{display:inline-flex;align-items:center;gap:3px;font-weight:700;color:var(--ink);white-space:nowrap}
.td-save i{font-size:15px}
.td-saved{margin-top:12px;display:inline-flex;align-items:center;gap:7px}

/* The where screen's reason for asking, in place of a choice. */
.ob-locwhy{display:flex;gap:12px;align-items:flex-start;background:var(--card);
  border:1.5px solid var(--hot);border-radius:16px;padding:14px 16px}
.ob-locwhy i{flex:none;font-size:24px;color:var(--hot);margin-top:2px}
.ob-locwhy p{margin:0;font-size:14.5px;line-height:1.45;color:var(--ink-2)}
.ob-locwhy b{display:block;font-size:16px;color:var(--ink);margin-bottom:2px}
.ob-here-ok{cursor:default}

/* The weekly goal: walks a week chosen, paces a week under each. */
.ob-goalsub{margin:0 0 12px;font-size:14.5px;color:var(--ink-2)}
.pickone.goalrow > i.ph{font-size:20px;color:var(--ink-2);flex:none}
.pickone.goalrow b{font-size:17px}
.ob-nogoal{display:block;margin:10px auto 0;padding:10px 14px;border:0;background:none;
  font:700 14.5px Gabarito,system-ui,sans-serif;color:var(--ink-2);text-decoration:underline;
  text-underline-offset:3px;cursor:pointer}
.tw-walks{margin:6px 0 0;font-size:12.5px;color:var(--muted)}

/* A coffee near a walk that can be chosen: a disc with an ink ring, like
   the P and T pins beside it. */
.cupring{position:relative;display:grid;place-items:center;width:100%;height:100%;
  background:#FBF8F2;border:2px solid #1E2833;border-radius:50%;
  box-shadow:0 1px 4px rgba(30,40,51,.35);box-sizing:border-box}
.cupring img{display:block}
.cupring i{position:absolute;right:-6px;top:-6px;font-size:13px;color:var(--hot);
  filter:drop-shadow(0 0 1px #1E2833)}

/* The optional summit: one line per top, under the stats, and a note on
   what kind of path it is. The pin is a mountain in the walk's own ink. */
.summitopt{display:flex;gap:9px;align-items:flex-start;margin:4px 0 6px;font-size:13.5px;
  line-height:1.45;color:var(--ink-2);font-weight:500}
.summitopt i{font-size:18px;color:var(--ink);margin-top:1px}
.summitopt b{color:var(--ink);font-weight:700}
.summitnote{margin:0 0 18px 27px;font-size:11.5px;line-height:1.5;color:var(--faint)}
.summitpin{width:26px;height:26px;border-radius:50%;background:var(--card);
  box-shadow:0 1px 4px rgba(0,0,0,.25);display:grid;place-items:center;font-size:15px;color:var(--ink)}

/* Walks of the same name in places not loaded (lookElsewhere). */
#results .elserow{list-style:none;margin:0 0 6px}
#results .elsehead{list-style:none}

/* ---------- onboarding, the three-act flow (Oct 2026) --------------------
   One column, centred, the width of a phone on any screen: on a laptop the
   560px column left every heading and lead hard against the left with a
   gutter of nothing to the right. Headings and the lines that are spoken
   rather than chosen are centred; tiles and rows keep their own alignment
   inside. And nothing scrolls - see the short-screen block at the end. */
.obhead,.obbody,.obfoot{max-width:460px}
#onboard .obhead h1{text-align:center}
#onboard .obstep{display:block;text-align:center}
#onboard .ob-lead{margin:0 auto;text-align:center;max-width:none}
#onboard .ob-after,#onboard .ob-goalsub{text-align:center}
#onboard .ob-after.obcol b{margin:0 5px}
.ob-proof{justify-content:center}
.ob-pf{align-items:center;text-align:center}

/* why: three rows and one line against the trail apps */
.ob-three{display:flex;flex-direction:column;gap:10px;margin:4px 0 0}
.ob-three-r{display:flex;align-items:center;gap:13px;margin:0;padding:12px 14px;
  border-radius:14px;background:var(--sunk);border:1px solid var(--line);
  animation:obRise .5s cubic-bezier(.16,1,.3,1) backwards;
  animation-delay:calc(var(--i) * 90ms + 120ms)}
.ob-three-r > i{font-size:24px;color:#B4632F;flex:none}
.ob-three-r b{display:block;font-size:15px;font-weight:700;color:var(--ink)}
.ob-three-r em{display:block;font-style:normal;font-size:12.5px;color:var(--muted);margin-top:1px}
.ob-vs{margin:16px 0 0;text-align:center;font:700 16px/1.3 Gabarito,system-ui,sans-serif;
  color:var(--ink);letter-spacing:-.01em}

/* aha: the one big number */
.ob-aha{display:flex;flex-direction:column;align-items:center;text-align:center;gap:6px;padding:6px 0 0}
.ob-aha-n{font:800 72px/1 Gabarito,system-ui,sans-serif;color:var(--ink);
  letter-spacing:-.04em;font-variant-numeric:tabular-nums;
  animation:obAhaIn .7s cubic-bezier(.34,1.4,.64,1) .1s backwards}
.ob-aha-l{font-size:15px;line-height:1.45;color:var(--ink-2);max-width:30ch}
.ob-aha-x{margin:14px 0 0;padding:12px 16px;border-radius:14px;background:var(--sunk);
  font-size:15px;line-height:1.45;color:var(--ink);max-width:32ch}
.ob-aha-x b{color:#B4632F}
@keyframes obAhaIn{from{opacity:0;transform:scale(.7)}to{opacity:1;transform:none}}

/* keep: three tiles, the first lit */
.ob-earn{display:grid;grid-template-columns:repeat(3,1fr);gap:9px;margin:2px 0 16px}
.ob-earn-t{display:flex;flex-direction:column;align-items:center;gap:7px;padding:16px 6px 14px;
  border-radius:16px;background:var(--sunk);border:1px solid var(--line);text-align:center;
  animation:obRise .5s cubic-bezier(.16,1,.3,1) backwards;
  animation-delay:calc(var(--i) * 90ms + 120ms)}
.ob-earn-t > i{font-size:28px;color:var(--muted)}
.ob-earn-t b{font-size:13px;font-weight:700;color:var(--ink)}
.ob-earn-t.lit{background:var(--hot);border-color:var(--hot)}
.ob-earn-t.lit > i{color:var(--ink)}

/* plan: the answers played back */
.ob-plan{display:flex;flex-direction:column;gap:2px;padding:6px 16px;border-radius:16px;
  background:var(--sunk);border:1px solid var(--line)}
.ob-plan p{display:flex;align-items:center;gap:11px;margin:0;padding:9px 0;
  font-size:14.5px;font-weight:600;color:var(--ink)}
.ob-plan p + p{border-top:1px solid var(--line)}
.ob-plan p > i{font-size:19px;color:#B4632F;flex:none}
.ob-30{margin:12px 0 0;text-align:center;font-size:14.5px;color:var(--ink-2)}
.ob-30 b{color:var(--ink)}
#onboard[data-step="plan"] .ob-q{text-align:center;margin:16px 0 8px}
.ob-when{justify-content:center}

/* payoff: the coffee lands as the line closes */
.ob-cup-in{animation:obCupIn .5s cubic-bezier(.34,1.56,.64,1) 1.1s backwards}
@keyframes obCupIn{from{opacity:0;transform:translateY(-10px) scale(.4)}to{opacity:1;transform:none}}
#onboard[data-step="payoff"] .ob-answer{justify-content:center;text-align:left}

@media (prefers-reduced-motion:reduce){
  .ob-three-r,.ob-earn-t,.ob-aha-n,.ob-cup-in{animation:none}
}

/* Short screens - a laptop window, an iPhone SE. The band shrinks before
   anything else does, then the tiles, so the question and its answers are
   always on one screen. */
@media (max-height:780px){
  .obscene.slim{height:clamp(64px,11vh,120px)}
  .obhead{padding-top:calc(14px + env(safe-area-inset-top))}
  .obgrid .pickone.tile{min-height:64px;padding:9px 11px}
  .ob-aha-n{font-size:60px}
  #onboard[data-step="payoff"] .ob-map{height:clamp(130px,24vh,170px)}
}
@media (max-height:680px){
  .obscene.slim{height:clamp(48px,8vh,80px)}
  .obgrid{gap:6px}
  .obgrid .pickone.tile{min-height:54px;gap:4px}
  .ob-three-r{padding:9px 12px}
  .ob-earn-t{padding:11px 6px 10px}
}

/* Three across for the who and what-stops tiles: two rows, not four. */
.obgrid.ob3{grid-template-columns:repeat(3,1fr);gap:7px}
.obgrid.ob3 .pickone.tile{min-height:78px;padding:10px 9px 10px;gap:5px}
.obgrid.ob3 .pickone.tile b{font-size:12.5px;line-height:1.22}
.obgrid.ob3 .pickone.tile .box{top:7px;right:7px;width:16px;height:16px}
@media (max-height:780px){
  .obgrid.ob3 .pickone.tile{min-height:66px}
  .ob-win-line{margin:0;padding:4px 0}
  .ob-win-name{margin-bottom:2px}
  .pickone.goalrow{padding:10px 13px;margin-bottom:6px}
  .ob-plan p{padding:7px 0}
  #onboard[data-step="plan"] .ob-q{margin:10px 0 6px}
  .ob-30{margin-top:9px}
}
#onboard .obcount{justify-content:center;text-align:center}

/* The rows rise one by one, so their box must not rise as well. */
#obBody.in > .ob-three,#obBody.in > .ob-earn,#obBody.in > .ob-aha{animation:none}

.ob-earn-t em{font-style:normal;font-size:11px;line-height:1.3;color:var(--muted)}
.ob-earn-t.lit em{color:#3a3020}

/* Start walk, beside Let's go. Quiet until it is the next thing to do -
   at the walk, or back in the app during the outing - then it takes the
   gold and the drive steps back. */
.gowalk{flex:none;display:flex;align-items:center;justify-content:center;min-height:50px;
  padding:0 16px;border-radius:14px;border:1px solid var(--rule);background:var(--card);
  color:var(--ink);cursor:pointer;font:800 15px Gabarito,system-ui,sans-serif;letter-spacing:-.01em}
.gowalk b{display:flex;align-items:center;gap:6px;font:inherit}
.gowalk i{font-size:18px}
.gowalk:focus-visible{outline:2px solid var(--hot);outline-offset:2px}
.gobar.walknow .gowalk,.gobar.walking .gowalk{flex:1;background:var(--hot);color:#232E3A;
  border-color:rgba(35,46,58,.45);box-shadow:var(--sh-gold)}
.gobar.walknow .gogo,.gobar.walking .gogo{flex:none;background:var(--card);box-shadow:none;
  border:1px solid var(--rule);padding:7px 14px}
.gobar.walknow #goLabel,.gobar.walking #goLabel{display:none}
.gobar.walking .gowalk{background:var(--ink);color:var(--card)}

/* ---------- onboarding progress: a trail, not a row of dots ------------ */
#obDots.obdots{display:block;padding:4px 22px 0;max-width:460px;margin:0 auto;width:100%;box-sizing:border-box}
.obtrail{position:relative;height:30px}
.obtrail > svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
.obtrail .tr-bg{fill:none;stroke:var(--rule);stroke-width:2.5;stroke-dasharray:1 7;stroke-linecap:round}
.obtrail .tr-on{fill:none;stroke:var(--moss);stroke-width:3;stroke-linecap:round;stroke-dasharray:100;
  stroke-dashoffset:100;transition:stroke-dashoffset .7s cubic-bezier(.45,.05,.25,1)}
.obtrail .tr-ticks i{position:absolute;width:6px;height:6px;margin:-3px 0 0 -3px;border-radius:50%;
  background:var(--rule)}
.obtrail .tr-ticks i.done{background:var(--moss)}
.obtrail .tr-ticks i.justdone{animation:dotDone .3s cubic-bezier(.34,1.56,.64,1)}
.obtrail .tr-me{position:absolute;width:16px;height:16px;margin:-8px 0 0 -8px;border-radius:50%;
  background:var(--ink);border:3px solid var(--card);box-sizing:border-box;
  box-shadow:0 1px 3px rgba(0,0,0,.3);
  transition:left .7s cubic-bezier(.45,.05,.25,1),top .7s cubic-bezier(.45,.05,.25,1)}
.obtrail .tr-cup{position:absolute;width:24px;height:24px;margin:-12px 0 0 -12px;border-radius:50%;
  background:var(--sunk);border:1px solid var(--rule);box-sizing:border-box;
  display:grid;place-items:center;transition:background .3s}
.obtrail .tr-cup.got{background:var(--hot);border-color:var(--hot);
  animation:trCup .5s cubic-bezier(.34,1.56,.64,1) .45s backwards}
@keyframes trCup{from{transform:scale(.6)}to{transform:none}}
.tr-acts{display:flex;justify-content:space-between;margin-top:3px;
  font:700 9.5px Gabarito,system-ui,sans-serif;letter-spacing:.09em;text-transform:uppercase;color:var(--faint)}
.tr-acts .past{color:var(--moss)}
.tr-acts .now{color:var(--ink)}
@media (max-height:680px){ .tr-acts{display:none} }
@media (prefers-reduced-motion:reduce){
  .obtrail .tr-on,.obtrail .tr-me{transition:none}
  .obtrail .tr-cup.got,.obtrail .tr-ticks i.justdone{animation:none}
}
@media (max-height:780px){
  .obtrail{height:24px}
  .tr-acts{margin-top:0}
  .ob-three{gap:7px}
  .ob-three-r{padding:9px 13px}
  #onboard[data-step="payoff"] .ob-map{height:clamp(120px,21vh,160px)}
  .obgrid.ob3 .pickone.tile{min-height:60px}
}
@media (max-height:780px){
  #onboard[data-step="who"] .ob-after{margin-top:5px}
  #obBuggyInline .ob-q{margin:10px 0 6px}
}
.obtrail .tr-me.in{opacity:0;transition:left .7s cubic-bezier(.45,.05,.25,1),top .7s cubic-bezier(.45,.05,.25,1),opacity .2s .6s}
.obtrail .tr-cup{width:26px;height:26px;margin:-13px 0 0 -13px}

/* ---------- the walk's actions: Directions and Start walk (Oct 2026) ----
   Each button says what it does and, underneath, when. Directions leads
   while you are not there yet; Start walk takes the gold at the walk, nearly
   there, or when the trip has had time; walking, one button finishes it. */
.gobar{gap:10px}
.gogo{flex:1.35}
.gowalk{flex:1;flex-direction:column;gap:1px;padding:7px 12px;min-height:56px}
.gowalk span{font:600 12px Gabarito,system-ui,sans-serif;color:var(--muted);white-space:nowrap}
.gobar.walknow .gowalk span{color:#3a3020}
.gobar.walknow .gogo{flex:0 0 auto;padding:7px 16px}
.gobar.walking .gogo{display:none}
.gobar.walking .gowalk{flex:1;background:var(--ink);color:var(--card);border-color:var(--ink);box-shadow:none}
.gobar.walking .gowalk span{color:color-mix(in srgb,var(--card) 70%,transparent)}
.gowalk.pulse{animation:goPulse 1.4s ease-out 2}
@keyframes goPulse{0%{box-shadow:0 0 0 0 rgba(217,164,65,.6)}100%{box-shadow:0 0 0 14px rgba(217,164,65,0)}}
.gomode{display:block;width:100%;border:0;background:var(--card);padding:0 14px 10px;margin-top:-4px;
  font:700 12.5px Gabarito,system-ui,sans-serif;color:var(--moss);text-align:center;cursor:pointer;
  text-decoration:underline;text-underline-offset:3px}
.gomode[hidden]{display:none}
.gotip{display:flex;align-items:center;gap:8px;margin:0 14px 8px;padding:10px 6px 10px 12px;
  border-radius:12px;background:var(--sunk);border:1px solid var(--line)}
.gotip[hidden]{display:none}
.gotip p{margin:0;flex:1;font-size:13px;line-height:1.4;color:var(--ink-2)}
.gotip button{flex:none;width:32px;height:32px;border:0;border-radius:8px;background:transparent;
  font-size:19px;color:var(--muted);cursor:pointer}
.pvpill{display:inline-flex;align-items:center;gap:7px;margin:10px 0 2px;height:36px;padding:0 14px;
  border-radius:999px;border:1px solid var(--rule);background:var(--card);color:var(--ink);
  font:700 13.5px Gabarito,system-ui,sans-serif;cursor:pointer}
.pvpill i{font-size:15px}
.pvpill:hover{background:var(--sunk)}
@media (prefers-reduced-motion:reduce){ .gowalk.pulse{animation:none} }
/* Just the cup, no number after it: the pill's padding is weighted to the
   right for the rating, which left a lone cup sitting against the left of
   its circle. Even all round when there is nothing else in it. */
.cupchoice.solo{padding:1px 4px}

/* ---------- the walk's reference sections (Oct 2026) ----------
   Nearby, On the route and About were rows of same-weight text. Each now
   has one shape: facilities as three tiles led by the distance, things on
   the way as pills, the description as a lead and a body. Radii follow
   the sheet's boxes (14px tiles, full pills); colour only from tokens. */
.fgrid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:2px 0 6px}
.ftile{background:var(--sunk);border-radius:14px;padding:12px 11px 12px;
  display:flex;flex-direction:column;align-items:flex-start;gap:1px;min-width:0}
.ftile i{display:grid;place-items:center;width:34px;height:34px;border-radius:50%;
  background:var(--card);color:var(--coffee);font-size:19px;margin-bottom:8px}
.ftile b{font-size:17px;font-weight:700;color:var(--ink);line-height:1.15;letter-spacing:-.01em}
.ftile span{font-size:12.5px;font-weight:600;color:var(--ink-2);line-height:1.3}
.ftile em{font-style:normal;font-size:11.5px;font-weight:500;color:var(--muted);
  line-height:1.3;margin-top:3px}
.ftile.none{background:transparent;box-shadow:inset 0 0 0 1px var(--line)}
.ftile.none i{background:var(--sunk);color:var(--faint)}
.ftile.none b{font-size:14px;color:var(--faint);font-weight:600}
.ftile.none span{color:var(--muted)}

.rpills{display:flex;flex-wrap:wrap;gap:8px;margin-top:2px}
.rpill{display:inline-flex;align-items:center;gap:7px;padding:8px 13px 8px 10px;
  border-radius:999px;background:var(--maybe-bg);color:var(--maybe);
  font-size:14px;font-weight:650;line-height:1.2}
.rpill i{font-size:17px}

.dsec.about .about-lead{font-size:16.5px;font-weight:650;color:var(--ink);
  line-height:1.4;margin:0 0 6px;max-width:60ch;letter-spacing:-.005em}
.dsec.about .about-rest{font-size:14.5px;font-weight:500;color:var(--ink-2);
  line-height:1.6;margin:0;max-width:62ch}
.dsec.about .desc.wiki{font-size:14.5px;line-height:1.6;color:var(--ink-2)}

@media (max-width:360px){
  .fgrid{grid-template-columns:repeat(2,minmax(0,1fr))}
}
.ftile em + em{margin-top:0}
/* The full list is a way into more, not a section of its own. */
.dsec.facts-all{margin-top:-12px}
.dsec.facts-all>summary{padding:6px 0 10px;min-height:44px}
.dsec.facts-all>summary h3{font-size:14px;font-weight:650;color:var(--ink-2);opacity:1;
  text-transform:none;letter-spacing:0;border:0;padding:0}
.dsec.facts-all{margin-bottom:12px}

/* The outing's actions under the picture: Preview as the one labelled
   pill, send and link as round icons beside it, all one height. */
.toprow{display:flex;align-items:center;gap:8px;margin:12px 0 4px}
.toprow .pvpill{margin:0;height:40px;flex:none}
.toprow .iact{width:40px;height:40px;border-width:1px}
.toprow .iact i{font-size:18px}

/* About sits under the picture now, so it is a block of the page's
   opening, not a section further down: no heading, a little air. */
.dsec.about.top{margin:12px 0 4px}
.dsec.about.top h3{display:none}

/* Every row in the full lists carries its kind, the same icon as its tile. */
.poi.withico{align-items:center}
.poi .pico{flex:none;width:30px;height:30px;border-radius:50%;display:grid;place-items:center;
  background:var(--sunk);color:var(--coffee);font-size:16px}
.poi.withico .d{min-width:46px}
.dsec.ref>summary h3 .hico{display:inline-flex;align-items:center;gap:8px;font-style:normal}
.dsec.ref>summary h3 .hico i{font-size:17px;color:var(--coffee)}

/* The sheet's own move between stops, for taps and anything that is not a
   drag (a drag sets its own glide from the flick). Apple's sheet curve:
   leaves at speed and eases a long way into rest, rather than the quick
   snap it was. */
#panel,#detail{transition:max-height .44s cubic-bezier(.32,.72,0,1)}
@media (prefers-reduced-motion: reduce){
  #panel,#detail{transition:max-height .16s linear}
}

/* Where a shuffle lands: a gold ring opening out once, then gone. */
.cw-land{pointer-events:none}
.cw-land i{position:absolute;inset:0;border-radius:50%;border:2.5px solid var(--hot);
  opacity:0;animation:cwLand 1.2s cubic-bezier(.22,.8,.3,1) forwards}
.cw-land i + i{animation-delay:.18s}
.cw-land::after{content:'';position:absolute;inset:5px;border-radius:50%;background:var(--hot);
  box-shadow:0 0 0 3px var(--card);animation:cwDot 1.4s ease forwards}
@keyframes cwLand{0%{transform:scale(.4);opacity:.9}100%{transform:scale(4.2);opacity:0}}
@keyframes cwDot{0%{transform:scale(0)}20%{transform:scale(1.15)}35%{transform:scale(1)}80%{opacity:1}100%{opacity:0}}
@media (prefers-reduced-motion: reduce){ .cw-land{display:none} }

/* Tiles that open their own list. */
button.ftile{font:inherit;text-align:left;border:0;cursor:pointer;position:relative;
  -webkit-tap-highlight-color:transparent;transition:background .18s ease,box-shadow .18s ease,transform .1s ease}
button.ftile:active{transform:scale(.97)}
button.ftile::after{content:'';position:absolute;top:16px;right:13px;width:6px;height:6px;
  border-right:1.5px solid var(--faint);border-bottom:1.5px solid var(--faint);
  transform:rotate(45deg);transition:transform .2s ease}
button.ftile.on{background:var(--card);box-shadow:inset 0 0 0 1.5px var(--hot)}
button.ftile.on::after{transform:rotate(-135deg) translate(-2px,-2px)}
button.ftile:focus-visible{outline:2px solid var(--hot);outline-offset:2px}
.fdrawer{margin-top:8px;background:var(--card);border-radius:14px;padding:2px 12px;
  box-shadow:inset 0 0 0 1px var(--line);animation:fdIn .26s cubic-bezier(.32,.72,0,1)}
.fdrawer .poi:last-child{border-bottom:0}
@keyframes fdIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion: reduce){ .fdrawer{animation:none} }

/* The outing's action bar: equal columns, a round icon over one word. */
.actbar{display:grid;grid-auto-flow:column;grid-auto-columns:1fr;gap:4px;margin:14px 0 6px}
.act{display:flex;flex-direction:column;align-items:center;gap:6px;padding:2px 0 0;
  background:none;border:0;font:600 12.5px/1.2 Gabarito,system-ui,sans-serif;color:var(--ink-2);
  cursor:pointer;text-decoration:none;-webkit-tap-highlight-color:transparent;min-width:0}
.act i{display:grid;place-items:center;width:48px;height:48px;border-radius:50%;
  background:var(--sunk);color:var(--ink);font-size:21px;
  transition:background .18s ease,transform .12s ease,color .18s ease}
.act span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.act:active i{transform:scale(.92)}
.act:focus-visible{outline:none}
.act:focus-visible i{box-shadow:0 0 0 2px var(--card),0 0 0 4px var(--hot)}
.act.prime i{background:var(--hot);color:var(--on-hot)}
.act.prime span{color:var(--ink)}
#saveWalk.on i{background:var(--ink);color:var(--card)}
#saveWalk.on span{color:var(--ink)}
#copyLink.done i{background:var(--yes-bg);color:var(--yes)}
@media (hover:hover){ .act:hover i{background:var(--line)} .act.prime:hover i{background:var(--hot)} }
/* The header's old save styles must not reach the bar's. */
#saveWalk.act,#saveWalk.act.on{width:auto;height:auto;padding:2px 0 0;background:none;color:var(--ink-2);
  display:flex;flex-direction:column;gap:6px;border:0;box-shadow:none;border-radius:0}
#saveWalk.act i{font-size:21px}
#saveWalk.act{font:600 12.5px/1.2 Gabarito,system-ui,sans-serif;white-space:normal}

/* How far you will drive: one track, equal cells, number over unit. */
.dsegs{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:4px;padding:4px;
  background:var(--sunk);border-radius:16px;margin-top:2px}
.dseg{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;
  height:56px;padding:0;border:0;border-radius:12px;background:transparent;color:var(--ink);
  font-family:Gabarito,system-ui,sans-serif;cursor:pointer;-webkit-tap-highlight-color:transparent;
  transition:background .22s cubic-bezier(.32,.72,0,1),box-shadow .22s ease,transform .1s ease}
.dseg b{font-size:19px;font-weight:800;line-height:1;letter-spacing:-.02em}
.dseg i{font-style:normal;font-size:11.5px;font-weight:600;line-height:1;color:var(--muted)}
.dseg.on{background:var(--hot);box-shadow:0 1px 2px rgba(30,40,51,.10),0 4px 10px -4px rgba(176,120,30,.45)}
.dseg.on i{color:var(--on-hot);opacity:.75}
.dseg:active{transform:scale(.96)}
.dseg:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
@media (hover:hover){ .dseg:not(.on):hover{background:var(--line)} }

/* A shuffle's flight: the basemap alone while the camera travels, the
   walk and its pins fading back in where it lands. */
.leaflet-overlay-pane,.leaflet-marker-pane,.leaflet-shadow-pane,.leaflet-tooltip-pane{
  transition:opacity .38s cubic-bezier(.32,.72,0,1)}
.cw-flying .leaflet-overlay-pane,.cw-flying .leaflet-marker-pane,
.cw-flying .leaflet-shadow-pane,.cw-flying .leaflet-tooltip-pane{opacity:0;transition-duration:.22s}

/* The shuffle's jump: the map steps back and the new place comes forward,
   centred on the part of the map above the sheet. */
#map.cw-jump{transform-origin:50% 36%;will-change:transform,opacity}

/* The coffee list's groups. */
.crhead{margin:16px 2px 4px;font:700 12px/1.2 Gabarito,system-ui,sans-serif;color:var(--muted)}
.crhead:first-child{margin-top:4px}
.crow.t2 .nm{font-weight:inherit}

/* Who it suits: pills grouped by the answer, the reason on tap. */
.wgroups{display:flex;flex-direction:column;gap:10px;margin-top:4px}
.wgroup{display:grid;grid-template-columns:72px minmax(0,1fr);align-items:start;gap:10px}
.wg-l{font:700 12.5px/30px Gabarito,system-ui,sans-serif;color:var(--muted)}
.wgroup.yes .wg-l{color:var(--yes)} .wgroup.maybe .wg-l{color:var(--maybe)} .wgroup.no .wg-l{color:var(--no)}
.wg-chips{display:flex;flex-wrap:wrap;gap:6px}
.wchip{display:inline-flex;align-items:center;gap:6px;height:30px;padding:0 11px 0 9px;border-radius:999px;
  border:0;font:650 13px Gabarito,system-ui,sans-serif;cursor:pointer;-webkit-tap-highlight-color:transparent;
  transition:box-shadow .15s ease,transform .1s ease}
.wchip i{font-size:15px}
.wchip.yes{background:var(--yes-bg);color:var(--yes)}
.wchip.maybe{background:var(--maybe-bg);color:var(--maybe)}
.wchip.no{background:var(--no-bg);color:var(--no)}
.wchip.sel{box-shadow:inset 0 0 0 1.5px currentColor}
.wchip.on{box-shadow:inset 0 0 0 2px currentColor}
.wchip:active{transform:scale(.96)}
.wchip:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
.wwhy{margin:12px 0 0;padding:10px 12px;border-radius:12px;background:var(--sunk);
  font-size:14px;line-height:1.45;color:var(--ink-2)}
.wtip{margin:10px 0 0;font-size:12.5px;color:var(--muted)}
/* The summit under the description, in its type. */
.summitopt{font-size:14.5px;line-height:1.55;color:var(--ink-2);margin:4px 0 4px}
.summitnote{margin:0 0 12px 27px;font-size:12.5px;color:var(--muted)}

/* On the walk: finding yourself and logging it, a matching pair at the end. */
.onday .onwalk{grid-template-columns:auto minmax(0,1fr) auto;align-items:center;margin:4px 0 0;
  background:var(--sunk);border-radius:14px}
.onday .onwalk .owgo{grid-column:3;grid-row:1;justify-self:end}
.onday .logit{margin:8px 0 0;border:0;border-radius:14px;background:var(--sunk);min-height:0;padding:12px 14px;gap:12px}
.onday .logit i{width:34px;height:34px;border-radius:10px;display:grid;place-items:center;
  background:var(--card);font-size:18px}
.onday .logit b{font:700 14.5px/1.3 Gabarito,system-ui,sans-serif}
.onday .logit em{font-size:13px;line-height:1.35}
.onday .logit:hover{background:var(--line)}

/* ---------- the walk's story: one type scale (Oct 2026) ----------
   Title 800; headline and labels 650; body regular. Nothing else. */
.dsec.about.top{margin:14px 0 8px}
.dsec.about .about-lead{font-size:18px;font-weight:650;line-height:1.35;color:var(--ink);margin:0 0 8px;letter-spacing:-.01em}
.dsec.about .about-rest{font-size:15px;font-weight:400;line-height:1.6;color:var(--ink-2);margin:0;white-space:pre-line}
.dsec.about .about-rest.clamp:not(.open){display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}
.readmore{margin:6px 0 0;padding:4px 0;border:0;background:none;cursor:pointer;
  font:650 14px Gabarito,system-ui,sans-serif;color:var(--ink);text-decoration:underline;text-underline-offset:3px}
.about-by{margin:10px 0 0;font-size:13px;line-height:1.45;color:var(--muted)}
.about-by a{color:inherit;text-decoration:underline;text-underline-offset:2px}
#detailBody .dcounty{font-size:14px;font-weight:500;color:var(--muted)}

/* The optional climb, as an offer you can see. */
.summitcard{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:center;
  margin:14px 0 0;padding:14px;border-radius:14px;background:var(--yes-bg)}
.summitcard .sc-i{display:grid;place-items:center;width:44px;height:44px;border-radius:12px;
  background:var(--card);color:var(--yes);font-size:22px}
.summitcard .sc-t{display:flex;flex-direction:column;gap:2px;min-width:0}
.summitcard .sc-k{font:650 12px/1.2 Gabarito,system-ui,sans-serif;color:var(--yes)}
.summitcard b{font:650 16px/1.3 Gabarito,system-ui,sans-serif;color:var(--ink)}
.summitcard .sc-m{font-size:13.5px;font-weight:400;line-height:1.4;color:var(--ink-2)}
.summitcard + .summitcard{margin-top:8px}
.summitnote{margin:8px 2px 4px;font-size:12.5px;font-weight:400;line-height:1.45;color:var(--muted)}
.summitcard .nw{white-space:nowrap}

/* ---------- the sheet's rhythm (Oct 2026) ----------
   One scale of space instead of whatever each block happened to carry:
   gaps of 0 to 26px, so a warning card ran straight into the next
   heading. Things that belong together sit 12-16px apart, steps of the
   story 20-24px, and a new section opens 36px down. Margins are set
   from the top only, so nothing double-counts. */
#detailBody > *{margin-bottom:0}
#detailBody > * + *{margin-top:16px}
#detailBody > .dcounty{margin-top:6px}
#detailBody > .wphoto{margin-top:18px}
#detailBody > .dsec.about.top{margin-top:20px}
#detailBody > .summitcard{margin-top:20px}
#detailBody > .summitcard + .summitcard{margin-top:8px}
#detailBody > .summitnote{margin-top:8px}
#detailBody > .legs{margin-top:22px}
#detailBody > .dscore{margin-top:14px}
#detailBody > .verdict{margin-top:12px}
#detailBody > .bygo{margin-top:12px}
#detailBody > .dsec.changeplan{margin-top:32px}
#detailBody > .plan{margin-top:24px}
#detailBody > .changeplan + .plan{margin-top:16px}
#detailBody > .actbar{margin-top:24px}
#detailBody > .dsec:not(.about):not(.changeplan){margin-top:36px}
#detailBody > .dsec > h3:first-child{margin-top:0}

/* Show me on the trail: one tappable card. */
button.onwalk{width:100%;border:0;font:inherit;text-align:left;cursor:pointer;color:inherit;
  -webkit-tap-highlight-color:transparent;transition:background .15s ease,transform .1s ease}
.onday button.onwalk{grid-template-columns:auto minmax(0,1fr) auto;align-items:center}
button.onwalk .owi{color:var(--ink)}
button.onwalk .owgo-c{color:var(--faint);font-size:16px}
button.onwalk:active{transform:scale(.99)}
@media (hover:hover){ button.onwalk:hover{background:var(--line)} }
.onday .logit > span{display:flex;flex-direction:column;gap:2px;min-width:0}
.onday .logit em{display:block;line-height:1.35 !important}
/* Preview like the rest of the bar: no accent (user's ask, Oct 2026). */
.act.prime i{background:var(--sunk);color:var(--ink)}
.act.prime span{color:var(--ink-2)}
@media (hover:hover){ .act.prime:hover i{background:var(--line)} }

.wphoto{container-type:inline-size}
#detailBody > .rpills.onroute{margin-top:12px}

/* The taste sheet leads with the download now the app is out. */
#joinSheet .js-store{display:flex;justify-content:center;width:100%;margin:14px 0 4px;text-decoration:none}
#joinSheet .js-android{margin-top:16px;font-size:14px}
