/* 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 */
  --paper:#E9E2D5;
  --card:#F5F0E7;
  --sunk:#DFD7C8;
  --ink:#232E3A;
  --ink-2:#3E4B58;
  --muted:#6E7A85;
  --faint:#96A0A9;
  --line:#CFC5B4;
  --rule:#C6BCA9;
  --line-2:#DED6C6;
  --hot:#D9A441;          /* muted gold, not a highlighter */
  --yes:#3B6B52;          /* the green of a wet field, not a traffic light */
  --maybe:#B07A34;
  --no:#A2483E;
  --yes-bg:#DCE5DB;
  --maybe-bg:#EEE1CB;
  --no-bg:#EEDAD3;
  --coffee:#B4623A;       /* roasted terracotta */
  --hard:0 1px 2px rgba(35,46,58,.10);
  --lift:0 2px 0 rgba(35,46,58,.05),0 14px 30px -16px rgba(35,46,58,.36);
  --lift-lg:0 2px 0 rgba(35,46,58,.06),0 30px 64px -24px rgba(35,46,58,.46);
  --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:#1B242E;
    --card:#232E3A;
    --sunk:#2C3846;
    --ink:#EDE6DA;
    --ink-2:#CDC5B7;
    --muted:#9AA4AE;
    --faint:#77828D;
    --line:#35424F;
    --rule:#3B4956;
    --line-2:#2B3846;
    --hot:#E6BC63;
    --yes:#7FB292;
    --maybe:#D8A362;
    --no:#D98A7E;
    --yes-bg:#1E2E28;
    --maybe-bg:#2E2820;
    --no-bg:#2F2321;
    --coffee:#DC8B5E;
    --hard:0 1px 2px rgba(35,46,58,.10);
    --lift:0 2px 0 rgba(0,0,0,.45),0 14px 30px -16px rgba(0,0,0,.8);
    --lift-lg:0 2px 0 rgba(0,0,0,.45),0 30px 64px -24px rgba(0,0,0,.9);
    --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:#1B242E;
    --card:#232E3A;
    --sunk:#2C3846;
    --ink:#EDE6DA;
    --ink-2:#CDC5B7;
    --muted:#9AA4AE;
    --faint:#77828D;
    --line:#35424F;
    --rule:#3B4956;
    --line-2:#2B3846;
    --hot:#E6BC63;
    --yes:#7FB292;
    --maybe:#D8A362;
    --no:#D98A7E;
    --yes-bg:#1E2E28;
    --maybe-bg:#2E2820;
    --no-bg:#2F2321;
    --coffee:#DC8B5E;
    --hard:0 1px 2px rgba(35,46,58,.10);
    --lift:0 2px 0 rgba(0,0,0,.45),0 14px 30px -16px rgba(0,0,0,.8);
    --lift-lg:0 2px 0 rgba(0,0,0,.45),0 30px 64px -24px rgba(0,0,0,.9);
    --tile:saturate(.12) brightness(.62) contrast(1.05) invert(.9) hue-rotate(175deg);
  }

*{box-sizing:border-box}
[hidden]{display:none !important}
html,body{height:100%;margin:0}
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,.rate,.rateval{
  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 ---------- */
#chrome{position:fixed;top:16px;left:16px;right:16px;z-index:800;
  display:flex;flex-direction:column;gap:10px;pointer-events:none}
#chrome>*{pointer-events:auto}

.bar{display:flex;align-items:center;gap:8px;max-width:520px;flex-wrap:nowrap;
  background:var(--card);border:1px solid var(--rule);border-radius:16px;
  box-shadow:var(--hard);padding:7px}
/* 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. */
/* The who pill sits inside the bar, to the right of the search field. */
.whopill{flex:none;display:flex;align-items:center;gap:6px;cursor:pointer;
  border:0;border-left:1px solid var(--rule);background:none;color:var(--muted);
  font:600 13px Gabarito,system-ui,sans-serif;padding:0 6px 0 10px;
  max-width:44%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.whopill #whoLbl{color:var(--ink);font-weight:700;overflow:hidden;text-overflow:ellipsis}
.whopill i{font-size:16px;flex:none}
.whopill:focus-visible{outline:2px solid var(--hot);outline-offset:2px}

.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}
.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(--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}
#panel.min{bottom:auto;height:auto}
#panel.min #results,#panel.min #credits,#panel.min #landing{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:10px;
  transition:transform .08s,background .15s}
.icon:hover{background:var(--sunk)}
.icon:active{transform:translate(1px,1px)}
.icon i{font-size:16px}

#results{list-style:none;margin:0;padding:8px;overflow-y:auto;flex:1;min-height:0}
#results li{padding:12px;border-radius:12px;cursor:pointer;display:grid;
  grid-template-columns:4px 1fr;gap:12px;align-items:start;border:2px solid transparent}
#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}
#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)}

.outing{border:1px solid var(--rule);border-radius:14px;overflow:hidden;margin-bottom:16px}
.outing h3{display:flex;justify-content:space-between;align-items:baseline;gap:10px;
  margin:0;padding:9px 13px;background:var(--ink);color:var(--card);
  font-size:12px;font-weight:700;letter-spacing:.02em}
.outing h3 b{color:var(--hot);font-weight:700}
.ostep{display:grid;grid-template-columns:62px 1fr auto;gap:10px;align-items:baseline;
  padding:9px 13px;border-top:1px solid var(--line-2);font-size:13.5px}
.ostep:first-of-type{border-top:0}
.ok{font-size:10.5px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;
  color:var(--faint)}
.oname{font-weight:600;min-width:0}
.oname i{display:block;font-style:normal;font-weight:500;font-size:12px;color:var(--muted);margin-top:1px}
.od{font-size:12px;color:var(--ink-2);white-space:nowrap}
.ostep.miss .oname{font-weight:500;color:var(--faint)}

.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}

.rate{font-size:12px;font-weight:700;padding:3px 9px;border-radius:999px;
  border:1px solid var(--rule);background:var(--card);color:var(--coffee);cursor:pointer}
.rate.empty{color:var(--muted);border-color:var(--line)}
.rate:hover{border-color:var(--ink)}
.ratebox{display:flex;align-items:center;gap:9px;padding:8px 0 2px}
.ratebox input[type=range]{flex:1;accent-color:var(--coffee)}
.rateval{font-size:13px;font-weight:700;min-width:32px;text-align:right;color:var(--coffee)}
.rateclear{border:0;background:none;color:var(--muted);font-size:11px;cursor:pointer;
  text-decoration:underline;font-weight:500}

/* ---------- filter sheet ---------- */
#scrim{position:fixed;inset:0;z-index:900;background:rgba(16,16,16,.34);animation:fade .16s ease}
@keyframes fade{from{opacity:0}}
#sheet{position:fixed;top:16px;right:16px;bottom:16px;width:392px;z-index:910;
  background:var(--card);border:1px solid var(--rule);border-radius:16px;
  box-shadow:var(--lift-lg);display:flex;flex-direction:column;overflow:hidden;
  animation:slide .2s cubic-bezier(.16,1,.3,1)}
@keyframes slide{from{opacity:0;transform:translateX(14px)}}
.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}
.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}
.lbl{display:flex;justify-content:space-between;align-items:baseline;
  font-size:10px;letter-spacing:.09em;text-transform:uppercase;color:var(--faint);
  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)}
.tier[data-tier=yes].on i{background:var(--yes)}
.tier[data-tier=maybe].on i{background:var(--maybe)}
.tier[data-tier=no].on i{background:var(--no)}

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:10px;left:10px;right:10px;gap:8px}
  .bar{padding:6px;box-shadow:none}
  /* 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:42dvh;
    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. */
  #detail{max-height:58dvh}
  #detail.tall{max-height:86dvh}
  #panel.min{max-height:none;height:auto}
  .grip{display:block;width:40px;height:5px;border-radius:5px;background:var(--line);
    margin:9px auto 0;flex:none;cursor:grab}
  #sheet{top:auto;left:0;right:0;bottom:0;width:auto;max-height:86dvh;
    border-radius:18px 18px 0 0;border-bottom:0}
  .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,
body[data-base="satellite"] .leaflet-tile-pane{filter:none}
body[data-base="satellite"]{--line-2:#2a2a28}

/* 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 */
.rate.prov{color:var(--ink-2);border-color:var(--line);cursor:default}
.rate.prov:hover{border-color:var(--line)}

/* 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}
.rate.live.empty{color:var(--faint)}

.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)}

.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 (saved / my walks / profile) ---------- */
#tabBody{overflow-y:auto;flex:1;min-height:0;padding:14px}
#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. */
@media (max-width:820px){
  #panel.tall,#detail.tall{
    max-height:calc(100dvh - var(--chrome-h,112px) - var(--tabh) - 26px)}
  #detail{max-height:58dvh}
  #detail.peeked{max-height:30dvh}
  /* 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}
}

/* ---------- 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)}

/* ---------- who is walking ---------- */
/* Nine personas in a scrolling rail meant five were always off-screen. A grid
   shows every one of them at once, with how many walks each has. */
#whoSheet{position:fixed;z-index:910;top:50%;left:50%;transform:translate(-50%,-50%);
  width:min(460px,calc(100vw - 32px));max-height:min(640px,calc(100dvh - 60px));
  display:flex;flex-direction:column;background:var(--card);
  border:1px solid var(--rule);border-radius:18px;box-shadow:var(--lift-lg);overflow:hidden}
.whogrid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;padding:14px;
  overflow-y:auto;flex:1;min-height:0}
.who{display:flex;flex-direction:column;align-items:center;justify-content:flex-start;
  gap:5px;padding:13px 6px 11px;cursor:pointer;text-align:center;
  background:var(--card);border:1px solid var(--rule);border-radius:14px;
  color:var(--ink);font-weight:600;font-size:12.5px;line-height:1.2;
  letter-spacing:-.015em;transition:transform .08s,background .15s,border-color .15s}
.who i{font-size:23px;color:var(--muted)}
.who span{display:block}
.who em{display:block;font:500 10.5px/1 JetBrains Mono,monospace;
  color:var(--faint);font-style:normal;min-height:10px}
.who:hover{background:var(--sunk);border-color:var(--ink)}
.who:active{transform:translate(1px,1px)}
.who.on{background:transparent;color:var(--ink);border-color:var(--ink);
  box-shadow:inset 0 0 0 1px var(--ink)}
.who.on i{color:var(--hot)}
.who.on em{color:rgba(255,255,255,.6)}
.who:focus-visible{outline:2px solid var(--hot);outline-offset:2px}
.whonote{margin:0;padding:0 16px 14px;font-size:11.5px;line-height:1.5;color:var(--faint)}

@media (max-width:820px){
  #whoSheet{top:auto;bottom:0;left:0;transform:none;width:auto;right:0;
    border-radius:18px 18px 0 0;border-bottom:0;max-height:82dvh}
  #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}
}
@media (max-width:380px){
  .whogrid{grid-template-columns:repeat(2,1fr)}
}

/* ---------- 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 ---------- */
#logSheet{position:fixed;z-index:910;top:50%;left:50%;transform:translate(-50%,-50%);
  width:min(440px,calc(100vw - 32px));max-height:min(680px,calc(100dvh - 60px));
  display:flex;flex-direction:column;background:var(--card);
  border:1px solid var(--rule);border-radius:18px;box-shadow:var(--lift-lg);overflow:hidden}
.logwalk{margin:0 0 18px;font-size:15px;font-weight:700;letter-spacing:-.02em;line-height:1.3}
.when{flex:1}
#logDate{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 outing: a labelled list, no frame and no black bar */
.outing{border:0;border-radius:0;margin-bottom:20px}
.outing h3{background:none;color:var(--faint);padding:0 0 7px;
  font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;font-weight:700;
  border-bottom:1px solid var(--ink)}
.outing h3 b{color:var(--ink-2)}
.ostep{padding:10px 0}
.ostep:first-of-type{border-top:0}

/* 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)}

.weeks{display:flex;align-items:flex-end;gap:4px;height:48px;margin-bottom:6px}
.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.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}

/* ---------- match my walk ---------- */
#matchSheet{position:fixed;z-index:910;top:50%;left:50%;transform:translate(-50%,-50%);
  width:min(460px,calc(100vw - 32px));max-height:min(700px,calc(100dvh - 60px));
  display:flex;flex-direction:column;background:var(--card);
  border:1px solid var(--rule);border-radius:18px;box-shadow:var(--lift-lg);overflow:hidden}
.matchnote{margin:8px 0 0;font-size:11.5px;line-height:1.5;color:var(--faint)}
.matchnote.warn{color:var(--maybe)}
#matchSheet .lbl b{float:right;font-weight:700;color:var(--ink);
  text-transform:none;letter-spacing:0;font-size:12.5px}
.mc{flex:1}
@media (max-width:820px){
  #matchSheet{top:auto;bottom:0;left:0;right:0;transform:none;width:auto;
    border-radius:18px 18px 0 0;border-bottom:0;max-height:82dvh}
}

/* 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}
.planline{margin:10px 0 0;font-size:12.5px;line-height:1.5;color:var(--muted);
  font-weight:500}

/* ---------- 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(--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}}

#detail:not([hidden]){animation:riseIn .26s cubic-bezier(.16,1,.3,1)}
#whoSheet:not([hidden]),#matchSheet:not([hidden]),#logSheet:not([hidden]),
#sheet:not([hidden]){animation:riseIn .24s cubic-bezier(.16,1,.3,1)}
#scrim:not([hidden]){animation:fadeIn .2s ease}
#landing:not([hidden]),#tabBody:not([hidden]){animation:riseIn .24s cubic-bezier(.16,1,.3,1)}

@media (max-width:820px){
  #detail:not([hidden]),#whoSheet:not([hidden]),#matchSheet:not([hidden]),
  #logSheet:not([hidden]),#sheet:not([hidden]){
    animation:sheetUp .3s 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,.who,.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,#whoSheet,#matchSheet,#logSheet,#sheet,#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 over pale streets and dark satellite alike. */
.cupmark{display:block;filter:drop-shadow(0 1px 1.5px rgba(0,0,0,.5))
                                drop-shadow(0 0 1px rgba(255,255,255,.9))}

/* 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(--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){
  #whoSheet .grip,#matchSheet .grip,#logSheet .grip,#sheet .grip{
    display:block;width:44px;height:5px;border-radius:5px;background:var(--line);
    margin:9px auto 2px;flex:none;cursor:grab;touch-action:none}
  #whoSheet,#matchSheet,#logSheet,#sheet{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}
.seg.ord.inline{margin-top:12px}

/* Planning reads as a sequence, so the steps are numbered - the order is real
   information here, not decoration: coffee, then parking, then the route. */
.plan-step{position:relative;padding-left:26px}
.plan-step::before{content:attr(data-step);position:absolute;left:0;top:-1px;
  width:18px;height:18px;border-radius:50%;background:var(--ink);color:var(--card);
  font:700 11px/18px JetBrains Mono,monospace;text-align:center}

/* On the way / near the trail, with how many of each. */
.seg.cmode{margin:2px 0 10px}
.cm{flex:1;flex-direction:row !important;gap:6px !important}
.cm em{font-style:normal;font-size:10.5px;font-weight:700;color:var(--faint);
  font-family:JetBrains Mono,monospace}
.cm.on em{color:var(--hot)}
.cm[disabled]{opacity:.45;cursor:not-allowed}
.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. */
.cfilters{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 12px}
.cfilters button{cursor:pointer;background:var(--card);border:1px solid var(--rule);
  border-radius:999px;padding:5px 11px;color:var(--muted);
  font:600 11.5px Gabarito,system-ui,sans-serif;letter-spacing:-.01em;
  transition:background .15s,border-color .15s,color .15s}
.cfilters button:hover{border-color:var(--ink);color:var(--ink)}
.cfilters button.on{background:transparent;border-color:var(--ink);color:var(--ink);
  box-shadow:inset 0 0 0 1px var(--ink)}
.cfilters .csort{margin-left:auto}
.cfilters .csort.on{background:var(--hot);border-color:var(--ink);color:var(--ink)}
/* Sample ratings are visibly provisional - dashed, never solid like a real one. */
.rate.demo{border-style:dashed;border-color:var(--line);color:var(--muted);
  font-variant-numeric:tabular-nums;cursor:help}
/* Needs a starting point, but it is a prompt rather than a dead control. */
.cm.needsloc{opacity:1;border-style:dashed}
.cm.needsloc em{color:var(--coffee);font-family:Gabarito,system-ui,sans-serif;
  font-weight:700;font-size:10px;text-transform:uppercase;letter-spacing:.04em}

/* 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:1px solid var(--rule);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)}
}
.planline.drive{margin-top:4px;font-weight:700;color:var(--ink);
  font-variant-numeric:tabular-nums}
.seg.ord.early{margin:0 0 10px}
/* 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)}
.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}
.plan-step[data-step="0"]::before{content:"0"}

/* 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}

/* 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}

/* ---------- the outing ticket ----------
   Draft A: the plan is a receipt being printed, not a page being scrolled. It
   grows one line per decision and never covers the map. */
#ticket{position:fixed;z-index:770;left:12px;right:12px;
  bottom:calc(var(--tabh) + env(safe-area-inset-bottom) + 10px);
  background:var(--card);border:1px solid var(--rule);border-radius:16px;
  box-shadow:var(--lift-lg);overflow:hidden;
  transition:transform .24s cubic-bezier(.16,1,.3,1)}
.thead{display:flex;align-items:center;gap:11px;width:100%;cursor:pointer;
  background:none;border:0;padding:11px 13px;text-align:left;color:var(--ink);
  border-bottom:2px solid transparent}
#ticket.open .thead{border-bottom-color:var(--ink)}
.tstub{width:30px;height:30px;flex:none;display:grid;place-items:center;
  background:var(--hot);border:1px solid var(--rule);border-radius:9px}
.tstub i{font-size:16px}
.tmain{flex:1;min-width:0}
.tmain em{display:block;font-style:normal;font-size:9.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--faint);font-weight:700}
.tmain b{display:block;font-size:14.5px;font-weight:800;letter-spacing:-.02em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tcaret{font-size:15px;color:var(--muted);transition:transform .2s ease}
#ticket.open .tcaret{transform:rotate(180deg)}

.trows{display:none;padding:4px 13px 12px}
#ticket.open .trows{display:block}
.trow{display:flex;align-items:center;gap:11px;padding:10px 0;
  border-bottom:1px dashed var(--line)}
.trow:last-child{border-bottom:0}
.tnum{width:22px;height:22px;flex:none;display:grid;place-items:center;
  border-radius:50%;border:1px solid var(--rule);color:var(--faint);
  font:700 10px/1 JetBrains Mono,monospace}
.trow.filled .tnum{background:var(--ink);border-color:var(--ink);color:var(--card)}
.tbody{flex:1;min-width:0}
.tbody span{display:block;font-size:9.5px;letter-spacing:.09em;
  text-transform:uppercase;color:var(--faint);font-weight:700}
.tbody b{display:block;font-size:14px;font-weight:700;letter-spacing:-.02em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.trow.empty .tbody b{font-weight:500;color:var(--faint)}
.tadd{flex:none;border:1px dashed var(--rule);background:none;color:var(--muted);
  border-radius:999px;padding:5px 11px;cursor:pointer;
  font:700 11.5px Gabarito,system-ui,sans-serif}
.tadd:hover{border-color:var(--ink);color:var(--ink)}
.tdist{flex:none;font:500 11.5px JetBrains Mono,monospace;color:var(--muted)}
.tfoot{display:flex;gap:8px;margin-top:11px}
.tfoot .btn{flex:1;justify-content:center;margin:0}

@media (min-width:821px){
  #ticket{left:16px;right:auto;width:380px;bottom:16px}
}

/* 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{padding:9px;box-shadow:var(--hard)}
.search{background:transparent;border:1px solid var(--rule)}
.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,
.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{
  background:var(--hot);
  color:var(--ink);
  border-color:var(--ink);
  box-shadow:none;
}
.chipctl.on i,.who.on i,.cm.on em,.tab.on i{color:var(--ink)}
.who.on em{color:var(--ink);opacity:.7}
.seg button.on em,.cfilters 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. */
.rate.prov{background:var(--hot);border-color:var(--ink);color:var(--ink)}
.rate.prov.empty,.rate.prov.ask{
  background:none; border-color:var(--line); color:var(--faint);
}

/* 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}
/* Showing the walks is what the planner is for, so it leads and sits first.
   Surprise me is the same search with the choosing done for you, which makes
   it the second option rather than a separate route in. */
#matchSurprise{flex:1;justify-content:center}
#matchGo{flex:1;justify-content:center}

/* The coffee step had four stacked rows of controls and a header that wrapped.
   One line for when you want it, one for where to look, one for the rest. */
.coffeebar{display:flex;align-items:center;gap:10px;margin:0 0 10px}
.cbl{font-size:10px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--faint);font-weight:700;flex:none}
.seg.ord.tight{margin:0;flex:none;gap:4px}
.seg.ord.tight button{flex:none;min-width:0;padding:6px 14px;font-size:12.5px}
.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}
.cfilters{gap:5px;margin-bottom:10px;flex-wrap:nowrap;overflow-x:auto;
  scrollbar-width:none;padding-bottom:2px;position:relative}
/* Fades the last chip out only while there is more to reach, so the row reads
   as scrollable rather than as a control someone forgot to finish. */
.cfilters.more{
  -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 26px),transparent);
  mask-image:linear-gradient(90deg,#000 calc(100% - 26px),transparent);
}
.cfilters::-webkit-scrollbar{display:none}
.cfilters button{flex:none}
.cfilters .csort{margin-left:4px}
.seg.cmode{margin:0 0 8px}

/* ---------- 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:clamp(120px,26vw,190px);
  object-fit:cover; background:var(--sunk);
}
/* 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(clamp(120px,26vw,190px) - 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)}

/* ---------- go button on the ticket ---------- */
/* The ticket says what the plan is; this acts on it. Sits between the header
   and the rows so it is reachable whether the ticket is open or shut. */
.gobtn{
  display:flex; align-items:center; justify-content:center; gap:7px;
  margin:0 12px 11px; padding:12px 18px; min-height:46px;
  background:var(--ink); color:var(--card); text-decoration:none;
  border-radius:12px;
  font:800 14.5px Gabarito,system-ui,sans-serif; letter-spacing:-.01em;
  transition:transform .15s ease, opacity .15s ease;
}
.gobtn[hidden]{display:none}
.gobtn:active{transform:scale(.985)}
.gobtn i{font-size:17px}
.gobtn:focus-visible{outline:2px solid var(--hot); outline-offset:2px}

/* ---------- 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,#whoBtn,#filterBtn,#resetAll{min-height:44px}
  #collapse,.icon{min-width:44px;min-height:44px}
  .sheetfoot .btn,.btn.solid,.btn.ghost{min-height:46px}
  .cfilters button,.tagpick button,.seg button{min-height:38px}
  /* 9.5px is a design detail on a desktop and unreadable on a phone. */
  .ostep i,.dsum,.ptags,.wslide figcaption,.landnote{font-size:11.5px}
  .lg-who,.dsec h3,.lbl{font-size:11px}
  .outing h3 b,.ostep .od i{font-size:11px}
  .outing h3,.ostep .ok,.stat span,.cbl{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}

/* ---------- the two jobs ---------- */
/* Sticky, so the way back to the other half is always one tap away however far
   down a pane you have read. The band has to be opaque and reach both edges of
   the sheet: a pill with margins let the content scroll through the gaps
   beside it, so headings appeared to run behind the tabs. #detailBody has
   20px of side padding, hence the -20px. */
.dtabs{
  position:sticky; top:-22px; z-index:5;
  display:flex; gap:4px;
  margin:16px -20px 14px; padding:10px 20px 12px;
  background:var(--card);
  border-bottom:1px solid var(--line);
}
.dtab{
  flex:1; min-height:40px; cursor:pointer; border:1px solid var(--rule);
  border-radius:10px; background:var(--sunk); color:var(--ink); opacity:.72;
  font:700 13px Gabarito,system-ui,sans-serif; letter-spacing:-.01em;
  transition:background .18s ease, opacity .18s ease, border-color .18s ease;
}
.dtab:hover{opacity:.9}
/* Gold ground, navy ink - the same selected state as every other control. */
.dtab.on{
  background:var(--hot); border-color:var(--ink); color:var(--ink);
  opacity:1; font-weight:800;
}
.dtab:focus-visible{outline:2px solid var(--hot); outline-offset:-2px}
.dpane[hidden]{display:none}
@media (max-width:820px){ .dtab{min-height:44px; font-size:13.5px} }

/* The ticket sits over the bottom of the sheet at every width, not just on a
   phone - the desktop rule was missing, so the last stat read half-hidden
   behind it. The height comes from the ticket itself, since it changes with
   the plan and grows when opened. */
#detailBody{padding-bottom:calc(var(--ticket-h, 0px) + 26px)}

/* Three places to look for coffee rather than two, so the labels get less
   room - the count drops under the name instead of sitting beside it. */
.seg.cmode.three{display:grid; grid-template-columns:repeat(3,1fr); gap:6px}
.seg.cmode.three .cm{
  display:flex; flex-direction:column; align-items:center; gap:2px;
  padding:8px 6px; min-height:52px; text-align:center; line-height:1.2;
  font-size:12px;
}
.seg.cmode.three .cm em{font-size:11px; font-style:normal; opacity:.7}

/* ---------- the coffee list as a table ---------- */
/* Four columns, the same on every row: how far out of your way, which place,
   what it scores, and whether it is your stop. Rows were laying themselves
   out around the name, so nothing lined up down the list. */
.poi.crow{
  display:grid;
  /* Every row is its own grid, so an auto column resolves to whatever that
     row happens to hold and no two rows agree. Fixed widths make the header
     and the rows line up on the same four columns. */
  grid-template-columns:66px minmax(0,1fr) 128px 30px;
  align-items:center; column-gap:10px; row-gap:2px;
  padding:10px 0; border-bottom:1px solid var(--line);
}
.poi.crow:last-child{border-bottom:0}
.poi.crow .d{
  grid-column:1; font:600 11.5px/1.25 'JetBrains Mono',ui-monospace,monospace;
  color:var(--muted); text-align:left; white-space:nowrap;
}
.poi.crow .cname{grid-column:2; min-width:0; display:block}
.poi.crow .pname{
  display:block; font-weight:700; font-size:14px; letter-spacing:-.01em;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.poi.crow .ptags{
  font-size:11px; color:var(--muted); margin-top:1px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.poi.crow .crate{grid-column:3; display:flex; align-items:center; gap:5px;
  justify-content:flex-start; min-width:0; flex-wrap:nowrap}
.poi.crow .pick{grid-column:4; justify-self:end}
.poi.crow.picked{background:transparent}

/* The header row shares the rows' grid, so a column name sits over the column
   it names and clicking it sets the order. */
.poi.crow.chead{
  padding:2px 0 7px; border-bottom:1px solid var(--rule);
  align-items:end;
}
/* A header that wraps to two lines stops looking like a column heading, so it
   holds one line and tightens instead. */
.crow.chead .th{
  background:none; border:0; padding:0; text-align:left; cursor:pointer;
  font:700 9.5px Gabarito,system-ui,sans-serif; letter-spacing:.06em;
  text-transform:uppercase; color:var(--faint);
  display:inline-flex; align-items:center; gap:3px; min-height:26px;
  white-space:nowrap; overflow:hidden;
}
.crow.chead .th.plain{cursor:default}
.crow.chead .th:not(.plain):hover{color:var(--ink)}
.crow.chead .th.on{color:var(--ink)}
.crow.chead .th:focus-visible{outline:2px solid var(--hot); outline-offset:2px}
/* A caret rather than a word, since the column name is already the label. */
.crow.chead .sar{
  width:5px; height:5px; border-left:1.5px solid currentColor;
  border-bottom:1.5px solid currentColor; transform:rotate(-45deg);
  margin-bottom:2px;
}
@media (max-width:820px){ .crow.chead .th{min-height:32px} }

/* On a narrow screen the fixed columns were eating the names - "Variety
   Coff...". The name is the thing you are choosing between, so it gets the
   room back and the numbers tighten up. */
@media (max-width:420px){
  .poi.crow{grid-template-columns:58px minmax(0,1fr) 120px 28px; column-gap:6px}
  .poi.crow .d{font-size:10.5px}
  .poi.crow .crate .rate{padding:3px 6px; font-size:11px}
}

/* ---------- adding a missing coffee shop ---------- */
.addcafe{
  display:flex; align-items:center; justify-content:center; gap:7px;
  width:100%; margin:10px 0 4px; padding:10px 14px; min-height:44px;
  background:none; border:1px dashed var(--rule); border-radius:11px;
  color:var(--muted); cursor:pointer;
  font:600 12.5px Gabarito,system-ui,sans-serif;
  transition:border-color .15s, color .15s;
}
.addcafe:hover{border-color:var(--ink); color:var(--ink)}
.addcafe i{font-size:15px}
#map.picking{cursor:crosshair}
#toast a{color:var(--hot); text-decoration:underline; text-underline-offset:2px}

/* ---------- 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. */
.cupchoice.quiet{
  transform:scale(.78); transform-origin:left center;
  opacity:.62; box-shadow:none;
}
.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 rating not yet fetched, because fetching it costs a billed call. */
.rate.live.ask{cursor:pointer; border-style:dotted; opacity:.55}
.rate.live.ask:hover{opacity:1; border-color:var(--ink)}

/* 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}

/* Three chips in the rating column - sample, live, Rate - must not spill into
   the tick beside them. */
.poi.crow .crate{overflow:hidden}
.poi.crow .crate .rate{padding:3px 7px; font-size:11.5px}

/* ---------- 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. */
#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}
.obfoot{flex:none;display:flex;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:2px 0 20px}
.obbrand img{width:78px;height:78px;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}
body.previewing #panel,body.previewing #detail,body.previewing #ticket,
body.previewing #chrome,body.previewing #mapctl,body.previewing #legend{
  opacity:0;pointer-events:none;transition:opacity .2s}
.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}
.stepbtns{display:flex;gap:8px}
.stepbtns .btn{flex:1;justify-content:center}
.stepbtns .btn.solid{flex:1.6}
.stepbtns .quiet{flex:0 0 46px}
.previewbtn{display:flex;align-items:center;gap:6px;flex:none;cursor:pointer;
  border:1px solid var(--rule);background:var(--card);color:var(--ink);
  border-radius:11px;padding:8px 11px;font:700 12.5px Gabarito,system-ui,sans-serif}
.previewbtn:hover{background:var(--sunk)}
.previewbtn[hidden]{display:none}
.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}
}
