/* ═══════════════════════════════════════════════════════════════
   PLAKKA — Shared Stylesheet

   File layout (read top to bottom):

     1. TOKENS       design tokens: colours, spacing, radii, shadows, z-indices
                     — edit these to change the look globally
     2. BASE         resets, typography, body defaults
     3. UTILITIES    small atomic classes for layout and typography
                     (.row, .col, .card, .fab, .hidden, .t-muted etc.)
                     — prefer these over inline styles
     4. COMPONENTS   named UI pieces: header, walk panel, share modal,
                     plaque detail modal, map overlays, footer, etc.

   Theme A: Classic Navy (default)
   Theme B: Twilight (dark, copper accents) via [data-theme="twilight"]

   Naming conventions:
     - Utilities are short: .row, .card, .fab, .t-sm
     - Components use BEM-light for hierarchy: .walk-panel__head
     - Legacy class names (wp-*, pdm-*) are kept where JS references them
═══════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════
   1. TOKENS
═══════════════════════════════════════════════════════════════ */

/* Auth guard — hides protected pages until /auth/me has validated.
   Applied to <html> by a script in the <head>, removed by auth-guard.js
   on success, or the page redirects on failure (so class is irrelevant).
   Using visibility (not display) keeps layout stable during the check. */
html.auth-guarded,
html.auth-guarded body {
  visibility: hidden;
}


/* ── THEME A: Classic Navy (default) ── */
:root {
  --bg:            #eef2f7;
  --hdr-bg:        #1b3a6b;
  --hdr-accent:    #1e8fd4;
  --hdr-text:      #ffffff;
  --hdr-input-bg:  rgba(255,255,255,.12);
  --hdr-input-bd:  rgba(255,255,255,.25);
  --hdr-input-fc:  rgba(255,255,255,.6);
  --hdr-btn-bg:    rgba(255,255,255,.12);
  --hdr-btn-hov:   rgba(255,255,255,.22);
  --toggle-bg:     rgba(255,255,255,.12);
  --btn-active-bg: #ffffff;
  --btn-active-fg: #1b3a6b;
  --pill-bg:       rgba(255,255,255,.15);
  --panel-bg:      #ffffff;
  --panel-shadow:  0 6px 32px rgba(0,0,0,.16);
  --panel-bd:      #e8eef5;
  --panel-faint:   #f0f4f8;
  --panel-hover:   #f4f9ff;
  --panel-hl:      #ebf4ff;
  --text-primary:  #1a2a3a;
  --text-secondary:#7a8fa8;
  --text-accent:   #1e8fd4;
  --text-label:    #3a5a80;
  --text-head:     #1b3a6b;
  --toast-bg:      rgba(27,58,107,.92);
  --hint-bg:       rgba(255,255,255,.96);
  --hint-bd:       #dce3ee;
  --grad-blue:     linear-gradient(135deg,#1b3a6b,#1a6ea8);
  --grad-green:    linear-gradient(135deg,#1a6b2a,#27ae60);
  --grad-orange:   linear-gradient(135deg,#c2410c,#f97316);
  --grad-red:      linear-gradient(135deg,#9f1239,#e11d48);
  --red:           #e11d48;
  --red-dark:      #9f1239;
  --red-darkest:   #7f1d1d;
  --theme-icon:    "🌙";
  --theme-label:   "Twilight";
}

/* ── THEME B: Twilight (dark + copper) ── */
[data-theme="twilight"] {
  --bg:            #0f1623;
  --hdr-bg:        #0a0f1a;
  --hdr-accent:    #c17d3c;
  --hdr-text:      #e8d5b7;
  --hdr-input-bg:  rgba(193,125,60,.1);
  --hdr-input-bd:  rgba(193,125,60,.3);
  --hdr-input-fc:  rgba(232,213,183,.7);
  --hdr-btn-bg:    rgba(193,125,60,.12);
  --hdr-btn-hov:   rgba(193,125,60,.22);
  --toggle-bg:     rgba(193,125,60,.1);
  --btn-active-bg: #c17d3c;
  --btn-active-fg: #0f1623;
  --pill-bg:       rgba(193,125,60,.2);
  --panel-bg:      #1a2235;
  --panel-shadow:  0 6px 32px rgba(0,0,0,.5);
  --panel-bd:      #2a3550;
  --panel-faint:   #141d2e;
  --panel-hover:   #1f2d44;
  --panel-hl:      #1a2d44;
  --text-primary:  #e8d5b7;
  --text-secondary:#8a9ab5;
  --text-accent:   #c17d3c;
  --text-label:    #a0b0c8;
  --text-head:     #e8d5b7;
  --toast-bg:      rgba(10,15,26,.95);
  --hint-bg:       rgba(26,34,53,.96);
  --hint-bd:       #2a3550;
  --grad-blue:     linear-gradient(135deg,#1a2a50,#2a4a80);
  --grad-green:    linear-gradient(135deg,#0f3020,#1a6b2a);
  --grad-orange:   linear-gradient(135deg,#6b2a0c,#c17d3c);
  --grad-red:      linear-gradient(135deg,#5f0f25,#9f1239);
  --red:           #e11d48;
  --red-dark:      #9f1239;
  --red-darkest:   #7f1d1d;
  --theme-icon:    "☀";
  --theme-label:   "Classic";
}

/* ── TOKENS: additive scales (theme-independent) ── */
:root {
  /* Spacing scale (based on 4px grid) */
  --space-0:   0;
  --space-1:   4px;
  --space-2:   8px;
  --space-3:   12px;
  --space-4:   16px;
  --space-5:   20px;
  --space-6:   24px;
  --space-8:   32px;
  --space-10:  40px;
  --space-12:  48px;

  /* Radius scale */
  --radius-sm:  6px;
  --radius-md:  10px;
  --radius-lg:  14px;
  --radius-xl:  20px;
  --radius-full: 9999px;

  /* Shadow scale (stacks cleanly with existing --panel-shadow) */
  --shadow-sm:  0 1px 3px rgba(0,0,0,.08);
  --shadow-md:  0 4px 12px rgba(0,0,0,.12);
  --shadow-lg:  0 8px 24px rgba(0,0,0,.18);
  --shadow-fab: 0 3px 12px rgba(0,0,0,.25);

  /* Z-index scale — use these named levels so stacking is predictable */
  --z-map:       400;   /* Leaflet's own layers */
  --z-map-ctrl:  800;   /* FABs, on-map buttons, overlays */
  --z-header:    1000;
  --z-modal:     2000;
  --z-sheet:     2500;  /* plaque detail bottom sheet */
  --z-toast:     3000;

  /* Font size scale */
  --fs-xs:   11px;
  --fs-sm:   12px;
  --fs-base: 14px;
  --fs-md:   15px;
  --fs-lg:   16px;
  --fs-xl:   18px;
  --fs-2xl:  22px;

  /* Common durations */
  --t-fast:   .12s;
  --t-base:   .15s;
  --t-slow:   .3s;

  /* ── Bucket palette ────────────────────────────────────────────
     Display colours for the 9 plaque-scheme buckets, used both in
     the admin Colours tab (chips) and on the map (markers) when
     "Show plaque colours" mode is on.

     Hex values are tuned for legibility on a typical map background
     and to remain distinguishable from each other. Brown vs Red and
     Green vs Blue are the close pairs to watch — the white border
     on every marker compensates by separating each marker from the
     map background, and the popup's text label gives a non-colour
     fallback for users who can't distinguish them.

     If these need tuning later: keep the variable names stable, edit
     the hex values here, and both admin chips and map markers update
     in lockstep.

     Note: --bucket-white is deliberately a very pale grey — pure white
     would disappear against the marker's white border. */
  --bucket-blue:   #1d4ed8;
  --bucket-black:  #1f2937;
  --bucket-green:  #15803d;
  --bucket-red:    #b91c1c;
  --bucket-white:  #f3f4f6;
  --bucket-yellow: #f59e0b;
  --bucket-brown:  #92400e;
  --bucket-grey:   #6b7280;
  --bucket-other:  #9ca3af;
}






/* ═══════════════════════════════════════════════════════════════
   2. BASE
═══════════════════════════════════════════════════════════════ */

*{margin:0;padding:0;box-sizing:border-box}
body{
  font-family:'Segoe UI',system-ui,sans-serif;
  height:100vh;height:100dvh;display:flex;flex-direction:column;
  overflow:hidden;background:var(--bg);
  transition:background .3s, color .3s;
  padding-top:calc(48px + env(safe-area-inset-top));
}

/* ═══════════════════════════════════════════════════════════════
   3. UTILITIES
   Small, atomic classes. Prefer these over inline styles.
═══════════════════════════════════════════════════════════════ */

/* ── Visibility ── */
/* .hidden is used by JS to toggle visibility; the !important wins over
   inline display values. Use classList.add('hidden') / remove('hidden'). */
.hidden { display: none !important; }
.invisible { visibility: hidden; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* ── Layout primitives ── */
/* .row          = horizontal flex with default gap and vertical-centre */
/* .col          = vertical flex, equivalent of stack with custom gap */
/* .cluster      = flex-wrap, useful for tag chips, action button rows */
/* .stack > *+*  = add vertical rhythm between children without margins collapsing */
.row      { display: flex; align-items: center; gap: var(--space-2); }
.row-end  { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-2); }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.col      { display: flex; flex-direction: column; gap: var(--space-2); }
.cluster  { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.stack > * + * { margin-top: var(--space-3); }
.stack-sm > * + * { margin-top: var(--space-2); }
.stack-lg > * + * { margin-top: var(--space-5); }

/* Spacing utilities (single direction, one-off tweaks) */
.mt-1 { margin-top: var(--space-1); } .mt-2 { margin-top: var(--space-2); }
.mt-3 { margin-top: var(--space-3); } .mt-4 { margin-top: var(--space-4); }
.mt-5 { margin-top: var(--space-5); } .mt-6 { margin-top: var(--space-6); }
.mb-1 { margin-bottom: var(--space-1); } .mb-2 { margin-bottom: var(--space-2); }
.mb-3 { margin-bottom: var(--space-3); } .mb-4 { margin-bottom: var(--space-4); }
.mb-5 { margin-bottom: var(--space-5); } .mb-6 { margin-bottom: var(--space-6); }

.flex-1 { flex: 1; }
.flex-shrink-0 { flex-shrink: 0; }
.text-center { text-align: center; }
.text-left   { text-align: left; }

/* ── Cards & surfaces ── */
/* .card = the standard panel that appears on every stats page.
   Replaces the repeated inline:
     background:var(--panel-bg);border-radius:14px;padding:28px;
     margin-bottom:24px;box-shadow:var(--panel-shadow) */
.card {
  background: var(--panel-bg);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  box-shadow: var(--panel-shadow);
}
.card--tight   { padding: var(--space-4); }
.card--center  { text-align: center; }

/* ── Empty state (used by many list pages when there's nothing to show) ── */
.empty-state {
  padding: var(--space-4);
  text-align: center;
  color: var(--text-secondary);
  font-size: var(--fs-base);
}
.empty-state--lg { padding: 40px; }
.empty-state__icon { font-size: 40px; margin-bottom: 12px; }

/* ── Typography ── */
.t-xs    { font-size: var(--fs-xs); }
.t-sm    { font-size: var(--fs-sm); }
.t-base  { font-size: var(--fs-base); }
.t-md    { font-size: var(--fs-md); }
.t-lg    { font-size: var(--fs-lg); }
.t-xl    { font-size: var(--fs-xl); }
.t-2xl   { font-size: var(--fs-2xl); }

.t-muted   { color: var(--text-secondary); }
.t-primary { color: var(--text-primary); }
.t-accent  { color: var(--text-accent); }
.t-head    { color: var(--text-head); }

.t-bold     { font-weight: 700; }
.t-semibold { font-weight: 600; }
.t-black    { font-weight: 900; }

.t-upper   { text-transform: uppercase; letter-spacing: .06em; }

/* ── Buttons (primitives — existing component buttons still work as-is) ── */
.btn-base {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--space-2);
  padding: 10px 14px;
  border: none; border-radius: var(--radius-md);
  font-size: var(--fs-base); font-weight: 700;
  cursor: pointer;
  transition: background var(--t-base), opacity var(--t-base), transform var(--t-fast);
  text-decoration: none;
  user-select: none;
}
.btn-base:active { transform: translateY(1px); }
.btn-primary { background: var(--grad-blue); color: #fff; }
.btn-primary:hover { opacity: .9; }
.btn-ghost   { background: var(--panel-faint); color: var(--text-label); border: 1px solid var(--panel-bd); }
.btn-ghost:hover { background: var(--panel-hover); }
.btn-danger  { background: var(--grad-red); color: #fff; }
.btn-danger:hover { opacity: .9; }

/* ── FAB (floating action button) ──
   Positioned by parent; .map-fab below handles map-specific placement. */
.fab {
  width: 48px; height: 48px;
  border-radius: 50%; border: none;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 22px; color: #fff;
  cursor: pointer;
  box-shadow: var(--shadow-fab);
  transition: background var(--t-base), transform var(--t-fast);
}
.fab:active { transform: translateY(1px); }
.fab--primary { background: var(--text-accent); }
.fab--danger  { background: var(--red); }
.fab--dark    { background: var(--red-darkest); }

/* Map-specific FAB positioning: bottom-right column, stackable.
   Use with the .fab base class. Extra siblings stack upward in 56px steps. */
.map-fab          { position: absolute; right: var(--space-3); z-index: var(--z-map-ctrl); }
.map-fab--b1      { bottom: 72px; }
.map-fab--b2      { bottom: 128px; }
.map-fab--b3      { bottom: 184px; }

/* Bottom-centre variant — for the Record FAB. Overrides .map-fab's right:
   ... with left: 50% + translateX. We re-declare .fab:active's translateY
   here too because the X-centring transform shadows it otherwise.
   bottom: 50px clears the walk-sheet peek (38px) by ~12px when a walk is
   open, and sits comfortably above the bottom of the map-wrap when no
   walk is loaded. z-index above the walk-sheet (1080) so the FAB stays
   tappable. */
.map-fab--bc {
  position: absolute;
  right: auto;
  left: 50%;
  bottom: 50px;
  transform: translateX(-50%);
  z-index: 1100;
}
.map-fab--bc:active { transform: translate(-50%, 1px); }

/* ── RECORD FAB ──
   Red filled circle with a white inner shape.
   .is-recording switches the inner shape from dot to square and adds a
   pulsing ring to telegraph "actively recording" status. */
.record-fab {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  border: 3px solid #fff;
  background: #dc2626;
  cursor: pointer;
  box-shadow: 0 3px 12px rgba(220,38,38,.45);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}
.record-fab__dot {
  width: 22px;
  height: 22px;
  background: #fff;
  border-radius: 50%;
  display: block;
  transition: border-radius var(--t-base), width var(--t-base), height var(--t-base);
}
.record-fab.is-recording .record-fab__dot {
  width: 16px;
  height: 16px;
  border-radius: 3px;
}
.record-fab.is-recording {
  /* Pulsing red ring around the button while recording. */
  animation: record-pulse 1.6s ease-out infinite;
}
@keyframes record-pulse {
  0%   { box-shadow: 0 3px 12px rgba(220,38,38,.45),
                     0 0 0 0 rgba(220,38,38,.5); }
  70%  { box-shadow: 0 3px 12px rgba(220,38,38,.45),
                     0 0 0 14px rgba(220,38,38,0); }
  100% { box-shadow: 0 3px 12px rgba(220,38,38,.45),
                     0 0 0 0 rgba(220,38,38,0); }
}

/* ── LIVE RECORDING STATS BADGE ──
   Bottom-centred pill, just above the Record FAB. Shown only while
   recording; JS toggles display between 'none' and 'inline-flex'. */
.record-stats {
  position: absolute;
  bottom: 92px;                 /* pill controls bottom 24px + height ~50px + 18px gap */
  left: 50%;
  transform: translateX(-50%);
  z-index: var(--z-map-ctrl);
  /* Switched from inline-flex to flex-column 2026-05-19 (session 7) so
     the paused-strip can stack on top of the metrics row. Inline-flex
     was fine when the badge was a single row, but with the optional
     amber header strip we need vertical stacking. */
  display: flex;
  flex-direction: column;
  background: rgba(255,255,255,0.96);
  border: 0.5px solid var(--color-border-tertiary, rgba(0,0,0,.12));
  border-radius: 14px;
  box-shadow: 0 2px 8px rgba(0,0,0,.12);
  font-size: 11px;
  color: var(--text-primary, #111);
  line-height: 1.2;
  white-space: nowrap;
  pointer-events: none;          /* never blocks taps on the map */
  overflow: hidden;              /* clip the paused-strip's rounded corners */
}
/* Amber "Paused" header strip — added 2026-05-19 (session 7). Sits
   above the metrics row when the recording is paused; hidden during
   active recording. Same visual language as Strava and Garmin Connect:
   amber/yellow conveys "still in progress but not capturing". */
.record-stats__paused-strip {
  background: #f59e0b;
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-align: center;
  padding: 3px 12px;
  text-transform: uppercase;
}
.record-stats__row {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 6px 12px;
}
.record-stats__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #dc2626;
  flex-shrink: 0;
  animation: record-pulse-dot 1.6s ease-out infinite;
}
/* When the badge is in paused state, freeze the pulse — the amber
   strip already conveys "not actively capturing", so the dot becoming
   solid (and slightly desaturated) reinforces the same message. */
.record-stats.is-paused .record-stats__dot {
  animation: none;
  background: #94a3b8;
}
@keyframes record-pulse-dot {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.45; }
}
.record-stats__metric {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
}
.record-stats__k {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.5px;
  color: var(--text-secondary, #666);
}
.record-stats__v {
  font-size: 12px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;  /* avoid widths shifting as digits change */
  color: var(--text-primary, #111);
}

/* ── Record controls — pause / resume / finish (2026-05-19, session 7)
   Replaced the round Record FAB. Container is bottom-centre; pills
   inside lay out horizontally with a gap when more than one is
   visible (the paused state shows Resume + Finish side-by-side).
   The container is hidden when recorder is idle — start a recording
   from the kebab "Record a walk" menu item, not from these. */
.record-controls {
  position: absolute;
  bottom: 110px;  /* clears walk-sheet peek (38px) with ~72px margin */
  left: 50%;
  transform: translateX(-50%);
  z-index: 1100;  /* above walk-sheet (1080) so pills stay tappable */
  display: flex;
  flex-direction: row;
  gap: 10px;
  /* No background — pills carry their own. */
}
.record-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 22px;
  border: none;
  border-radius: 999px;
  font-size: 15px;
  font-weight: 700;
  color: #fff;
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(0,0,0,.22);
  -webkit-tap-highlight-color: transparent;
  min-width: 130px;
  justify-content: center;
  transition: transform .08s, box-shadow .15s, background .15s;
}
.record-pill:active { transform: scale(.97); }
.record-pill svg { flex-shrink: 0; }
.record-pill--pause  { background: #f59e0b; }   /* amber — traffic-light "slow/caution": matches the paused stats strip */
.record-pill--pause:hover  { background: #d97706; }
.record-pill--resume { background: #16a34a; }   /* green — traffic-light "go": resume the recording */
.record-pill--resume:hover { background: #15803d; }
.record-pill--finish { background: #1f2937; }   /* near-black — destructive */
.record-pill--finish:hover { background: #111827; }

/* ═══════════════════════════════════════════════════════════════
   4. COMPONENTS
   Named UI pieces. Legacy class names (wp-*, pdm-*, etc.) are kept
   because JS references them. New components should use BEM-light
   naming: .block, .block__element, .block--modifier.
═══════════════════════════════════════════════════════════════ */

/* ── THEME TOGGLE BUTTON ── */
#btn-theme{
  padding:0;width:32px;height:32px;border:none;
  background:var(--hdr-btn-bg);border-radius:50%;
  color:var(--hdr-text);font-size:15px;cursor:pointer;
  flex-shrink:0;display:flex;align-items:center;justify-content:center;
  transition:background .15s;
  align-self:center;margin-left:8px;margin-right:10px;
}
#btn-theme:hover{background:var(--hdr-btn-hov)}

/* ── COMPACT HEADER ── */
header{
  background:var(--hdr-bg);color:var(--hdr-text);
  padding:env(safe-area-inset-top) 0 0;height:calc(48px + env(safe-area-inset-top));
  display:flex;align-items:stretch;gap:0;
  flex-shrink:0;z-index:1100;
  box-shadow:0 2px 10px rgba(0,0,0,.28);
  transition:background .3s;
  overflow:hidden;
  position:fixed;top:0;left:0;right:0;
}
/* .sw (search wrap) is now a fixed-position floating card defined inline
   in index.html (top-level body child, not header). The old inline-header
   styles that lived here have been removed — they were forcing a 220px
   width which clipped the new full-width search box. */
.mode-toggle{
  display:flex;background:var(--toggle-bg);
  border-radius:7px;padding:2px;gap:2px;flex-shrink:0;
  align-self:center;margin-left:10px;
}
.mode-btn{
  padding:4px 8px;border:none;border-radius:5px;
  font-size:11px;font-weight:700;cursor:pointer;
  color:rgba(255,255,255,.4);background:transparent;
  display:flex;align-items:center;gap:4px;
  text-decoration:line-through;text-decoration-color:rgba(255,255,255,.25);
  min-height:32px;transition:all .15s;
}
.mode-btn.active{
  background:var(--btn-active-bg);color:var(--btn-active-fg);
  text-decoration:none;box-shadow:0 1px 4px rgba(0,0,0,.18);
}
.dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
.dot-b{background:#1e8fd4}.dot-g{background:#27ae60}
.btn-reset-hdr{
  padding:0;width:32px;height:32px;border:none;
  background:var(--hdr-btn-bg);border-radius:50%;
  color:var(--hdr-text);font-size:17px;font-weight:700;cursor:pointer;
  flex-shrink:0;display:flex;align-items:center;justify-content:center;
  align-self:center;margin-left:auto;
  border:1.5px solid rgba(255,255,255,.25);
  transition:background .15s, transform .15s;
}
.btn-reset-hdr:hover{background:var(--hdr-btn-hov); transform:rotate(-30deg);}

/* ── MAP ── */
.map-wrap{flex:1;position:relative;overflow:hidden}
#map{width:100%;height:100%}

/* ── WALK PANEL ── */
#walk-panel{
  position:absolute;top:12px;right:12px;width:310px;
  background:var(--panel-bg);border-radius:12px;
  box-shadow:var(--panel-shadow);z-index:900;
  display:none;flex-direction:column;max-height:calc(100% - 24px);overflow:hidden;
  transition:background .3s;
}
#walk-panel.open{display:flex}
.wp-head{
  color:#fff;padding:13px 40px 11px 13px;
  border-radius:12px 12px 0 0;flex-shrink:0;position:relative;
}
.wp-head.th-blue{background:var(--grad-blue)}
.wp-head.th-green{background:var(--grad-green)}
.wp-head.th-orange{background:var(--grad-orange)}
.wp-r1{display:flex;align-items:center;gap:8px;margin-bottom:7px}
.wp-icon{font-size:20px}
.wp-head h2{font-size:13px;font-weight:700;line-height:1.3;flex:1}
.wp-x{
  position:absolute;top:9px;right:9px;background:rgba(255,255,255,.18);
  border:none;color:#fff;width:24px;height:24px;border-radius:50%;
  cursor:pointer;font-size:12px;display:flex;align-items:center;justify-content:center;
}
.wp-x:hover{background:rgba(255,255,255,.3)}
.wp-stats{display:grid;grid-template-columns:1fr 1fr 1fr;gap:4px;margin-bottom:7px}
.wp-stat{background:rgba(255,255,255,.14);border-radius:5px;padding:6px 4px;text-align:center}
.wp-stat-n{font-size:16px;font-weight:800;display:block;line-height:1}
.wp-stat-l{font-size:9px;opacity:.7;letter-spacing:.05em;text-transform:uppercase;margin-top:2px;display:block}
#route-status{font-size:10px;font-weight:600;display:flex;align-items:center;gap:4px;opacity:.85}
#rsdot{width:6px;height:6px;border-radius:50%;background:rgba(255,255,255,.4);flex-shrink:0}
#btn-stops-toggle{
  display:none;width:100%;padding:8px 12px;
  background:var(--panel-faint);border:none;
  border-top:1px solid var(--panel-bd);border-bottom:1px solid var(--panel-bd);
  font-size:12px;font-weight:600;color:var(--text-label);cursor:pointer;text-align:center;
}
.stop-list{overflow-y:auto;flex:1}
.stop-item{
  display:flex;align-items:flex-start;gap:9px;padding:9px 12px;
  border-bottom:1px solid var(--panel-faint);cursor:pointer;transition:background .1s;
}
.stop-item:last-child{border-bottom:none}
.stop-item:hover{background:var(--panel-hover)}
.stop-item.hl{background:var(--panel-hl)}
.snum{
  width:24px;height:24px;border-radius:50%;color:#fff;font-size:10px;font-weight:700;
  display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:1px;
}
.sbody{flex:1;min-width:0}
.stitle{font-size:12px;font-weight:600;color:var(--text-primary);line-height:1.3;margin-bottom:1px}
.ssub{font-size:11px;color:var(--text-secondary);line-height:1.4}
.sdist{font-size:10px;font-weight:600;margin-top:2px;color:var(--text-accent)}
.stag{font-size:10px;color:#e67e22;font-weight:600}
.wp-foot{
  padding:9px 12px;border-top:1px solid var(--panel-bd);
  display:flex;gap:7px;flex-shrink:0;
}
.wp-foot .btn{flex:1;font-size:11px}
.btn{
  padding:6px 12px;border:none;border-radius:6px;
  font-size:12px;font-weight:600;cursor:pointer;white-space:nowrap;transition:all .15s;
}
.btn-grey{
  background:var(--panel-faint);color:var(--text-label);
  border:1px solid var(--panel-bd);
}
.btn-grey:hover{background:var(--panel-hover)}

/* ── SPINNER ── */
#wp-spin{
  position:absolute;inset:0;background:rgba(255,255,255,.92);
  z-index:50;border-radius:12px;display:none;flex-direction:column;
  align-items:center;justify-content:center;gap:8px;
}
[data-theme="twilight"] #wp-spin{background:rgba(15,22,35,.92)}
#wp-spin.on{display:flex}
#wp-spin p{font-size:12px;color:var(--text-secondary);font-weight:600}
.spin{border-radius:50%;animation:spin .8s linear infinite}
.spin-sm{width:26px;height:26px;border:3px solid var(--panel-bd);border-top-color:var(--text-accent)}
@keyframes spin{to{transform:rotate(360deg)}}

/* ── SHARE MODAL ── */
#share-modal{
  display:none;position:absolute;inset:0;
  background:rgba(0,0,0,.5);z-index:1200;align-items:flex-end;justify-content:center;
}
#share-modal.on{display:flex}
.share-sheet{
  background:var(--panel-bg);border-radius:20px 20px 0 0;
  padding:20px 20px max(20px,env(safe-area-inset-bottom)) 20px;
  width:100%;max-width:480px;
}
.share-sheet-handle{width:40px;height:4px;background:var(--panel-bd);border-radius:2px;margin:0 auto 16px}
.share-sheet h3{font-size:15px;font-weight:700;color:var(--text-head);margin-bottom:4px}
.share-sheet p{font-size:12px;color:var(--text-secondary);margin-bottom:14px}
.share-big-btns{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:14px}
.share-big-btn{
  display:flex;align-items:center;justify-content:center;gap:8px;
  padding:13px;border:none;border-radius:10px;font-size:14px;font-weight:700;cursor:pointer;
}
.share-row{display:flex;gap:7px}
.share-row input{
  flex:1;padding:8px 10px;border:1px solid var(--panel-bd);border-radius:7px;
  font-size:12px;font-family:monospace;color:var(--text-head);
  background:var(--panel-faint);outline:none;
}
#share-stops{
  font-size:11px;color:var(--text-secondary);margin-top:10px;
  padding-top:10px;border-top:1px solid var(--panel-faint);
}
.share-close{
  display:block;width:100%;margin-top:12px;padding:12px;
  background:var(--panel-faint);border:none;border-radius:10px;
  font-size:14px;font-weight:600;color:var(--text-label);cursor:pointer;
}

/* ── MAP OVERLAYS ── */
#pr-banner{
  position:absolute;top:10px;left:50%;transform:translateX(-50%);
  background:rgba(27,58,107,.88);color:#fff;font-size:12px;
  padding:6px 14px;border-radius:20px;z-index:800;pointer-events:none;
}
[data-theme="twilight"] #pr-banner{background:rgba(10,15,26,.9);color:var(--hdr-text)}
#toast{
  position:absolute;bottom:28px;left:50%;transform:translateX(-50%);
  background:var(--toast-bg);color:#fff;font-size:12px;
  padding:7px 16px;border-radius:20px;z-index:800;pointer-events:none;
  opacity:0;transition:opacity .3s;white-space:nowrap;
}
#toast.on{opacity:1}

/* ── LEGEND ── */
#btn-legend{
  position:absolute;top:10px;right:10px;z-index:710;
  background:var(--panel-bg);border:1px solid var(--panel-bd);
  border-radius:20px;padding:6px 12px;font-size:12px;font-weight:600;
  color:var(--text-label);cursor:pointer;box-shadow:0 2px 8px rgba(0,0,0,.12);
}
.legend{
  position:absolute;top:52px;right:10px;background:var(--panel-bg);
  border-radius:8px;padding:9px 12px;box-shadow:0 2px 10px rgba(0,0,0,.12);
  z-index:700;font-size:11px;color:var(--text-label);display:none;
}
.legend strong{
  display:block;margin-bottom:5px;font-size:10px;
  text-transform:uppercase;letter-spacing:.07em;color:var(--text-head);
}
.lr{display:flex;align-items:center;gap:7px;margin-bottom:3px}
.lr:last-child{margin-bottom:0}
.ld{width:12px;height:12px;border-radius:50%;flex-shrink:0}

/* ── POPUP ── */
.wk-popup{font-size:13px;line-height:1.5;max-width:260px}
.wk-popup img{width:100%;max-height:140px;object-fit:cover;border-radius:5px;display:block;margin-bottom:6px}

/* ── CUSTOM LOCATIONS ── */
.dot-c{background:#e11d48}
.wp-head.th-red{background:var(--grad-red)}
#btn-add-loc:hover{opacity:.88}
#btn-add-loc.active{background:var(--red-dark)!important;box-shadow:0 0 0 5px rgba(225,29,72,.3)!important}
#btn-del-loc:hover{opacity:.88}
#btn-del-loc.active{background:var(--red-darkest)!important;box-shadow:0 0 0 5px rgba(127,29,29,.35)!important}
#map.add-mode{cursor:crosshair!important}
#map.del-mode{cursor:not-allowed!important}
#loc-modal{
  display:none;position:absolute;inset:0;background:rgba(0,0,0,.5);
  z-index:1200;align-items:flex-end;justify-content:center;
}
#loc-modal.on{display:flex!important}
@media(min-width:601px){
  #loc-modal{align-items:center;justify-content:center}
  #loc-modal>div{border-radius:16px;max-width:420px}
}

/* ── NAV LINK ── */
#btn-leaderboard{
  padding:0;width:32px;height:32px;border:none;
  background:var(--hdr-btn-bg);border-radius:50%;
  color:var(--hdr-text);font-size:15px;cursor:pointer;
  flex-shrink:0;display:flex;align-items:center;justify-content:center;
  text-decoration:none;transition:background .15s;
}
#btn-leaderboard:hover{background:var(--hdr-btn-hov)}

/* ── MOBILE ── */
@media(max-width:600px){
  header{padding:env(safe-area-inset-top) 8px 0;height:calc(48px + env(safe-area-inset-top));gap:6px}
  .mode-btn{padding:3px 6px}
  #btn-add-loc{right:12px;width:52px;height:52px;font-size:24px}
  #walk-panel{
    width:100%!important;right:0!important;bottom:0;top:auto!important;
    border-radius:16px 16px 0 0;max-height:80vh;
  }
  #walk-panel.open{display:flex}
  .wp-head{border-radius:16px 16px 0 0;padding:12px 40px 10px 12px}
  .wp-foot{padding:10px;padding-bottom:max(10px,env(safe-area-inset-bottom))}
  .wp-foot .btn{padding:10px 8px;font-size:12px}
  .stop-item{padding:10px 12px}
  #toast{bottom:16px;font-size:11px}
  #pr-banner{font-size:11px}
  #btn-legend{bottom:auto;top:10px;right:10px;left:auto}
  .legend{bottom:auto;top:52px;right:10px;left:auto}
}
@media(min-width:601px){
  #walk-panel{width:310px;right:12px;top:12px;border-radius:12px;max-height:calc(100% - 24px)}
  #share-modal{align-items:center;justify-content:center}
  .share-sheet{border-radius:16px;max-width:420px;padding:24px}
  .share-sheet-handle{display:none}
}


/* ── SITE NAV ── */
.site-nav {
  display: flex; align-items: center;
  flex-shrink: 0; gap: 0; height: 48px;
}

/* ── Hamburger menu button ───────────────────────────────── */
.ph-menu-wrap {
  position: relative;
  flex-shrink: 0;
  margin-right: 4px;
}

.ph-menu-btn {
  display: flex; align-items: center; justify-content: center;
  width: 40px; height: 40px;
  background: var(--hdr-btn-bg);
  border: 1.5px solid rgba(255,255,255,.2);
  border-radius: 8px;
  color: #fff;
  cursor: pointer;
  font-size: 18px;
  transition: background .15s;
  flex-shrink: 0;
}
.ph-menu-btn:hover { background: var(--hdr-btn-hov); }

/* Dropdown panel */
.ph-menu-dropdown {
  display: none;
  position: fixed;
  top: 52px;
  left: 8px;
  background: var(--hdr-bg);
  border: 1px solid rgba(255,255,255,.15);
  border-radius: 10px;
  box-shadow: 0 8px 32px rgba(0,0,0,.35);
  z-index: 1200;
  min-width: 180px;
  overflow: hidden;
  padding: 6px 0;
}
.ph-menu-dropdown.open { display: block; }

.ph-menu-item {
  display: flex; align-items: center;
  padding: 12px 18px;
  font-size: 14px; font-weight: 700;
  color: rgba(255,255,255,.8);
  text-decoration: none;
  gap: 10px;
  transition: background .12s, color .12s;
  white-space: nowrap;
}
.ph-menu-item:hover { background: rgba(255,255,255,.1); color: #fff; }
.ph-menu-item.active {
  color: #fff;
  background: rgba(255,255,255,.12);
  border-left: 3px solid var(--hdr-accent);
  padding-left: 15px;
}

/* Sign in link in nav */
.nav-link.nav-signin {
  display: flex; align-items: center;
  height: 36px; padding: 0 14px;
  font-size: 13px; font-weight: 700;
  color: rgba(255,255,255,.85);
  text-decoration: none;
  background: var(--hdr-btn-bg);
  border: 1.5px solid rgba(255,255,255,.2);
  border-radius: 8px;
  transition: background .15s;
  white-space: nowrap;
  margin-right: 4px;
}
.nav-link.nav-signin:hover { background: var(--hdr-btn-hov); color: #fff; }

/* ── LEADERBOARD PAGE SHARED STYLES ── */
.lb-page{
  min-height:100vh;background:var(--bg);
  font-family:'Segoe UI',system-ui,sans-serif;
  display:flex;flex-direction:column;
  transition:background .3s;
}
.lb-header{
  background:var(--hdr-bg);color:var(--hdr-text);
  padding:0;height:48px;display:flex;align-items:stretch;
  box-shadow:0 2px 10px rgba(0,0,0,.28);flex-shrink:0;overflow:hidden;
}
/* .lb-header a removed — nav links must not get width:32px */
.lb-body{flex:1;padding:20px 16px;max-width:900px;margin:0 auto;width:100%}
.lb-grid{display:grid;grid-template-columns:1fr 1fr;gap:20px}
@media(max-width:640px){.lb-grid{grid-template-columns:1fr}}
.lb-card{
  background:var(--panel-bg);border-radius:12px;
  box-shadow:var(--panel-shadow);overflow:hidden;
  transition:background .3s;
}
.lb-card-head{
  padding:14px 16px 12px;border-bottom:1px solid var(--panel-bd);
  display:flex;align-items:center;gap:10px;
}
.lb-card-icon{font-size:22px}
.lb-card-title{font-size:14px;font-weight:700;color:var(--text-head)}
.lb-card-sub{font-size:11px;color:var(--text-secondary);margin-top:1px}
.lb-row{
  display:flex;align-items:center;gap:10px;
  padding:10px 16px;border-bottom:1px solid var(--panel-faint);
  transition:background .1s;
}
.lb-row:last-child{border-bottom:none}
.lb-row:hover{background:var(--panel-hover)}
.lb-rank{
  width:28px;height:28px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  font-size:11px;font-weight:800;flex-shrink:0;
}
.lb-rank-1{background:linear-gradient(135deg,#f59e0b,#fbbf24);color:#fff}
.lb-rank-2{background:linear-gradient(135deg,#94a3b8,#cbd5e1);color:#fff}
.lb-rank-3{background:linear-gradient(135deg,#b45309,#d97706);color:#fff}
.lb-rank-n{background:var(--panel-faint);color:var(--text-secondary)}
.lb-info{flex:1;min-width:0}
.lb-name{font-size:13px;font-weight:600;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lb-detail{font-size:11px;color:var(--text-secondary);margin-top:1px}
.lb-bar-wrap{width:90px;flex-shrink:0}
.lb-bar-bg{height:6px;background:var(--panel-faint);border-radius:3px;overflow:hidden}
.lb-bar-fill{height:100%;border-radius:3px;transition:width .6s ease}
.lb-score{font-size:13px;font-weight:700;color:var(--text-accent);width:36px;text-align:right;flex-shrink:0}
.lb-badge{
  font-size:10px;font-weight:700;padding:2px 7px;border-radius:10px;
  background:rgba(30,143,212,.15);color:var(--text-accent);flex-shrink:0;
}

/* ═══════════════════════════════════════════════════════
   ORIENTATION-AWARE STYLES
   Phones in landscape: header shrinks, panels adjust
   Phones in portrait: full-height map, bottom sheet walks
═══════════════════════════════════════════════════════ */

/* Portrait phone — optimise vertical space */
@media (max-width: 600px) and (orientation: portrait) {
  header {
    height: calc(44px + env(safe-area-inset-top));
    padding-top: env(safe-area-inset-top);
  }
  .site-nav .site-name {
    font-size: 14px;
    padding-right: 10px;
  }
  /* nav links are now in dropdown — no horizontal size override needed */
  /* .sw width override removed — search bar is now a full-width floating card */
  .mode-btn span:last-child { display: none; } /* hide label text, keep dot */
  #walk-panel {
    width: 100% !important; right: 0 !important;
    bottom: 0; top: auto !important;
    border-radius: 16px 16px 0 0;
    max-height: 55vh;
  }
  #btn-add-loc { width: 50px; height: 50px; }
  #btn-del-loc { width: 50px; height: 50px; }
}

/* Landscape phone — header must be compact, map needs all vertical space */
@media (max-height: 500px) and (orientation: landscape) {
  header {
    height: calc(38px + env(safe-area-inset-top));
    padding-top: env(safe-area-inset-top);
  }
  .site-nav { height: 38px; }
  .site-nav .site-name {
    font-size: 13px; padding-right: 8px; height: 38px;
  }
  .site-nav a.nav-link {
    height: 38px; padding: 0 10px; font-size: 11px;
  }
  .mode-btn { padding: 2px 5px; font-size: 10px; min-height: 26px; }
  .mode-btn span:last-child { display: none; } /* hide text, keep dot */
  /* Walk panel becomes a narrow side panel in landscape */
  #walk-panel {
    width: 260px !important;
    top: 6px !important; right: 6px !important;
    bottom: auto; border-radius: 10px !important;
    max-height: calc(100vh - 50px) !important;
  }
  #btn-add-loc { width: 40px; height: 40px; font-size: 18px; }
  #btn-del-loc { width: 40px; height: 40px; font-size: 16px; }
  #btn-capture { width: 40px; height: 40px; font-size: 16px; }
  #toast { bottom: 10px; font-size: 10px; }
  .wp-head { padding: 8px 36px 8px 10px; }
  .wp-stat-n { font-size: 14px; }
  .stop-item { padding: 6px 10px; }
  .stitle { font-size: 11px; }
  .ssub { font-size: 10px; }
}

/* Landscape phone — leaderboard page needs scrollable body */
@media (max-height: 500px) and (orientation: landscape) {
  .lb-header { height: 38px; }
  .lb-header .site-nav { height: 38px; }
  .lb-header .site-nav .site-name { height: 38px; font-size: 13px; }
  .lb-header .site-nav a.nav-link { height: 38px; font-size: 11px; padding: 0 10px; }
  .lb-body { padding: 10px 12px 24px; }
}

/* JS adds .is-landscape / .is-portrait to <html> for JS-driven layout tweaks */
html.is-landscape .landscape-hide { display: none !important; }
html.is-portrait  .portrait-hide  { display: none !important; }

/* ── CAPTURE MODE ── */
#btn-capture {
  position:absolute;top:calc(50% - 84px);right:12px;z-index:800;
  width:48px;height:48px;border-radius:50%;border:none;
  background:#0ea5e9;color:#fff;font-size:20px;cursor:pointer;
  box-shadow:0 3px 12px rgba(14,165,233,.45);
  display:flex;align-items:center;justify-content:center;
  transition:background .15s,box-shadow .15s;
}
#btn-capture:hover{opacity:.88}
#btn-capture.active{
  background:#0284c7!important;
  box-shadow:0 0 0 5px rgba(14,165,233,.35)!important;
  animation:capture-pulse 1.5s infinite;
}
#btn-capture.gps-searching{
  background:#f59e0b!important;
  box-shadow:0 0 0 5px rgba(245,158,11,.3)!important;
}
@keyframes capture-pulse{
  0%,100%{box-shadow:0 0 0 5px rgba(14,165,233,.35)}
  50%{box-shadow:0 0 0 10px rgba(14,165,233,.1)}
}
.user-location-dot{
  width:16px;height:16px;background:#0ea5e9;
  border:3px solid #fff;border-radius:50%;
  box-shadow:0 0 0 3px rgba(14,165,233,.4),0 2px 6px rgba(0,0,0,.3);
  animation:loc-pulse 2s infinite;
}
@keyframes loc-pulse{
  0%,100%{box-shadow:0 0 0 3px rgba(14,165,233,.4),0 2px 6px rgba(0,0,0,.3)}
  50%{box-shadow:0 0 0 8px rgba(14,165,233,.1),0 2px 6px rgba(0,0,0,.3)}
}
#toast.toast-success{background:rgba(21,128,61,.95)!important}
#toast.toast-fail{background:rgba(185,28,28,.95)!important}
#captured-badge{
  position:absolute;top:calc(50% - 130px);right:8px;z-index:801;
  background:#22c55e;color:#fff;font-size:9px;font-weight:800;
  border-radius:10px;padding:2px 5px;min-width:18px;text-align:center;
  display:none;box-shadow:0 1px 4px rgba(0,0,0,.3);
}
@media(max-height:500px) and (orientation:landscape){
  #btn-capture{top:calc(50% - 66px);right:10px;width:40px;height:40px;font-size:16px}
  #captured-badge{top:calc(50% - 110px);right:6px}
}

/* ── SITE FOOTER ─────────────────────────────────────────────── */
.site-footer {
  background: var(--hdr-bg);
  color: rgba(255,255,255,.7);
  margin-top: auto;
  flex-shrink: 0;
}
.sf-inner {
  max-width: 1100px;
  margin: 0 auto;
  padding: 24px 20px 20px;
}
.sf-links {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 20px;
  margin-bottom: 16px;
  padding-bottom: 16px;
  border-bottom: 1px solid rgba(255,255,255,.15);
}
.sf-links a {
  color: rgba(255,255,255,.75);
  text-decoration: none;
  font-size: 12px;
  font-weight: 600;
  transition: color .15s;
}
.sf-links a:hover { color: #fff; }
.sf-copy p {
  font-size: 12px;
  margin-bottom: 4px;
  color: rgba(255,255,255,.6);
}
.sf-copy p:first-child { font-weight: 700; color: rgba(255,255,255,.85); }
.sf-legal { font-size: 11px !important; color: rgba(255,255,255,.45) !important; line-height: 1.6; }

/* Pages that scroll need flex column body */
body.page-scroll {
  height: auto;
  min-height: 100vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}

/* Plaque action popup - Leaflet popup override */
.leaflet-popup-content-wrapper {
  padding: 0 !important;
  border-radius: 12px !important;
  overflow: hidden;
  box-shadow: 0 8px 32px rgba(0,0,0,.25) !important;
  min-width: 240px;
  max-width: 300px;
}
.leaflet-popup-content {
  margin: 0 !important;
  width: auto !important;
}
.leaflet-popup-tip-container { margin-top: -1px; }
.plaque-popup-inner {
  font-family: 'Segoe UI', system-ui, sans-serif;
}
.plaque-popup-head {
  background: var(--grad-blue);
  color: #fff;
  padding: 12px 14px 10px;
  /* Reserve room on the right for the close button so a long plaque name
     can't run under it. The button is 30px wide + 8px right inset. */
  padding-right: 48px;
}
.plaque-popup-name {
  font-size: 14px;
  font-weight: 800;
  line-height: 1.25;
  margin-bottom: 6px;
  /* Long plaque names — wrap rather than overflow. Most names fit on
     two lines comfortably; very long ones (e.g. "The Royal Society for
     the Prevention of Cruelty to Animals") wrap to three. */
  word-wrap: break-word;
  overflow-wrap: break-word;
  hyphens: auto;
}
/* Tags row — sits below the name, holds the optional Category pill.
   (The Stop pill was replaced by a progress-ring badge — see below.) */
.plaque-popup-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}
.plaque-popup-category {
  display: inline-block;
  font-size: 10px;
  font-weight: 700;
  padding: 3px 9px;
  border-radius: 999px;
  letter-spacing: .04em;
  text-transform: uppercase;
  line-height: 1.4;
  white-space: nowrap;
  background: rgba(255,255,255,.18);
  color: #fff;
}

/* Header — flex-row variant when a stop ring is present. The ring sits
   to the right of the name+category column; the column shrinks to make
   room. Right-padding reserves space so the ring doesn't slide under
   the Leaflet × close button (which is absolutely positioned at the
   popup's top-right corner). */
.plaque-popup-head--with-ring {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-right: 44px;
}
.plaque-popup-head--with-ring .plaque-popup-head-text {
  flex: 1;
  min-width: 0;            /* allow truncation, prevent overflow */
}
.plaque-popup-head--with-ring .plaque-popup-name {
  /* Long names are truncated server-side at 60 chars but also need to
     wrap in the column rather than overflow. */
  word-wrap: break-word;
  overflow-wrap: break-word;
}

/* Stop progress ring — amber arc fills proportional to stopNum/total.
   54×54 SVG, ring stroke 4px, white centre stack with STOP / num / of N.
   Tooltip on the wrapper carries the full "Stop N of M — WalkName". */
.plaque-popup-stopring {
  flex-shrink: 0;
  width: 54px;
  height: 54px;
  position: relative;
  cursor: help;            /* hint there's a tooltip */
}
.plaque-popup-stopring svg {
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);   /* arc starts at 12 o'clock */
}
.plaque-popup-stopring .ring-bg {
  fill: none;
  stroke: rgba(255,255,255,.18);
  stroke-width: 4;
}
.plaque-popup-stopring .ring-prog {
  fill: none;
  stroke: #f59e0b;             /* amber-500 */
  stroke-width: 4;
  stroke-linecap: round;
}
.plaque-popup-stopring .ring-num {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-weight: 800;
  line-height: 1;
}
.plaque-popup-stopring .ring-lbl {
  font-size: 8px;
  opacity: .8;
  letter-spacing: .1em;
  margin-bottom: 1px;
}
.plaque-popup-stopring .ring-val {
  font-size: 17px;
}
.plaque-popup-stopring .ring-total {
  font-size: 9px;
  opacity: .65;
  margin-top: 1px;
}
.plaque-popup-addr {
  font-size: 11px;
  opacity: .8;
  margin-bottom: 2px;
}
/* .plaque-popup-inscription is styled inline in index.html — see the
   "Plaque popup inscription" block there. The popup is light-themed
   (white body, slate-grey inscription card) since 2026-04-25. */
.plaque-popup-actions {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 0;
}
.plaque-popup-btn {
  padding: 10px 6px;
  border: none;
  font-size: 11px;
  font-weight: 700;
  cursor: pointer;
  text-align: center;
  transition: background .12s;
  border-top: 1px solid var(--panel-bd);
  background: var(--panel-bg);
  color: var(--text-primary);
  line-height: 1.3;
}
.plaque-popup-btn:not(:last-child) { border-right: 1px solid var(--panel-bd); }
.plaque-popup-btn:hover { background: var(--panel-hover); }
.plaque-popup-btn.btn-capture { color: #0ea5e9; }
.plaque-popup-btn.btn-capture:disabled { color: #22c55e; cursor: default; }
.plaque-popup-btn.btn-walk { color: var(--text-accent); }
.plaque-popup-btn.btn-close-p { color: var(--text-secondary); }








/* ── FOOTER ──────────────────────────────────────────────── */
.site-footer{background:var(--hdr-bg);color:rgba(255,255,255,.65);flex-shrink:0;border-top:1px solid rgba(255,255,255,.08)}
.sf-inner{max-width:1100px;margin:0 auto;padding:14px 20px calc(12px + env(safe-area-inset-bottom, 0px));display:flex;flex-wrap:wrap;align-items:center;gap:8px 20px}
.sf-links{display:flex;flex-wrap:wrap;gap:4px 14px;list-style:none;padding:0;margin:0}
.sf-links a{color:rgba(255,255,255,.6);text-decoration:none;font-size:11px;font-weight:500;transition:color .15s;white-space:nowrap}
.sf-links a:hover{color:#fff}
.sf-copy{font-size:11px;color:rgba(255,255,255,.45);margin:0;flex:1;min-width:200px}
@media(max-width:600px){.sf-inner{padding:12px 16px calc(12px + env(safe-area-inset-bottom, 0px))}.sf-copy{width:100%}}

/* ── NAV USER DROPDOWN ───────────────────────────────────────── */
.nav-user { margin-left: auto; }
.nav-user-wrap { position: relative; }
.nav-user-btn-inner {
  background: none; border: none; cursor: pointer;
  color: rgba(255,255,255,.85); font-size: 13px; font-weight: 600;
  padding: 5px 10px; border-radius: 6px;
  transition: background .15s; white-space: nowrap;
}
.nav-user-btn-inner:hover { background: var(--hdr-btn-bg); color: #fff; }
.nav-user-dropdown {
  display: none;
  position: fixed;          /* escape overflow:hidden on header */
  background: var(--panel-bg);
  border: 1px solid var(--panel-bd);
  border-radius: 10px;
  box-shadow: 0 8px 28px rgba(0,0,0,.25);
  min-width: 175px;
  padding: 4px 0;
  z-index: 9999;            /* above everything */
}
.nav-user-dropdown.open { display: block; }
.nav-dd-item {
  display: flex; align-items: center; gap: 9px;
  padding: 10px 14px; font-size: 13px; font-weight: 600;
  color: var(--text-primary); text-decoration: none;
  background: none; border: none; width: 100%;
  text-align: left; cursor: pointer;
  transition: background .12s; white-space: nowrap;
}
.nav-dd-item:hover { background: var(--panel-hover); }
.nav-dd-signout { color: var(--red, #e11d48); }

#btn-locate {
  position: absolute;
  bottom: 76px;
  left: 10px;
  z-index: 800;
  width: 40px;
  height: 40px;
  background: rgba(255,255,255,0.92);
  border: none;
  border-radius: 8px;
  box-shadow: 0 1px 5px rgba(0,0,0,.3);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #333;
  padding: 0;
  transition: background .15s, transform .2s, color .15s;
}
#btn-locate:hover {
  background: #fff;
  color: #1a6ea8;
}
#btn-locate.locating {
  color: #1a6ea8;
  animation: scope-pulse 1s ease-in-out infinite;
}
#btn-locate.located {
  color: #16a34a;
}
/* While live-tracking, button stays accent blue + shows a subtle green
   pulsing dot in the corner to indicate GPS is actively updating. */
#btn-locate.tracking {
  color: #1a6ea8;
  position: absolute;
}
#btn-locate.tracking::after {
  content: '';
  position: absolute;
  top: 4px; right: 4px;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: #16a34a;
  box-shadow: 0 0 0 2px #fff;
  animation: tracking-pulse 1.5s ease-in-out infinite;
}
@keyframes tracking-pulse {
  0%, 100% { opacity: 1;   transform: scale(1); }
  50%      { opacity: 0.5; transform: scale(0.85); }
}
@keyframes scope-pulse {
  0%, 100% { transform: scale(1);   opacity: 1; }
  50%       { transform: scale(1.1); opacity: .7; }
}

/* ── LAYERS FAB ─────────────────────────────────────────────────────
   "Show my walks" toggle, promoted out of the actions menu (2026-04-25).
   Lives at top-right of the map — top edge aligns horizontally with the
   Leaflet zoom +/- buttons on the left, mirroring their visual treatment.
   Active state uses the same amber-tinted pattern as the actions-menu
   pills so toggle-on feels consistent. */
#btn-layers {
  position: absolute;
  top: 10px;        /* horizontally aligned with Leaflet zoom +/- buttons */
  right: 10px;
  z-index: 800;
  width: 40px;
  height: 40px;
  background: rgba(255,255,255,0.92);
  border: none;
  border-radius: 8px;
  box-shadow: 0 1px 5px rgba(0,0,0,.3);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #333;
  padding: 0;
  transition: background .15s, color .15s, box-shadow .15s;
}
#btn-layers:hover {
  background: #fff;
  color: #1a6ea8;
}
#btn-layers.is-active {
  background: #fffbeb;     /* amber-50 — matches actions-menu active state */
  color: #92400e;          /* amber-800 */
  box-shadow: 0 1px 5px rgba(245,158,11,.35), 0 0 0 1px rgba(245,158,11,.18);
}

/* Mode badges — TWO stacked pseudo-elements at the bottom-right corner.
   ::before is the blue "P" (Plaques) on top.
   ::after  is the yellow "W" (Walks) underneath.
   .mode-plaques shows only P, .mode-walks shows only W, .mode-both shows
   both stacked. Vertical offsets are absolute so each letter sits at a
   fixed slot regardless of which is visible. */
#btn-layers::before,
#btn-layers::after {
  position: absolute;
  right: -3px;
  width: 14px;
  height: 14px;
  border-radius: 7px;
  font-size: 9px;
  font-weight: 800;
  line-height: 14px;
  text-align: center;
  letter-spacing: 0;
  box-shadow: 0 0 0 1.5px #fff;
  display: none;        /* shown per mode below */
}
#btn-layers::before {
  /* Upper slot — blue "P" for the Plaques layer. */
  content: 'P';
  bottom: 13px;
  background: #1d4ed8;  /* royal-blue, matches the brand */
  color: #fff;
}
#btn-layers::after {
  /* Lower slot — yellow "W" for the Walks layer. */
  content: 'W';
  bottom: -3px;
  background: #facc15;  /* amber-400 */
  color: #78350f;       /* amber-900 — readable on yellow */
}

/* Visibility per mode. */
#btn-layers.mode-plaques::before { display: block; }
#btn-layers.mode-walks::after    { display: block; }
#btn-layers.mode-both::before    { display: block; }
#btn-layers.mode-both::after     { display: block; }

/* Suppress the layers FAB while route-building. Same reasoning as
   .actions-menu — top-right competes with the route-builder hint and
   "Cancel" pill that appear during route mode. */
body.route-building #btn-layers {
  display: none !important;
}


/* Hide footer on touch / mobile devices — evaluated at paint, never races */
@media (hover: none), (pointer: coarse), (max-width: 768px) {
  .site-footer { display: none !important; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   PLAKKA UI POLISH — mobile-first improvements
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 1. Background — subtle gradient instead of flat grey ─────────────────── */
body {
  background: linear-gradient(160deg, #e8eef7 0%, #eef2f7 50%, #e4ecf5 100%) !important;
  background-attachment: fixed !important;
}

/* ── 2. Page-level wrapper max-width — full-width on mobile ────────────────── */
.friends-wrap,
.auth-wrap {
  padding-left: 12px !important;
  padding-right: 12px !important;
}

@media (min-width: 600px) {
  .friends-wrap,
  .auth-wrap {
    padding-left: 20px !important;
    padding-right: 20px !important;
  }
}

/* ── 3. Cards — warmer shadow, slight lift on hover ────────────────────────── */
.fr-card {
  box-shadow: 0 2px 12px rgba(27,58,107,.08), 0 1px 3px rgba(0,0,0,.06);
  transition: box-shadow .2s ease, transform .15s ease;
  border: 1px solid rgba(27,58,107,.08) !important;
}

.fr-card:hover {
  box-shadow: 0 6px 24px rgba(27,58,107,.13), 0 2px 6px rgba(0,0,0,.08);
  transform: translateY(-1px);
}

/* ── 4. Friend card avatar — gradient instead of flat blue ─────────────────── */
.fr-avatar {
  background: var(--grad-blue) !important;
  box-shadow: 0 2px 8px rgba(27,58,107,.25);
}

/* ── 5. Friend card — coloured left border based on context ────────────────── */
.fr-card:has(.fr-btn-accept) {
  border-left: 3px solid #f59e0b !important;
}
.fr-card:has(.fr-btn-remove) {
  border-left: 3px solid var(--text-accent) !important;
}
.fr-card:has(.fr-btn-add) {
  border-left: 3px solid #16a34a !important;
}

/* ── 6. Tabs — larger touch targets, better active indicator ───────────────── */
.fr-tab,
.auth-tab,
.ch-tab-btn {
  min-height: 44px !important;
  font-size: 14px !important;
  letter-spacing: .01em;
  transition: color .15s, border-bottom-color .15s;
}

@media (max-width: 400px) {
  .fr-tab { font-size: 12px !important; padding: 11px 4px !important; }
  .ch-tab-btn { font-size: 12px !important; }
}

/* ── 7. Challenges profile card — subtle gradient header ───────────────────── */
.ch-profile-card {
  background: linear-gradient(135deg, #fff 60%, #f0f6ff 100%) !important;
  box-shadow: 0 2px 16px rgba(27,58,107,.1) !important;
  border: 1px solid rgba(27,58,107,.08) !important;
}

.ch-profile-avatar {
  background: var(--grad-blue) !important;
  box-shadow: 0 3px 10px rgba(27,58,107,.3) !important;
}

/* ── 8. Challenge cards — warmer, lift on tap ──────────────────────────────── */
.ch-card {
  box-shadow: 0 2px 12px rgba(27,58,107,.08) !important;
  border: 1px solid rgba(27,58,107,.06) !important;
  transition: box-shadow .2s ease;
}

/* ── 9. Alphabet / plakkaology grid cells — smoother transitions ───────────── */
.alph-cell,
.plak-cell {
  transition: background .2s ease, transform .1s ease, box-shadow .2s ease !important;
}

.alph-cell.done:active,
.plak-cell.filled:active {
  transform: scale(.94);
}

/* ── 10. Progress bars — rounded ends, subtle animation ────────────────────── */
.ch-bar-fill {
  border-radius: 4px !important;
  transition: width .6s cubic-bezier(.4,0,.2,1) !important;
}

.ch-bar-bg {
  border-radius: 4px !important;
}

/* ── 11. Buttons — larger touch targets, smoother press ────────────────────── */
.fr-btn,
.league-btn,
.auth-btn,
.fr-search-btn {
  min-height: 40px !important;
  transition: opacity .15s ease, transform .1s ease, background .15s ease !important;
}

.fr-btn:active,
.league-btn:active,
.auth-btn:active {
  transform: scale(.96) !important;
  opacity: .85 !important;
}

/* ── 12. Input fields — slightly larger on mobile ──────────────────────────── */
.field input,
.fr-search-input,
.league-input,
.wd-rename-input {
  min-height: 44px !important;
  font-size: 16px !important; /* prevents iOS zoom on focus */
}

/* ── 13. Login page — warmer header gradient ───────────────────────────────── */
.auth-header {
  background: var(--grad-blue) !important;
  padding: 32px 28px 24px !important;
}

.auth-header h1 {
  font-size: 28px !important;
  letter-spacing: -.03em;
}

.auth-card {
  box-shadow: 0 8px 40px rgba(27,58,107,.18) !important;
  border-radius: 20px !important;
  overflow: hidden;
}

/* ── 14. Micro-animations — modals slide up smoothly ───────────────────────── */
@keyframes plakka-slide-up {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes plakka-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.ch-card,
.fr-card,
.auth-card {
  animation: plakka-fade-in .25s ease both;
}

/* ── 15. Section labels — slightly more prominent ──────────────────────────── */
.fr-section-label,
.league-section-label {
  font-size: 11px !important;
  font-weight: 800 !important;
  letter-spacing: .1em !important;
  color: var(--text-accent) !important;
  text-transform: uppercase !important;
  margin-bottom: 10px !important;
  padding-bottom: 6px !important;
  border-bottom: 1.5px solid var(--panel-bd) !important;
}

/* ── 16. Empty states — more visual ────────────────────────────────────────── */
.fr-empty,
.league-empty {
  background: var(--panel-faint) !important;
  border-radius: 12px !important;
  padding: 32px 20px !important;
  margin: 8px 0 !important;
  border: 1.5px dashed var(--panel-bd) !important;
  color: var(--text-secondary) !important;
}

/* ── 17. League list items — touch-friendly ────────────────────────────────── */
.league-list-item {
  min-height: 56px !important;
  transition: background .15s ease !important;
  border-radius: 10px !important;
}

.league-list-item:active {
  background: var(--panel-hover) !important;
}

/* ── 18. Header nav — ensure consistent height ─────────────────────────────── */
.site-nav,
header {
  min-height: 44px;
}

/* ── 19. Map page capture toggle button — pill style ───────────────────────── */
/* ── 20. Toast notifications — more polished ───────────────────────────────── */
#toast {
  border-radius: 12px !important;
  font-weight: 600 !important;
  letter-spacing: .01em !important;
  box-shadow: 0 4px 20px rgba(0,0,0,.25) !important;
}
/* Animate only when the toast is shown (class .on is added by toast() JS).
   Avoid animation-fill-mode: both here — it made the final opacity stick
   so the toast would never fade out again. Default fill-mode = none, so
   after the animation ends the opacity reverts to the base 0 (hidden). */
#toast.on {
  animation: plakka-slide-up .25s ease;
}

/* ── 21. Map popup — more polished ─────────────────────────────────────────── */
.plaque-action-popup .leaflet-popup-content-wrapper {
  border-radius: 16px !important;
  box-shadow: 0 8px 32px rgba(0,0,0,.18) !important;
}

.plaque-popup-btn {
  min-height: 36px !important;
  border-radius: 8px !important;
  font-size: 12px !important;
  transition: all .15s ease !important;
}

.plaque-popup-btn:active {
  transform: scale(.95) !important;
}

/* ── 22. Scrollbars — slim and branded on webkit (mobile chrome) ───────────── */
::-webkit-scrollbar { width: 4px; height: 4px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: rgba(27,58,107,.2); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: rgba(27,58,107,.35); }

/* ── 23. Leaderboard table — better mobile spacing ─────────────────────────── */
@media (max-width: 480px) {
  .lb-table th,
  .lb-table td {
    padding: 10px 8px !important;
    font-size: 12px !important;
  }
}

/* ── 24. About page hero — more immersive ──────────────────────────────────── */
.about-hero {
  background: var(--grad-blue) !important;
  border-radius: 0 0 24px 24px !important;
  box-shadow: 0 4px 24px rgba(27,58,107,.2) !important;
}

/* ── 25. Mini challenge cards in Themed Challenges ─────────────────────────── */
.mini-challenge {
  border-radius: 12px !important;
  border: 1px solid rgba(27,58,107,.08) !important;
  box-shadow: 0 1px 6px rgba(27,58,107,.06) !important;
  transition: box-shadow .2s ease !important;
  overflow: hidden;
}

.mini-head {
  min-height: 48px !important;
}


/* Legacy alias — pdm-slide-up used in index.html inline modals */
@keyframes pdm-slide-up {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: translateY(0); }
}


/* ═══════════════════════════════════════════════════════════════════════════
   LEAGUES + WALKS — shared styles for leagues.html, walks.html
   (previously inline in challenges.html)
   ═══════════════════════════════════════════════════════════════════════════ */

.league-pending-row, .league-member-row {
  display:flex; align-items:center; justify-content:space-between;
  padding:8px 10px; border-radius:8px; margin-bottom:4px;
  background:var(--panel-faint); }

.league-pending-row { border-left:3px solid #f59e0b; }

.league-member-row  { border-left:3px solid #16a34a; }

.league-row-name { font-size:13px; font-weight:600; color:var(--text-primary); }

.league-row-meta { font-size:11px; color:var(--text-secondary); margin-top:1px; }

.league-row-btns { display:flex; gap:6px; flex-shrink:0; }

.league-share-row { display:flex; align-items:center; gap:8px; margin-top:8px; flex-wrap:wrap; }

.league-code-display { font-family:monospace; font-size:15px; font-weight:800;
  letter-spacing:3px; color:var(--text-accent); background:var(--panel-faint);
  padding:4px 10px; border-radius:6px; }

.lli-row { display:flex;align-items:center;justify-content:space-between; }

.lli-name { font-size:15px;font-weight:700;color:var(--text-head); }

.lli-meta { font-size:12px;color:var(--text-secondary);margin-top:3px; }

.lli-arrow { font-size:20px;color:var(--text-secondary);flex-shrink:0; }

/* ── League detail view ─────────────────────────────────────── */
.ld-header {
  display:flex;align-items:center;gap:10px;margin-bottom:12px;
}

.ld-back-btn {
  background:none;border:none;color:var(--text-accent);font-size:16px;
  font-weight:700;cursor:pointer;padding:4px 0;flex-shrink:0;
}

.ld-title {
  flex:1;font-size:17px;font-weight:800;color:var(--text-head);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}

.ld-admin-section { padding-top:14px;border-top:1px solid var(--panel-faint); }

.ld-back-btn {
  background:none;border:none;color:var(--text-accent);font-size:16px;
  font-weight:700;cursor:pointer;padding:4px 0;flex-shrink:0;
}

.ld-title {
  flex:1;font-size:17px;font-weight:800;color:var(--text-head);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}

.ld-admin-section { padding-top:14px;border-top:1px solid var(--panel-faint); }

/* ── Additional leagues/walks styles ─────────────────────── */

/* ── League admin panel ─────────────────────────────────────── */
.league-admin-section { margin-top:14px; }
.league-admin-title { font-size:12px; font-weight:700; text-transform:uppercase;
  letter-spacing:.5px; color:var(--text-secondary); margin-bottom:8px; }
.league-pending-row, .league-member-row {
  display:flex; align-items:center; justify-content:space-between;
  padding:8px 10px; border-radius:8px; margin-bottom:4px;
  background:var(--panel-faint); }
.league-pending-row { border-left:3px solid #f59e0b; }
.league-member-row  { border-left:3px solid #16a34a; }
.league-row-name { font-size:13px; font-weight:600; color:var(--text-primary); }
.league-row-meta { font-size:11px; color:var(--text-secondary); margin-top:1px; }
.league-row-btns { display:flex; gap:6px; flex-shrink:0; }
.btn-approve { background:#16a34a; color:#fff; border:none; border-radius:6px;
  padding:4px 10px; font-size:12px; font-weight:700; cursor:pointer; }
.btn-reject  { background:transparent; border:1px solid #e11d48; color:#e11d48;
  border-radius:6px; padding:4px 10px; font-size:12px; font-weight:700; cursor:pointer; }
.btn-approve:hover { opacity:.85; }
.btn-reject:hover  { background:#e11d48; color:#fff; }
/* Pending request banner (user's own pending request) */
.league-pending-badge {
  display:inline-block; font-size:10px; font-weight:700; text-transform:uppercase;
  background:#f59e0b22; color:#b45309; border:1px solid #f59e0b; border-radius:6px;
  padding:2px 7px; margin-left:6px; vertical-align:middle; }
/* Share button */
.btn-whatsapp { background:#25D366; color:#fff; border:none; border-radius:7px;
  padding:6px 12px; font-size:12px; font-weight:700; cursor:pointer;
  display:flex; align-items:center; gap:5px; }
.btn-whatsapp:hover { opacity:.85; }
.league-share-row { display:flex; align-items:center; gap:8px; margin-top:8px; flex-wrap:wrap; }
.league-code-display { font-family:monospace; font-size:15px; font-weight:800;
  letter-spacing:3px; color:var(--text-accent); background:var(--panel-faint);
  padding:4px 10px; border-radius:6px; }

/* ── League list view ───────────────────────────────────────── */
.league-section-label {
  font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;
  color:var(--text-secondary);margin:12px 0 6px;
}
.league-list-item {
  background:var(--panel-bg);border:1px solid var(--panel-bd);border-radius:10px;
  padding:12px 14px;margin-bottom:8px;cursor:pointer;transition:border-color .15s;
}
.league-list-item:hover { border-color:var(--text-accent); }
.league-list-item.pending { cursor:default;opacity:.7; }
.league-list-item.pending:hover { border-color:var(--panel-bd); }
.lli-row { display:flex;align-items:center;justify-content:space-between; }
.lli-name { font-size:15px;font-weight:700;color:var(--text-head); }
.lli-meta { font-size:12px;color:var(--text-secondary);margin-top:3px; }
.lli-arrow { font-size:20px;color:var(--text-secondary);flex-shrink:0; }
.lli-admin-badge {
  font-size:9px;font-weight:800;background:#f59e0b22;color:#b45309;
  border:1px solid #f59e0b;border-radius:4px;padding:1px 5px;vertical-align:middle;margin-left:5px;
}
.lli-pending-badge {
  font-size:9px;font-weight:800;background:#e11d4822;color:#e11d48;
  border:1px solid #e11d48;border-radius:4px;padding:1px 5px;vertical-align:middle;margin-left:5px;
}
/* ── League detail view ─────────────────────────────────────── */
.ld-header {
  display:flex;align-items:center;gap:10px;margin-bottom:12px;
}
.ld-back-btn {
  background:none;border:none;color:var(--text-accent);font-size:16px;
  font-weight:700;cursor:pointer;padding:4px 0;flex-shrink:0;
}
.ld-title {
  flex:1;font-size:17px;font-weight:800;color:var(--text-head);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.ld-leave-btn {
  background:none;border:1px solid var(--panel-bd);color:var(--text-secondary);
  border-radius:6px;padding:4px 10px;font-size:12px;cursor:pointer;flex-shrink:0;
}
.ld-leave-btn:hover { border-color:#e11d48;color:#e11d48; }
.ld-tabs {
  display:flex;gap:4px;margin-bottom:14px;border-bottom:2px solid var(--panel-bd);
}
.ld-tab-btn {
  padding:8px 16px;font-size:13px;font-weight:700;border:none;background:none;
  cursor:pointer;color:var(--text-secondary);border-bottom:3px solid transparent;
  margin-bottom:-2px;transition:color .15s;
}
.ld-tab-btn.active { color:var(--text-accent);border-bottom-color:var(--text-accent); }
.ld-tab-btn:hover { color:var(--text-primary); }
.ld-admin-section { padding-top:14px;border-top:1px solid var(--panel-faint); }
/* ── League/Walks classes that were only in JS-generated HTML (never styled) ── */

.league-loading {
  text-align:center; padding:32px 20px;
  color:var(--text-secondary); font-size:14px;
}

.league-actions {
  display:flex; gap:8px; margin-bottom:14px;
}

.league-action-btn {
  flex:1; padding:10px 12px; border:none; border-radius:8px;
  font-size:13px; font-weight:700; cursor:pointer;
  transition:opacity .15s, transform .1s;
}
.league-action-btn:active { transform:scale(.96); opacity:.85; }

.league-create-btn {
  background:var(--grad-blue); color:#fff;
}

.league-join-btn {
  background:var(--panel-faint); color:var(--text-label);
  border:1.5px solid var(--panel-bd);
}

.league-form-card {
  background:var(--panel-faint); border-radius:12px;
  padding:16px; margin-bottom:12px;
  border:1px solid var(--panel-bd);
  animation:plakka-fade-in .2s ease;
}

.league-form-title {
  font-size:15px; font-weight:800; color:var(--text-head);
  margin-bottom:12px;
}

.league-form-error {
  color:var(--red); font-size:13px;
  margin-top:6px; display:none;
}

.league-form-btns {
  display:flex; gap:8px; margin-top:12px;
}

.league-standings {
  width:100%; border-collapse:collapse;
  font-size:13px; margin-top:8px;
}

.league-standings th {
  text-align:left; padding:8px 10px;
  font-size:11px; font-weight:700;
  text-transform:uppercase; letter-spacing:.06em;
  color:var(--text-secondary);
  border-bottom:2px solid var(--panel-bd);
}

.league-standings td {
  padding:10px 10px; border-bottom:1px solid var(--panel-faint);
  color:var(--text-primary);
}

.league-standings tr:last-child td { border-bottom:none; }

.league-my-rank {
  background:var(--panel-hl) !important;
  font-weight:700;
}

.league-my-rank td { color:var(--text-accent) !important; }

.league-btn-ghost {
  background:none !important;
  border:1.5px solid var(--panel-bd) !important;
  color:var(--text-secondary) !important;
}

.league-join-btn-sm {
  padding:5px 12px; font-size:12px; font-weight:700;
  background:var(--grad-blue); color:#fff;
  border:none; border-radius:6px; cursor:pointer;
}

.league-search-row {
  display:flex; gap:8px; margin-bottom:12px;
}

.league-search-input {
  flex:1;
}

.league-search-result {
  padding:10px 12px; border-radius:8px;
  background:var(--panel-faint);
  border:1px solid var(--panel-bd);
  margin-bottom:6px;
  display:flex; align-items:center; justify-content:space-between;
}

.league-search-name {
  font-size:14px; font-weight:700; color:var(--text-head);
}

.league-search-meta {
  font-size:12px; color:var(--text-secondary); margin-top:2px;
}

.league-code-display {
  background:var(--panel-faint); border:1.5px solid var(--panel-bd);
  border-radius:8px; padding:10px 14px;
  font-size:18px; font-weight:900; letter-spacing:.15em;
  color:var(--text-head); text-align:center;
  margin:8px 0;
}

.league-share-row {
  display:flex; gap:8px; margin-top:8px;
}


/* ═══════════════════════════════════════════════════════════════
   PASS 2A — Map page form & button components
   Walk panel footer buttons, share actions, bottom-sheet form
═══════════════════════════════════════════════════════════════ */

/* ── Button colour modifiers for action buttons ──
   Use alongside .btn or .share-big-btn (component), e.g.:
     <button class="btn btn--whatsapp">...
   Semantic names chosen over raw colours so re-theming is a one-line change. */
.btn--whatsapp   { background: #25D366; color: #fff; }
.btn--share      { background: #7c3aed; color: #fff; }
.btn--fit        { background: #1e8fd4; color: #fff; }
.btn--nav-share  { background: var(--text-head); color: #fff; }
.btn--copy       { background: #7c3aed; color: #fff; padding: 8px 14px; border-radius: 7px; font-size: 12px; font-weight: 600; }

/* ── Bottom sheet modal (backdrop + panel + handle) ──
   Shared pattern for "slide up from bottom" modals. Display toggled by JS:
     - default: hidden
     - .bottom-sheet.is-open or JS .style.display = 'flex' to show */
.bottom-sheet {
  display: none;
  position: absolute; inset: 0;
  background: rgba(0,0,0,.5);
  z-index: var(--z-modal);
  align-items: flex-end;
  justify-content: center;
}
.bottom-sheet.is-open { display: flex; }
.bottom-sheet__panel {
  background: var(--panel-bg);
  border-radius: 20px 20px 0 0;
  padding: 20px 20px max(20px, env(safe-area-inset-bottom)) 20px;
  width: 100%;
  max-width: 500px;
}
.bottom-sheet__handle {
  width: 40px; height: 4px;
  background: var(--panel-bd);
  border-radius: 2px;
  margin: 0 auto 16px;
}
.bottom-sheet__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 4px;
}
.bottom-sheet__title {
  font-size: 15px;
  font-weight: 700;
  color: var(--text-head);
}
.bottom-sheet__close {
  background: none; border: none;
  font-size: 18px; cursor: pointer;
  color: var(--text-secondary);
}

/* ── Compact form controls (used inside bottom-sheet panels) ── */
.form-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-label);
  display: block;
  margin-bottom: 3px;
}
.form-hint {
  font-size: 11px;
  color: var(--text-secondary);
  margin-bottom: 8px;
}
.form-input {
  width: 100%;
  padding: 9px 10px;
  border: 1px solid var(--panel-bd);
  border-radius: 8px;
  font-size: 14px;
  outline: none;
  margin-bottom: 10px;
  background: var(--panel-bg);
  color: var(--text-primary);
}
.form-input:focus { border-color: var(--text-accent); }
.form-error {
  background: #fef2f2;
  border: 1px solid #fca5a5;
  border-radius: 8px;
  padding: 10px 12px;
  margin-bottom: 12px;
  font-size: 12px;
  color: #991b1b;
  line-height: 1.5;
}

/* ── Warning banner (amber variant of form-error for non-critical notices) ── */
.warning-banner {
  background: rgba(245,158,11,.1);
  border: 1px solid rgba(245,158,11,.4);
  border-radius: 8px;
  padding: 10px 14px;
  font-size: 12px;
  color: #92400e;
  margin-bottom: 16px;
  line-height: 1.5;
}

/* ── Photo upload drop zone ── */
.photo-upload-zone {
  width: 100%;
  height: 90px;
  border: 2px dashed var(--panel-bd);
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  margin-bottom: 14px;
  overflow: hidden;
  background: var(--panel-faint);
  position: relative;
}
.photo-upload-zone__icon {
  font-size: 22px;
  margin-bottom: 4px;
}
.photo-upload-zone__label {
  font-size: 11px;
  color: var(--text-secondary);
}
.photo-upload-zone__preview {
  width: 100%; height: 100%;
  object-fit: cover;
  position: absolute; inset: 0;
}

/* ── Dialog action row (used at the bottom of a form-in-sheet) ── */
.dialog-actions {
  display: flex;
  gap: 8px;
}
.btn--save-primary {
  flex: 1;
  padding: 12px;
  background: var(--red);
  color: #fff;
  border: none;
  border-radius: 10px;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
}
.btn--save-primary:hover { opacity: .92; }
.btn--cancel {
  padding: 12px 16px;
  background: var(--panel-faint);
  color: var(--text-label);
  border: none;
  border-radius: 10px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.btn--cancel:hover { background: var(--panel-hover); }


/* ═══════════════════════════════════════════════════════════════
   PASS 2B — Map diagnostic modal & legend swatches
═══════════════════════════════════════════════════════════════ */

/* ── Diagnostic modal (centred, used for API diagnostics + future debug UI) ──
   Similar to .bottom-sheet in that JS toggles display between 'none' and 'flex'. */
.center-modal {
  display: none;
  position: absolute; inset: 0;
  background: rgba(0,0,0,.55);
  z-index: var(--z-modal);
  align-items: center;
  justify-content: center;
}
.center-modal.is-open { display: flex; }
.center-modal__panel {
  background: var(--panel-bg);
  border-radius: var(--radius-lg);
  padding: 22px;
  width: min(520px, calc(100vw - 24px));
  max-height: 80vh;
  overflow-y: auto;
  box-shadow: 0 8px 40px rgba(0,0,0,.3);
}
.center-modal__header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 14px;
}
.center-modal__title {
  font-size: 15px;
  font-weight: 700;
  color: var(--text-head);
}
.center-modal__close {
  background: none; border: none;
  font-size: 20px; cursor: pointer;
  color: var(--text-secondary);
  line-height: 1;
}
.center-modal__body {
  font-size: 12px;
  line-height: 1.7;
}
.center-modal__body--mono {
  font-family: monospace;
}
.center-modal__status {
  color: var(--text-secondary);
}

/* Action row for confirm-style modals (e.g. stop-record-modal).
   Two buttons side-by-side; primary fills, cancel is tighter. The
   existing .btn--save-primary class already declares flex:1, so it
   expands naturally inside this flex row. */
.center-modal__actions {
  display: flex;
  gap: 10px;
  padding: 12px 16px 16px;
  align-items: stretch;
}
.center-modal__actions .btn--cancel {
  flex: 0 0 auto;
}

/* ── Legend swatches ──
   Use with existing .lr and .ld. Colour is per-item via modifier class. */
.ld--plaque    { background: #1e8fd4; border: 2px solid #fff; }
.ld--parkrun   { background: #27ae60; border: 2px solid #fff; }
.ld--walkstart { background: #e67e22; border: 2px solid #fff; }
.ld--custom    { background: #e11d48; border: 2px solid #fff; }
.ld--route     { width: 20px; height: 3px; border-radius: 2px; background: #1e8fd4; }
.ld--route-offline { width: 20px; height: 3px; border-radius: 2px; background: #dc2626; }


/* ═══════════════════════════════════════════════════════════════
   PASS 2C — Header mini-buttons, route hint, location FABs
═══════════════════════════════════════════════════════════════ */

/* ── Header mini-buttons (create route / end route) ──
   Compact pill buttons that sit in the header next to the search box.
   Colour via modifier. */
.header-btn {
  padding: 5px 12px;
  font-size: 12px;
  font-weight: 700;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  color: #fff;
  transition: opacity var(--t-base);
  align-self: center;
  margin-left: 6px;
  flex-shrink: 0;
}
.header-btn:hover { opacity: .88; }
.header-btn--create { background: #1a6ea8; }
.header-btn--end    { background: #15803d; }

/* Wrapper for header button pairs (e.g. create/end route).
   JS toggles display between 'none' and 'flex' on this container. */
.header-btn-group {
  gap: 6px;
  align-items: center;
}

/* ── Route builder hint bar ──
   Pill that floats at the top-centre of the map while building a route. */
.route-hint {
  position: absolute;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(26,110,168,.95);
  color: #fff;
  padding: 10px 16px;
  border-radius: 14px;
  font-size: 13px;
  font-weight: 700;
  z-index: 850;
  max-width: calc(100vw - 20px);
  box-shadow: 0 2px 12px rgba(0,0,0,.3);
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  justify-content: center;
}
.route-hint .rh-msg {
  white-space: normal;
  line-height: 1.3;
}
.route-hint .rh-actions {
  display: flex;
  gap: 8px;
  flex-wrap: nowrap;
}
.route-hint .rh-btn {
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 700;
  background: rgba(255,255,255,.22);
  border: 1px solid rgba(255,255,255,.5);
  border-radius: 10px;
  color: #fff;
  cursor: pointer;
  transition: background .12s, border-color .12s;
  white-space: nowrap;
}
.route-hint .rh-btn:hover:not(:disabled) {
  background: rgba(255,255,255,.35);
}
.route-hint .rh-btn:disabled {
  opacity: .5;
  cursor: not-allowed;
}
.route-hint .rh-btn--primary {
  background: #16a34a;
  border-color: #15803d;
}
.route-hint .rh-btn--primary:hover:not(:disabled) { background: #15803d; }
.route-hint .rh-btn--danger {
  background: rgba(239,68,68,.2);
  border-color: rgba(254,202,202,.7);
}
.route-hint .rh-btn--danger:hover:not(:disabled) {
  background: rgba(220,38,38,.35);
  border-color: #fecaca;
}

/* ── Custom-location FABs ──
   Use .fab base (defined earlier) + .map-fab positioning + a colour class.
   Explicit colour-tinted shadows help these read as "actionable" over the map. */
.fab--add-loc {
  background: var(--red);
  box-shadow: 0 3px 12px rgba(225,29,72,.45);
  font-size: 22px;
  transition: background var(--t-base), box-shadow var(--t-base);
}
.fab--del-loc {
  background: var(--red-darkest);
  box-shadow: 0 3px 12px rgba(127,29,29,.45);
  font-size: 20px;
  transition: background var(--t-base), box-shadow var(--t-base);
}

/* Layers FAB — white background with a dark icon. Matches the map's
   filter chip aesthetic (white-on-map control surface). .is-active flips
   to a tinted state when plaques are currently showing — so the user
   can read at a glance whether the toggle is "on" or "off". */
.fab--layers {
  background: #fff;
  color: #0f172a;
  box-shadow: 0 2px 8px rgba(0,0,0,.18);
  transition: background var(--t-base), color var(--t-base);
}
.fab--layers:hover { background: #f8fafc; }
.fab--layers.is-active {
  background: var(--text-accent, #0C447C);
  color: #fff;
}


/* ═══════════════════════════════════════════════════════════════
   STEP 1 — Content page components
   Patterns for static content pages: about, terms, privacy sections,
   and any info-heavy page. Designed for reuse across all pages.
═══════════════════════════════════════════════════════════════ */

/* ── Body override for non-map pages ──
   index.html body is 100vh fixed with overflow:hidden (map page).
   Content pages need normal scrolling. Apply with <body class="content-page">
   or leave inline per-page override as at present. */
.content-page {
  overflow-y: auto;
  height: auto;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* ── Page content wrapper ──
   Centred max-width column with sensible padding. Used as the main container
   for any content page (about, terms, etc). */
.page-content {
  flex: 1;
  max-width: 860px;
  margin: 0 auto;
  padding: 32px 20px 60px;
  width: 100%;
}

/* ── Section heading ── */
.section-title {
  font-size: 20px;
  font-weight: 800;
  color: var(--text-head);
  margin-bottom: 14px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.section-title--sm {
  font-size: 18px;
}

/* ── Prose (body copy inside content cards) ── */
.prose {
  font-size: 14px;
  color: var(--text-primary);
  line-height: 1.75;
}
.prose + .prose,
.prose + .prose-footnote {
  margin-top: 12px;
}
.prose-footnote {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.75;
}

.prose-list {
  font-size: 14px;
  color: var(--text-primary);
  line-height: 1.9;
  padding-left: 20px;
}
.prose-list li + li { margin-top: 2px; }

/* ── Stat cards (three-up stat strip used on about page) ── */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin-bottom: 40px;
}
@media (max-width: 520px) {
  .stat-grid { grid-template-columns: 1fr; }
}
.stat-card {
  background: var(--panel-bg);
  border-radius: var(--radius-md);
  padding: 24px;
  text-align: center;
  box-shadow: var(--panel-shadow);
}
.stat-card__value {
  font-size: 36px;
  font-weight: 900;
  color: var(--text-accent);
  display: block;
  line-height: 1;
  margin-bottom: 4px;
}
.stat-card__label {
  font-size: 12px;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: .07em;
}

/* ── Feature list (icon + title + description grid) ── */
.feature-list {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
@media (max-width: 520px) {
  .feature-list { grid-template-columns: 1fr; }
}
.feature-item {
  display: flex;
  gap: 14px;
  align-items: flex-start;
}
.feature-item__icon {
  font-size: 28px;
  flex-shrink: 0;
}
.feature-item__title {
  font-size: 14px;
  color: var(--text-primary);
  display: block;
}
.feature-item__desc {
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.5;
  margin-top: 4px;
}

/* ── Hero card (blue-gradient banner for page intros & CTAs) ── */
.hero-card {
  background: var(--grad-blue);
  color: #fff;
  border-radius: var(--radius-lg);
  padding: 48px 40px;
  margin-bottom: 40px;
  text-align: center;
  position: relative;
  overflow: hidden;
}
.hero-card--compact {
  padding: 32px;
  margin-top: 32px;
}
.hero-card__watermark {
  position: absolute;
  right: -20px;
  bottom: -40px;
  font-size: 200px;
  opacity: .07;
  pointer-events: none;
  line-height: 1;
}
.hero-card__title {
  font-size: 36px;
  font-weight: 900;
  letter-spacing: -.03em;
  margin-bottom: 10px;
}
.hero-card__title--sm {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: normal;
}
.hero-card__subtitle {
  font-size: 16px;
  opacity: .85;
  max-width: 540px;
  margin: 0 auto;
  line-height: 1.6;
}
.hero-card__subtitle--sm {
  font-size: 14px;
  opacity: .85;
  margin-bottom: 20px;
}

/* ── CTA buttons (bigger, pill-ish, for use inside hero cards) ── */
.cta-btn {
  display: inline-block;
  padding: 12px 28px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 700;
  text-decoration: none;
  margin-right: 10px;
}
.cta-btn--primary {
  background: #fff;
  color: var(--text-head);
}
.cta-btn--ghost {
  background: rgba(255,255,255,.15);
  color: #fff;
  padding: 12px 24px;
  border: 2px solid rgba(255,255,255,.4);
}

/* ── Pill label (small uppercase section marker) ── */
.pill-label {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: .05em;
}

/* ── Quick-links row (wrapping flex row of small links) ── */
.quick-links {
  background: var(--panel-bg);
  border-radius: var(--radius-md);
  padding: 16px 20px;
  margin-bottom: 24px;
  box-shadow: var(--panel-shadow);
  display: flex;
  flex-wrap: wrap;
  gap: 10px 20px;
}
.quick-links__title {
  width: 100%;
}
.quick-links__link {
  font-size: 13px;
  color: var(--text-accent);
  text-decoration: none;
}
.quick-links__link:hover { text-decoration: underline; }

/* ── Copyright footer (end-of-page legal text) ── */
.copyright-footer {
  text-align: center;
  padding: 20px 0 40px;
  color: var(--text-secondary);
  font-size: 12px;
  line-height: 1.6;
}


/* ═══════════════════════════════════════════════════════════════
   MAP PAGE COMPONENTS
   (relocated from index.html inline <style> block — Phase 1)
   Plaque detail modal, stats row, walks overlay, demo overlay,
   street-view button, captured toggle, sign-in popup.
═══════════════════════════════════════════════════════════════ */

/* ── Plaque Detail Modal ────────────────────────────────────────────────── */
#plaque-detail-modal {
  position: fixed; inset: 0; z-index: 2500;
  display: flex; align-items: flex-end; justify-content: center;
}
.pdm-backdrop {
  position: absolute; inset: 0;
  background: rgba(0,0,0,.45);
}
.pdm-card {
  position: relative; z-index: 1;
  background: var(--panel-bg, #fff);
  border-radius: 20px 20px 0 0;
  width: 100%; max-width: 560px;
  max-height: 85vh; overflow-y: auto;
  box-shadow: 0 -4px 32px rgba(0,0,0,.25);
  animation: pdm-slide-up .25s ease;
}
@keyframes pdm-slide-up {
  from { transform: translateY(60px); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}
.pdm-close {
  position: absolute; top: 12px; right: 16px; z-index: 2;
  background: rgba(0,0,0,.08); border: none; border-radius: 50%;
  width: 30px; height: 30px; font-size: 18px; line-height: 1;
  cursor: pointer; color: inherit;
  display: flex; align-items: center; justify-content: center;
}
.pdm-close:hover { background: rgba(0,0,0,.15); }
.pdm-cat-bar {
  padding: 6px 16px;
  font-size: 11px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .07em; color: #fff;
  border-radius: 20px 20px 0 0;
}
.pdm-body { padding: 16px 20px 28px; }
.pdm-name {
  font-size: 22px; font-weight: 900; color: var(--text-head, #1e293b);
  margin: 0 0 8px; line-height: 1.2;
}
.pdm-meta {
  font-size: 13px; color: var(--text-secondary, #64748b);
  margin-bottom: 10px;
}
.pdm-inscription {
  /* Updated 2026-05-07c — soft grey backdrop card. Sizing/colour
     bumped up in index.html for the modal context. The card visual
     treatment carries an implicit "this is the plaque text" meaning
     so no INSCRIPTION label is rendered above it. Info blocks below
     (Address / Issued by) deliberately use a different idiom (flat,
     thin-bordered) to create hierarchy: card = "the plaque speaks",
     bordered rows = "facts about the plaque". */
  font-size: 13px; color: #475569;
  font-style: italic; line-height: 1.55;
  margin: 10px 0 16px;
  padding: 14px 16px;
  background: #f1f5f9;
  border: 0;
  border-radius: 10px;
}
.pdm-stats {
  display: flex; flex-direction: column; gap: 10px;
  margin-bottom: 16px;
}
.pdm-stat {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  background: var(--panel-faint, rgba(0,0,0,.04));
  padding: 10px 14px; border-radius: 10px;
  font-size: 14px; color: var(--text-primary, #334155);
}
.pdm-stat-icon { font-size: 20px; flex-shrink: 0; }
.pdm-stat-label { color: var(--text-secondary, #64748b); font-size: 13px; }
.pdm-stat-val { font-size: 18px; font-weight: 900; color: var(--text-accent, #1a6ea8); }
.pdm-stat-loading { color: var(--text-secondary, #94a3b8); font-size: 13px; font-style: italic; }
.pdm-stat-uncaptured { color: var(--text-secondary, #94a3b8); font-size: 13px; }
.pdm-captured-badge {
  text-align: center; padding: 10px;
  background: rgba(22,163,74,.1); color: #15803d;
  border-radius: 10px; font-size: 14px; font-weight: 700;
}
.pdm-capture-btn {
  width: 100%; padding: 13px;
  background: var(--text-accent, #1a6ea8); color: #fff;
  border: none; border-radius: 12px;
  font-size: 15px; font-weight: 700; cursor: pointer;
  transition: opacity .15s;
}
.pdm-capture-btn:hover { opacity: .85; }

/* Sticky modal footer holding the Visit button. Lives outside the
   scrollable pdm-body so the button is always visible regardless of
   how much content is above. Drop shadow at the top edge so scrolled
   content reads as "going under" the footer rather than abutting it. */
.pdm-footer {
  flex-shrink: 0;
  padding: 12px 20px calc(12px + env(safe-area-inset-bottom, 0px));
  background: #fff;
  border-top: 1px solid rgba(0,0,0,0.06);
  box-shadow: 0 -4px 12px rgba(0,0,0,0.04);
}

/* Compact meta row: replaces the verbose "Address" / "Issued by" labelled
   blocks with a one-line summary plus an (i) toggle. Saves vertical space
   so the Visit button is more likely to be visible without scrolling.
   Tap the (i) to expand the full Address + Issued by details below. */
.pdm-meta-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
  padding: 8px 12px;
  background: rgba(15,23,42,0.04);
  border-radius: 10px;
  font-size: 13px;
  color: var(--text-secondary, #475569);
  min-width: 0;
}
.pdm-meta-summary {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pdm-meta-summary em {
  font-style: italic;
  color: var(--text-secondary, #94a3b8);
}
.pdm-meta-toggle {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  background: transparent;
  border: none;
  border-radius: 50%;
  color: var(--text-accent, #1a6ea8);
  cursor: pointer;
  padding: 0;
  transition: background .15s;
}
.pdm-meta-toggle:hover { background: rgba(15,23,42,0.08); }
.pdm-meta-toggle:active { transform: scale(0.94); }
.pdm-meta-toggle[aria-expanded="true"] {
  background: rgba(26,110,168,0.12);
}

/* Expanded details panel — same layout as the old pdm-info-blocks. */
.pdm-meta-details {
  margin-top: 8px;
  padding: 12px 14px;
  background: rgba(15,23,42,0.02);
  border-radius: 10px;
  border: 1px solid rgba(0,0,0,0.04);
}
.pdm-meta-details[hidden] { display: none; }
.pdm-meta-details .pdm-info-block {
  margin-bottom: 10px;
}
.pdm-meta-details .pdm-info-block:last-child {
  margin-bottom: 0;
}
.pdm-meta-details .pdm-info-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--text-secondary, #64748b);
  font-weight: 600;
  margin-bottom: 2px;
}
.pdm-meta-details .pdm-info-value {
  font-size: 14px;
  color: var(--text-primary, #0f172a);
  line-height: 1.4;
}

/* Inscription clamp — cap default height with line-clamp; Read more
   button sits inside the block at bottom-right with a gradient fade
   beneath it so the chopped last line reads as a deliberate fade rather
   than an awkward cut. JS reveals the button only when the content
   actually overflows (checked via scrollHeight vs clientHeight). */
.pdm-inscription-wrap {
  position: relative;
  margin-top: 12px;
}
#plaque-detail-modal .pdm-inscription-wrap .pdm-inscription {
  display: -webkit-box;
  -webkit-line-clamp: 5;
  -webkit-box-orient: vertical;
  overflow: hidden;
  /* No max-height: a fixed em cap doesn't align to the line grid and slices
     through a line (the mid-line crop bug). -webkit-line-clamp alone
     truncates cleanly between lines. white-space:normal (not the base rule's
     pre-wrap) is required so the clamp counts wrapped lines correctly; the
     #id prefix lets it beat index.html's #plaque-detail-modal .pdm-inscription
     rule. Expanding restores pre-wrap so the full text keeps its line breaks. */
  white-space: normal !important;
  margin: 0 !important;
}
.pdm-inscription-wrap .pdm-inscription {
  display: -webkit-box;
  -webkit-line-clamp: 5;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: 0 !important;
}
#plaque-detail-modal .pdm-inscription-wrap.is-expanded .pdm-inscription,
.pdm-inscription-wrap.is-expanded .pdm-inscription {
  -webkit-line-clamp: unset;
  max-height: none;
  overflow: visible;
  white-space: pre-wrap !important;
}
/* Read more — a clean button on its OWN LINE below the inscription box.
   (Previously absolute-positioned inside the wrap with a fade gradient, but
   that anchored to the full text height — not the clamped height — so on long
   inscriptions the button floated mid-block over greyed-out words. A plain
   below-box button is clearer and never overlaps the text.) */
.pdm-inscription-more {
  display: none;  /* shown by JS only when the clamp is active */
  margin: 6px 2px 0;
  padding: 2px 0;
  border: none;
  background: transparent;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-accent, #1a6ea8);
  cursor: pointer;
  font-style: normal;  /* override inscription's italic */
  text-decoration: underline;
  text-align: left;
}
.pdm-inscription-more:hover { text-decoration: none; }
.pdm-inscription-wrap.is-expanded .pdm-inscription-more {
  margin-top: 8px;
}

/* "Pin here" — secondary action for reporting an incorrect plaque location.
   Disabled now (backend not yet wired); styling reflects the disabled state. */
.pdm-pin-btn {
  width: 100%;
  margin-top: 8px;
  padding: 11px;
  background: transparent;
  color: var(--text-primary, #1f2937);
  border: 1.5px solid var(--panel-bd, rgba(0,0,0,.15));
  border-radius: 12px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  opacity: 1;
}
.pdm-pin-btn:hover { opacity: 0.85; }
.pdm-pin-btn:disabled,
.pdm-pin-btn[disabled] {
  cursor: not-allowed;
  opacity: 0.65;
  border-style: dashed;
  color: var(--text-secondary, #6b7280);
}
.pdm-pin-btn:disabled:hover,
.pdm-pin-btn[disabled]:hover { opacity: 0.65; }
.pdm-pin-badge {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  background: var(--panel-faint, rgba(0,0,0,.06));
  color: var(--text-secondary, #6b7280);
  padding: 2px 7px;
  border-radius: 10px;
}

/* Plaque-level stats row in detail modal */
.pdm-plaque-stats {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin: 10px 0;
  padding: 10px 14px;
  background: var(--panel-faint, rgba(0,0,0,.04));
  border-radius: 10px;
}
.pdm-plaque-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  flex: 1;
  min-width: 60px;
}
.pdm-plaque-num {
  font-size: 22px;
  font-weight: 900;
  color: var(--text-accent, #1a6ea8);
  line-height: 1;
}
.pdm-plaque-lbl {
  font-size: 11px;
  color: var(--text-secondary, #64748b);
  text-align: center;
  line-height: 1.3;
}


/* Captured plaques toggle button — legacy header-button styling.
   When the button lives inside the actions menu (now the default), reset
   those background/border/pseudo-element rules so it inherits the clean
   menu-item look. */
#btn-captured-toggle {
  display: none;
  align-items: center;
  gap: 5px;
  height: 34px;
  padding: 0 10px 0 8px;
  background: rgba(34,197,94,.18);
  border: 1.5px solid rgba(34,197,94,.5);
  border-radius: 8px;
  color: #fff;
  cursor: pointer;
  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;
  transition: background .15s, border-color .15s;
  flex-shrink: 0;
}
#btn-captured-toggle::before {
  content: '\2713';
  font-size: 14px;
  font-weight: 900;
  color: #4ade80;
}
#btn-captured-toggle:hover {
  background: rgba(34,197,94,.28);
  border-color: #4ade80;
}
#btn-captured-toggle.active {
  background: #16a34a;
  border-color: #15803d;
  color: #fff;
  box-shadow: 0 0 0 2px rgba(34,197,94,.35);
}
#btn-captured-toggle.active::before {
  color: #fff;
}
#captured-toggle-count {
  font-size: 13px;
  font-weight: 800;
}

/* Override pill-button styles when the captured-toggle is inside the actions
   menu. Match the new floating-pill treatment of other menu items. The
   captured-toggle isn't currently rendered in the menu (removed 2026-04-23)
   but this guard remains defensive in case it's reintroduced. */
.actions-menu #btn-captured-toggle,
.actions-menu #btn-captured-toggle.active {
  background: #ffffff;
  border: none;
  border-radius: 999px;
  height: auto;
  padding: 14px 18px;
  color: var(--text-head, #1b3a6b);
  box-shadow: 0 4px 14px rgba(15,23,42,.18), 0 1px 3px rgba(15,23,42,.08);
  font-size: 15px;
  font-weight: 600;
}
.actions-menu #btn-captured-toggle:hover {
  background: #f8fafc;
  border: none;
  color: var(--text-head, #1b3a6b);
}
.actions-menu #btn-captured-toggle::before,
.actions-menu #btn-captured-toggle.active::before {
  content: none;
}
.actions-menu #captured-toggle-count {
  font-size: 11px;
  font-weight: 800;
}


/* Sign-in prompt button in plaque popup */
.plaque-popup-btn.btn-signin-prompt {
  background: var(--panel-faint);
  color: var(--text-accent);
  border: 1.5px solid var(--text-accent);
}
.plaque-popup-btn.btn-signin-prompt:hover {
  background: var(--text-accent);
  color: #fff;
}


/* ── Demo overlay ──────────────────────────────────────────── */
#demo-overlay {
  position: fixed;
  bottom: 80px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 4000;
  width: 100%;
  max-width: 360px;
  padding: 0 12px;
  box-sizing: border-box;
  pointer-events: none;
}
#demo-card {
  background: linear-gradient(135deg, #1b3a6b, #0e4f80);
  border-radius: 16px;
  padding: 18px 18px 16px;
  box-shadow: 0 8px 40px rgba(0,0,0,.45);
  pointer-events: all;
  animation: pdm-slide-up .3s ease;
}


/* Street View button */
.plaque-popup-btn.btn-streetview {
  background: rgba(66, 133, 244, 0.12);
  color: #4285f4;
  border: 1px solid rgba(66, 133, 244, 0.35);
}
.plaque-popup-btn.btn-streetview:hover {
  background: #4285f4;
  color: #fff;
}


/* Show walks overlay button */
#btn-show-walks {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  background: var(--hdr-btn-bg);
  border: 1.5px solid rgba(255,255,255,.25);
  border-radius: 8px;
  color: #fff;
  cursor: pointer;
  font-size: 16px;
  transition: background .15s, border-color .15s;
  flex-shrink: 0;
}
#btn-show-walks:hover {
  background: var(--hdr-btn-hov);
}
#btn-show-walks.active {
  background: #16a34a;
  border-color: #15803d;
  box-shadow: 0 0 0 2px rgba(34,197,94,.35);
}
/* Walks overlay panel */
#walks-overlay-panel {
  position: absolute;
  bottom: 80px;
  left: 8px;
  z-index: 1500;
  background: var(--panel-bg);
  border-radius: 12px;
  box-shadow: 0 4px 24px rgba(0,0,0,.2);
  width: 240px;
  max-height: 50vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  animation: plakka-slide-up .2s ease;
}
@media (max-width: 480px) {
  #walks-overlay-panel {
    width: calc(100vw - 16px);
    left: 8px;
    right: 8px;
    bottom: 70px;
  }
}
#walks-overlay-panel .wop-header {
  padding: 12px 14px 8px;
  font-size: 14px;
  font-weight: 800;
  color: var(--text-head);
  border-bottom: 1px solid var(--panel-bd);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
#walks-overlay-panel .wop-toggle-row {
  padding: 8px 14px;
  border-bottom: 1px solid var(--panel-faint);
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 13px;
  color: var(--text-secondary);
}
#walks-overlay-panel .wop-list {
  overflow-y: auto;
  padding: 6px 0;
  flex: 1;
}
#walks-overlay-panel .wop-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  cursor: pointer;
  transition: background .12s;
  border-left: 3px solid transparent;
}
#walks-overlay-panel .wop-item:hover { background: var(--panel-hover); }
#walks-overlay-panel .wop-item.active { border-left-color: var(--text-accent); background: var(--panel-hl); }
#walks-overlay-panel .wop-dot {
  width: 10px; height: 10px; border-radius: 50%;
  flex-shrink: 0;
}
#walks-overlay-panel .wop-name {
  font-size: 13px; font-weight: 600; color: var(--text-primary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1;
}
#walks-overlay-panel .wop-meta {
  font-size: 11px; color: var(--text-secondary);
}
/* Toggle switch */
.wop-switch {
  position: relative; width: 36px; height: 20px;
}
.wop-switch input { opacity:0; width:0; height:0; }
.wop-switch-slider {
  position: absolute; inset: 0; border-radius: 20px;
  background: var(--panel-bd); cursor: pointer;
  transition: background .2s;
}
.wop-switch-slider:before {
  content: ''; position: absolute;
  width: 14px; height: 14px; border-radius: 50%;
  left: 3px; top: 3px;
  background: #fff; transition: transform .2s;
}
.wop-switch input:checked + .wop-switch-slider { background: #16a34a; }
.wop-switch input:checked + .wop-switch-slider:before { transform: translateX(16px); }


/* ── ACTIONS MENU (⋯ button + dropdown) ─────────────────────────────── */

/* Header trigger button for the actions menu. */
.btn-actions-hdr {
  padding: 0; width: 32px; height: 32px; border: none;
  background: var(--hdr-btn-bg); border-radius: 50%;
  color: var(--hdr-text); font-size: 22px; font-weight: 700;
  cursor: pointer; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  align-self: center; margin-left: 6px; margin-right: 8px;
  border: 1.5px solid rgba(255,255,255,.25);
  transition: background .15s, transform .15s;
  line-height: 1;
}
.btn-actions-hdr:hover { background: var(--hdr-btn-hov); }
.btn-actions-hdr:active { transform: scale(0.94); }

/* --right variant: floats to the far right (for pages without a reset button). */
.btn-actions-hdr--right { margin-left: auto; }

/* Dark variant — used on pages with a light-background header area (profile). */
.btn-actions-hdr--dark {
  background: var(--panel-faint, rgba(0,0,0,0.04));
  color: var(--text-head, #1b3a6b);
  border: 1.5px solid var(--panel-bd, rgba(0,0,0,0.1));
  margin-left: 8px;
  margin-right: 0;
}
.btn-actions-hdr--dark:hover { background: var(--panel-hover, rgba(0,0,0,0.08)); }

/* Dropdown menu — hidden by default, slides down when is-open.
   Styled to match Plakka's navy+blue palette rather than a flat white sheet. */
/* ── Actions menu — Strava-style floating pills ─────────────────────────
   Each item is its own white pill with soft shadow, no surrounding card.
   The container is just a positioning wrapper. Items cascade in on open. */
/* ── ACTIONS MENU ──────────────────────────────────────────────────
   Drops down from the header's ⋮ button. Single continuous card,
   Strava-style — items live INSIDE one rounded white panel separated
   by hairline dividers, NOT as separate floating pills (2026-04-25).
   With one item the card collapses neatly to a single pill. Items can
   still toggle (.is-active / .active) for amber-tinted state.

   Right-edge aligns with the layers FAB (right: 10px) so the menu
   sits ON TOP OF the FAB while open — the FAB is hidden until the
   menu closes. Visually cleaner than two elements jostling for the
   top-right zone. */
.actions-menu {
  position: fixed;
  top: 56px;
  right: 10px;
  min-width: 180px;
  max-width: 240px;
  background: #ffffff;
  border: none;
  border-radius: 16px;
  box-shadow: 0 8px 24px rgba(15,23,42,.18), 0 1px 3px rgba(15,23,42,.08);
  z-index: 1200;
  padding: 6px;       /* small inner padding so the divider stops short of the edge */
  display: flex;
  flex-direction: column;
  overflow: hidden;
  opacity: 0;
  transform: translateY(-4px);
  pointer-events: none;
  transition: opacity .15s ease, transform .15s ease;
}
.actions-menu.is-open {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

/* Suppress the actions menu entirely while route-building. The route-hint
   sits at top centre and the menu sits at top right; on narrow Android
   viewports they overlap unreadably. Belt-and-braces — startRouteBuilder
   calls closeActionsMenu(), but this CSS rule guarantees the menu is
   invisible even if the menu somehow gets reopened during route mode. */
body.route-building .actions-menu {
  display: none !important;
}

.actions-menu__item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 12px 14px;
  background: transparent;        /* card supplies the background */
  border: none;
  border-radius: 10px;             /* soft corner so hover/active highlight feels tidy inside the card */
  font-size: 15px;
  font-weight: 600;
  color: var(--text-head, #1b3a6b);
  cursor: pointer;
  text-align: left;
  min-height: 44px;
  text-decoration: none;
  box-shadow: none;
  position: relative;
  transition: background .12s, color .12s;
}

/* Hairline divider between items (skip after last) — keeps the card feeling
   like one continuous surface rather than disconnected pills. */
.actions-menu__item + .actions-menu__item {
  border-top: 1px solid #f1f5f9;   /* slate-100 */
  border-radius: 0 0 10px 10px;
}
.actions-menu__item + .actions-menu__item ~ .actions-menu__item {
  border-radius: 0;
}
.actions-menu__item:last-child:not(:first-child) {
  border-radius: 0 0 10px 10px;
}

.actions-menu__item:hover {
  background: #f8fafc;       /* slate-50 — subtle, matches in-card hover */
}
.actions-menu__item:active {
  background: #f1f5f9;       /* slate-100 */
}

/* Toggled-on state: amber tint with leading dot indicator. Same colours
   as the layers FAB so toggle-on feels visually coherent across both
   surfaces. Both .is-active and .active matched (legacy + new). */
.actions-menu__item.is-active,
.actions-menu__item.active {
  background: #fffbeb;     /* amber-50 */
  color: #92400e;          /* amber-800 */
}
.actions-menu__item.is-active::before,
.actions-menu__item.active::before {
  content: '';
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: #f59e0b;     /* amber-500 */
  flex-shrink: 0;
  margin-right: 2px;
}

.actions-menu__icon {
  font-size: 18px;
  width: 22px;
  text-align: center;
  flex-shrink: 0;
  color: var(--text-accent, #1e8fd4);
}

/* Toggle-style menu item — keeps the row look but pushes the count to
   the right. Used by the "Captured plaques only" toggle. */
.actions-menu__item--toggle { justify-content: space-between; }
.actions-menu__item--toggle .actions-menu__item-label { flex: 1; margin-right: 8px; }

.actions-menu__tick {
  display: none;
  color: #16a34a;
  font-size: 16px;
  font-weight: 800;
  margin-right: 4px;
  flex-shrink: 0;
}
.actions-menu__item.is-active .actions-menu__tick { display: inline-block; }
.actions-menu__item.is-active .actions-menu__count {
  background: var(--text-accent, #1e8fd4);
  color: #fff;
}

/* Sign-out item — red tint on label for destructive action */
.actions-menu__item--signout {
  color: #dc2626;
  font-weight: 500;
}
.actions-menu__item--signout:hover {
  background: #fef2f2;
  color: #b91c1c;
}
.actions-menu__item--signout .actions-menu__icon { color: inherit; }

.actions-menu__count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--text-accent, #1e8fd4);
  color: #fff;
  font-size: 11px;
  font-weight: 800;
  padding: 2px 9px;
  border-radius: 10px;
  min-width: 24px;
  height: 20px;
  flex-shrink: 0;
  letter-spacing: 0.02em;
}

.actions-menu__sep {
  height: 1px;
  background: var(--panel-bd, rgba(0,0,0,0.08));
  margin: 6px 10px;
}

/* Strength slider row inside the menu. */
.actions-menu__slider { padding: 10px 16px 14px; }
.actions-menu__slider-row {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 10px;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary, #1a2a3a);
}
.actions-menu__label { flex: 1; }
.actions-menu__slider-value {
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--text-accent, #1e8fd4);
  min-width: 26px;
  text-align: right;
}
.actions-menu__slider input[type=range] {
  width: 100%; height: 5px;
  -webkit-appearance: none; appearance: none;
  background: var(--panel-bd, rgba(0,0,0,0.15));
  border-radius: 3px; outline: none;
  cursor: pointer;
}
.actions-menu__slider input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--text-accent, #1e8fd4);
  cursor: pointer; border: 2px solid #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,0.2);
}
.actions-menu__slider input[type=range]::-moz-range-thumb {
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--text-accent, #1e8fd4);
  cursor: pointer; border: 2px solid #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,0.2);
}


/* ── BOTTOM NAV (mobile only — hidden on desktop) ───────────────────── */

/* Three-tab bottom navigation bar. Map / Visits / My Plakka.
   Visible only on viewports 700px wide or less — desktop keeps its header nav.
   Injected on every page by nav.js; CSS controls visibility.
   Fixed to the viewport bottom on every page so it's always there. */
.bottom-nav {
  display: none;
  height: 64px;
  background: #fff;
  border-top: 1px solid rgba(0,0,0,0.08);
  z-index: 1050;
  padding-bottom: env(safe-area-inset-bottom, 0);
  box-shadow: 0 -4px 16px rgba(27,58,107,0.12);
  flex-shrink: 0;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  /* Force GPU compositing to avoid jitter/scroll-lag on mobile browsers
     (iOS Safari and mobile Chrome both handle fixed-position elements
     better when they're on their own compositor layer). */
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
  will-change: transform;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.bottom-nav__tab {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 6px 4px;
  text-decoration: none;
  color: #666;
  font-size: 10px;
  font-weight: 600;
  gap: 2px;
  background: transparent;
  border: none;
  cursor: pointer;
  min-height: 44px;
  -webkit-tap-highlight-color: transparent;
}
.bottom-nav__tab.is-active {
  color: var(--text-head, #1b3a6b);
  background: var(--panel-hover, rgba(30,143,212,0.08));
  font-weight: 800;
  box-shadow: inset 0 3px 0 var(--text-accent, #1e8fd4);
}
.bottom-nav__tab.is-active .bottom-nav__icon { transform: scale(1.1); }
.bottom-nav__tab.is-active .bottom-nav__label {
  color: var(--text-accent, #1e8fd4);
  font-weight: 800;
}
.bottom-nav__tab:active { background: rgba(0,0,0,0.04); }

.bottom-nav__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: transform .15s ease;
}
.bottom-nav__svg {
  width: 24px;
  height: 24px;
  display: block;
}
.bottom-nav__label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.2px;
}

/* "Back to My Plakka" variant — single full-width link for sub-pages. */
.bottom-nav--back { align-items: stretch; }
.bottom-nav__back {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  text-decoration: none;
  color: var(--text-accent, #1e8fd4);
  font-size: 14px;
  font-weight: 700;
  -webkit-tap-highlight-color: transparent;
  background: transparent;
  min-height: 44px;
}
.bottom-nav__back:hover { background: rgba(0,0,0,0.02); }
.bottom-nav__back:active { background: rgba(0,0,0,0.06); }
.bottom-nav__back-arrow {
  font-size: 20px;
  line-height: 1;
}
.bottom-nav__back-label {
  font-size: 14px;
  font-weight: 700;
}

/* Show bottom nav on mobile; hide the site footer (desktop chrome).
   Pages with scrolling content (auth-guarded pages + content pages) get
   bottom padding so content doesn't hide behind the fixed nav. */
@media (max-width: 700px) {
  .bottom-nav { display: flex; }
  .site-footer { display: none !important; }

  /* Scrolling pages — add padding to body so last content isn't hidden */
  html.auth-guarded body,
  body.content-page {
    padding-bottom: 64px;
    padding-bottom: calc(64px + env(safe-area-inset-bottom, 0));
  }

  /* Map page (index.html) — body is 100dvh overflow:hidden flex, so we
     shrink the flex child .map-wrap instead. .map-wrap only exists on
     index.html so this rule is safely scoped.
     NOTE: reserve only the nav's 64px CONTENT height here. The body is
     100dvh, which already excludes the system-gesture-bar region, and the
     fixed .bottom-nav carries its own padding-bottom:env(safe-area-inset-
     bottom). Adding the inset here too double-counts it and leaves a gap
     between the map and the nav (the pale band bug, fixed 2026-05-26). */
  .map-wrap {
    margin-bottom: 64px;
  }
}

/* ── LEADERBOARD — narrow-portrait adjustments ────────────────────────
   On mobile phones in PORTRAIT, hide lower-priority columns on the
   Plaque Rankings table so the plaque name gets more width.
   In landscape (or wider viewports) all columns show.

   Plaques table columns: 1=#, 2=Plaque, 3=Borough, 4=Visits, 5=Strength, 6=Category
*/
@media (max-width: 700px) and (orientation: portrait) {
  /* Plaques table: hide Borough (col 3), Strength (col 5), Category (col 6).
     Visible columns: # / Plaque / Visits */
  #plaque-table th:nth-child(3),
  #plaque-table td:nth-child(3),
  #plaque-table th:nth-child(5),
  #plaque-table td:nth-child(5),
  #plaque-table th:nth-child(6),
  #plaque-table td:nth-child(6) {
    display: none;
  }
}

/* ── Walk info floating button ────────────────────────────────────────
   Sits in the top-right of the map viewport when a walk is displayed
   but the walk panel is closed. Tapping it re-opens the walk panel.
   Hidden by default; shown by updateWalkFabVisibility() in index.html. */
#btn-walk-info {
  position: absolute;
  top: 58px;
  right: 10px;
  z-index: 800;
  display: none; /* toggled by JS to 'flex' when relevant */
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  background: var(--panel-bg, #fff);
  color: var(--text-head, #1b3a6b);
  border: 1px solid var(--panel-bd, rgba(0,0,0,0.1));
  border-radius: 20px;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(27,58,107,0.15);
  transition: transform .15s, box-shadow .15s;
}
#btn-walk-info:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 14px rgba(27,58,107,0.2);
}
#btn-walk-info:active { transform: translateY(0); }

/* Mobile: keep it nicely positioned below the header (still 48px tall) */
@media (max-width: 700px) {
  #btn-walk-info {
    top: 58px;
    right: 10px;
    padding: 7px 12px;
    font-size: 12px;
  }
}


/* ═══════════════════════════════════════════════════════════════
   PLAQUE COLOURS — actions-menu controls + filter chips + map markers
   for the "Show plaque colours" feature (added 2026-05-05).

   The toggle lives in the actions menu (⋮ button → menu). When ON,
   markers render with bucket-coloured fills; when OFF (default),
   the existing medal-fill / capture-border behaviour is unchanged.

   Filter chips (one per bucket) sit alongside the toggle. Each chip
   is a click-target — toggling it filters which schemes are visible.
   The chips are always present (independent of the toggle state) so
   "Filter to Blue plaques" works in either marker mode.
═══════════════════════════════════════════════════════════════ */

/* Section divider in the actions menu */
.actions-menu__section {
  border-top: 1px solid var(--panel-bd);
  padding: 10px 12px 4px;
}
.actions-menu__section-title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin: 0 0 6px;
}

/* Toggle row — label + switch on right */
.actions-toggle {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 0;
  cursor: pointer;
  user-select: none;
  font-size: 14px;
  color: var(--text-primary);
}
.actions-toggle:hover { color: var(--text-head); }
.actions-toggle input[type="checkbox"] { display: none; }
.actions-toggle .switch {
  width: 36px; height: 20px;
  background: #cbd5e1;
  border-radius: 10px;
  position: relative;
  transition: background var(--t-base);
  flex-shrink: 0;
}
.actions-toggle .switch::after {
  content: '';
  position: absolute; top: 2px; left: 2px;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,.2);
  transition: left var(--t-base);
}
.actions-toggle input:checked + .switch { background: #15803d; }
.actions-toggle input:checked + .switch::after { left: 18px; }

/* Filter chip strip in the actions menu — wraps to multiple rows on
   narrow screens. Order matches Buckets() server-side. */
.scheme-chips {
  display: flex; flex-wrap: wrap; gap: 6px;
  padding: 4px 0 8px;
}
.scheme-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px;
  border: 1.5px solid var(--panel-bd);
  border-radius: 14px;
  background: var(--panel-bg);
  font-size: 12px;
  font-weight: 600;
  color: var(--text-primary);
  cursor: pointer;
  user-select: none;
  transition: opacity var(--t-fast), border-color var(--t-fast);
}
.scheme-chip:hover { border-color: var(--text-head); }
.scheme-chip .scheme-dot {
  width: 10px; height: 10px;
  border-radius: 50%;
  border: 1px solid rgba(0,0,0,.2);
  flex-shrink: 0;
}
/* When chip is OFF (scheme excluded), fade everything */
.scheme-chip.is-off {
  opacity: 0.4;
  text-decoration: line-through;
}
.scheme-chip.is-off:hover { opacity: 0.7; }

/* Per-bucket dot colour — matches the map markers exactly */
.scheme-dot--blue   { background: var(--bucket-blue);   }
.scheme-dot--black  { background: var(--bucket-black);  }
.scheme-dot--green  { background: var(--bucket-green);  }
.scheme-dot--red    { background: var(--bucket-red);    }
.scheme-dot--white  { background: var(--bucket-white);  }
.scheme-dot--yellow { background: var(--bucket-yellow); }
.scheme-dot--brown  { background: var(--bucket-brown);  }
.scheme-dot--grey   { background: var(--bucket-grey);   }
.scheme-dot--other  { background: var(--bucket-other);  }

/* Reset button below chips */
.scheme-chip-reset {
  align-self: center;
  margin-left: auto;
  background: none; border: none;
  font-size: 11px;
  color: var(--text-secondary);
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 4px;
}
.scheme-chip-reset:hover {
  background: var(--panel-hover);
  color: var(--text-head);
}

/* Map markers in colours mode. Used by app.js renderPlaqueMarkers()
   when filter.colourMode === true. The marker is an 18px (or 26px
   when searching) round dot with bucket-coloured fill, plus a
   capture-state border (green when captured, white otherwise).

   Implementation note: app.js writes inline style for fill colour
   (so it can pull from the CSS variables via getComputedStyle, or
   resolve at JS level via a small palette object). The classes
   below provide hover + the visited-state border treatment, but
   the actual fill comes from inline style at render time. This
   keeps the CSS slim — only one rule for the marker shell. */
.pl-marker-coloured {
  width: 100%; height: 100%;
  border-radius: 50%;
  border: 2px solid #fff;
  box-shadow: 0 1px 4px rgba(0,0,0,.3);
  box-sizing: border-box;
}
/* Captured-state in colours mode — green border replaces the white */
.pl-marker-coloured.is-captured {
  border-color: #16a34a;
  border-width: 3px;
}

/* ── WALK SHEET ─────────────────────────────────────────────────────────
   Bottom sheet companion for index.html's walk-following experience.
   Three height tiers: peek (default), half, full. See walk-sheet.js for
   the JS that drives mount/destroy/drag/snap.

   Z-index: 1080 — above bottom-nav (1050), below filter modal (1100) and
   plaque popup (1600). The filter modal taking precedence is deliberate;
   filtering plaques is a deliberate modal interaction that needs the
   sheet out of the way.

   Heights:
     peek — 38px fixed: drag handle + one-line title
     half — 55vh: shows header buttons + 3-4 stops
     full — 92vh: covers the bottom-nav, list-replacement reading mode
*/
.walk-sheet {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 64px;  /* sits above bottom-nav by default */
  bottom: calc(64px + env(safe-area-inset-bottom, 0px));
  background: #fff;
  border-radius: 14px 14px 0 0;
  box-shadow: 0 -4px 18px rgba(0,0,0,0.12);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  z-index: 1080;
  height: 38px;
  transition: height 0.22s cubic-bezier(0.4, 0, 0.2, 1),
              bottom 0.22s cubic-bezier(0.4, 0, 0.2, 1);
  /* GPU compositing — same reasoning as .bottom-nav: avoids jitter on
     mobile when the sheet height changes via transition. */
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
  will-change: height, bottom;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.walk-sheet--peek { height: 38px; }
.walk-sheet--half { height: 55vh; }
/* Full tier: covers the bottom-nav, so anchor to bottom: 0 instead of
   above the nav. The height matches the mockup's "all but the blue
   header" coverage. */
.walk-sheet--full {
  height: 92vh;
  bottom: 0;
  border-radius: 14px 14px 0 0;
}

/* Drag handle — the strip with the visible bar. Strip itself is the
   touch target (~28px tall including padding) so it's easy to grip;
   the visible bar inside is the visual affordance. */
.walk-sheet__handle {
  padding: 8px 0 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  cursor: ns-resize;
  touch-action: none;  /* prevent browser drag interpreting it as scroll */
  user-select: none;
  -webkit-user-select: none;
}
.walk-sheet__handle-bar {
  width: 40px;
  height: 4px;
  border-radius: 2px;
  background: #cbd5e1;
}
.walk-sheet__handle:active .walk-sheet__handle-bar {
  background: #94a3b8;
}

/* Peek strip — shown ONLY when sheet is in peek state. Title only,
   single-line, ellipsised. Right padding leaves room for the record FAB
   which floats above the sheet's bottom-right (no overlap with title). */
.walk-sheet__peek-strip {
  padding: 0 60px 8px 14px;
  flex-shrink: 0;
  display: none;
}
.walk-sheet--peek .walk-sheet__peek-strip {
  display: block;
}
.walk-sheet__peek-title {
  font-size: 13px;
  font-weight: 500;
  color: #0f172a;
  line-height: 1.2;
  margin: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Header — shown in half + full. Hidden in peek. Contains title, stats,
   and the two action buttons. */
.walk-sheet__header {
  padding: 6px 14px 12px;
  border-bottom: 0.5px solid rgba(0,0,0,0.07);
  flex-shrink: 0;
  display: none;
}
.walk-sheet--half .walk-sheet__header,
.walk-sheet--full .walk-sheet__header {
  display: block;
}
.walk-sheet__title {
  font-size: 16px;
  font-weight: 500;
  color: #0f172a;
  line-height: 1.25;
  margin: 0;
}
.walk-sheet__meta {
  font-size: 12px;
  color: #64748b;
  margin: 4px 0 0;
}

/* Action buttons row. padding-right reserves space for the record FAB. */
.walk-sheet__hdr-btns {
  display: flex;
  gap: 8px;
  margin-top: 10px;
  padding-right: 56px;
}
.walk-sheet__btn {
  flex: 1;
  padding: 9px 8px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 500;
  text-align: center;
  cursor: pointer;
  border: none;
  font-family: inherit;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  transition: background 0.12s, transform 0.08s;
}
.walk-sheet__btn:active {
  transform: scale(0.97);
}
.walk-sheet__btn--done {
  background: #16a34a;
  color: #fff;
}
.walk-sheet__btn--done:hover {
  background: #15803d;
}
.walk-sheet__btn--close {
  background: transparent;
  color: #475569;
  border: 0.5px solid rgba(0,0,0,0.18);
}
.walk-sheet__btn--close:hover {
  background: rgba(0,0,0,0.04);
}

/* Stops list — scrollable, fills remaining vertical space. Padding-bottom
   accounts for the safe-area-inset on full-tier (when the sheet covers
   the nav, the list ends just above the home indicator). */
.walk-sheet__stops {
  padding: 6px 14px;
  overflow-y: auto;
  flex: 1;
  min-height: 0;
  display: none;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 8px;
}
.walk-sheet--half .walk-sheet__stops,
.walk-sheet--full .walk-sheet__stops {
  display: block;
}
.walk-sheet--full .walk-sheet__stops {
  padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
}

/* Stop card. Tap → opens plaque popup (same as map marker tap). */
.walk-sheet__stop {
  display: flex;
  gap: 10px;
  padding: 9px 0;
  border-bottom: 0.5px solid rgba(0,0,0,0.06);
  align-items: flex-start;
  cursor: pointer;
  transition: background 0.12s;
}
.walk-sheet__stop:last-child { border-bottom: none; }
.walk-sheet__stop:active { background: rgba(0,0,0,0.03); }

/* Current/next-stop highlight — amber background row, extends to sheet
   edges via negative margin. Matches the mockup. */
.walk-sheet__stop--current {
  background: #fff7ed;
  margin: 0 -14px;
  padding-left: 14px;
  padding-right: 14px;
}

/* Stop number badge. Numbers for default/current, checkmark for done. */
.walk-sheet__stop-num {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: #1a6ea8;
  color: #fff;
  font-size: 11px;
  font-weight: 500;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  line-height: 1;
  margin-top: 1px;
}
.walk-sheet__stop-num--done {
  background: #16a34a;
}
.walk-sheet__stop-num--current {
  background: #ea580c;
  box-shadow: 0 0 0 3px rgba(234,88,12,0.22);
}

.walk-sheet__stop-info {
  flex: 1;
  min-width: 0;
}
.walk-sheet__stop-name {
  font-size: 13px;
  font-weight: 500;
  color: #0f172a;
  margin: 0;
  line-height: 1.25;
  word-wrap: break-word;
}
.walk-sheet__stop-detail {
  font-size: 11px;
  color: #64748b;
  margin: 2px 0 0;
  line-height: 1.35;
}

/* Per-leg distance: "0.4 km to next stop". A subtle italicised hint
   sitting under the address line. Slightly indented so it visually
   "belongs to" the stop above it rather than reading as the next
   stop's intro. */
.walk-sheet__stop-leg {
  font-size: 10px;
  color: #94a3b8;
  margin: 4px 0 0;
  font-style: italic;
  line-height: 1.2;
}

/* When the walk sheet is open, hide the bottom-nav in full state so the
   sheet visually covers it. Nav remains in DOM (positioned behind the
   sheet) so accessibility tools can still tab to it; only the visual
   layer hides. */
body.walk-sheet-open .walk-sheet--full ~ nav.bottom-nav,
body.walk-sheet-open nav.bottom-nav.is-hidden-by-sheet {
  /* No display:none — keep nav reachable for screen readers.
     The sheet's z-index + opacity-1 surface visually obscures it. */
}
