/* ==========================================================================
   RydR — design tokens
   Palette: neutral slate surfaces, a single confident blue accent, calm
   amber caution and red alert. Type is Inter throughout for a clean,
   modern app feel; telemetry numbers use JetBrains Mono for precision.
   ========================================================================== */
:root{
  --bg-void:#0a0c11;
  --bg-panel:#12151c;
  --bg-panel-raised:#181c26;
  --bg-panel-hover:#1e2330;
  --border-subtle:#212632;
  --border-strong:#333c4c;

  --neon-green:#4f8cff;
  --neon-green-dim:#2c5fc7;
  --neon-green-glow:rgba(79,140,255,0.28);
  --cyan:#22d3ee;
  --alert-red:#ef4444;
  --alert-red-glow:rgba(239,68,68,0.3);
  --warn-amber:#f59e0b;
  /* Labs category accent — nothing else in the app uses violet, which is
     the point: it reads as "new/experimental" at a glance. Light-toned
     themes override this one token below (search "labs-violet") instead
     of every theme needing its own tuned value, since nothing else keys
     off it. */
  --labs-violet:#a78bfa;

  --text-primary:#eef1f5;
  --text-muted:#8b93a3;
  /* Was #565e6c — 2.6-2.8:1 against the panel backgrounds it's actually
     used on (stat labels, panel titles), well under WCAG AA's 4.5:1 for
     normal text. Lightened to clear 4.5:1+ against both --bg-panel and
     --bg-panel-raised while staying visibly dimmer than --text-muted so
     the two still read as a hierarchy, not a coin-flip. */
  --text-dim:#818999;

  /* Menu panel background is its own token (not just re-derived from
     --bg-panel) so it can stay a translucent glass surface — every theme
     sets this to match its own light/dark direction so .menu-link's
     existing --text-muted/--text-primary tokens always land on the
     correct contrast side. */
  --menu-panel-bg:rgba(18,21,28,0.92);

  --font-display:'Barlow Condensed',sans-serif;
  --font-body:'Inter',sans-serif;
  --font-mono:'JetBrains Mono',monospace;

  --radius-sm:8px;
  --radius-md:14px;
  --radius-lg:20px;
  --touch:48px;
}

*{box-sizing:border-box;}
html,body{margin:0;padding:0;}
body{
  background:var(--bg-void);
  background-image:
    radial-gradient(circle at 20% 0%, rgba(79,140,255,0.05), transparent 45%),
    radial-gradient(circle at 85% 100%, rgba(34,211,238,0.03), transparent 45%);
  color:var(--text-primary);
  font-family:var(--font-body);
  min-height:100vh;
  -webkit-font-smoothing:antialiased;
}
a{color:inherit;text-decoration:none;}
button{font-family:inherit;}
::selection{background:var(--neon-green-dim);color:#02110a;}

:focus-visible{
  outline:2px solid var(--neon-green);
  outline-offset:2px;
  border-radius:4px;
}

@media (prefers-reduced-motion: reduce){
  *{animation-duration:0.01ms !important; transition-duration:0.01ms !important;}
}

/* Cross-Document View Transitions (Chrome/Edge on Android as of this
   writing) — a soft cross-fade between full page navigations instead of
   a hard flash-to-white, at the cost of zero JS and zero risk: browsers
   without support simply ignore this at-rule and navigate exactly as
   before. Skipped under reduced-motion for the same reason every other
   animation in this file is. */
@media (prefers-reduced-motion: no-preference){
  @view-transition{
    navigation:auto;
  }
}

/* Labs category accent (see --labs-violet near the top of :root) needs a
   darker, light-background-safe value on every light-toned theme — one
   shared rule instead of six separate per-theme overrides, since nothing
   else keys off this token yet. */
body.theme-light, body.theme-silver, body.theme-sand, body.theme-highvis, body.theme-alpine, body.theme-cloud{
  --labs-violet:#7c5cd6;
}

/* ---------- layout shell ---------- */
.app-shell{
  display:flex;
  flex-direction:column;
  min-height:100vh;
}

/* ---------- Track HUD (racing-telemetry inspired full-screen view) ----------
   Landscape-first layout (matches the reference this was built from); the
   media query near the bottom of this block stacks everything vertically
   for portrait/narrow screens instead of squeezing the horizontal layout. */
.hud-shell{
  background: radial-gradient(circle at 50% 0%, #10151d 0%, #05070a 70%);
  color:#eef3fa;
  padding:28px clamp(16px, 4vw, 48px);
  overflow-y:auto;
}
.hud-topbar{
  display:grid;
  grid-template-columns:1fr auto 1fr;
  align-items:start;
  gap:16px;
  margin-bottom:28px;
  padding-left:44px;
  /* .hud-shell is a flex column with a fixed height:100vh (see
     .full-screen-view). Without flex-shrink:0, a flex column squeezes
     any item that doesn't fit rather than letting the column overflow
     and scroll — and it does this disproportionately, so a row holding
     large fixed-size children (the 220-280px gauge cards below) can get
     squashed down to a few px while those children refuse to shrink,
     spilling out over whatever comes right after them in the layout.
     Locking every row to its natural height turns "silently overlap
     the next section" into "the view scrolls," which is what
     .hud-shell's own overflow-y:auto was already trying to provide. */
  flex-shrink:0;
}
.hud-timer{ display:flex; flex-direction:column; gap:4px; }
.hud-timer-main{ font-family:var(--font-mono); font-size:28px; font-weight:700; letter-spacing:0.02em; }
.hud-timer-sub{ display:flex; gap:14px; font-size:12px; color:#7d8ba0; font-family:var(--font-mono); }
.hud-timer-sub b{ color:#c7d3e6; font-weight:600; }
.hud-brand{ display:flex; flex-direction:column; align-items:center; gap:4px; text-align:center; position:relative; }
.hud-back-btn{
  position:absolute; left:-52px; top:-4px;
  width:36px; height:36px; border-radius:10px;
  display:grid; place-items:center;
  background:rgba(255,255,255,0.06); border:1px solid rgba(255,255,255,0.14); color:#c7d3e6; cursor:pointer;
  font-size:16px;
}
.hud-brand-title{ font-family:var(--font-display); font-weight:700; font-size:16px; letter-spacing:0.03em; color:#fff; text-transform:uppercase; }
.hud-brand-sub{ font-size:11px; color:#7d8ba0; }
.hud-style-toggle{ display:flex; gap:4px; margin-top:8px; background:rgba(255,255,255,0.05); border-radius:999px; padding:3px; }
.hud-style-btn{
  border:none; background:transparent; color:#7d8ba0;
  font-family:var(--font-display); font-weight:600; font-size:10px; letter-spacing:0.04em; text-transform:uppercase;
  padding:5px 12px; border-radius:999px; cursor:pointer;
}
.hud-style-btn.active{ background:rgba(255,255,255,0.14); color:#fff; }
body.theme-light .hud-style-toggle{ background:rgba(0,0,0,0.05); }
body.theme-light .hud-style-btn{ color:#5c6478; }
body.theme-light .hud-style-btn.active{ background:#fff; color:#161a22; box-shadow:0 1px 4px rgba(0,0,0,0.1); }
.hud-weather{ display:flex; flex-direction:column; align-items:flex-end; gap:2px; font-size:12px; color:#9aa8bd; text-align:right; }
.hud-weather div:first-child{ color:#c7d3e6; }

/* Horizontal row on landscape/wide screens (this HUD's primary use case —
   phone mounted landscape on a bike) — if the gauges + mini-stats block
   don't all fit, the row scrolls horizontally instead of squeezing.
   Portrait screens get a stacked layout instead (see the orientation
   media query below); the old trigger for that was `max-width:900px`
   *or* portrait, which also caught plenty of phones in landscape
   (routinely under 900px wide) and stacked them too — narrowed to
   portrait-only so landscape never stacks. */
.hud-gauges-row{
  display:flex;
  align-items:center;
  justify-content:center;
  gap:24px;
  margin-bottom:24px;
  /* See .hud-topbar's comment — this row is the one that actually held
     the 220-280px gauge cards, so it's the one that was visibly
     collapsing to a few px and letting them overlap the topbar/back
     button. */
  flex-shrink:0;
  overflow-x:auto;
  overflow-y:hidden;
  scroll-snap-type:x proximity;
  -webkit-overflow-scrolling:touch;
  padding-bottom:6px; /* keeps the scrollbar from crowding the gauges' drop shadows */
}
.hud-gauges-row::-webkit-scrollbar{ height:6px; }
.hud-gauges-row::-webkit-scrollbar-track{ background:rgba(255,255,255,0.05); border-radius:3px; }
.hud-gauges-row::-webkit-scrollbar-thumb{ background:rgba(79,140,255,0.4); border-radius:3px; }
.hud-gauge-slot{ display:flex; justify-content:center; flex:0 0 auto; scroll-snap-align:center; }
/* Analog/Digital toggle — Analog (.hud-gauge-block) is the default; the
   toggle in the topbar adds .style-digital to .hud-shell to swap which
   variant shows in each slot. */
.hud-shell.style-digital .hud-gauge-block{ display:none; }
.hud-digital-card{ display:none; }
.hud-shell.style-digital .hud-digital-card{ display:flex; }

/* Digital gauge — modern EV-dashboard style: flat card, thin progress
   ring, big flat digits, no bezel/ticks/glass. */
.hud-digital-card{
  position:relative;
  width:220px; height:220px;
  border-radius:28px;
  background:linear-gradient(160deg, #131a26 0%, #070a10 100%);
  border:1px solid rgba(255,255,255,0.08);
  box-shadow:0 20px 50px rgba(0,0,0,0.5), inset 0 1px 0 rgba(255,255,255,0.06);
  flex-direction:column; align-items:center; justify-content:center;
  overflow:hidden;
}
.hud-digital-card::before{
  content:"";
  position:absolute; inset:0; border-radius:inherit;
  background:linear-gradient(180deg, rgba(255,255,255,0.06), transparent 45%);
  pointer-events:none;
}
.hud-digital-card svg{ position:absolute; inset:10px; width:calc(100% - 20px); height:calc(100% - 20px); }
.hud-digital-value{ position:relative; z-index:1; font-family:var(--font-mono); font-weight:800; font-size:52px; color:#fff; line-height:1; }
.hud-digital-unit{ position:relative; z-index:1; font-family:var(--font-display); font-size:12px; letter-spacing:0.16em; text-transform:uppercase; color:#7d8ba0; margin-top:6px; }

.hud-gauge-block{ position:relative; display:flex; justify-content:center; max-width:280px; margin:0 auto; }
/* Metallic bezel ring — brushed-metal conic gradient with a lit top edge
   and shadowed underside, like a machined gauge surround. */
.hud-gauge-block::before{
  content:"";
  position:absolute;
  top:50%; left:50%; transform:translate(-50%,-50%);
  width:94%; height:94%;
  border-radius:50%;
  z-index:0;
  background:
    radial-gradient(circle at 50% 50%, transparent 78%, rgba(0,0,0,0.5) 79%, transparent 82%),
    conic-gradient(from 200deg, #4a5262, #8b95a6, #3d4452, #1a1e25, #6b7688, #93a0b3, #262b33, #4a5262);
  box-shadow:
    0 10px 26px rgba(0,0,0,0.55),
    inset 0 2px 3px rgba(255,255,255,0.25),
    inset 0 -3px 8px rgba(0,0,0,0.7);
}
/* Carbon-fiber face, inset within the bezel — must stay BEHIND the SVG
   (ticks/needle) even though ::after normally paints above real children;
   explicit z-index below the svg's fixes that. */
.hud-gauge-block::after{
  content:"";
  position:absolute;
  top:50%; left:50%; transform:translate(-50%,-50%);
  width:82%; height:82%;
  border-radius:50%;
  z-index:1;
  background-color:#0b0e13;
  background-image:
    repeating-linear-gradient(45deg, rgba(255,255,255,0.05) 0, rgba(255,255,255,0.05) 1px, transparent 1px, transparent 6px),
    repeating-linear-gradient(-45deg, rgba(255,255,255,0.05) 0, rgba(255,255,255,0.05) 1px, transparent 1px, transparent 6px),
    repeating-linear-gradient(45deg, rgba(0,0,0,0.45) 0, rgba(0,0,0,0.45) 3px, transparent 3px, transparent 6px),
    repeating-linear-gradient(-45deg, rgba(0,0,0,0.45) 0, rgba(0,0,0,0.45) 3px, transparent 3px, transparent 6px);
  background-size:6px 6px;
  box-shadow:inset 0 0 26px rgba(0,0,0,0.75), inset 0 3px 4px rgba(0,0,0,0.8);
}
.hud-gauge-block svg{ position:relative; z-index:2; width:100%; max-width:280px; height:auto; }
/* Glass dome reflection — sits above the needle/ticks, like real cover glass. */
.hud-gauge-glass{
  position:absolute;
  z-index:3;
  top:7%; left:16%;
  width:68%; height:36%;
  border-radius:50%;
  background:linear-gradient(180deg, rgba(255,255,255,0.22), rgba(255,255,255,0.03) 65%, transparent);
  transform:rotate(-10deg);
  pointer-events:none;
}
.hud-gauge-overlay{
  position:absolute; z-index:4; top:50%; left:50%; transform:translate(-50%,-50%);
  text-align:center; pointer-events:none;
}
.hud-gauge-value{ font-family:var(--font-mono); font-size:clamp(34px, 6vw, 54px); font-weight:800; color:#fff; line-height:1; }
.hud-gauge-unit{ font-family:var(--font-display); font-size:12px; letter-spacing:0.14em; color:#7d8ba0; margin-top:4px; text-transform:uppercase; }

.hud-mini-stats{ display:flex; flex-direction:column; gap:16px; flex:0 0 auto; }
.hud-mini-label{ font-family:var(--font-display); font-size:10px; letter-spacing:0.1em; text-transform:uppercase; color:#7d8ba0; }
.hud-mini-value{ font-family:var(--font-mono); font-size:20px; font-weight:700; color:#fff; margin-top:4px; }

.hud-bottom-row{
  display:grid;
  grid-template-columns:220px 1fr 220px;
  gap:16px;
  /* See .hud-topbar's comment. */
  flex-shrink:0;
}
.hud-panel{
  position:relative;
  background-color:#0d1117;
  background-image:
    linear-gradient(rgba(255,255,255,0.03), rgba(255,255,255,0.03)),
    repeating-linear-gradient(45deg, rgba(255,255,255,0.035) 0, rgba(255,255,255,0.035) 1px, transparent 1px, transparent 7px),
    repeating-linear-gradient(-45deg, rgba(255,255,255,0.035) 0, rgba(255,255,255,0.035) 1px, transparent 1px, transparent 7px),
    repeating-linear-gradient(45deg, rgba(0,0,0,0.35) 0, rgba(0,0,0,0.35) 3px, transparent 3px, transparent 7px),
    repeating-linear-gradient(-45deg, rgba(0,0,0,0.35) 0, rgba(0,0,0,0.35) 3px, transparent 3px, transparent 7px);
  background-size:auto, 7px 7px, 7px 7px, 7px 7px, 7px 7px;
  border:1px solid rgba(255,255,255,0.1);
  border-radius:16px;
  padding:14px;
}
.hud-mini-stat{
  position:relative;
  background-color:#0d1117;
  background-image:
    linear-gradient(rgba(255,255,255,0.04), rgba(255,255,255,0.04)),
    repeating-linear-gradient(45deg, rgba(255,255,255,0.035) 0, rgba(255,255,255,0.035) 1px, transparent 1px, transparent 7px),
    repeating-linear-gradient(-45deg, rgba(255,255,255,0.035) 0, rgba(255,255,255,0.035) 1px, transparent 1px, transparent 7px),
    repeating-linear-gradient(45deg, rgba(0,0,0,0.35) 0, rgba(0,0,0,0.35) 3px, transparent 3px, transparent 7px),
    repeating-linear-gradient(-45deg, rgba(0,0,0,0.35) 0, rgba(0,0,0,0.35) 3px, transparent 3px, transparent 7px);
  background-size:auto, 7px 7px, 7px 7px, 7px 7px, 7px 7px;
  border:1px solid rgba(255,255,255,0.1);
  border-radius:14px; padding:12px 18px; min-width:110px; text-align:center;
}
.hud-heading-panel{ display:flex; flex-direction:column; align-items:center; justify-content:center; gap:8px; }
.hud-mini-gauge-frame{
  position:relative;
  width:120px; height:120px;
  border-radius:50%;
  background:
    radial-gradient(circle at 50% 50%, transparent 82%, rgba(0,0,0,0.5) 83%, transparent 86%),
    conic-gradient(from 200deg, #4a5262, #8b95a6, #3d4452, #1a1e25, #6b7688, #93a0b3, #262b33, #4a5262);
  box-shadow:0 4px 12px rgba(0,0,0,0.5), inset 0 2px 3px rgba(255,255,255,0.25), inset 0 -2px 5px rgba(0,0,0,0.7);
  display:flex; align-items:center; justify-content:center;
}
.hud-mini-gauge-frame svg{ position:relative; width:88%; height:88%; }
.hud-gauge-glass-sm{ top:10%; left:20%; width:60%; height:32%; }
.hud-panel-label{ font-family:var(--font-display); font-size:11px; letter-spacing:0.1em; text-transform:uppercase; color:#7d8ba0; }
.hud-map-panel{ position:relative; padding:0; overflow:hidden; min-height:220px; }
.hud-map-panel #hudMap{ width:100%; height:100%; min-height:220px; }
.hud-map-caption{
  position:absolute; left:12px; bottom:10px;
  font-family:var(--font-display); font-size:12px; font-weight:600; color:#fff;
  text-shadow:0 1px 4px rgba(0,0,0,0.6);
}
.hud-stats-panel{ display:flex; flex-direction:column; gap:12px; justify-content:center; }
.hud-stat-box{ text-align:center; }
.hud-stat-box .v{ font-family:var(--font-mono); font-size:22px; font-weight:700; color:#fff; }
.hud-stat-box .k{ font-family:var(--font-display); font-size:10px; letter-spacing:0.1em; text-transform:uppercase; color:#7d8ba0; margin-top:2px; }

/* Light HUD skin — toggled by the app's existing light theme */
body.theme-light .hud-shell{
  background: radial-gradient(circle at 50% 0%, #f3f6fb 0%, #e4e9f2 70%);
  color:#161a22;
}
body.theme-light .hud-timer-sub{ color:#5c6478; }
body.theme-light .hud-timer-sub b{ color:#1c2230; }
body.theme-light .hud-back-btn{ background:#fff; border-color:#dde2ec; color:#3a4152; }
body.theme-light .hud-brand-title{ color:#161a22; }
body.theme-light .hud-brand-sub,
body.theme-light .hud-weather{ color:#5c6478; }
body.theme-light .hud-weather div:first-child{ color:#1c2230; }
body.theme-light .hud-gauge-value{ color:#161a22; }
body.theme-light .hud-gauge-unit{ color:#5c6478; }
body.theme-light .hud-mini-stat{ background:#fff; border-color:#e1e4ea; box-shadow:0 2px 10px rgba(0,0,0,0.05); }
body.theme-light .hud-mini-value{ color:#161a22; }
body.theme-light .hud-panel{ background:#fff; border-color:#e1e4ea; box-shadow:0 2px 10px rgba(0,0,0,0.05); }
body.theme-light .hud-stat-box .v{ color:#161a22; }

/* Narrow/wide-but-still-cramped: topbar and the bottom panel row stack
   for readability. Kept on max-width so a landscape phone (routinely
   under 900px wide) still gets this — it only affects the topbar/bottom
   panels, not the gauges row, so it doesn't fight the orientation query
   below. */
@media (max-width: 900px){
  .hud-topbar{ grid-template-columns:1fr; text-align:center; gap:10px; }
  .hud-back-btn{ position:static; margin:0 auto 6px; }
  .hud-weather{ align-items:center; text-align:center; }
  .hud-bottom-row{ grid-template-columns:1fr; }
}

/* Portrait only: the gauges row stacks vertically instead of the
   horizontal/scrollable strip it uses everywhere else — landscape
   (this HUD's primary use case) must never trigger this, only a
   genuinely portrait screen should. */
@media (orientation: portrait){
  .hud-gauges-row{
    flex-direction:column;
    overflow-x:visible;
    overflow-y:visible;
  }
  .hud-mini-stats{ flex-direction:row; justify-content:center; }
}

/* ---------- bottom tab bar v2 (alternative nav, Settings > Appearance) ----------
   5 large primary destinations + a "More" tab that opens the same
   categorized drawer as the hamburger menu, instead of a second,
   separately-maintained nav structure — the iOS/Android "tab bar + More"
   pattern. Sized for a gloved thumb glancing down at a handlebar mount:
   64px-tall targets (up from ~52px), bigger icons and labels. */
.bottom-tab-bar{
  display:none;
  position:fixed; left:0; right:0; bottom:0; z-index:520;
  align-items:stretch;
  background:var(--menu-panel-bg);
  border-top:1px solid var(--border-subtle);
  padding:4px 4px calc(4px + env(safe-area-inset-bottom, 0px));
  box-shadow:0 -6px 20px rgba(0,0,0,0.12);
  backdrop-filter:blur(16px);
  -webkit-backdrop-filter:blur(16px);
}
body.nav-tabbar .bottom-tab-bar{ display:flex; }
body.nav-tabbar.view-fullscreen .bottom-tab-bar{ display:none; }
body.nav-tabbar .menu-btn{ display:none; }
body.nav-tabbar .main{ padding-bottom:128px; }
.tab-bar-item{
  flex:1 1 0; min-width:0;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px;
  min-height:64px;
  padding:6px 2px;
  border-radius:14px;
  background:none; border:none;
  color:var(--text-dim);
  text-decoration:none;
  font-family:var(--font-display); font-weight:700; font-size:11px; letter-spacing:0.02em;
  cursor:pointer;
  transition:color 0.15s ease, background 0.15s ease, transform 0.1s ease;
}
.tab-bar-item svg{ width:26px; height:26px; }
.tab-bar-item:active{ transform:scale(0.94); background:var(--bg-panel-hover); }
.tab-bar-item.active{ color:var(--neon-green); }

/* ---------- floating menu trigger + slide-in drawer ---------- */
.menu-btn{
  position:fixed; top:12px; left:12px; z-index:600;
  width:48px; height:48px;
  display:grid; place-items:center;
  background:var(--bg-panel);
  border:1px solid var(--border-subtle);
  border-radius:var(--radius-sm);
  color:var(--text-muted);
  font-size:20px;
  cursor:pointer;
  box-shadow:0 2px 10px rgba(0,0,0,0.3);
  transition:color 0.15s ease, border-color 0.15s ease, background 0.15s ease, transform 0.1s ease;
}
.menu-btn:hover{ color:var(--neon-green); border-color:var(--neon-green-dim); background:var(--bg-panel-hover); }
.menu-btn:active{ transform:scale(0.93); }

/* Scrim behind the drawer — dims the app so the (now much larger) touch
   targets are the only thing competing for attention, and gives the
   drawer a tap-anywhere-to-close target. @starting-style lets this fade
   in/out smoothly without a display:none flash-of-nothing on the very
   first frame; browsers without support for it just get an instant show/
   hide instead of the fade, so this only ever adds polish, never breaks. */
.nav-scrim{
  position:fixed; inset:0; z-index:585;
  background:rgba(0,0,0,0.45);
  opacity:0;
  display:none;
  transition:opacity 0.28s ease;
}
.nav-scrim.open{ display:block; opacity:1; }
@starting-style{
  .nav-scrim.open{ opacity:0; }
}

/* ---------- Header Status Bar ---------- */
.header-status-bar{
  position:fixed; top:12px; left:64px;
  right:20px;
  height:44px; z-index:200;
  display:flex; align-items:center; justify-content:center;
  padding:2px 14px;
  background:transparent;
  border:none;
  box-shadow:none;
  font-family:var(--font-display);
  font-size:13px;
  color:var(--text-primary);
  overflow:hidden;
  user-select:none;
  opacity:1;
  transition:opacity 0.25s ease;
}
.header-status-bar.is-faded{
  opacity:0;
  pointer-events:none;
}

@media (min-width:1440px){
  .header-status-bar{ right:calc(50vw - 680px); }
}

.header-status-center{
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  text-align:center; min-width:0; max-width:100%;
}

.header-status-time{
  font-family:'Barlow Condensed', var(--font-display);
  font-weight:300;
  font-size:22px;
  color:var(--neon-green);
  letter-spacing:0.05em;
  line-height:1;
  margin-bottom:0px;
}

.header-status-location{
  font-size:10px;
  font-weight:600;
  color:var(--text-muted);
  line-height:1.1;
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
  max-width:320px;
}

.header-status-right{
  position:absolute; right:14px; top:50%; transform:translateY(-50%);
  display:flex; align-items:center;
}

.header-status-rec{
  display:none; align-items:center; gap:6px;
  padding:4px 10px;
  border-radius:999px;
  background:rgba(239,68,68,0.12);
  border:1px solid rgba(239,68,68,0.32);
}
.header-status-rec.recording,
.header-status-rec.paused{ display:flex; }
.header-status-rec .rec-dot{
  width:8px; height:8px; border-radius:50%;
  background:var(--alert-red);
  box-shadow:0 0 8px var(--alert-red-glow);
  animation:recPulse 1.2s infinite ease-in-out;
  flex-shrink:0;
}
.header-status-rec-label{
  font-family:var(--font-display);
  font-weight:700; font-size:11px; letter-spacing:0.06em;
  text-transform:uppercase;
  color:var(--alert-red);
}
.header-status-rec.paused{
  background:rgba(245,158,11,0.12);
  border-color:rgba(245,158,11,0.32);
}
.header-status-rec.paused .rec-dot{
  background:var(--warn-amber);
  box-shadow:0 0 8px rgba(245,158,11,0.35);
  animation:none;
}
.header-status-rec.paused .header-status-rec-label{ color:var(--warn-amber); }

@keyframes recPulse{
  0%{ transform:scale(0.85); opacity:0.7; }
  50%{ transform:scale(1.25); opacity:1.0; }
  100%{ transform:scale(0.85); opacity:0.7; }
}

@media (max-width:480px){
  .header-status-bar{ left:60px; right:12px; padding:2px 8px; }
  .header-status-location{ max-width:150px; font-size:9.5px; }
  .header-status-time{ font-size:18px; }
}
/* ---------- primary navigation drawer v2 ----------
   Redesigned around one job: a rider glancing at a phone mounted on
   handlebars can find and hit the right row without close attention or
   fine motor precision. Rebuilt from scratch rather than restyled:
   - Rows are 64px tall (was 50px) with 18px type (was 16px) — comfortably
     inside typical glove-tap guidance, well past the 44-48px baseline.
   - Items are grouped into color-coded categories (Ride/Navigate/Log/
     Labs/Settings) instead of one flat list, so the eye can jump straight
     to a section instead of reading every row. Category colors reuse the
     app's own already theme-tuned tokens (--neon-green/--cyan/--warn-
     amber/--text-dim) so every existing theme "just works"; only Labs
     needed a new token (--labs-violet, defined near :root) since nothing
     else in the app used violet.
   - Panel width is min(88vw, 380px) with its own scroll — Material's
     "leave a sliver of context visible" sizing — instead of a fixed
     288px that would've had to either crowd five category headers plus
     ~11 rows or get its own inner overflow bug on a short phone.
   - @view-transition (see near :root) gives this a soft cross-fade
     between pages on browsers that support the Cross-Document View
     Transitions API (Chrome/Edge on Android as of this writing) — a
     pure-CSS progressive enhancement, inert and harmless elsewhere. */
.menu-panel{
  position:fixed; top:0; left:0; z-index:590;
  width:min(88vw, 380px); height:100vh; height:100dvh;
  display:flex;
  flex-direction:column;
  background:var(--menu-panel-bg);
  border-right:1px solid var(--border-subtle);
  box-shadow:16px 0 40px rgba(0,0,0,0.45);
  backdrop-filter:blur(16px);
  -webkit-backdrop-filter:blur(16px);
  transform:translateX(-100%);
  transition:transform 0.3s cubic-bezier(0.16,1,0.3,1);
  overflow-y:auto;
  overscroll-behavior-y:contain;
  padding-bottom:calc(16px + env(safe-area-inset-bottom, 0px));
}
.menu-panel.open{ transform:translateX(0); }
.menu-brand{
  position:sticky; top:0; z-index:1;
  display:flex; align-items:center; gap:12px;
  padding:18px 18px 16px;
  font-family:var(--font-display);
  font-weight:700; font-size:18px;
  background:var(--menu-panel-bg);
  border-bottom:1px solid var(--border-subtle);
}
.menu-brand .mark{
  width:36px;height:36px;
  display:grid;place-items:center;
  color:#fff;
  background:var(--neon-green);
  border-radius:var(--radius-sm);
  font-family:var(--font-display);
  font-weight:700; font-size:17px;
}
.menu-brand small{
  display:block;
  font-family:var(--font-mono);
  font-size:10px;
  letter-spacing:0.14em;
  color:var(--text-dim);
  font-weight:500;
  margin-top:2px;
}

.nav-home{
  display:block; margin:14px 12px 6px;
}
.nav-category{ margin:18px 12px 6px; }
.nav-category-header{
  display:flex; align-items:center; gap:8px;
  padding:0 10px 8px;
  font-family:var(--font-display); font-weight:800; font-size:12px;
  letter-spacing:0.14em; text-transform:uppercase;
  color:var(--text-dim);
}
.nav-category-dot{
  width:9px; height:9px; border-radius:50%; flex:0 0 auto;
  background:var(--cat-color, var(--neon-green));
  box-shadow:0 0 8px color-mix(in srgb, var(--cat-color, var(--neon-green)) 60%, transparent);
}
.nav-category[data-cat="ride"]{ --cat-color:var(--neon-green); }
.nav-category[data-cat="navigate"]{ --cat-color:var(--cyan); }
.nav-category[data-cat="log"]{ --cat-color:var(--warn-amber); }
.nav-category[data-cat="labs"]{ --cat-color:var(--labs-violet); }
.nav-category[data-cat="settings"]{ --cat-color:var(--text-dim); }

.nav-divider{ height:1px; background:var(--border-subtle); margin:16px 18px; }

.menu-link{
  display:flex; align-items:center; gap:14px;
  width:100%; min-height:64px;
  padding:0 12px;
  border:none; background:transparent;
  border-radius:14px;
  color:var(--text-primary);
  font-family:var(--font-display); font-weight:600; font-size:18px;
  text-align:left; cursor:pointer;
  transition:background 0.15s ease, color 0.15s ease, transform 0.1s ease;
}
.menu-link + .menu-link{ margin-top:2px; }
.menu-link:hover{ background:var(--bg-panel-hover); color:var(--text-primary); }
.menu-link:active{ transform:scale(0.98); background:var(--bg-panel-hover); }
.menu-link.active{
  color:var(--cat-color, var(--neon-green));
  background:color-mix(in srgb, var(--cat-color, var(--neon-green)) 12%, transparent);
  font-weight:700;
}
.nav-home > .menu-link{ font-size:19px; }
.menu-link-icon{
  width:40px; height:40px; flex:0 0 auto;
  display:grid; place-items:center;
  border-radius:11px;
  font-size:20px;
  background:color-mix(in srgb, var(--cat-color, var(--text-dim)) 14%, transparent);
}
.nav-home .menu-link-icon{
  background:color-mix(in srgb, var(--neon-green) 16%, transparent);
}
.icon-btn{
  min-width:var(--touch); min-height:var(--touch);
  display:grid; place-items:center;
  background:var(--bg-panel);
  border:1px solid var(--border-subtle);
  border-radius:10px;
  color:var(--text-muted);
  cursor:pointer;
}
.icon-btn:hover{color:var(--neon-green); border-color:var(--border-strong);}

.main{
  flex:1;
  width:100%;
  max-width:1400px;
  margin:0 auto;
  padding:76px 20px 90px;
}

/* ---------- panels ---------- */
.panel,
.map-box {
  background: transparent;
  padding: 16px;
  transition: background 0.25s ease, border-color 0.25s ease;
}
.panel-title{
  font-family:var(--card-custom-font, var(--font-display));
  font-weight:700;
  font-size:var(--card-custom-title-size, 13px);
  letter-spacing:0.06em;
  text-transform:uppercase;
  color:var(--card-custom-muted-color, var(--text-dim));
  margin:0 0 14px;
  display:flex; align-items:center; justify-content:space-between;
  /* A title paired with a trailing status/button can run out of room on
     narrow cards. Without wrap, flexbox's default shrink behavior squeezes
     both items to fit on one line, which breaks text internally mid-word
     instead of just dropping the second item to its own line. */
  flex-wrap:wrap; row-gap:4px;
}
/* Keeps the title itself intact (no mid-word break) when the row wraps —
   only the trailing status text/button should ever drop to its own line. */
.panel-title-text{ white-space:nowrap; flex-shrink:0; }

/* Card typography & text color overrides */
.rr-card {
  font-family: var(--card-custom-font, var(--font-body));
}
.rr-card .speed-value,
.rr-card .weather-temp,
.rr-card .v,
.rr-card .value,
.rr-card .plugin-value {
  color: var(--card-custom-text-color, var(--text-primary));
}
.rr-card .k,
.rr-card .weather-cond,
.rr-card .plugin-label {
  color: var(--card-custom-muted-color, var(--text-muted));
}

/* ---------- dashboard card layout ---------- */
.rr-card{
  display:none;
  position:relative;
  background:var(--card-custom-bg, var(--bg-panel));
  border:1px solid var(--border-subtle);
  border-radius:var(--radius-lg);
  box-shadow:0 4px var(--shadow-blur, 12px) rgba(0, 0, 0, var(--shadow-opacity, 0.18));
  overflow:hidden;
  transition:background 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease;
  /* Lets descendants (e.g. .weather-panel below) adapt their own layout to
     how narrow this specific card actually is — the Layout editor can put
     any card into a 1/3-width row, a half row, or full width, so a fixed
     breakpoint on the viewport can't tell a component how much room it
     really has. Only the inline (width) axis is queried. */
  container-type:inline-size;
}

/* Top-Down Glowing Edge Overlay (subtle by default; user-adjustable in Settings > Appearance) */
.rr-card::before,
.clock-preview-box#cardPreviewBox::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1.5px;
  background: linear-gradient(
    180deg,
    var(--neon-green, #4f8cff) 0%,
    var(--neon-green-glow, rgba(79,140,255,0.28)) calc(var(--glow-coverage, 8%) * 0.75),
    transparent var(--glow-coverage, 8%)
  );
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
  z-index: 2;
}

/* Top Sheen Metallic Reflection Overlay (subtle by default; user-adjustable) */
.rr-card::after,
.clock-preview-box#cardPreviewBox::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, var(--sheen-opacity, 0.05)) 0%,
    rgba(255, 255, 255, calc(var(--sheen-opacity, 0.05) * 0.2)) calc(var(--glow-coverage, 8%) * 0.8),
    transparent var(--glow-coverage, 8%)
  );
  pointer-events: none;
  z-index: 1;
}

.layout-row .rr-card{ display:block; min-width:0; }
.layout-root{
  display:flex; flex-direction:column; gap:16px;
  margin-bottom:16px;
}
/* Inner panels inherit transparent background from .rr-card */
.rr-card > .panel,
.rr-card > .speed-panel {
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
}

/* Disabled Background for Individual Component Card */
.rr-card.no-card-bg {
  background: transparent !important;
  border-color: transparent !important;
  box-shadow: none !important;
}
.rr-card.no-card-bg::before,
.rr-card.no-card-bg::after {
  display: none !important;
}

/* Spotify Card Exemption: Retains its original dark brand background */
.rr-card[data-card-id="spotify"] {
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  overflow: visible;
}
.rr-card[data-card-id="spotify"]::before,
.rr-card[data-card-id="spotify"]::after {
  display: none !important;
}

.layout-row{
  display:flex; flex-wrap:nowrap; gap:12px; align-items:stretch;
  background:transparent !important;
  border:none !important;
  box-shadow:none !important;
  padding:0 !important;
}
.layout-row.multi-card-row{
  background:transparent !important;
  border:none !important;
  box-shadow:none !important;
  padding:0 !important;
}
.layout-row .rr-card{ flex:1 1 0; }
.layout-row .rr-card[data-card-id="map"],
.layout-row .rr-card[data-card-id="route"]{ flex:1.6 1 0; }
.layout-row .rr-card > .panel,
.layout-row .rr-card > .speed-panel{ height:100%; }

.speed-panel{
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  background:transparent;
  border:none;
  border-radius:var(--radius-lg);
  padding:20px;
  position:relative;
  overflow:hidden;
}
.speed-panel::before{
  content:"";
  position:absolute; inset:0;
  background:linear-gradient(180deg, transparent 60%, rgba(79,140,255,0.05));
  pointer-events:none;
}
.speed-panel svg{ width:100%; height:auto; max-width:240px; }
.speed-panel.style-digital svg{ display:none; }
/* In analog mode .speed-overlay sits absolutely centered over the visible
   SVG gauge. In digital mode there's no SVG to center over — if it stayed
   absolutely positioned, it would contribute no height to the flex column,
   so the panel would collapse to just its padding and overflow:hidden
   would clip the (often much taller) digital number. Making it a normal
   flow child here lets the panel size itself to the actual text. */
.speed-panel.style-digital .speed-overlay{
  position:static;
  transform:none;
}
.speed-overlay{
  position:absolute; top:50%; left:50%;
  transform:translate(-50%, -50%);
  text-align:center;
  pointer-events:none;
}
.speed-value{
  font-family:var(--speedo-font, var(--font-mono));
  font-weight:700;
  font-size:var(--speedo-size, clamp(28px, 9vw, 64px));
  line-height:1;
  color:var(--speedo-fg, var(--neon-green));
  text-shadow:0 0 20px var(--speedo-fg-glow, var(--neon-green-glow));
}
.speed-unit{
  font-family:var(--font-display);
  font-size:13px;
  font-weight:500;
  letter-spacing:0.08em;
  color:var(--text-muted);
  margin-top:4px;
}

.mini-gauge-row{
  display:flex; gap:16px;
}
.mini-gauge{
  flex:1;
  display:flex; flex-direction:column; align-items:center;
  background:var(--bg-panel);
  border:1px solid var(--border-subtle);
  border-radius:var(--radius-md);
  padding:12px;
  min-width:0;
}
.mini-gauge svg{ width:100%; height:auto; max-width:140px; }
.mini-gauge .label{
  font-family:var(--font-display);
  font-size:11px; letter-spacing:0.06em;
  color:var(--text-dim); text-transform:uppercase;
  margin-top:6px;
}
.mini-gauge .value{
  font-family:var(--font-mono);
  font-size:20px; font-weight:700;
  color:var(--text-primary);
}

/* record button */
.record-btn{
  min-height:56px;
  width:100%;
  border-radius:var(--radius-md);
  border:1px solid var(--neon-green-dim);
  background:linear-gradient(180deg, rgba(79,140,255,0.16), rgba(79,140,255,0.04));
  color:var(--neon-green);
  font-family:var(--font-display);
  font-weight:600;
  font-size:16px;
  letter-spacing:0.02em;
  display:flex; align-items:center; justify-content:center; gap:10px;
  cursor:pointer;
  transition:border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.record-btn .dot{
  width:12px;height:12px;border-radius:50%;
  background:var(--neon-green);
  box-shadow:0 0 10px var(--neon-green-glow);
}
.record-btn.recording{
  border-color:var(--alert-red);
  background:linear-gradient(180deg, rgba(255,59,92,0.18), rgba(255,59,92,0.05));
  color:var(--alert-red);
}
.record-btn.recording .dot{
  background:var(--alert-red);
  box-shadow:0 0 10px var(--alert-red-glow);
  animation:pulse 1.4s ease-in-out infinite;
}
.record-btn.paused{
  border-color:var(--warn-amber);
  background:linear-gradient(180deg, rgba(255,176,32,0.18), rgba(255,176,32,0.05));
  color:var(--warn-amber);
}
.record-btn.paused .dot{
  background:var(--warn-amber);
  box-shadow:0 0 10px rgba(255,176,32,0.35);
}
@keyframes pulse{
  0%,100%{opacity:1; transform:scale(1);}
  50%{opacity:0.4; transform:scale(0.8);}
}
.rec-meta{
  display:flex; justify-content:space-between;
  font-family:var(--font-mono);
  font-size:12px; color:var(--text-muted);
  margin-top:8px;
}
.auto-toggle{
  display:flex; align-items:center; justify-content:space-between;
  margin-top:10px;
  font-family:var(--font-body);
  font-size:13px; font-weight:500; letter-spacing:0; color:var(--text-muted);
}
.switch{
  width:42px;height:24px;border-radius:14px;
  background:var(--bg-void); border:1px solid var(--border-strong);
  position:relative; cursor:pointer; flex-shrink:0;
}
.switch::after{
  content:"";
  position:absolute; top:2px; left:2px;
  width:18px;height:18px;border-radius:50%;
  background:var(--text-dim);
  transition:transform .18s ease, background .18s ease;
}
.switch.on{border-color:var(--neon-green-dim);}
.switch.on::after{
  transform:translateX(18px);
  background:var(--neon-green);
  box-shadow:0 0 8px var(--neon-green-glow);
}

/* weather widget */
.weather-panel{
  display:flex; flex-direction:column;
  position:relative;
}
.weather-main-row{
  display:flex; align-items:center; gap:16px;
}
.weather-temp{
  font-family:var(--font-mono); font-size:38px; font-weight:700; color:var(--text-primary);
}
.weather-cond{
  font-family:var(--font-body); font-weight:500; font-size:14px; color:var(--text-muted); text-transform:capitalize;
}
.weather-stats{
  margin-left:auto;
  display:flex; gap:18px;
}
.weather-stat{text-align:right;}
.weather-stat .v{font-family:var(--font-mono); font-size:16px; color:var(--text-primary);}
.weather-stat .k{font-family:var(--font-display); font-size:10px; letter-spacing:0.06em; color:var(--text-dim); text-transform:uppercase;}
.weather-icon{font-size:40px; line-height:1;}

.weather-precip-toggle{
  appearance:none; border:1px solid var(--border-subtle); background:var(--bg-void);
  color:var(--text-muted); border-radius:10px; width:34px; height:34px; flex-shrink:0;
  display:flex; align-items:center; justify-content:center; font-size:16px; cursor:pointer;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.weather-precip-toggle[aria-expanded="true"]{
  background:rgba(79,140,255,0.16); border-color:rgba(79,140,255,0.5); color:var(--text-primary);
}
.weather-precip-drawer{
  max-height:0; overflow:hidden; opacity:0;
  transition: max-height 0.28s ease, opacity 0.2s ease, margin-top 0.28s ease;
}
.weather-precip-drawer.open{ max-height:200px; opacity:1; margin-top:14px; }
.weather-precip-drawer-title{
  font-family:var(--font-display); font-size:11px; letter-spacing:0.06em; text-transform:uppercase;
  color:var(--text-dim); margin-bottom:10px;
}
.weather-precip-chart{
  display:flex; align-items:flex-end; gap:10px; height:120px;
  overflow-x:auto; overflow-y:hidden; -webkit-overflow-scrolling:touch;
  scrollbar-width:none;
}
.weather-precip-chart::-webkit-scrollbar{ display:none; }

/* Weather is a full "icon + temp + condition + wind/clouds + precip toggle"
   panel, but the default dashboard layout groups it into a 1/3-width row
   alongside Heading and Lean Angle — at that width the row's content was
   nearly 3x wider than the card (measured: ~307px of content in a ~107px
   card), clipping the condition text and stat labels mid-word. This
   re-flows the same content into a compact stack instead of shrinking it
   past readability, and applies whenever the card itself is narrow —
   including if a user drags Weather into a different row via the Layout
   editor — rather than assuming one fixed viewport breakpoint. */
@container (max-width:220px){
  /* A 2-column (icon | text) layout was tried first, but at this width the
     icon alone eats most of the row, squeezing the text column down to
     ~28px — narrow enough that break-word wrapped every single character
     onto its own line. Stacking everything full-width, one row per piece
     of info, gives each row the whole ~100px+ card width instead of a
     sliver of it, so normal word-wrap is all that's needed. */
  .weather-main-row{
    display:flex;
    flex-direction:column;
    align-items:flex-start;
    gap:4px;
    padding-right:32px;
  }
  .weather-icon{ font-size:26px; }
  .weather-temp{ font-size:22px; }
  .weather-cond{ font-size:12px; }
  .weather-stats{
    width:100%;
    margin-left:0;
    flex-wrap:wrap;
    justify-content:flex-start;
    gap:4px 14px;
  }
  .weather-stat{ text-align:left; }
  .weather-precip-toggle{ position:absolute; top:0; right:0; }
}
.wp-bar-col{
  display:flex; flex-direction:column; align-items:center; justify-content:flex-end;
  flex:0 0 32px; height:100%; gap:5px;
}
.wp-bar-pct{
  font-family:var(--font-mono); font-size:10px; font-weight:700; color:var(--text-primary);
  white-space:nowrap;
}
.wp-bar-track{
  width:100%; max-width:26px; flex:1; display:flex; align-items:flex-end;
  background:rgba(127,127,127,0.12); border-radius:5px; overflow:hidden;
}
.wp-bar-fill{
  width:100%; min-height:3px; border-radius:5px 5px 0 0;
  background:linear-gradient(180deg, #7ec4ff, #3b7ce0);
}
.wp-bar-time{
  font-family:var(--font-mono); font-size:9px; color:var(--text-dim); white-space:nowrap;
}

.precip-alert{
  display:flex; align-items:center; gap:10px;
  background:rgba(255,176,32,0.1);
  border:1px solid rgba(255,176,32,0.35);
  color:var(--warn-amber);
  padding:10px 14px;
  border-radius:var(--radius-md);
  font-family:var(--font-display);
  font-size:14px;
  letter-spacing:0.02em;
  margin-bottom:16px;
}

/* two column: map + route */
.content-grid{
  display:grid;
  grid-template-columns:1.6fr 1fr;
  gap:16px;
}
@media (max-width:980px){
  .content-grid{grid-template-columns:1fr;}
}
#map{
  width:100%; height:420px;
  border-radius:var(--radius-md);
  border:1px solid var(--border-subtle);
  background:var(--bg-panel-raised);
}
.map-wrap{ position:relative; }
.map-locate-btn{
  position:absolute; right:12px; bottom:12px; z-index:5;
  width:42px; height:42px; border-radius:50%;
  display:grid; place-items:center;
  background:var(--bg-panel); border:1px solid var(--border-subtle);
  color:var(--text-muted); font-size:16px; cursor:pointer;
  box-shadow:0 2px 10px rgba(0,0,0,0.35);
}
.map-locate-btn:hover{ color:var(--neon-green); border-color:var(--neon-green-dim); }
.map-locate-btn.is-loading{ opacity:0.55; pointer-events:none; animation:pulse 1s ease-in-out infinite; }
.current-location-label{
  font-family:var(--font-body); font-weight:400; text-transform:none; letter-spacing:0;
  font-size:12px; color:var(--text-muted); margin-left:6px;
}
.current-location-label:empty{ display:none; }
.map-toolbar{
  display:flex; gap:8px; margin-top:10px;
}
.radar-controls{
  margin-top:10px;
  background:var(--bg-panel-raised);
  border:1px solid var(--border-subtle);
  border-radius:var(--radius-md);
  padding:10px 12px;
}
.chip-btn{
  min-height:40px;
  padding:0 14px;
  border-radius:20px;
  border:1px solid var(--border-subtle);
  background:var(--bg-panel-raised);
  color:var(--text-muted);
  font-family:var(--font-display);
  font-weight:600; font-size:13px; letter-spacing:0.04em;
  cursor:pointer;
  display:flex; align-items:center; gap:6px;
}
.chip-btn.active{ color:var(--neon-green); border-color:var(--neon-green-dim); background:rgba(79,140,255,0.08);}

/* route planner */
.route-form{display:flex; gap:8px; margin-bottom:12px;}
.route-form input{
  flex:1;
  min-height:var(--touch);
  background:var(--bg-void);
  border:1px solid var(--border-subtle);
  border-radius:var(--radius-sm);
  padding:0 14px;
  color:var(--text-primary);
  font-family:var(--font-body);
  font-size:15px;
}
.route-form input::placeholder{color:var(--text-dim);}
.btn{
  min-height:var(--touch);
  padding:0 20px;
  border-radius:var(--radius-sm);
  border:1px solid var(--btn-primary-border, var(--neon-green-dim));
  background:var(--btn-primary-bg, var(--neon-green));
  color:var(--btn-primary-color, #ffffff);
  font-family:var(--font-display);
  font-weight:600; font-size:14px; letter-spacing:0.01em;
  cursor:pointer;
  transition:filter 0.15s ease, box-shadow 0.15s ease, background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
  box-shadow:0 1px 2px rgba(0,0,0,0.18);
}
.btn:hover{
  filter:brightness(1.08);
  box-shadow:0 3px 10px rgba(0,0,0,0.22);
}
.btn:active{ filter:brightness(0.97); }
.btn.small{
  min-height:36px;
  padding:0 14px;
  font-size:12.5px;
}
.btn.secondary{
  background:var(--btn-secondary-bg, var(--bg-panel-raised));
  color:var(--text-primary);
  border:1px solid var(--btn-secondary-border, var(--border-subtle));
  box-shadow:none;
}
.btn.secondary:hover,
.btn.secondary.active{
  background:var(--bg-panel-hover);
  border-color:var(--neon-green);
  color:var(--neon-green);
}
.btn.danger{
  background:transparent;
  color:var(--alert-red);
  border:1px solid var(--alert-red);
  box-shadow:none;
}
.btn.danger:hover{
  background:var(--alert-red);
  color:#ffffff;
}
.btn.danger:disabled{
  opacity:0.4;
  cursor:default;
  filter:none;
}
.route-summary{
  display:flex; gap:20px;
  font-family:var(--font-mono);
  margin-bottom:10px;
  padding-bottom:10px;
  border-bottom:1px solid var(--border-subtle);
}
.route-summary div span{display:block; font-family:var(--font-display); font-size:10px; color:var(--text-dim); letter-spacing:0.06em; text-transform:uppercase;}
.directions-list{
  list-style:none; margin:0; padding:0;
  max-height:260px; overflow-y:auto;
}
.directions-list li{
  display:flex; gap:10px;
  padding:10px 0;
  border-bottom:1px dashed var(--border-subtle);
  font-size:14px;
}
.directions-list li:last-child{border-bottom:none;}
.step-idx{
  font-family:var(--font-mono);
  color:var(--neon-green);
  min-width:22px;
}
.empty-state{
  color:var(--text-dim);
  font-family:var(--font-body);
  font-size:14px;
  text-align:center;
  padding:30px 10px;
}

/* ---------- history page ---------- */
.ride-log-header{
  display:flex; align-items:center; justify-content:space-between;
  gap:12px; margin-bottom:16px; flex-wrap:wrap;
}
.ride-log-view-toggle{
  display:flex; gap:4px;
  background:var(--bg-panel-raised);
  border:1px solid var(--border-subtle);
  border-radius:999px; padding:3px;
}
.ride-log-view-btn{
  border:none; background:transparent; color:var(--text-muted);
  font-family:var(--font-display); font-weight:600; font-size:12px; letter-spacing:0.03em;
  padding:7px 16px; border-radius:999px; cursor:pointer;
}
.ride-log-view-btn.active{ background:var(--bg-panel); color:var(--neon-green); }
.ride-log-header-actions{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
#combineModeBtn.active{ background:rgba(79,140,255,0.18); border-color:rgba(79,140,255,0.55); color:var(--text-primary); }

.ride-log-sort-row{
  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  margin-bottom:16px;
}
.ride-log-sort-label{
  font-family:var(--font-display); font-size:11px; letter-spacing:0.06em; text-transform:uppercase;
  color:var(--text-dim);
}
.ride-log-sort-select{
  min-height:var(--touch);
  background:var(--bg-panel-raised); border:1px solid var(--border-subtle);
  border-radius:var(--radius-sm); color:var(--text-primary);
  font-family:var(--font-body); font-size:13px;
  padding:0 12px; cursor:pointer;
}
.ride-log-sort-dir-btn{
  min-height:var(--touch);
  background:var(--bg-panel-raised); border:1px solid var(--border-subtle);
  border-radius:var(--radius-sm); color:var(--text-muted);
  font-family:var(--font-display); font-weight:600; font-size:12px;
  padding:0 14px; cursor:pointer;
  white-space:nowrap;
}
.ride-log-sort-dir-btn:hover{ color:var(--neon-green); border-color:var(--neon-green-dim); }

.ride-map-view{ display:flex; flex-direction:column; gap:14px; }
.ride-map-picker select{
  width:100%; min-height:var(--touch);
  background:var(--bg-panel); border:1px solid var(--border-subtle);
  border-radius:var(--radius-sm); color:var(--text-primary);
  padding:0 14px; font-family:var(--font-body); font-size:15px; cursor:pointer;
}
.ride-map-wrap{
  border-radius:var(--radius-lg); overflow:hidden;
  border:1px solid var(--border-subtle);
}
#rideMapCanvas{ width:100%; height:60vh; min-height:360px; background:var(--bg-panel-raised); }
.ride-map-stats{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(110px,1fr));
  gap:10px;
}
.ride-map-stats .box{
  background:var(--bg-panel); border:1px solid var(--border-subtle);
  border-radius:var(--radius-md); padding:12px; text-align:center;
}
.ride-map-stats .box .v{ font-family:var(--font-mono); font-size:18px; color:var(--neon-green); }
.ride-map-stats .box .k{ font-family:var(--font-display); font-size:10px; color:var(--text-dim); letter-spacing:0.1em; text-transform:uppercase; margin-top:4px; }

.ride-grid{
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(300px,1fr));
  gap:16px;
}
.ride-card{
  background:var(--bg-panel);
  border:1px solid var(--border-subtle);
  border-radius:var(--radius-lg);
  padding:16px;
  cursor:pointer;
  transition:border-color .15s ease, transform .15s ease;
}
.ride-card:hover{border-color:var(--neon-green-dim); transform:translateY(-2px);}
.ride-card canvas{width:100%; height:110px; display:block; border-radius:var(--radius-sm); background:var(--bg-void); margin-bottom:12px;}
.ride-card-title{
  font-family:var(--font-display); font-weight:700; font-size:17px;
  color:var(--text-primary);
  margin-bottom:6px;
  overflow:hidden; text-overflow:ellipsis; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
  cursor:text;
  border-radius:6px;
  /* Room for the long-press-to-edit affordance without shifting layout
     on hover/focus. */
  padding:2px 4px; margin-left:-4px; margin-right:-4px;
}
.ride-card-title:hover{ background:var(--bg-panel-raised); }
.ride-card-title-input{
  width:100%;
  font:inherit; font-weight:700; color:var(--text-primary);
  background:var(--bg-panel-raised);
  border:1px solid var(--neon-green-dim);
  border-radius:6px;
  padding:2px 6px;
  margin:-2px -6px;
}
.ride-card .date-row{display:flex; align-items:center; justify-content:space-between; gap:8px;}
.ride-card .date{font-family:var(--font-display); font-weight:600; font-size:15px; color:var(--text-primary);}
.ride-card .weather-chip{
  flex-shrink:0;
  font-family:var(--font-mono); font-size:12px; font-weight:600; color:var(--text-muted);
  background:var(--bg-panel-raised); border:1px solid var(--border-subtle);
  border-radius:20px; padding:3px 10px;
  white-space:nowrap;
}
.ride-card .stats{
  display:grid; grid-template-columns:repeat(3,1fr);
  gap:8px; margin-top:12px;
}
.ride-card .stat .v{font-family:var(--font-mono); font-size:16px; color:var(--neon-green);}
.ride-card .stat .k{font-family:var(--font-display); font-size:10px; color:var(--text-dim); letter-spacing:0.1em; text-transform:uppercase;}

/* ---------- combine trips ---------- */
.ride-card{ position:relative; }
.ride-card.combine-mode{ padding-left:46px; }
.ride-card.combine-mode.selected{ border-color:var(--neon-green); box-shadow:0 0 0 1px var(--neon-green); }
.ride-card-checkbox{
  display:none;
  position:absolute; left:14px; top:16px; z-index:2;
  width:24px; height:24px; border-radius:50%;
  border:2px solid var(--border-strong); background:var(--bg-panel-raised);
  align-items:center; justify-content:center;
  font-size:13px; color:transparent;
}
.ride-card.combine-mode .ride-card-checkbox{ display:flex; }
.ride-card.combine-mode.selected .ride-card-checkbox{
  background:var(--neon-green); border-color:var(--neon-green); color:#06280f;
}
.combine-actionbar{
  position:fixed; left:50%; bottom:22px; transform:translateX(-50%);
  z-index:210;
  display:flex; align-items:center; gap:14px;
  background:var(--bg-panel-raised); border:1px solid var(--border-strong);
  border-radius:999px; padding:10px 12px 10px 20px;
  box-shadow:0 12px 32px rgba(0,0,0,0.35);
  font-family:var(--font-display); font-size:13px; color:var(--text-muted);
}
.combine-order-list{ display:flex; flex-direction:column; gap:8px; max-height:50vh; overflow-y:auto; }
.combine-order-item{
  display:flex; align-items:center; gap:10px;
  background:var(--bg-panel-raised); border:1px solid var(--border-subtle);
  border-radius:var(--radius-md); padding:10px 12px;
}
.combine-order-item .combine-order-num{
  font-family:var(--font-mono); font-weight:700; color:var(--neon-green);
  width:22px; text-align:center; flex-shrink:0;
}
.combine-order-item .combine-order-info{ flex:1; min-width:0; }
.combine-order-item .combine-order-date{ font-family:var(--font-display); font-weight:600; font-size:13px; color:var(--text-primary); }
.combine-order-item .combine-order-meta{ font-family:var(--font-mono); font-size:11px; color:var(--text-muted); }
.combine-order-item .combine-order-btns{ display:flex; gap:4px; flex-shrink:0; }
.combine-order-item .combine-order-btns button{
  appearance:none; border:1px solid var(--border-subtle); background:var(--bg-void);
  color:var(--text-primary); border-radius:6px; width:30px; height:30px; cursor:pointer; font-size:13px;
}
.combine-order-item .combine-order-btns button:disabled{ opacity:0.3; cursor:default; }

/* ---------- route editor ---------- */
/* Higher than .menu-btn's fixed z-index:600 — a true full-screen overlay
   (unlike the other, centered modals, which sit inset enough not to
   collide with the corner hamburger button) needs to actually cover it,
   not just sit visually behind it while still being "in front". Compound
   selector (.modal-overlay.route-editor-overlay, not just
   .route-editor-overlay) deliberately outranks the base .modal-overlay's
   own z-index:100 rule, which is defined later in this file — at equal
   specificity that source-order would otherwise let it win and silently
   put this back behind the hamburger button. Confirmed live: without the
   compound selector, getComputedStyle reported z-index 100, not 650. */
.modal-overlay.route-editor-overlay{ z-index:650; padding:0; }
.route-editor-box{
  width:100%; height:100%; max-width:none; max-height:none;
  background:var(--bg-void); display:flex; flex-direction:column;
}
.route-editor-header{
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:14px 16px; border-bottom:1px solid var(--border-subtle);
  background:var(--bg-panel);
}
.route-editor-body{
  flex:1; overflow-y:auto; padding:14px 16px 8px;
  display:flex; flex-direction:column; gap:12px;
}
.route-editor-map-wrap{
  border-radius:var(--radius-lg); overflow:hidden; border:1px solid var(--border-subtle);
  height:min(46vh, 420px); background:var(--bg-panel-raised);
}
#routeEditorMap{ width:100%; height:100%; }
.route-editor-scrub-row{ display:flex; align-items:center; gap:10px; }
.route-editor-play-btn{ width:40px; height:40px; flex-shrink:0; border-radius:50%; padding:0; }
.route-editor-scrub{ flex:1; accent-color:#4f8cff; }
.route-editor-time{ font-family:var(--font-mono); font-size:12px; color:var(--text-muted); width:52px; text-align:right; flex-shrink:0; }
.route-editor-scrub-track{
  position:relative; height:14px; border-radius:7px; background:var(--bg-panel-raised);
  border:1px solid var(--border-subtle); overflow:hidden;
}
.re-track-range{
  position:absolute; top:0; bottom:0;
  background:rgba(79,140,255,0.4); border-left:2px solid #4f8cff; border-right:2px solid #4f8cff;
}
.re-track-cursor{
  position:absolute; top:-2px; bottom:-2px; width:2px; background:#ff9d2e;
  box-shadow:0 0 6px rgba(255,157,46,0.8);
}
.route-editor-toolbar{ display:flex; flex-wrap:wrap; gap:8px; }
.route-editor-toolbar .btn{ flex:1 1 auto; min-width:100px; font-size:12px; padding:9px 10px; }
.route-editor-toolbar .btn.active{ background:rgba(79,140,255,0.22); border-color:rgba(79,140,255,0.6); color:var(--text-primary); }
.route-editor-gfx-row{
  display:flex; flex-wrap:wrap; align-items:center; gap:8px;
  padding-top:10px; border-top:1px solid var(--border-subtle);
}
.route-editor-gfx-row .btn{ font-size:12px; padding:8px 12px; }
.route-editor-changelist{
  background:var(--bg-panel); border:1px solid var(--border-subtle);
  border-radius:var(--radius-md); padding:10px 12px;
}
.route-editor-changelist-title{
  font-family:var(--font-display); font-size:11px; letter-spacing:0.06em; text-transform:uppercase;
  color:var(--text-dim); margin-bottom:6px;
}
.route-editor-changelist ul{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:4px; }
.route-editor-changelist li{
  font-family:var(--font-mono); font-size:12px; color:var(--text-muted);
  padding-left:14px; position:relative;
}
.route-editor-changelist li::before{ content:"–"; position:absolute; left:0; color:var(--neon-green); }
.route-editor-footer{
  display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap;
  padding:12px 16px; border-top:1px solid var(--border-subtle); background:var(--bg-panel);
}
.route-editor-live-stats{ font-family:var(--font-mono); font-size:12px; color:var(--text-muted); }
.replay-route-marker{
  width:14px; height:14px; border-radius:50%; background:#ff9d2e;
  border:2px solid #1a0f05; box-shadow:0 0 0 4px rgba(255,157,46,0.28);
}

/* ---------- ride detail ---------- */
.detail-header{
  display:flex; align-items:center; justify-content:space-between;
  margin-bottom:16px; flex-wrap:wrap; gap:10px;
}
.detail-stats{
  display:grid; grid-template-columns:repeat(auto-fit, minmax(100px, 1fr));
  gap:12px; margin-bottom:16px;
}
.detail-stats .box{
  background:var(--bg-panel); border:1px solid var(--border-subtle);
  border-radius:var(--radius-md); padding:12px; text-align:center;
}
.detail-stats .box .v{font-family:var(--font-mono); font-size:18px; color:var(--neon-green);}
.detail-stats .box .k{font-family:var(--font-display); font-size:10px; color:var(--text-dim); letter-spacing:0.1em; text-transform:uppercase; margin-top:4px;}
.playback-bar{
  display:flex; align-items:center; gap:12px; margin-top:10px;
}
.playback-bar input[type=range]{flex:1; accent-color:var(--neon-green);}
.chart-panel{margin-top:16px;}
.chart-panel canvas{width:100%; height:180px;}

/* ---------- light theme override ---------- */
body.theme-light{
  --bg-void:#f4f5f7;
  --bg-panel:#ffffff;
  --bg-panel-raised:#f8f9fb;
  --bg-panel-hover:#eef0f4;
  --border-subtle:#e1e4ea;
  --border-strong:#c7ccd6;
  --text-primary:#161a22;
  --text-muted:#4b525f;
  /* Was #70788a — 4.2-4.43:1 against the panel backgrounds it's actually
     used on, just under WCAG AA's 4.5:1 for normal text. Darkened to
     clear 4.5:1+ against both --bg-panel and --bg-panel-raised while
     staying visibly lighter than --text-muted (dim still recedes toward
     the light background more than muted does). */
  --text-dim:#616980;
  --neon-green:#3568e0;
  --neon-green-dim:#c3d6fb;
  --neon-green-glow:rgba(53,104,224,0.16);
  --menu-panel-bg:rgba(255,255,255,0.92);
}
body.theme-light .speed-value{color:#f2f4f2;}
body.theme-light .btn.primary{color:#ffffff;}

.trip-footer{
  display:grid;
  grid-template-columns:repeat(4,1fr);
  gap:8px;
  margin-top:12px;
  padding-top:12px;
  border-top:1px solid var(--border-subtle);
}
.trip-footer .trip-stat{
  background:var(--bg-panel-raised);
  border:1px solid var(--border-subtle);
  border-radius:var(--radius-md);
  padding:10px 6px;
  text-align:center;
}
.trip-footer .trip-stat .v{
  font-family:var(--font-mono);
  font-size:15px;
  color:var(--neon-green);
}
.trip-footer .trip-stat .k{
  font-family:var(--font-display);
  font-size:9px;
  color:var(--text-dim);
  letter-spacing:0.08em;
  text-transform:uppercase;
  margin-top:2px;
}
@media (max-width:520px){
  .modal-overlay{ padding:8px; }
  .modal-box{ padding:12px; border-radius:18px; }
  .settings-tabs{ grid-template-columns:repeat(2, minmax(0, 1fr)); }
  .settings-tab{ min-height:36px; font-size:11px; }
  .trip-footer{grid-template-columns:repeat(2,1fr);} 
}

@media (max-width:480px){
  .trip-footer{grid-template-columns:repeat(2,1fr);} 
}

/* ---------- settings modal ---------- */
.modal-overlay{
  position:fixed; inset:0; z-index:100;
  background:rgba(5,7,9,0.72);
  backdrop-filter:blur(3px);
  display:flex; align-items:center; justify-content:center;
  padding:16px;
}
.modal-box{
  width:min(100%, 540px);
  max-height:min(88vh, 860px);
  overflow:hidden;
  display:flex; flex-direction:column;
  background:var(--card-bg-gradient, var(--bg-panel));
  border:1px solid var(--border-strong);
  border-radius:24px;
  padding:16px;
  box-shadow:0 18px 44px rgba(0,0,0,0.45);
}
.modal-header{
  display:flex; align-items:center; justify-content:space-between;
  gap:10px;
  margin-bottom:10px;
  flex-shrink:0;
}
.modal-header h3{
  margin:0;
  font-family:var(--font-display);
  font-size:20px;
  color:var(--text-primary);
}
.modal-desc{
  color:var(--text-muted);
  font-size:13px;
  line-height:1.6;
  margin:0 0 14px;
}
.current-default-row{
  display:flex; align-items:center; justify-content:space-between;
  gap:10px;
  background:var(--bg-panel-raised);
  border:1px solid var(--border-subtle);
  border-radius:var(--radius-md);
  padding:10px 12px;
  font-size:14px;
}
.settings-hero{
  display:flex; align-items:flex-start; justify-content:space-between;
  gap:10px;
  background:linear-gradient(90deg, rgba(79,140,255,0.12), rgba(34,211,238,0.08));
  border:1px solid var(--border-subtle);
  border-radius:16px;
  padding:12px 14px;
  margin-bottom:12px;
}
.settings-pill{
  flex-shrink:0;
  border:1px solid var(--neon-green-dim);
  color:var(--neon-green);
  background:rgba(79,140,255,0.1);
  border-radius:999px;
  padding:6px 10px;
  font-family:var(--font-display);
  font-weight:600;
  font-size:11px;
  letter-spacing:0.05em;
  text-transform:uppercase;
}

/* ---------- collapsible settings groups (native <details>, no JS needed) ---------- */
.settings-group{
  background:var(--bg-panel-raised);
  border:1px solid var(--border-subtle);
  border-radius:var(--radius-md);
  margin-bottom:10px;
  overflow:hidden;
}
.settings-group summary{
  list-style:none;
  cursor:pointer;
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:14px 16px;
  font-family:var(--font-display);
  font-weight:600; font-size:14px;
  color:var(--text-primary);
  user-select:none;
}
.settings-group summary::-webkit-details-marker{ display:none; }
.settings-group summary .sg-meta{
  font-family:var(--font-body);
  font-weight:400; font-size:12px;
  color:var(--text-muted);
  margin-left:auto; margin-right:4px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:40%;
}
.settings-group summary::after{
  content:"";
  flex-shrink:0;
  width:9px; height:9px;
  border-right:2px solid var(--text-dim);
  border-bottom:2px solid var(--text-dim);
  transform:rotate(-45deg);
  transition:transform 0.2s ease;
  margin-top:-3px;
}
.settings-group[open] summary::after{ transform:rotate(45deg); margin-top:0; }
.settings-group[open] summary{ border-bottom:1px solid var(--border-subtle); }
.settings-group-body{ padding:4px 16px 16px; }
.settings-group summary:hover{ color:var(--neon-green); }
.plugin-settings-card{
  background:var(--bg-panel-raised);
  border:1px solid var(--border-subtle);
  border-radius:16px;
  padding:12px;
  margin-bottom:10px;
}
.settings-row{
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:9px 0; border-bottom:1px solid var(--border-subtle);
  font-family:var(--font-body); font-size:14px; color:var(--text-primary);
}
.settings-row:last-child{ border-bottom:none; }
.settings-row input[type="checkbox"]{ width:20px; height:20px; flex-shrink:0; accent-color:var(--neon-green); }
.plugin-list{ display:flex; flex-direction:column; gap:8px; }
.plugin-list .route-form{ flex-wrap:wrap; }
.plugin-list .route-form input{ flex:1 1 180px; }
.plugin-list-item{
  display:flex; align-items:center; justify-content:space-between;
  gap:10px;
  background:var(--bg-panel);
  border:1px solid var(--border-subtle);
  border-radius:12px;
  padding:10px 12px;
}
.plugin-list-item strong{ display:block; color:var(--text-primary); }
.plugin-list-item span{ display:block; color:var(--text-muted); font-size:12px; margin-top:2px; }
.plugin-actions{ display:flex; align-items:center; gap:8px; }
.plugin-actions .btn{ min-height:36px; padding:0 12px; }
.settings-tabs{
  display:grid;
  grid-template-columns:repeat(4, minmax(0, 1fr));
  gap:4px;
  background:var(--bg-panel-raised);
  padding:4px; border-radius:14px;
  margin-bottom:12px;
  flex-shrink:0;
}
.settings-tab{
  min-height:40px;
  border:none; background:transparent;
  color:var(--text-muted);
  font-family:var(--font-display); font-weight:600; font-size:11px; letter-spacing:0.04em;
  border-radius:10px; cursor:pointer;
  white-space:nowrap;
  overflow:hidden; text-overflow:ellipsis;
  padding:0 6px;
}
.settings-tab.active{ background:var(--bg-panel); color:var(--neon-green); }
.settings-panel{
  flex:1; min-height:0; overflow-y:auto; padding-right:2px;
}

/* ---------- forecast card ---------- */
.forecast-days{
  display:flex; gap:10px; overflow-x:auto; padding-bottom:4px;
}
.forecast-day{
  position:relative;
  flex:0 0 96px;
  background:var(--bg-panel-raised);
  border:1px solid var(--border-subtle);
  border-radius:var(--radius-md);
  padding:10px 8px;
  text-align:center;
  cursor:pointer;
}
.forecast-day:hover, .forecast-day:focus-visible{ border-color:var(--border-strong); outline:none; }
.forecast-day.active{ border-color:var(--neon-green); }
.forecast-day.has-alert{ padding-top:26px; }
.forecast-day .fd-label{
  font-family:var(--font-display); font-size:11px; letter-spacing:0.08em;
  text-transform:uppercase; color:var(--text-dim);
}
.forecast-day .fd-icon{ font-size:26px; margin:6px 0; }
.forecast-day .fd-temps{ font-family:var(--font-mono); font-size:13px; }
.forecast-day .fd-hi{ color:var(--text-primary); font-weight:700; }
.forecast-day .fd-lo{ color:var(--text-dim); margin-left:4px; }
.forecast-day .fd-meta{ font-size:10px; color:var(--text-muted); margin-top:4px; }

/* Small alert strip pinned across the top of a forecast-day card, shown
   only when checkWeatherAlerts() found an NWS watch/warning overlapping
   that calendar day. Its own click is caught before the card's, so
   tapping it opens the alert's detail instead of the day's forecast. */
.forecast-day-alert-banner{
  position:absolute; top:0; left:0; right:0; z-index:2;
  display:block; width:100%;
  background:linear-gradient(180deg, rgba(255,59,92,0.95), rgba(190,28,58,0.95));
  color:#fff; border:none; border-radius:var(--radius-md) var(--radius-md) 0 0;
  font-family:var(--font-display); font-size:9px; font-weight:700; letter-spacing:0.02em;
  padding:4px 6px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  cursor:pointer;
}

/* ---------- forecast day detail modal ---------- */
.fdm-alert-banner{
  display:flex; align-items:center; gap:8px; width:100%;
  background:linear-gradient(180deg, rgba(255,59,92,0.95), rgba(190,28,58,0.95));
  color:#fff; border:none; border-radius:var(--radius-md);
  font-family:var(--font-display); font-size:13px; font-weight:600;
  padding:10px 12px; margin-bottom:14px; cursor:pointer; text-align:left;
}
.fdm-alert-banner .fdm-alert-icon{ font-size:16px; flex-shrink:0; }
.fdm-alert-banner .fdm-alert-text{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.fdm-alert-banner .fdm-alert-chevron{ font-size:18px; opacity:0.8; flex-shrink:0; }

.fdm-summary{ display:flex; align-items:center; gap:14px; margin-bottom:14px; }
.fdm-summary-icon{ font-size:44px; flex-shrink:0; }
.fdm-summary-main{ min-width:0; }
.fdm-summary-temps{ font-family:var(--font-mono); font-size:22px; }
.fdm-hi{ color:var(--text-primary); font-weight:700; }
.fdm-lo{ color:var(--text-dim); margin-left:6px; }
.fdm-summary-desc{ font-size:13px; color:var(--text-muted); text-transform:capitalize; margin-top:2px; }

.fdm-stat-grid{
  display:grid; grid-template-columns:1fr 1fr; gap:8px;
  margin-bottom:16px;
}
.fdm-stat{
  background:var(--bg-panel-raised); border:1px solid var(--border-subtle); border-radius:var(--radius-sm);
  padding:8px 10px; display:flex; flex-direction:column; gap:2px;
}
.fdm-stat-label{ font-family:var(--font-display); font-size:10px; letter-spacing:0.06em; text-transform:uppercase; color:var(--text-dim); }
.fdm-stat-value{ font-family:var(--font-mono); font-size:15px; color:var(--text-primary); }

.fdm-segments{ display:flex; gap:8px; overflow-x:auto; padding-bottom:4px; margin-bottom:6px; }
.fdm-segment{
  flex:0 0 68px; text-align:center;
  background:var(--bg-panel-raised); border:1px solid var(--border-subtle); border-radius:var(--radius-sm);
  padding:8px 4px;
}
.fdm-segment-time{ font-family:var(--font-display); font-size:9px; letter-spacing:0.04em; text-transform:uppercase; color:var(--text-dim); }
.fdm-segment-icon{ font-size:18px; margin:4px 0; }
.fdm-segment-temp{ font-family:var(--font-mono); font-size:13px; color:var(--text-primary); font-weight:700; }
.fdm-segment-pop{ font-size:9px; color:var(--text-muted); margin-top:2px; }

.fdm-carousel-title{
  font-family:var(--font-display); font-size:11px; letter-spacing:0.08em; text-transform:uppercase;
  color:var(--text-dim); margin:8px 0 8px; padding-top:10px; border-top:1px solid var(--border-subtle);
}
.fdm-carousel{ margin-bottom:2px; }

/* ---------- layout editor (Settings > Layout) ---------- */
.layout-editor-rows{ display:flex; flex-direction:column; gap:10px; }
.layout-editor-row{
  background:var(--bg-panel-raised);
  border:1px solid var(--border-subtle);
  border-radius:var(--radius-md);
  padding:8px;
}
.row-grip{
  font-family:var(--font-mono); font-size:11px; color:var(--text-dim);
  letter-spacing:0.1em; text-transform:uppercase;
  padding:2px 4px 8px; cursor:grab; user-select:none;
}
.layout-editor-chips{
  display:flex; flex-wrap:wrap; gap:8px; min-height:40px;
}
.layout-editor-chip{
  display:flex; align-items:center; gap:6px;
  background:var(--bg-panel);
  border:1px solid var(--border-subtle);
  border-radius:20px;
  padding:6px 10px;
  font-size:13px;
  cursor:grab;
  user-select:none;
}
.layout-editor-chip.is-hidden{ opacity:0.45; }
.layout-editor-chip.is-selected{
  border-color:var(--neon-green);
  box-shadow:0 0 0 2px var(--neon-green-dim);
  background:rgba(79,140,255,0.1);
}
.layout-editor-chip{ touch-action:manipulation; }
.layout-drop-slot{
  width:14px;
  min-height:34px;
  flex-shrink:0;
  padding:0;
  border-radius:6px;
  border:1px dashed var(--neon-green-dim);
  background:rgba(79,140,255,0.08);
  cursor:pointer;
}
.layout-drop-slot:hover, .layout-drop-slot:active{ background:rgba(79,140,255,0.22); }
.layout-drop-slot-newrow{
  display:block;
  width:100%;
  min-height:40px;
  margin-top:8px;
  border-radius:var(--radius-md);
  border:1px dashed var(--neon-green-dim);
  background:rgba(79,140,255,0.06);
  color:var(--neon-green);
  font-family:var(--font-display);
  font-size:12px;
  letter-spacing:0.06em;
  text-transform:uppercase;
  cursor:pointer;
}
.layout-editor-chip .grip{ color:var(--text-dim); }
.layout-editor-chip .chip-eye{
  background:none; border:none; cursor:pointer; font-size:14px; padding:0; line-height:1;
}
.layout-add-row-btns{ display:flex; gap:8px; margin-top:12px; }
.layout-add-row-btn{ width:100%; }
.sortable-ghost{ opacity:0.3; }
.sortable-chosen{ box-shadow:0 0 0 2px var(--neon-green-dim); }

/* Carousel row in the editor: same chip strip as a normal row, but boxed
   with a dashed accent border so it reads as a distinct row type, and its
   "+" column-add control lives inline at the end of the chip row (the
   "| chip | chip | + |" layout this was requested as). */
.layout-editor-row.is-carousel{
  border:1px dashed var(--neon-green-dim);
  background:rgba(79,140,255,0.05);
}
.layout-add-column-btn{
  flex-shrink:0;
  width:34px; height:34px;
  border-radius:50%;
  border:1px dashed var(--neon-green-dim);
  background:rgba(79,140,255,0.1);
  color:var(--neon-green);
  font-family:var(--font-display);
  font-size:16px; font-weight:700;
  cursor:pointer;
}
.layout-add-column-btn:hover{ background:rgba(79,140,255,0.22); }
.layout-editor-placeholder select{
  min-height:34px;
  border-radius:20px;
  border:1px dashed var(--border-strong);
  background:var(--bg-panel);
  color:var(--text-muted);
  font-size:12px;
  padding:0 10px;
  cursor:pointer;
}

/* ---------- dashboard carousel row (js/carousel.js) ---------- */
.layout-row.carousel-row{ display:block; }
.rr-carousel{ display:flex; flex-direction:column; gap:6px; }
.rr-carousel-main{
  display:flex; align-items:stretch; gap:6px;
}
/* The only part that clips/scrolls — arrows live outside it in their own
   gutter (below) rather than overlaid on top of the card, so they can
   never cover a card's own left/right-aligned content. */
.rr-carousel-viewport{
  flex:1; min-width:0; overflow:hidden;
  border-radius:var(--radius-lg);
}
.rr-carousel-track{
  display:flex; align-items:stretch;
  touch-action:pan-y;
}
.rr-carousel-slide{
  /* Actual width/flex-basis is set inline by js/carousel.js (a bit
     narrower than the viewport, so the next card peeks in at the edge) —
     these are just a same-render fallback before that JS runs. */
  flex:0 0 100%;
  width:100%;
  min-width:0;
  box-sizing:border-box;
}
.rr-carousel-slide > .rr-card{ width:100%; }
.rr-carousel-arrow{
  flex-shrink:0; align-self:center;
  width:40px; height:40px;
  border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:var(--bg-panel-raised);
  border:1px solid var(--border-subtle);
  color:var(--text-primary);
  font-size:20px; line-height:1;
  cursor:pointer;
  transition:opacity 0.2s ease, background 0.2s ease;
}
.rr-carousel-arrow:hover:not(:disabled){ background:var(--bg-panel); }
.rr-carousel-arrow:disabled{ opacity:0.3; pointer-events:none; }
.rr-carousel-dots{
  display:flex; justify-content:center; align-items:center; gap:6px;
}
.rr-carousel-dot{
  width:6px; height:6px; border-radius:50%; border:none; padding:0;
  background:var(--border-strong);
  cursor:pointer;
  transition:width 0.2s ease, border-radius 0.2s ease, background 0.2s ease;
}
.rr-carousel-dot.active{ width:16px; border-radius:3px; background:var(--neon-green); }

/* ---------- screensaver ---------- */
/* True black (not the app's usual near-black void) so an OLED panel can
   turn those pixels fully off, plus a near-static DOM updated on a slow
   1s interval instead of every GPS tick — this is deliberately the
   cheapest screen a phone can show while still lit for GPS recording. No
   gradients, shadows, or animation here on purpose. */
.screensaver-modal{
  position:fixed; inset:0; z-index:200;
  background:#000;
  display:flex; align-items:center; justify-content:center;
  cursor:pointer;
  -webkit-tap-highlight-color:transparent;
}
.screensaver-topbar{
  position:absolute; top:0; left:0; right:0;
  display:flex; align-items:center; justify-content:center;
  gap:14px;
  padding:22px 16px 0;
}
.screensaver-clock{
  font-family:var(--font-mono);
  font-weight:700;
  font-size:22px;
  color:#fff;
  letter-spacing:0.04em;
}
.screensaver-rec{
  display:none; align-items:center; gap:6px;
  position:absolute; right:20px; top:22px;
}
.screensaver-rec.recording,
.screensaver-rec.paused{ display:flex; }
.screensaver-rec .rec-dot{
  width:9px; height:9px; border-radius:50%;
  background:var(--alert-red);
  animation:recPulse 1.2s infinite ease-in-out;
}
.screensaver-rec.paused .rec-dot{ background:var(--warn-amber); animation:none; }
.screensaver-rec-label{
  font-family:var(--font-display);
  font-weight:700; font-size:11px; letter-spacing:0.08em;
  text-transform:uppercase;
  color:var(--alert-red);
}
.screensaver-rec.paused .screensaver-rec-label{ color:var(--warn-amber); }

.screensaver-alert{
  display:none; align-items:center; gap:8px;
  position:absolute; top:64px; left:50%; transform:translateX(-50%);
  max-width:min(86vw, 480px);
  background:rgba(239,68,68,0.18);
  border:1px solid rgba(239,68,68,0.5);
  color:#fff;
  padding:8px 16px;
  border-radius:999px;
  font-family:var(--font-body);
  font-weight:500;
  font-size:12.5px;
  cursor:pointer;
  -webkit-tap-highlight-color:transparent;
}
.screensaver-alert.show{ display:flex; }
.screensaver-alert-icon{ font-size:15px; flex-shrink:0; }
.screensaver-alert-text{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

.screensaver-widgets{
  display:flex; flex-direction:column; align-items:center; gap:10px;
}
.screensaver-widget{ text-align:center; }
.screensaver-value{
  font-family:var(--font-mono);
  font-weight:700;
  font-size:min(30vw, 220px);
  line-height:1;
  color:#fff;
}
.screensaver-value-sm{ font-size:min(14vw, 90px); }
.screensaver-label{
  font-family:var(--font-display);
  font-size:16px;
  letter-spacing:0.3em;
  color:#7a7a7a;
  margin-top:8px;
  text-transform:uppercase;
  overflow:hidden;
  white-space:nowrap;
  max-width:min(80vw, 320px);
  margin-inline:auto;
}
.screensaver-label.scrolling-label,
.screensaver-value.scrolling-label,
.screensaver-spotify-time.scrolling-label{
  display:block;
  overflow:hidden;
  white-space:nowrap;
}
.scrolling-label-track{
  display:inline-block;
  padding-right:12px;
  white-space:nowrap;
  will-change:transform;
}
.scrolling-label .scrolling-label-track{
  animation: screensaver-scroll 7.5s ease-in-out infinite;
  animation-delay: 1.2s;
}
@keyframes screensaver-scroll {
  0%, 18% { transform: translateX(0); }
  82%, 100% { transform: translateX(calc(-50% - 6px)); }
}
.screensaver-hint{
  position:absolute; bottom:26px; left:0; right:0;
  text-align:center;
  font-family:var(--font-body);
  font-size:12px;
  color:#3a3a3a;
}
.screensaver-widget-check{
  display:flex; align-items:center; gap:10px;
  font-family:var(--font-body); font-size:14px; color:var(--text-primary);
  padding:8px 0;
  cursor:pointer;
}
.screensaver-widget-check input{ width:18px; height:18px; accent-color:var(--neon-green); cursor:pointer; }

/* ---------- top alert banner (precip along route / weather watches) ---------- */
.top-banner{
  position:fixed; top:0; left:0; right:0; z-index:150;
  display:flex; align-items:center; gap:10px;
  padding:12px 16px;
  background:linear-gradient(180deg, rgba(255,59,92,0.95), rgba(190,28,58,0.95));
  color:#fff;
  font-family:var(--font-display);
  font-size:14px;
  cursor:pointer;
  box-shadow:0 4px 16px rgba(0,0,0,0.35);
}
.top-banner-icon{ font-size:18px; flex-shrink:0; }
.top-banner-text{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.top-banner-more{ font-family:var(--font-mono); font-size:11px; opacity:0.85; flex-shrink:0; }
.top-banner-close{ font-family:var(--font-body); font-size:11px; opacity:0.75; flex-shrink:0; }

/* ---------- Settings > Speedometer ---------- */
.speedo-style-toggle{ display:flex; gap:8px; }
.speedo-style-btn{
  flex:1; min-height:44px;
  border:1px solid var(--border-subtle);
  background:var(--bg-panel-raised);
  border-radius:var(--radius-md);
  color:var(--text-muted);
  font-family:var(--font-display); font-weight:600; font-size:14px;
  cursor:pointer;
}
.speedo-style-btn.active{
  border-color:var(--neon-green-dim);
  color:var(--neon-green);
  background:rgba(79,140,255,0.08);
}
.spotify-art-style-btn{
  flex:1; min-height:44px;
  border:1px solid var(--border-subtle);
  background:var(--bg-panel-raised);
  border-radius:var(--radius-md);
  color:var(--text-muted);
  font-family:var(--font-display); font-weight:600; font-size:14px;
  cursor:pointer;
}
.spotify-art-style-btn.active{
  border-color:var(--neon-green-dim);
  color:var(--neon-green);
  background:rgba(79,140,255,0.08);
}
.speedo-preview{
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  position:relative;
  background:var(--speedo-bg, radial-gradient(circle at 50% 30%, var(--bg-panel-raised), var(--bg-panel) 70%));
  border:1px solid var(--border-subtle);
  border-radius:var(--radius-lg);
  padding:20px;
  margin-bottom:6px;
}
.speedo-preview svg{ width:160px; height:160px; }
.speedo-preview.style-digital svg{ display:none; }
.speedo-preview.style-digital .speedo-preview-overlay{
  position:static;
  transform:none;
}
.speedo-preview-overlay{
  position:absolute; top:50%; left:50%;
  transform:translate(-50%,-50%);
  text-align:center; pointer-events:none;
}
.speedo-preview-value{
  font-family:var(--speedo-font, var(--font-mono));
  font-weight:700;
  font-size:var(--speedo-size-preview, 40px);
  color:var(--speedo-fg, var(--neon-green));
  text-shadow:0 0 24px var(--speedo-fg-glow, var(--neon-green-glow));
  line-height:1;
}
.color-picker-row{ display:flex; gap:16px; }
.color-picker-row label{
  flex:1; display:flex; flex-direction:column; gap:6px;
  font-family:var(--font-body); font-size:13px; color:var(--text-muted);
}
.color-picker-row input[type=color]{
  width:100%; height:44px;
  border:1px solid var(--border-subtle); border-radius:8px;
  background:var(--bg-void); cursor:pointer; padding:2px;
}
.color-picker-row input[type=color]:disabled{ opacity:0.35; cursor:not-allowed; }
.transparent-check{
  display:flex; align-items:center; gap:8px;
  font-family:var(--font-body); font-size:13px; color:var(--text-muted);
  margin-top:8px; cursor:pointer;
}
.transparent-check input{ width:16px; height:16px; accent-color:var(--neon-green); cursor:pointer; }

/* ---------- speedometer session stats (max/avg speed while recording) ---------- */
.speedo-session-stats{
  display:grid; grid-template-columns:1fr 1fr; gap:8px;
  margin-top:10px;
}
.speedo-stat{
  background:var(--bg-panel-raised);
  border:1px solid var(--border-subtle);
  border-radius:var(--radius-md);
  padding:10px 6px;
  text-align:center;
}
.speedo-stat .v{ font-family:var(--font-mono); font-size:20px; font-weight:700; color:var(--neon-green); }
.speedo-stat .k{
  font-family:var(--font-display); font-size:10px; letter-spacing:0.1em;
  color:var(--text-dim); text-transform:uppercase; margin-top:2px;
}

/* ---------- plugin cards ---------- */
.plugin-card{ position:relative; display:block; }
.plugin-shell{
  position:relative;
  background:var(--card-custom-bg, var(--bg-panel));
  border:1px solid var(--border-subtle);
  border-radius:20px;
  padding:12px;
  min-height:170px;
  display:flex; flex-direction:column;
  gap:10px;
}
.plugin-head{ display:flex; align-items:center; justify-content:space-between; gap:10px; }
.plugin-head-copy{ display:flex; align-items:center; gap:8px; min-width:0; }
.plugin-icon{ width:34px; height:34px; border-radius:10px; display:grid; place-items:center; background:rgba(79,140,255,0.14); color:var(--neon-green); font-size:18px; flex-shrink:0; }
.plugin-title{ font-family:var(--font-display); font-weight:700; font-size:14px; color:var(--text-primary); }
.plugin-meta{ font-family:var(--font-body); font-size:11px; color:var(--text-muted); }
.plugin-resize-grip{
  position:absolute; right:8px; bottom:8px;
  width:24px; height:24px; flex-shrink:0; cursor:ns-resize; touch-action:none;
  background:linear-gradient(135deg, transparent 50%, var(--text-dim) 50%, var(--text-dim) 60%, transparent 60%, transparent 68%, var(--text-dim) 68%, var(--text-dim) 78%, transparent 78%);
  border-radius:6px;
}
.plugin-body{ flex:1; }
.plugin-surface{
  height:100%; border-radius:16px; padding:12px; display:flex; flex-direction:column; gap:10px;
  background:radial-gradient(circle at top left, var(--neon-green-glow), transparent 40%), var(--bg-panel-raised);
  border:1px solid var(--border-subtle);
}
.plugin-surface.light{ background:linear-gradient(135deg, rgba(31,156,86,0.16), rgba(255,255,255,0.95)); color:#0f1a12; }
.plugin-stat-row{ display:flex; align-items:center; justify-content:space-between; gap:10px; }
/* Two label/value pairs each. space-between reads fine on a narrow card
   (where the two items already sit close to the edges anyway), but this
   same card can also end up full-width via the Layout editor — there,
   space-between flings the pairs to opposite corners of the row with a
   huge dead gap between them, breaking the "these four stats belong
   together" grouping. Clustering with a fixed gap and letting it wrap
   keeps the pairs legible as one group at any card width. */
.plugin-meta-row,
.plugin-footer{ display:flex; align-items:center; flex-wrap:wrap; gap:10px 28px; }
.plugin-big{ font-family:var(--font-mono); font-size:calc(28px * var(--plugin-scale, 1)); font-weight:700; color:var(--neon-green); display:flex; align-items:flex-end; gap:4px; }
.plugin-big span{ font-family:var(--font-display); font-size:10px; letter-spacing:0.06em; text-transform:uppercase; color:var(--text-muted); margin-bottom:4px; }
.plugin-chip{
  border:1px solid var(--neon-green-dim); color:var(--neon-green); background:rgba(79,140,255,0.12); padding:6px 8px; border-radius:999px;
  font-family:var(--font-display); font-size:10px; letter-spacing:0.12em; text-transform:uppercase;
}
.plugin-label{ font-family:var(--font-display); font-size:10px; letter-spacing:0.06em; text-transform:uppercase; color:var(--text-dim); }

/* ---------- Apex Drag & Launch plugin card ----------
   Drag-strip telemetry HUD: a mini launch-tree light bar, an LED-style
   digit readout with HUD corner brackets, and angled motorsport-tab chip
   selectors. Built entirely from the app's existing tokens rather than a
   one-off palette — --neon-green is the app's single confident accent
   (it renders as blue; --cyan is the token set's secondary telemetry
   tone), --warn-amber for staged/armed, --alert-red for the danger/arm
   action — so the card reads as "this app's drag timer," not a bolted-on
   component. State (idle/armed/running/finished) is driven by a
   data-state attribute on .ad-surface set from apex-drag.js. */
.ad-surface{ display:flex; flex-direction:column; gap:14px; }
.ad-sub-head{ display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap; }
.ad-target-row{ display:flex; gap:6px; flex-wrap:wrap; }

.ad-chip{
  border:1px solid var(--border-subtle);
  background:var(--bg-panel-raised);
  color:var(--text-muted);
  font-family:var(--font-display); font-weight:600; font-size:12px; letter-spacing:0.01em;
  padding:8px 14px 8px 17px;
  /* A slight angled cut on both edges — a motorsport "tab selector" look
     instead of a generic pill, echoing the diagonal energy of a drag
     strip without resorting to a literal checkered pattern. */
  clip-path:polygon(9px 0, 100% 0, calc(100% - 9px) 100%, 0 100%);
  cursor:pointer;
  transition:border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.ad-chip.selected{ border-color:var(--neon-green-dim); color:var(--neon-green); background:rgba(79,140,255,0.12); }

.ad-history-icon-btn{
  border:1px solid var(--border-subtle);
  background:var(--bg-panel-raised);
  color:var(--text-muted);
  font-family:var(--font-display); font-weight:600; font-size:12px;
  padding:6px 14px; border-radius:999px; cursor:pointer;
  white-space:nowrap;
}
.ad-history-icon-btn:hover{ color:var(--neon-green); border-color:var(--neon-green-dim); }

.ad-timer-box{
  position:relative;
  background:var(--bg-void);
  border:1px solid var(--border-subtle);
  border-radius:var(--radius-md);
  padding:20px 18px 18px;
  display:flex; flex-direction:column; align-items:center; gap:2px;
  overflow:hidden;
  transition:border-color 0.25s ease;
}
/* HUD corner brackets — a light telemetry-frame cue rather than a plain
   box, reinforcing "this is an instrument reading," not just a number. */
.ad-timer-box::before,
.ad-timer-box::after{
  content:""; position:absolute; width:14px; height:14px;
  border:2px solid var(--border-strong); opacity:0.7; pointer-events:none;
}
.ad-timer-box::before{ top:7px; left:7px; border-right:none; border-bottom:none; }
.ad-timer-box::after{ bottom:7px; right:7px; border-left:none; border-top:none; }

.ad-tree-lights{ display:flex; gap:6px; margin-bottom:4px; }
.ad-tree-light{
  width:9px; height:9px; border-radius:50%;
  background:var(--bg-panel-hover);
  box-shadow:inset 0 0 0 1px var(--border-strong);
  transition:background 0.2s ease, box-shadow 0.2s ease;
}
.ad-tree-light.green{ margin-left:5px; }

.ad-status-pill{
  font-family:var(--font-display); font-weight:700; font-size:10px; letter-spacing:0.1em; text-transform:uppercase;
  color:var(--text-dim);
  background:var(--bg-panel);
  border:1px solid var(--border-subtle);
  padding:4px 11px; border-radius:999px; margin-bottom:8px;
  transition:color 0.2s ease, border-color 0.2s ease;
}
.ad-time-digits{
  font-family:var(--font-mono); font-weight:700;
  font-variant-numeric:tabular-nums;
  font-size:calc(36px * var(--plugin-scale, 1));
  color:var(--text-primary);
  text-shadow:0 0 18px rgba(238,241,245,0.1);
  transition:color 0.2s ease, text-shadow 0.3s ease;
}
.ad-speed-sub{
  font-family:var(--font-mono); font-size:13px; letter-spacing:0.01em; color:var(--text-muted); margin-top:2px;
  font-variant-numeric:tabular-nums;
}

@keyframes ad-tree-pulse{ 0%,100%{ opacity:1; } 50%{ opacity:0.4; } }

.ad-surface[data-state="armed"] .ad-tree-light.amber{
  background:var(--warn-amber);
  box-shadow:0 0 8px 1px rgba(245,158,11,0.55), inset 0 0 0 1px rgba(245,158,11,0.75);
  animation:ad-tree-pulse 0.9s ease-in-out infinite;
}
.ad-surface[data-state="armed"] .ad-tree-light.amber:nth-child(2){ animation-delay:0.15s; }
.ad-surface[data-state="armed"] .ad-tree-light.amber:nth-child(3){ animation-delay:0.3s; }
.ad-surface[data-state="armed"] .ad-status-pill{ color:var(--warn-amber); border-color:rgba(245,158,11,0.4); }
.ad-surface[data-state="armed"] .ad-time-digits{
  color:var(--warn-amber); text-shadow:0 0 20px rgba(245,158,11,0.32);
  /* "WAITING FOR MOTION" is a text label, not digits — the digit size
     that fits "0.000s" wraps a phrase this long onto two cramped lines. */
  font-size:calc(15px * var(--plugin-scale, 1)); letter-spacing:0.04em;
}
.ad-surface[data-state="armed"] .ad-timer-box{ border-color:rgba(245,158,11,0.4); }

.ad-surface[data-state="running"] .ad-tree-light.amber{ background:var(--warn-amber); box-shadow:inset 0 0 0 1px rgba(245,158,11,0.75); }
.ad-surface[data-state="running"] .ad-tree-light.green{
  background:var(--neon-green);
  box-shadow:0 0 10px 2px var(--neon-green-glow), inset 0 0 0 1px var(--neon-green);
  animation:ad-tree-pulse 0.6s ease-in-out infinite;
}
.ad-surface[data-state="running"] .ad-status-pill{ color:var(--neon-green); border-color:var(--neon-green-dim); }
.ad-surface[data-state="running"] .ad-time-digits{ color:var(--neon-green); text-shadow:0 0 22px var(--neon-green-glow); }
.ad-surface[data-state="running"] .ad-timer-box{ border-color:var(--neon-green-dim); }

.ad-surface[data-state="finished"] .ad-tree-light.amber{ background:var(--warn-amber); box-shadow:inset 0 0 0 1px rgba(245,158,11,0.75); }
.ad-surface[data-state="finished"] .ad-tree-light.green{ background:var(--neon-green); box-shadow:0 0 8px 1px var(--neon-green-glow), inset 0 0 0 1px var(--neon-green); }
.ad-surface[data-state="finished"] .ad-status-pill{ color:var(--neon-green); border-color:var(--neon-green-dim); }

.ad-arm-btn{
  position:relative;
  min-height:var(--touch); width:100%;
  border-radius:var(--radius-sm);
  border:1px solid var(--alert-red);
  background:linear-gradient(180deg, rgba(239,68,68,0.14), rgba(239,68,68,0.04));
  color:var(--alert-red);
  font-family:var(--font-display); font-weight:700; font-size:14px; letter-spacing:0.02em;
  cursor:pointer;
  overflow:hidden;
  transition:filter 0.15s ease, border-color 0.2s ease, color 0.2s ease, background 0.2s ease;
}
.ad-arm-btn:hover{ filter:brightness(1.06); }
.ad-arm-btn:active{ filter:brightness(0.94); }
.ad-arm-btn-label{ position:relative; z-index:1; }
/* Thin hazard-stripe edge instead of striping the whole button — a nod to
   drag-strip signage that stays a detail, not decoration overload. */
.ad-arm-btn::before{
  content:""; position:absolute; inset:0 auto 0 0; width:6px;
  background:repeating-linear-gradient(-45deg, currentColor 0 4px, transparent 4px 8px);
  opacity:0.5;
}
.ad-surface[data-state="armed"] .ad-arm-btn,
.ad-surface[data-state="running"] .ad-arm-btn{
  border-color:var(--warn-amber);
  color:var(--warn-amber);
  background:linear-gradient(180deg, rgba(245,158,11,0.16), rgba(245,158,11,0.04));
}
.plugin-value{ font-family:var(--font-mono); font-size:calc(12px * var(--plugin-scale, 1)); color:var(--text-primary); margin-top:2px; }
.plugin-surface.light .plugin-value{ color:#1a231d; }
.plugin-surface.light .plugin-label{ color:#4f6654; }

/* ---------- Ride Pulse: instrument-cluster redesign ----------
   A completely bespoke card, styled like a physical motorcycle dash
   rather than a grid of generic stat tiles: a halogen-amber speedometer
   arc, a lean-angle "horizon" dial that actually tilts a bike glyph left/
   right, a heading compass, an idiot-light REC indicator, and an all-time
   "logbook" with a mechanical rolling-digit odometer. Deliberately uses
   its own fixed dark gauge-face palette (not the app's per-theme tokens)
   the same way plugins/chase-cam-3d and spotify-playlists already do for
   their own bespoke cards — a backlit dash face reads the same whether
   the rest of the app is in light or dark theme, same as a real
   motorcycle's cluster does. For that reason it also opts out of the
   Settings > Appearance "custom card text color" knob (.rr-card
   .plugin-value/.plugin-label), same as those two cards already do —
   arbitrary user text colors would break the gauge-face contrast this
   was tuned against. */
.rp-cluster{
  --rp-face:#14161a; --rp-face-raised:#1c1f24; --rp-rim:#2a2e35;
  --rp-amber:#ffb020; --rp-amber-dim:#c98f3a; --rp-red:#ff3b3b;
  --rp-ice:#eaf6ff; --rp-text-dim:#8790a0; --rp-track:#2c313a;
  background:
    radial-gradient(circle at 30% 0%, rgba(255,176,32,0.07), transparent 55%),
    var(--rp-face);
  border-radius:var(--radius-md);
  padding:calc(14px * var(--plugin-scale, 1));
  display:flex; flex-direction:column; gap:calc(10px * var(--plugin-scale, 1));
  font-family:var(--font-body);
  position:relative;
  width:100%; max-width:100%; box-sizing:border-box;
  overflow:hidden;
}
/* Faint brushed-metal grain — a repeating diagonal hairline pattern, not
   an image, so it stays crisp at any card scale and costs nothing to load. */
.rp-cluster::before{
  content:""; position:absolute; inset:0; pointer-events:none; z-index:0;
  background-image:repeating-linear-gradient(115deg, rgba(255,255,255,0.025) 0px, rgba(255,255,255,0.025) 1px, transparent 1px, transparent 5px);
}
/* A flex column's cross-axis (width) default is align-items:stretch, but
   that still yields to a child's own min-content width if it's wider —
   min-width:0 here is the blanket fix so no direct child (hero row,
   placards row, logbook) can push the card wider than its container. */
.rp-cluster > *{ position:relative; z-index:1; min-width:0; max-width:100%; }

.rp-hero{ display:flex; align-items:center; gap:calc(10px * var(--plugin-scale, 1)); min-width:0; }
.rp-speed-gauge{
  position:relative;
  /* flex-basis:0 with hero-side sharing the same basis+grow means the
     two split available space evenly instead of one taking a fixed
     share and dumping the entire squeeze onto the other — that's what
     was actually forcing hero-side's content past its own box before.
     --plugin-scale is a vertical/density knob elsewhere in this app (the
     resize grip only drags on Y), so it never grows the *available*
     width — max-width is capped in cqw (relative to .rr-card, which is
     already a container) instead of multiplying by scale, so the gauge
     can't demand more horizontal room than the card actually has. */
  flex:1 1 0;
  min-width:56px;
  max-width:min(150px, 42cqw);
  aspect-ratio:200 / 116;
}
.rp-speed-svg{ width:100%; height:100%; display:block; overflow:visible; }
.rp-speed-track{ fill:none; stroke:var(--rp-track); stroke-width:11; stroke-linecap:round; }
.rp-speed-fill{
  fill:none; stroke:var(--rp-amber); stroke-width:11; stroke-linecap:round;
  filter:drop-shadow(0 0 5px rgba(255,176,32,0.55));
  transition:stroke-dashoffset 0.25s cubic-bezier(0.22,1,0.36,1), stroke 0.25s ease;
}
.rp-speed-fill.is-redline{ stroke:var(--rp-red); filter:drop-shadow(0 0 6px rgba(255,59,59,0.6)); }
.rp-speed-tick{ stroke:var(--rp-rim); stroke-width:2.5; stroke-linecap:round; }
.rp-speed-readout{
  position:absolute; left:0; right:0; bottom:calc(-2px * var(--plugin-scale, 1));
  display:flex; flex-direction:column; align-items:center; line-height:1;
}
.rp-speed-num{
  font-family:'Orbitron', var(--font-display); font-weight:800;
  /* .rr-card is a container (container-type:inline-size) — capping with
     a cqw-relative value means the numeral automatically scales itself
     down on a genuinely narrow/1-third-width card instead of overflowing
     the gauge it sits on once that gauge has shrunk below its usual size. */
  font-size:min(calc(34px * var(--plugin-scale, 1)), 15cqw);
  color:var(--rp-ice);
  letter-spacing:0.01em; text-shadow:0 0 14px rgba(234,246,255,0.25);
}
.rp-speed-unit{
  font-family:var(--font-display); font-weight:600; font-size:min(calc(9px * var(--plugin-scale, 1)), 4cqw);
  letter-spacing:0.14em; color:var(--rp-text-dim); margin-top:1px;
}

.rp-hero-side{
  display:flex; flex-direction:column; gap:calc(6px * var(--plugin-scale, 1));
  flex:1 1 0; min-width:70px;
}

.rp-rec-light{
  display:flex; align-items:center; gap:6px;
  padding:4px min(calc(8px * var(--plugin-scale, 1)), 3cqw);
  background:var(--rp-face-raised); border:1px solid var(--rp-rim); border-radius:999px;
  /* Sized to its own content but docked to the column's right edge — same
     reasoning as the mini-gauge rows below: rp-hero-side is a flex-grow
     column that's often much wider than any single row's content, so
     without an explicit anchor everything here just hugs the left edge
     and leaves a dead gap on the right, right where a rider glancing over
     from the speedometer would expect HDG/LEAN to actually be. */
  width:fit-content; max-width:100%; align-self:flex-end;
}
.rp-rec-dot{
  width:8px; height:8px; border-radius:50%; flex:0 0 auto;
  background:var(--rp-text-dim);
}
.rp-rec-light.is-recording .rp-rec-dot{
  background:var(--rp-red); box-shadow:0 0 8px 1px rgba(255,59,59,0.75);
  animation:rp-rec-pulse 1.4s ease-in-out infinite;
}
@keyframes rp-rec-pulse{ 0%,100%{ opacity:1; } 50%{ opacity:0.35; } }
.rp-rec-text{
  font-family:var(--font-display); font-weight:700; font-size:min(calc(9.5px * var(--plugin-scale, 1)), 4cqw);
  letter-spacing:0.1em; color:var(--rp-text-dim); white-space:nowrap;
}
.rp-rec-light.is-recording .rp-rec-text{ color:var(--rp-ice); }

.rp-mini-gauge{
  display:flex; align-items:center; justify-content:flex-end;
  gap:min(calc(7px * var(--plugin-scale, 1)), 3cqw); min-width:0; max-width:100%;
}
.rp-mini-gauge svg{
  width:min(calc(32px * var(--plugin-scale, 1)), 10cqw);
  height:min(calc(32px * var(--plugin-scale, 1)), 10cqw);
  flex:0 0 auto;
}
.rp-mini-face{ fill:var(--rp-face-raised); stroke:var(--rp-rim); stroke-width:2; }
.rp-mini-tick{ stroke:var(--rp-rim); stroke-width:2.5; stroke-linecap:round; }
.rp-mini-horizon{ stroke:var(--rp-rim); stroke-width:1.5; stroke-dasharray:2 2; }
.rp-bike-glyph{ transform-box:fill-box; transform-origin:50% 50%; transition:transform 0.2s ease-out; }
.rp-bike-wheel{ fill:none; stroke:var(--rp-ice); stroke-width:3; }
.rp-bike-frame{ fill:none; stroke:var(--rp-amber); stroke-width:2.6; stroke-linecap:round; stroke-linejoin:round; }
.rp-bike-glyph.is-flat .rp-bike-frame{ stroke:var(--rp-text-dim); }
.rp-compass-n{
  font-family:var(--font-display); font-weight:700; font-size:8px; fill:var(--rp-text-dim);
  text-anchor:middle;
}
.rp-compass-needle{ transform-box:fill-box; transform-origin:50% 50%; transition:transform 0.25s ease-out; }
.rp-needle-shape{ fill:var(--rp-amber); }
.rp-mini-label{
  font-family:var(--font-display); font-weight:600; font-size:min(calc(9.5px * var(--plugin-scale, 1)), 4cqw);
  letter-spacing:0.06em; color:var(--rp-text-dim); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  min-width:0;
}
.rp-mini-label b{ color:var(--rp-ice); font-weight:700; margin-left:3px; }

.rp-placards{ display:flex; gap:calc(8px * var(--plugin-scale, 1)); }
.rp-placard{
  flex:1; min-width:0; display:flex; align-items:center; gap:8px;
  background:var(--rp-face-raised); border:1px solid var(--rp-rim);
  border-radius:var(--radius-sm); padding:calc(7px * var(--plugin-scale, 1)) calc(9px * var(--plugin-scale, 1));
}
.rp-placard > div{ min-width:0; }
.rp-placard-icon{ font-size:min(calc(14px * var(--plugin-scale, 1)), 6cqw); flex:0 0 auto; filter:grayscale(0.15); }
.rp-placard-label{
  font-family:var(--font-display); font-weight:600; font-size:min(calc(8.5px * var(--plugin-scale, 1)), 3.6cqw);
  letter-spacing:0.1em; text-transform:uppercase; color:var(--rp-text-dim); white-space:nowrap;
}
.rp-placard-value{
  font-family:var(--font-mono); font-size:min(calc(11.5px * var(--plugin-scale, 1)), 4.8cqw); color:var(--rp-ice);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; margin-top:1px;
}

/* A literal stretch of road as the section break — a dashed lane line
   down an asphalt strip, exactly what separates "right now" from "the
   road behind you" on this dash. */
.rp-road-divider{
  height:10px; border-radius:3px; position:relative; overflow:hidden;
  background:linear-gradient(180deg, #22262d, #1a1d23);
  border:1px solid var(--rp-rim);
}
.rp-lane-line{
  position:absolute; top:50%; left:0; right:0; height:2px; transform:translateY(-50%);
  background-image:repeating-linear-gradient(90deg, var(--rp-amber-dim) 0 10px, transparent 10px 20px);
  opacity:0.8;
}

.rp-logbook{ display:flex; flex-direction:column; gap:calc(8px * var(--plugin-scale, 1)); }
.rp-logbook-title{
  font-family:var(--font-display); font-weight:700; font-size:min(calc(10.5px * var(--plugin-scale, 1)), 4.4cqw);
  letter-spacing:0.1em; text-transform:uppercase; color:var(--rp-text-dim);
}
.rp-logbook-title span{ font-weight:500; text-transform:none; letter-spacing:0; color:var(--rp-text-dim); opacity:0.75; }
.rp-logbook-empty{ font-family:var(--font-body); font-size:12px; color:var(--rp-text-dim); }

.rp-odometer{
  display:flex; align-items:center; gap:3px;
  background:var(--rp-face-raised); border:1px solid var(--rp-rim); border-radius:var(--radius-sm);
  padding:calc(8px * var(--plugin-scale, 1)) calc(10px * var(--plugin-scale, 1));
  /* Was width:fit-content with fixed-px digit boxes — content that never
     shrinks, so on a narrow card or a scaled-up card it just pushed past
     the card's edge instead of adapting. Digits now flex-share whatever
     width is actually available (min-width:0 lets them go below their
     own text's min-content size, same fix as everywhere else in this
     card), each capped at its old size so a wide card still looks like a
     normal-proportioned odometer instead of stretching. */
  width:100%; max-width:100%; box-sizing:border-box; min-width:0;
}
.rp-odo-digit{
  font-family:var(--font-mono); font-weight:700; font-size:min(calc(18px * var(--plugin-scale, 1)), 7cqw);
  color:var(--rp-ice); background:var(--rp-face);
  border:1px solid var(--rp-rim); border-radius:3px;
  flex:1 1 0; min-width:0; max-width:calc(16px * var(--plugin-scale, 1)); text-align:center;
  box-shadow:inset 0 2px 3px rgba(0,0,0,0.5);
}
.rp-odo-tenths{
  font-family:var(--font-mono); font-weight:700; font-size:min(calc(14px * var(--plugin-scale, 1)), 5.5cqw);
  color:var(--rp-face); background:var(--rp-amber);
  border-radius:3px; flex:0 1 auto; min-width:0; max-width:calc(13px * var(--plugin-scale, 1)); text-align:center;
  margin-left:2px;
}
.rp-odo-unit{
  font-family:var(--font-display); font-weight:700; font-size:min(calc(9px * var(--plugin-scale, 1)), 3.6cqw);
  letter-spacing:0.08em; color:var(--rp-text-dim); margin-left:6px;
  flex:0 0 auto; white-space:nowrap;
}

.rp-spec-sheet{
  /* A bare `1fr` track's *minimum* size is its content's min-content
     width, not 0 — with nowrap label/value text inside, that silently
     forced the whole grid (and the card around it) wider than the
     container on anything narrower than the content demanded.
     minmax(0, 1fr) is the actual "share space, shrink freely" track. */
  display:grid; grid-template-columns:minmax(0, 1fr) minmax(0, 1fr);
  gap:0 calc(14px * var(--plugin-scale, 1));
  min-width:0;
}
.rp-spec-row{
  display:flex; align-items:baseline; justify-content:space-between; gap:6px;
  padding:calc(5px * var(--plugin-scale, 1)) 0;
  border-bottom:1px solid var(--rp-rim);
  min-width:0;
}
.rp-spec-k{
  font-family:var(--font-display); font-weight:500; font-size:min(calc(10px * var(--plugin-scale, 1)), 4.2cqw);
  letter-spacing:0.02em; color:var(--rp-text-dim);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0;
}
.rp-spec-v{
  font-family:var(--font-mono); font-weight:700; font-size:min(calc(11.5px * var(--plugin-scale, 1)), 4.8cqw);
  color:var(--rp-amber-dim); white-space:nowrap; flex:0 0 auto;
}

/* Card is narrow (Layout editor's 1/3-width column, or a small phone) —
   drop the two-column spec sheet to one so values never truncate. */
@container (max-width: 260px){
  .rp-spec-sheet{ grid-template-columns:1fr; }
  .rp-placards{ flex-direction:column; }
}

/* ---------- 3D Chase Cam plugin card ---------- */
.cc3d-surface{ padding:0; overflow:hidden; }
.cc3d-map-wrap{
  position:relative; width:100%; height:calc(320px * var(--plugin-scale, 1));
  background:var(--card-custom-bg, var(--bg-panel));
}
/* MapLibre adds its own "maplibregl-map" class directly to the container
   element it's given, and that library's stylesheet sets
   .maplibregl-map{position:relative; overflow:hidden}. That stylesheet
   loads dynamically (after this one), so at equal specificity
   (single-class selector either way) it wins the cascade and overrides
   this rule's position:absolute — collapsing .cc3d-map to 0 height in
   normal flow (its only child, the canvas, is itself position:absolute
   per MapLibre's own CSS, so contributes nothing to auto-height), and
   MapLibre's overflow:hidden then clips the correctly-sized canvas down
   to that zero-height box. Confirmed live: a real device reported the
   canvas rendering fine internally (889x836) while this container read
   0 height. The compound selector's higher specificity (two classes vs
   MapLibre's one) makes this win regardless of load order — no
   !important needed, and none added, so a real future override still can. */
.cc3d-map-wrap .cc3d-map{ position:absolute; inset:0; }
.cc3d-map .maplibregl-ctrl-logo,
.cc3d-map .maplibregl-ctrl-attrib{ display:none !important; }
.cc3d-fade-overlay{
  /* Fades the top of the map into the card's own themed background —
     a plain gradient overlay, not a CSS mask on the map/canvas itself.
     A `mask-image`/`-webkit-mask-image` on an element containing a WebGL
     canvas is a known compatibility landmine: on some browsers/GPUs the
     masked canvas renders fully invisible instead of partially faded,
     which is exactly what happened here (report: "map only shows the
     glow ring" — i.e. the whole map had gone invisible, mask and all).
     A sibling overlay achieves the same visual result without ever
     touching how the canvas itself composites. */
  position:absolute; inset:0; z-index:1; pointer-events:none;
  background:linear-gradient(to bottom, var(--card-custom-bg, var(--bg-panel)) 0%, rgba(0,0,0,0) 60%);
}
.cc3d-status{
  position:absolute; inset:0; z-index:3;
  display:flex; flex-direction:column; align-items:center; justify-content:center; text-align:center; padding:16px; gap:10px;
  background:var(--card-custom-bg, var(--bg-panel)); color:var(--text-primary);
  font-family:var(--font-display); font-size:12px; letter-spacing:0.02em;
}
.cc3d-status-retry{
  font-family:var(--font-display); font-weight:700; font-size:12px; letter-spacing:0.04em; text-transform:uppercase;
  padding:8px 18px; border-radius:999px; cursor:pointer;
  background:#ff9d2e; color:#1a0f05; border:none;
}
.cc3d-status-retry:hover{ filter:brightness(1.08); }
.cc3d-glow-ring{
  /* top must match CHASE_FOCUS_FRACTION in chase-cam-3d.js — the actual
     3D bike model now renders there (via MapLibre's `padding` camera
     option, not a CSS position), since a passenger-POV chase cam frames
     the rider low with the road extending ahead rather than dead center.
     This ring is a plain CSS decoration with no tie to the map's real
     camera, so it has to be told the same number by hand. */
  position:absolute; top:68%; left:50%; z-index:1;
  width:34%; aspect-ratio:1;
  transform:translate(-50%, -50%);
  border-radius:50%;
  border:3px solid rgba(255,157,46,0.55);
  box-shadow:0 0 22px 3px rgba(255,157,46,0.35), inset 0 0 18px 2px rgba(255,157,46,0.25);
  pointer-events:none;
  animation:cc3d-pulse 2.6s ease-in-out infinite;
}
.cc3d-glow-ring::before{
  content:"";
  position:absolute; inset:-22%;
  border-radius:50%;
  border:1px solid rgba(255,157,46,0.3);
}
@keyframes cc3d-pulse{
  0%, 100%{ opacity:0.5; transform:translate(-50%, -50%) scale(0.94); }
  50%{ opacity:0.9; transform:translate(-50%, -50%) scale(1.03); }
}
/* Mount point for the shared RydRDebugConsole (js/debug-console.js) —
   the console itself is a self-contained component that injects its own
   styling, this just gives it a slot below the map (rather than the old
   always-on overlay on top of it) and undoes .cc3d-surface's padding:0
   so it doesn't sit flush against the card edges. Empty/invisible unless
   the rider has turned on in-app debugging for this card in Settings >
   Advanced > Developer. */
.cc3d-debug-mount{ padding:0 12px 10px; }
.cc3d-hud{ position:absolute; left:10px; bottom:10px; z-index:2; display:flex; gap:8px; pointer-events:none; }
.cc3d-hud-chip{
  background:rgba(5,7,10,0.72); backdrop-filter:blur(4px);
  border:1px solid rgba(255,157,46,0.4); color:#ffb060;
  font-family:var(--font-mono); font-weight:700; font-size:12px;
  padding:4px 10px; border-radius:999px;
}
.cc3d-recenter-btn{
  position:absolute; right:10px; bottom:10px; z-index:2;
  width:34px; height:34px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:rgba(5,7,10,0.72); backdrop-filter:blur(4px);
  border:1px solid rgba(255,157,46,0.4); color:#ffb060;
  font-size:17px; cursor:pointer;
}
.cc3d-recenter-btn:hover{ filter:brightness(1.15); }
.cc3d-close-btn{
  position:absolute; right:10px; top:10px; z-index:2;
  width:30px; height:30px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:rgba(5,7,10,0.72); backdrop-filter:blur(4px);
  border:1px solid rgba(255,157,46,0.4); color:#ffb060;
  font-size:14px; cursor:pointer;
}
.cc3d-close-btn:hover{ filter:brightness(1.15); }

/* Default dashboard-card state — nothing loaded, nothing rendering, until
   tapped open. See the renderCollapsed()/openLive() split in
   chase-cam-3d.js: this is the single heaviest card on the dashboard
   (a live WebGL context + continuous GPS subscription), so unlike every
   other card it doesn't get to just idle here by default. */
.cc3d-collapsed{
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:12px; padding:28px 18px; text-align:center;
  min-height:calc(200px * var(--plugin-scale, 1));
}
.cc3d-collapsed-icon{ font-size:30px; }
.cc3d-collapsed-desc{
  font-family:var(--font-body); font-size:12.5px; line-height:1.5;
  color:var(--text-muted); max-width:32ch; margin:0;
}

/* ---------- 3D Chase Map (chase-map.html) — the same chase-cam-3d plugin
   card, stretched to fill the whole viewport instead of a small resizable
   dashboard card. Only overrides the plugin's own fixed card chrome
   (rounded corners, border, the calc(320px * scale) card height) — the
   map/HUD/recenter-button markup and behavior underneath are untouched. */
.chase-map-page{
  position:fixed; inset:0; overflow:hidden;
}
.chase-map-fullhost{ position:absolute; inset:0; }
/* padding:0/gap:0 undo .plugin-surface's card insets, and flex:1 1 auto +
   min-height:0 (the standard flexbox fix for a sized child inside a
   column flex container) make the map itself claim 100% of the page
   rather than 100% of whatever's left after the debug-mount sibling and
   the removed gap — without min-height:0 a flex item's automatic minimum
   size is its content size, which would still leave it short. */
.chase-map-fullhost .cc3d-surface{ height:100%; border-radius:0; border:none; padding:0; gap:0; }
.chase-map-fullhost .cc3d-map-wrap{ flex:1 1 auto; min-height:0; height:auto; }
.chase-map-fullhost .cc3d-debug-mount{ flex:0 0 auto; padding:0; }
.chase-map-fullhost .cc3d-debug-mount:empty{ display:none; }

/* Live "current street" toast — glass panel anchored in the same top row
   the header status bar uses elsewhere (left:64px clears the fixed
   .menu-btn instead of sitting under it), always dark/glassy regardless of
   the site theme since it always sits over this page's dark 3D map, same
   choice already made for the plugin card's own HUD chips. */
.chase-toast{
  position:fixed; z-index:50;
  top:calc(12px + env(safe-area-inset-top, 0px));
  left:64px; right:12px; max-width:420px;
  display:flex; align-items:flex-start; gap:10px;
  padding:11px 16px;
  border-radius:14px;
  background:rgba(8,11,16,0.62);
  border:1px solid rgba(255,255,255,0.1);
  box-shadow:0 6px 24px rgba(0,0,0,0.35), inset 0 1px 0 rgba(255,255,255,0.06);
  backdrop-filter:blur(14px) saturate(140%);
  -webkit-backdrop-filter:blur(14px) saturate(140%);
  pointer-events:none;
}
.chase-toast-icon{
  flex:0 0 auto; margin-top:1px; font-size:15px; line-height:1;
  filter:drop-shadow(0 0 6px rgba(255,157,46,0.55));
}
.chase-toast-text{ min-width:0; display:flex; flex-direction:column; gap:2px; }
.chase-toast-place{
  font-family:var(--font-display); font-weight:700; font-size:16px; letter-spacing:0.01em;
  color:#fff; line-height:1.2;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.chase-toast-road{
  font-family:var(--font-body); font-weight:500; font-size:12.5px; letter-spacing:0.01em;
  color:rgba(255,255,255,0.68); line-height:1.3;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
@media (max-width:480px){
  .chase-toast{ left:60px; right:10px; padding:9px 13px; gap:8px; }
  .chase-toast-place{ font-size:14.5px; }
  .chase-toast-road{ font-size:11.5px; }
}

/* ---------- Spotify card ----------
   Deliberately styled to match the official Spotify app rather than RydR's
   theme. Fully isolated with !important rules so that theme changes (light/dark/silver/etc.)
   or custom card background/font settings NEVER alter the authentic dark Spotify design.
   
   Every size below is multiplied by --sp-scale, set by dragging the corner
   grip, so a rider can size the hit targets once for gloved hands. */

/* Card wrapper & panel isolation */
.rr-card[data-card-id="spotify"] {
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  overflow: visible !important;
}
.rr-card[data-card-id="spotify"]::before,
.rr-card[data-card-id="spotify"]::after {
  display: none !important;
}

.spotify-panel,
.spotify-panel-preview {
  --sp-scale: 1;
  position: relative !important;
  background: linear-gradient(180deg, #181818 0%, #121212 100%) !important;
  border: 1px solid #282828 !important;
  border-radius: 12px !important;
  padding: 16px !important;
  padding-bottom: 22px !important;
  overflow: hidden !important;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5) !important;
  font-family: Circular, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
  color: #ffffff !important;
  transition: none !important;
}

/* Header */
.spotify-head { display: flex !important; align-items: center !important; gap: 8px !important; margin-bottom: 14px !important; }
.spotify-mark { width: 20px !important; height: 20px !important; flex-shrink: 0 !important; display: block !important; }
.spotify-mark svg { width: 100% !important; height: 100% !important; display: block !important; }
.spotify-head-label {
  font-family: Circular, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
  font-weight: 700 !important;
  font-size: 13px !important;
  color: #ffffff !important;
  letter-spacing: -0.01em !important;
}
.spotify-status {
  margin-left: auto !important;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace !important;
  font-size: 10px !important;
  color: #b3b3b3 !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
  white-space: nowrap !important;
  max-width: 55% !important;
}

/* Header Action Buttons */
.spotify-icon-btn {
  flex-shrink: 0 !important;
  width: 32px !important;
  height: 32px !important;
  min-width: 32px !important;
  border-radius: 50% !important;
  display: grid !important;
  place-items: center !important;
  background: transparent !important;
  border: 1px solid #3a3a3a !important;
  color: #b3b3b3 !important;
  font-family: Circular, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
  font-size: 15px !important;
  font-weight: 700 !important;
  line-height: 1 !important;
  cursor: pointer !important;
  padding: 0 !important;
  margin-left: 6px !important;
  transition: all 0.2s ease !important;
}
.spotify-icon-btn img {
  width: 16px !important;
  height: 16px !important;
  display: block !important;
  object-fit: contain !important;
}
.spotify-icon-btn:hover { color: #ffffff !important; border-color: #5a5a5a !important; transform: scale(1.06) !important; }
.spotify-icon-btn:disabled { opacity: 0.35 !important; cursor: not-allowed !important; transform: none !important; }
.spotify-icon-btn.is-saved {
  color: #000000 !important;
  background: #1DB954 !important;
  border-color: #1DB954 !important;
}
.spotify-icon-btn.is-saved:hover { background: #1ed760 !important; border-color: #1ed760 !important; }

/* Playlist rows — shared by the standalone Spotify Playlists card below */
.spotify-recent-list { display: flex !important; flex-direction: column !important; gap: 2px !important; }
.spotify-recent-item {
  display: flex !important;
  align-items: center !important;
  gap: 10px !important;
  width: 100% !important;
  min-height: 44px !important;
  padding: 6px !important;
  border: none !important;
  border-radius: 8px !important;
  background: transparent !important;
  cursor: pointer !important;
  text-align: left !important;
  transition: background 0.15s ease !important;
}
.spotify-recent-item:hover { background: #383838 !important; }
.spotify-recent-item.is-playing {
  background: rgba(29, 185, 84, 0.15) !important;
  box-shadow: inset 0 0 0 1px #1DB954 !important;
}
.spotify-recent-item-art {
  width: 32px !important;
  height: 32px !important;
  border-radius: 4px !important;
  flex-shrink: 0 !important;
  background: #333333 center/cover no-repeat !important;
}
.spotify-recent-item-name {
  font-family: Circular, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
  font-size: 13px !important;
  color: #ffffff !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
  white-space: nowrap !important;
  min-width: 0 !important;
}

/* Spotify Playlists card — same spotify-panel/spotify-head chrome as the
   main controller card, its own rr-card so it scrolls/lays out
   independently instead of living inside a hamburger dropdown. */
.spotify-playlists-panel { padding-bottom: 16px !important; }
.spotify-playlists-list {
  max-height: 340px !important;
  overflow-y: auto !important;
}

/* Track Metadata & Artwork */
.spotify-now { display: flex !important; align-items: center !important; gap: 12px !important; margin-bottom: 12px !important; min-width: 0 !important; }
.spotify-art {
  width: calc(60px * var(--sp-scale)) !important;
  height: calc(60px * var(--sp-scale)) !important;
  border-radius: 8px !important;
  /* background-color, not the `background` shorthand — the shorthand
     implicitly resets background-image to `none` for any component it
     doesn't mention, and with !important that permanently wins over the
     background-image the JS sets inline once a track loads (an inline
     style only beats a stylesheet rule when neither has !important) —
     the album art was rendering, just always hidden behind this. */
  background-color: #282828 !important;
  background-position: center !important;
  background-size: cover !important;
  background-repeat: no-repeat !important;
  flex-shrink: 0 !important;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.6) !important;
}
.spotify-art-demo { background-image: url('/icons/spotify_album_art.png') !important; background-size: cover !important; }
.spotify-meta { min-width: 0 !important; flex: 1 !important; }

/* Background art-style: fills the whole player with the album cover
   (::before) and fades it into the player's own dark background via a
   linear gradient that spans the full player height (::after), so the
   track info and controls stay legible without a separate scrim. The
   panel already clips to its border-radius via overflow:hidden, so the
   full-bleed layers pick that up for free. */
.spotify-panel.art-mode-background::before {
  content: "" !important;
  position: absolute !important;
  inset: 0 !important;
  background-image: var(--spotify-bg-image, none) !important;
  background-size: cover !important;
  background-position: center !important;
  z-index: 0 !important;
}
.spotify-panel.art-mode-background::after {
  content: "" !important;
  position: absolute !important;
  inset: 0 !important;
  background: linear-gradient(to bottom, rgba(18, 18, 18, 0) 0%, rgba(18, 18, 18, 0.55) 60%, #121212 100%) !important;
  z-index: 1 !important;
  pointer-events: none !important;
}
.spotify-panel.art-mode-background > .spotify-head,
.spotify-panel.art-mode-background > .spotify-now,
.spotify-panel.art-mode-background > .spotify-progress,
.spotify-panel.art-mode-background > .spotify-controls,
.spotify-panel.art-mode-background > #spotifyBody,
.spotify-panel.art-mode-background > #spotifyConnectBtn,
.spotify-panel.art-mode-background > .resize-grip {
  position: relative !important;
  z-index: 2 !important;
}
/* The small thumbnail swatch is redundant once the art fills the whole
   player, so it's hidden rather than doubled up. */
.spotify-panel.art-mode-background .spotify-art { display: none !important; }
.spotify-track-name {
  font-family: Circular, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
  font-weight: 700 !important;
  font-size: calc(15px * var(--sp-scale)) !important;
  color: #ffffff !important;
  line-height: 1.25 !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
  white-space: nowrap !important;
}
.spotify-artist {
  font-family: Circular, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
  font-weight: 400 !important;
  font-size: calc(12px * var(--sp-scale)) !important;
  color: #b3b3b3 !important;
  margin-top: 3px !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
  white-space: nowrap !important;
}

/* Progress Bar */
.spotify-progress { display: flex !important; align-items: center !important; gap: 8px !important; margin-bottom: 14px !important; }
.spotify-time {
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace !important;
  font-size: calc(10px * var(--sp-scale)) !important;
  color: #b3b3b3 !important;
  flex-shrink: 0 !important;
}
.spotify-bar {
  flex: 1 !important;
  height: 4px !important;
  border-radius: 2px !important;
  background: #4d4d4d !important;
  overflow: visible !important;
  position: relative !important;
  cursor: pointer !important;
}
.spotify-bar-fill {
  height: 100% !important;
  width: 0% !important;
  background: #ffffff !important;
  border-radius: 2px !important;
  position: relative !important;
  transition: background 0.15s ease !important;
}
.spotify-progress:hover .spotify-bar-fill {
  background: #1DB954 !important;
}
.spotify-progress:hover .spotify-bar-fill::after {
  content: "" !important;
  position: absolute !important;
  right: -5px !important;
  top: -4px !important;
  width: 12px !important;
  height: 12px !important;
  border-radius: 50% !important;
  background: #ffffff !important;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.4) !important;
}

/* Controls & Buttons */
.spotify-controls {
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  gap: calc(18px * var(--sp-scale)) !important;
}
.spotify-btn {
  width: calc(40px * var(--sp-scale)) !important;
  height: calc(40px * var(--sp-scale)) !important;
  border-radius: 50% !important;
  display: grid !important;
  place-items: center !important;
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  color: transparent !important;
  font-size: 0 !important;
  line-height: 0 !important;
  cursor: pointer !important;
  padding: 0 !important;
  overflow: hidden !important;
  transition: transform 0.15s ease, opacity 0.15s ease !important;
}
.spotify-btn img {
  width: 100% !important;
  height: 100% !important;
  display: block !important;
  object-fit: contain !important;
  pointer-events: none !important;
}
.spotify-btn:hover { transform: scale(1.08) !important; }
.spotify-btn-play {
  width: calc(52px * var(--sp-scale)) !important;
  height: calc(52px * var(--sp-scale)) !important;
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
}
.spotify-btn-play img {
  width: 100% !important;
  height: 100% !important;
}
.spotify-btn-play:hover { transform: scale(1.06) !important; }
.spotify-btn:disabled { opacity: 0.35 !important; pointer-events: none !important; transform: none !important; }

/* Corner Resize Grip */
.resize-grip {
  position: absolute !important;
  right: 0 !important;
  bottom: 0 !important;
  width: 30px !important;
  height: 30px !important;
  cursor: ns-resize !important;
  touch-action: none !important;
  background: linear-gradient(135deg, transparent 50%, #4d4d4d 50%, #4d4d4d 60%, transparent 60%, transparent 68%, #4d4d4d 68%, #4d4d4d 78%, transparent 78%) !important;
}
.resize-grip:hover {
  background: linear-gradient(135deg, transparent 50%, #1DB954 50%, #1DB954 60%, transparent 60%, transparent 68%, #1DB954 68%, #1DB954 78%, transparent 78%) !important;
}
.spotify-panel-preview { margin-bottom: 6px !important; }

/* Screensaver variant: same information, none of the chrome. Flat colors,
   no album art, no gradients — cheapest thing to render while still
   showing what's playing and how far in. */
.screensaver-value-xs{ font-size:calc(min(7vw, 30px) * var(--sp-scale, 1)); }
.screensaver-spotify-time{
  font-family:var(--font-mono);
  font-size:calc(13px * var(--sp-scale, 1));
  color:#7a7a7a; margin-top:6px;
}

/* ==========================================================================
   APP THEMES (Harley Iron & Fire, Synthwave, Stealth, Desert, Apex, Light)
   ========================================================================== */

/* ==========================================================================
   APP THEMES (Harley Iron & Fire, Synthwave, Stealth, Desert, Apex, Light)
   ========================================================================== */

/* 1. Harley Davidson — Iron & Fire */
body.theme-harley {
  --bg-void: #0b0c0e;
  --bg-panel: #141518;
  --bg-panel-raised: #1d1e23;
  --bg-panel-hover: #272a31;
  --border-subtle: #2d3038;
  --border-strong: #ff5500;

  --card-bg-gradient: linear-gradient(145deg, #191b22 0%, #111216 100%);
  --speedo-bg: radial-gradient(circle at 50% 30%, #262934 0%, #111215 75%);
  --btn-primary-bg: linear-gradient(135deg, #ff5500 0%, #d94400 100%);
  --btn-primary-color: #ffffff;
  --btn-primary-border: #ff7722;
  --btn-secondary-bg: #1d1e23;
  --btn-secondary-border: #383c47;

  --neon-green: #ff5500; /* Molten Fire Orange */
  --neon-green-dim: #993300;
  --neon-green-glow: rgba(255, 85, 0, 0.4);
  --cyan: #ffaa00; /* Polished Chrome Gold */
  --alert-red: #ff2200;
  --warn-amber: #ffaa00;

  --text-primary: #f2f4f8;
  --text-muted: #9aa1ad;
  --text-dim: #5c626d;
  background-image:
    radial-gradient(circle at 15% 0%, rgba(255,85,0,0.12), transparent 45%),
    radial-gradient(circle at 85% 100%, rgba(255,170,0,0.08), transparent 50%);
}

/* 2. Cyber Synthwave */
body.theme-synthwave {
  --bg-void: #0d0818;
  --bg-panel: #150d26;
  --bg-panel-raised: #1f1437;
  --bg-panel-hover: #2c1b4e;
  --border-subtle: #341e5b;
  --border-strong: #ff007f;

  --card-bg-gradient: linear-gradient(145deg, #1d1133 0%, #120a20 100%);
  --speedo-bg: radial-gradient(circle at 50% 30%, #2d1a4d 0%, #140c26 75%);
  --btn-primary-bg: linear-gradient(135deg, #ff007f 0%, #cc0066 100%);
  --btn-primary-color: #ffffff;
  --btn-primary-border: #ff3399;
  --btn-secondary-bg: #1f1437;
  --btn-secondary-border: #422673;

  --neon-green: #ff007f; /* Hot Magenta */
  --neon-green-dim: #99004d;
  --neon-green-glow: rgba(255, 0, 127, 0.45);
  --cyan: #00f0ff; /* Electric Cyan */
  --alert-red: #ff0044;
  --warn-amber: #ffb700;

  --text-primary: #f7efff;
  --text-muted: #a795c4;
  --text-dim: #605179;
  background-image:
    radial-gradient(circle at 20% 0%, rgba(255,0,127,0.14), transparent 45%),
    radial-gradient(circle at 80% 100%, rgba(0,240,255,0.12), transparent 50%);
}

/* 3. Carbon Stealth */
body.theme-stealth {
  --bg-void: #070809;
  --bg-panel: #0d0f12;
  --bg-panel-raised: #14171d;
  --bg-panel-hover: #1c212a;
  --border-subtle: #202733;
  --border-strong: #3b4759;

  --card-bg-gradient: linear-gradient(145deg, #12151c 0%, #090b0e 100%);
  --speedo-bg: radial-gradient(circle at 50% 30%, #1a2029 0%, #0c0f13 75%);
  --btn-primary-bg: linear-gradient(135deg, #42a5f5 0%, #1976d2 100%);
  --btn-primary-color: #ffffff;
  --btn-primary-border: #64b5f6;
  --btn-secondary-bg: #14171d;
  --btn-secondary-border: #293242;

  --neon-green: #64b5f6; /* Glacier Ice */
  --neon-green-dim: #1e5387;
  --neon-green-glow: rgba(100, 181, 246, 0.35);
  --cyan: #90caf9;
  --alert-red: #ef5350;
  --warn-amber: #ffa726;

  --text-primary: #e8ecef;
  --text-muted: #808e9b;
  --text-dim: #485460;
  background-image:
    radial-gradient(circle at 10% 10%, rgba(100,181,246,0.06), transparent 40%),
    radial-gradient(circle at 90% 90%, rgba(30,83,135,0.1), transparent 40%);
}

/* 4. Desert Rally */
body.theme-desert {
  --bg-void: #110d09;
  --bg-panel: #1a140f;
  --bg-panel-raised: #241c15;
  --bg-panel-hover: #31241c;
  --border-subtle: #3a2b20;
  --border-strong: #d97706;

  --card-bg-gradient: linear-gradient(145deg, #221a13 0%, #140f0a 100%);
  --speedo-bg: radial-gradient(circle at 50% 30%, #312318 0%, #1a140f 75%);
  --btn-primary-bg: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
  --btn-primary-color: #0f0b07;
  --btn-primary-border: #fbbf24;
  --btn-secondary-bg: #241c15;
  --btn-secondary-border: #423122;

  --neon-green: #f59e0b; /* Sunset Gold */
  --neon-green-dim: #92400e;
  --neon-green-glow: rgba(245, 158, 11, 0.4);
  --cyan: #fb923c; /* Copper */
  --alert-red: #ef4444;
  --warn-amber: #f59e0b;

  --text-primary: #fbf3eb;
  --text-muted: #a89485;
  --text-dim: #635347;
  background-image:
    radial-gradient(circle at 15% 0%, rgba(245,158,11,0.1), transparent 45%),
    radial-gradient(circle at 85% 100%, rgba(251,146,60,0.08), transparent 50%);
}

/* 5. Titanium Apex */
body.theme-apex {
  --bg-void: #0a0e13;
  --bg-panel: #111720;
  --bg-panel-raised: #18212d;
  --bg-panel-hover: #222d3e;
  --border-subtle: #2a374a;
  --border-strong: #ccff00;

  --card-bg-gradient: linear-gradient(145deg, #151e2b 0%, #0d121a 100%);
  --speedo-bg: radial-gradient(circle at 50% 30%, #202c3d 0%, #111720 75%);
  --btn-primary-bg: linear-gradient(135deg, #ccff00 0%, #a3cc00 100%);
  --btn-primary-color: #0c1203;
  --btn-primary-border: #ddff33;
  --btn-secondary-bg: #18212d;
  --btn-secondary-border: #2e3e54;

  --neon-green: #ccff00; /* High-Vis Telemetry Yellow */
  --neon-green-dim: #739900;
  --neon-green-glow: rgba(204, 255, 0, 0.4);
  --cyan: #00e5ff; /* Laser Blue */
  --alert-red: #ff2a4b;
  --warn-amber: #ffb700;

  --text-primary: #edf3fa;
  --text-muted: #8b9bb0;
  --text-dim: #4e5e73;
  background-image:
    radial-gradient(circle at 15% 0%, rgba(204,255,0,0.08), transparent 45%),
    radial-gradient(circle at 85% 100%, rgba(0,229,255,0.07), transparent 50%);
}

/* 6. Silver Touring (Light: Polished Silver & Cobalt Blue) */
body.theme-silver {
  --bg-void: #e2e8f0;
  --bg-panel: #ffffff;
  --bg-panel-raised: #f1f5f9;
  --bg-panel-hover: #cbd5e1;
  --border-subtle: #cbd5e1;
  --border-strong: #2563eb;

  --btn-primary-bg: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%);
  --btn-primary-color: #ffffff;
  --btn-primary-border: #3b82f6;
  --btn-secondary-bg: #f1f5f9;
  --btn-secondary-border: #cbd5e1;

  --neon-green: #2563eb; /* Cobalt Blue */
  --neon-green-dim: #1d4ed8;
  --neon-green-glow: rgba(37, 99, 235, 0.25);
  --cyan: #0284c7;
  --alert-red: #dc2626;
  --warn-amber: #d97706;

  --text-primary: #1e293b;
  --text-muted: #475569;
  --text-dim: #64748b;
  --menu-panel-bg: rgba(255,255,255,0.92);
  background-image:
    radial-gradient(circle at 15% 0%, rgba(37,99,235,0.07), transparent 45%),
    radial-gradient(circle at 85% 100%, rgba(2,132,199,0.06), transparent 50%);
}

/* 7. Desert Dunes (Light: Warm Sand & Terracotta Copper) */
body.theme-sand {
  --bg-void: #f3eee8;
  --bg-panel: #fbf8f5;
  --bg-panel-raised: #eee7df;
  --bg-panel-hover: #e5dbcf;
  --border-subtle: #dcd0c2;
  --border-strong: #ea580c;

  --btn-primary-bg: linear-gradient(135deg, #ea580c 0%, #c2410c 100%);
  --btn-primary-color: #ffffff;
  --btn-primary-border: #f97316;
  --btn-secondary-bg: #eee7df;
  --btn-secondary-border: #dcd0c2;

  --neon-green: #ea580c; /* Terracotta Copper */
  --neon-green-dim: #c2410c;
  --neon-green-glow: rgba(234, 88, 12, 0.25);
  --cyan: #d97706;
  --alert-red: #dc2626;
  --warn-amber: #d97706;

  --text-primary: #271c19;
  --text-muted: #5c4740;
  --text-dim: #7d655c;
  --menu-panel-bg: rgba(255,255,255,0.92);
  background-image:
    radial-gradient(circle at 15% 0%, rgba(234,88,12,0.07), transparent 45%),
    radial-gradient(circle at 85% 100%, rgba(217,119,6,0.06), transparent 50%);
}

/* 8. High-Vis Safety (Light: Daylight Lime & Slate) */
body.theme-highvis {
  --bg-void: #edf2f7;
  --bg-panel: #ffffff;
  --bg-panel-raised: #e2e8f0;
  --bg-panel-hover: #cbd5e0;
  --border-subtle: #cbd5e0;
  --border-strong: #65a30d;

  --btn-primary-bg: linear-gradient(135deg, #65a30d 0%, #4d7c0f 100%);
  --btn-primary-color: #ffffff;
  --btn-primary-border: #84cc16;
  --btn-secondary-bg: #e2e8f0;
  --btn-secondary-border: #cbd5e0;

  --neon-green: #4d7c0f; /* High-Vis Lime */
  --neon-green-dim: #3f6212;
  --neon-green-glow: rgba(101, 163, 13, 0.25);
  --cyan: #0284c7;
  --alert-red: #dc2626;
  --warn-amber: #ca8a04;

  --text-primary: #0f172a;
  --text-muted: #334155;
  --text-dim: #64748b;
  --menu-panel-bg: rgba(255,255,255,0.92);
  background-image:
    radial-gradient(circle at 15% 0%, rgba(101,163,13,0.08), transparent 45%),
    radial-gradient(circle at 85% 100%, rgba(2,132,199,0.05), transparent 50%);
}

/* 9. Alpine Snow (Light: Ice White & Sky Blue) */
body.theme-alpine {
  --bg-void: #f0f7ff;
  --bg-panel: #ffffff;
  --bg-panel-raised: #e1f0ff;
  --bg-panel-hover: #cce4ff;
  --border-subtle: #b8daff;
  --border-strong: #0284c7;

  --btn-primary-bg: linear-gradient(135deg, #0284c7 0%, #0369a1 100%);
  --btn-primary-color: #ffffff;
  --btn-primary-border: #38bdf8;
  --btn-secondary-bg: #e1f0ff;
  --btn-secondary-border: #b8daff;

  --neon-green: #0284c7; /* Sky Blue */
  --neon-green-dim: #0369a1;
  --neon-green-glow: rgba(2, 132, 199, 0.25);
  --cyan: #06b6d4;
  --alert-red: #e11d48;
  --warn-amber: #d97706;

  --text-primary: #0c4a6e;
  --text-muted: #1e3a8a;
  --text-dim: #475569;
  --menu-panel-bg: rgba(255,255,255,0.92);
  background-image:
    radial-gradient(circle at 15% 0%, rgba(2,132,199,0.08), transparent 45%),
    radial-gradient(circle at 85% 100%, rgba(6,182,212,0.07), transparent 50%);
}

/* 10. Slate Pro — Indigo (Dark, professional, inspired by this redesign) */
body.theme-indigo {
  --bg-void: #0c0d14;
  --bg-panel: #15161f;
  --bg-panel-raised: #1c1e2b;
  --bg-panel-hover: #242637;
  --border-subtle: #262838;
  --border-strong: #3a3d54;

  --card-bg-gradient: linear-gradient(145deg, #1a1c29 0%, #101120 100%);
  --speedo-bg: radial-gradient(circle at 50% 30%, #232537 0%, #14151f 75%);
  --btn-primary-bg: linear-gradient(135deg, #8b7cf6 0%, #6d5ce8 100%);
  --btn-primary-color: #ffffff;
  --btn-primary-border: #a498f9;
  --btn-secondary-bg: #1c1e2b;
  --btn-secondary-border: #33354a;

  --neon-green: #8b7cf6; /* Indigo */
  --neon-green-dim: #5b4fc4;
  --neon-green-glow: rgba(139, 124, 246, 0.3);
  --cyan: #38bdf8;
  --alert-red: #f87171;
  --warn-amber: #fbbf24;

  --text-primary: #f1f0f7;
  --text-muted: #948fa8;
  --text-dim: #5c5870;
  background-image:
    radial-gradient(circle at 15% 0%, rgba(139,124,246,0.08), transparent 45%),
    radial-gradient(circle at 85% 100%, rgba(56,189,248,0.06), transparent 50%);
}

/* 11. Cloud Pro (Light, professional, inspired by this redesign) */
body.theme-cloud {
  --bg-void: #eef1f5;
  --bg-panel: #ffffff;
  --bg-panel-raised: #f6f8fb;
  --bg-panel-hover: #eaeef4;
  --border-subtle: #e2e6ee;
  --border-strong: #c7cede;

  --btn-primary-bg: linear-gradient(135deg, #2f6fed 0%, #1d54c9 100%);
  --btn-primary-color: #ffffff;
  --btn-primary-border: #4c86f5;
  --btn-secondary-bg: #f6f8fb;
  --btn-secondary-border: #dde2ec;

  --neon-green: #2f6fed; /* Confident blue */
  --neon-green-dim: #1d54c9;
  --neon-green-glow: rgba(47, 111, 237, 0.16);
  --cyan: #06b6d4;
  --alert-red: #dc2626;
  --warn-amber: #d97706;

  --text-primary: #161a22;
  --text-muted: #464e5c;
  --text-dim: #6b7280;
  --menu-panel-bg: rgba(255,255,255,0.92);
  background-image:
    radial-gradient(circle at 15% 0%, rgba(47,111,237,0.05), transparent 45%),
    radial-gradient(circle at 85% 100%, rgba(6,182,212,0.04), transparent 50%);
}

/* ---------- Theme Selection Cards ---------- */
.theme-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 10px;
  margin-bottom: 16px;
}

.theme-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  padding: 10px;
  background: var(--bg-panel-raised);
  border: 1px solid var(--border-subtle);
  border-radius: 12px;
  cursor: pointer;
  text-align: left;
  transition: all 0.2s ease;
}

.theme-card:hover {
  border-color: var(--neon-green);
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(0,0,0,0.3);
}

.theme-card.active {
  border-color: var(--neon-green);
  background: var(--bg-panel-hover);
  box-shadow: 0 0 12px var(--neon-green-glow);
}

.theme-swatch-bar {
  display: flex;
  width: 100%;
  height: 20px;
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid rgba(255,255,255,0.1);
}

.theme-swatch-bar span {
  flex: 1;
  height: 100%;
}

.theme-card-info strong {
  display: block;
  font-family: var(--font-display);
  font-size: 13px;
  color: var(--text-primary);
}

.theme-card-info small {
  display: block;
  font-size: 11px;
  color: var(--text-muted);
}

.color-chip {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 2px solid var(--border-subtle);
  cursor: pointer;
  transition: transform 0.15s ease;
}

.color-chip:hover {
  transform: scale(1.2);
  border-color: var(--text-primary);
}
.screensaver-spotify-controls{
  display:flex; align-items:center; justify-content:center;
  gap:calc(22px * var(--sp-scale, 1)); margin-top:18px;
}
.screensaver-spotify-btn{
  width:calc(58px * var(--sp-scale, 1));
  height:calc(58px * var(--sp-scale, 1));
  border-radius:50%;
  display:grid; place-items:center;
  background:transparent;
  border:2px solid #444;
  color:#fff;
  font-size:calc(22px * var(--sp-scale, 1));
  cursor:pointer; padding:0; line-height:1;
  -webkit-tap-highlight-color:transparent;
}

footer.foot{
  text-align:center; color:var(--text-dim); font-family:var(--font-mono);
  font-size:11px; padding:30px 10px 10px;
}

/* Screensaver widget reordering list in Settings */
.screensaver-widget-choices {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 10px;
}
.ss-widget-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--bg-panel-raised, rgba(255, 255, 255, 0.05));
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.1));
  border-radius: 8px;
  padding: 8px 12px;
  transition: background 0.2s, border-color 0.2s;
}
.ss-widget-item:hover {
  background: var(--bg-panel-hover, rgba(255, 255, 255, 0.08));
  border-color: rgba(255, 255, 255, 0.2);
}
.ss-widget-left {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 500;
  font-size: 14px;
  color: var(--text-primary, #fff);
}
.ss-drag-grip {
  cursor: grab;
  color: rgba(255, 255, 255, 0.4);
  font-size: 16px;
  user-select: none;
}
.ss-widget-reorder-btns {
  display: flex;
  gap: 4px;
}
.ss-reorder-btn {
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.15);
  color: #fff;
  width: 30px;
  height: 30px;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font-size: 12px;
  transition: all 0.2s ease;
}
.ss-reorder-btn:hover:not(:disabled) {
  background: var(--neon-green, #1db954);
  color: #000;
  border-color: var(--neon-green, #1db954);
  transform: scale(1.05);
}
.ss-reorder-btn:disabled {
  opacity: 0.25;
  cursor: not-allowed;
}

/* Rider Maps & Full-Screen Views */
.full-screen-view {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: var(--bg-dark, #0b0f17);
  z-index: 500;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
}

.perf-header-bar {
  height: 56px;
  background: rgba(11, 15, 23, 0.95);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px;
  gap: 12px;
  backdrop-filter: blur(10px);
}

/* Drag Racing Christmas Tree Overlay */
.drag-tree-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.92);
  z-index: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
}

.drag-tree-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  background: #111827;
  border: 2px solid #374151;
  border-radius: 20px;
  padding: 30px;
  box-shadow: 0 0 40px rgba(0, 0, 0, 0.8);
}

.tree-stage-lights, .tree-count-lights {
  display: flex;
  gap: 14px;
}

.light {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background: #1f2937;
  border: 2px solid #4b5563;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 800;
  color: #6b7280;
  transition: all 0.15s ease;
}

.stage-light.active {
  background: #f59e0b;
  color: #000;
  box-shadow: 0 0 20px #f59e0b;
  border-color: #fbbf24;
}

.amber-light.active {
  background: #ff9100;
  color: #000;
  box-shadow: 0 0 24px #ff9100;
  border-color: #ffa726;
}

.tree-green-light {
  width: 90px;
  height: 90px;
  border-radius: 50%;
  background: #064e3b;
  border: 4px solid #059669;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

.tree-green-light.active {
  background: #00e676;
  border-color: #ffffff;
  box-shadow: 0 0 50px #00e676, inset 0 0 20px #ffffff;
  transform: scale(1.15);
}

.green-text {
  font-size: 24px;
  font-weight: 900;
  color: #ffffff;
  text-shadow: 0 0 10px #000;
}

.drag-tree-status {
  font-size: 18px;
  font-weight: 800;
  color: #ff9100;
  letter-spacing: 1px;
}

/* Performance Center Grid */
.perf-main-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  padding: 16px;
  flex: 1;
  overflow-y: auto;
}

@media (max-width: 768px) {
  .perf-main-grid {
    grid-template-columns: 1fr;
  }
}

.perf-card {
  background: rgba(22, 28, 39, 0.8);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  padding: 16px;
  display: flex;
  flex-direction: column;
}

.perf-hero-digits {
  display: flex;
  gap: 20px;
  justify-content: space-around;
  margin: 20px 0;
  background: rgba(0, 0, 0, 0.3);
  padding: 16px;
  border-radius: 12px;
}

.perf-digit-group {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.perf-digit-group .v {
  font-size: 42px;
  font-weight: 900;
  color: #00e5ff;
}
.perf-digit-group .k {
  font-size: 11px;
  color: #9ca3af;
}

.perf-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: auto;
}

.social-share-img {
  width: 100%;
  border-radius: 10px;
  margin-bottom: 12px;
  border: 1px solid rgba(255, 255, 255, 0.15);
}

.proximity-badge {
  background: rgba(0, 229, 255, 0.15);
  border: 1px solid #00e5ff;
  color: #00e5ff;
  font-size: 11px;
  font-weight: 800;
  padding: 4px 8px;
  border-radius: 6px;
  margin-bottom: 10px;
  display: inline-block;
}

.log-run-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 12px;
  background: rgba(255, 255, 255, 0.04);
  border-radius: 8px;
  margin-bottom: 6px;
}
.log-run-item small {
  display: block;
  color: #9ca3af;
  font-size: 11px;
}

/* Full-Screen Rider Maps & Performance Views */
.full-screen-view {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: #0b0f17;
  z-index: 500;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  /* This duplicates the earlier .full-screen-view rule (same file) but
     comes later in the cascade, so at equal specificity it wins — and it
     used to hard-clip with overflow:hidden, silently overriding
     .hud-shell's own overflow-y:auto. On any view whose flex-column
     content is taller than the viewport (routinely true for the Track
     HUD in landscape, its own stated primary use case), that meant
     content past the fold wasn't just scrolled out of reach, it was
     unreachable full stop — including the back button once the gauges
     row's overflow (see .hud-gauges-row below) pushed into the topbar. */
  overflow-x: hidden;
  overflow-y: auto;
}

/* Floating controls replace the old top toolbar entirely — a full-width bar
   competed with the map for space and duplicated event listeners already
   registered by js/maps-nav.js's attachControlListeners() were what made the
   Layers button and Recenter silently misbehave (two handlers toggling/
   navigating against each other on one tap). Floating buttons keep a single
   owner per control and read as a more modern, map-first layout. */
.maps-fab-back,
.maps-fab {
  position: fixed;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(15, 23, 42, 0.82);
  border: 1px solid rgba(255, 255, 255, 0.14);
  color: #f1f5f9;
  font-size: 18px;
  cursor: pointer;
  backdrop-filter: blur(10px);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.4);
  z-index: 510;
  transition: transform 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}
.maps-fab-back:hover,
.maps-fab:hover {
  border-color: rgba(255, 145, 0, 0.5);
  background: rgba(15, 23, 42, 0.95);
}
.maps-fab-back:active,
.maps-fab:active {
  transform: scale(0.94);
}
.maps-fab-back {
  top: 12px;
  left: 64px; /* clears the always-on hamburger .menu-btn at left:12px */
}
.maps-fab-stack {
  position: fixed;
  top: 12px;
  right: 16px;
  z-index: 510;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.maps-fab-stack .maps-fab {
  position: static;
}

.maps-canvas {
  position: relative !important;
  flex: 1 !important;
  flex-grow: 1 !important;
  width: 100% !important;
  height: 100% !important;
  min-height: 400px !important;
  background: #e5e3df !important;
  display: block !important;
  overflow: hidden !important;
}

.leaflet-container {
  width: 100% !important;
  height: 100% !important;
  min-height: 400px !important;
  background: #e5e3df !important;
  z-index: 1 !important;
}

.maps-layer-drawer {
  position: fixed;
  top: 172px; /* clears the 3-button .maps-fab-stack above it */
  right: 16px;
  z-index: 510;
  background: rgba(15, 23, 42, 0.95);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 12px;
  padding: 14px 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(12px);
  color: #fff;
  min-width: 240px;
  max-width: calc(100vw - 32px);
}
.maps-layer-drawer-title {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #94a3b8;
  margin-bottom: 2px;
}
.maps-layer-option label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  cursor: pointer;
  color: #e2e8f0;
}
.maps-layer-radius {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding-top: 8px;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}
.maps-layer-radius label {
  font-size: 13px;
  color: #e2e8f0;
}
.maps-layer-radius select {
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.18);
  color: #fff;
  border-radius: 8px;
  padding: 5px 8px;
  font-size: 12px;
}

.maps-footer-hud {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  background: rgba(15, 23, 42, 0.95);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  z-index: 510;
  gap: 14px;
  backdrop-filter: blur(12px);
}
.maps-hud-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.maps-hud-stat .v {
  font-size: 18px;
  font-weight: 800;
  color: #00e5ff;
}
.maps-hud-stat .k {
  font-size: 10px;
  color: #94a3b8;
}
.maps-nav-instruction {
  font-weight: 700;
  font-size: 14px;
  color: #fff;
}
.maps-nav-sub {
  font-size: 12px;
  color: #94a3b8;
}

/* Leaflet divIcon for curvy-road/POI/event/dealer pins — a colored circle
   per category (checkered flag for race tracks, etc.) instead of a plain
   dot. Plain circle rather than a rotated teardrop — one less transform to
   get wrong on top of Leaflet's own icon positioning transform. */
.category-pin-marker { background: transparent; border: none; }
.category-pin {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 2px solid #0b0f17;
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
}
.category-pin span {
  font-size: 15px;
  line-height: 1;
}
.road-sign-pin {
  width: 30px;
  height: 30px;
  filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.5));
}
.road-sign-pin svg {
  width: 100%;
  height: 100%;
}

/* ---------- Destination search modal ---------- */
/* .full-screen-view sits at z-index:500 and this modal is opened from
   inside one (#mapsView), so it needs to sit above that layer the same way
   the Apex Drag settings modal does — the app's default .modal-overlay
   (z-index:100) would otherwise render behind the map. */
.maps-search-modal-overlay {
  z-index: 610;
}
.maps-search-modal-box {
  max-width: 480px;
}
.maps-search-modal-field {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
  flex-shrink: 0;
}
.maps-search-modal-field input {
  flex: 1;
  padding: 10px 12px;
  background: var(--bg-panel-raised);
  border: 1px solid var(--border-subtle);
  border-radius: 8px;
  color: var(--text-primary);
  font-size: 14px;
}
.maps-search-modal-results {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.maps-search-category-title {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 8px;
}
.maps-search-category-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.maps-search-result {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  background: var(--bg-panel-raised);
  border: 1px solid var(--border-subtle);
  border-radius: 10px;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.maps-search-result:hover {
  border-color: rgba(255, 145, 0, 0.5);
  background: var(--bg-panel-hover, var(--bg-panel-raised));
}
.maps-search-result-name {
  font-weight: 600;
  font-size: 13px;
  color: var(--text-primary);
}
.maps-search-result-meta {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 2px;
}
.maps-search-result-distance {
  font-family: var(--font-mono);
  font-size: 12px;
  color: #ff9100;
  white-space: nowrap;
  flex-shrink: 0;
}
.maps-search-result > div:not(.maps-search-result-thumb):not(.maps-search-result-distance) {
  flex: 1;
  min-width: 0;
}
.maps-search-result-thumb {
  width: 44px;
  height: 44px;
  border-radius: 8px;
  object-fit: cover;
  flex-shrink: 0;
  cursor: pointer;
  border: 1px solid var(--border-subtle);
}

/* ---------- Where to Ride page ---------- */
.wtr-item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 12px;
  padding: 12px;
  background: var(--bg-panel-raised);
  border: 1px solid var(--border-subtle);
  border-radius: 10px;
  transition: border-color 0.15s ease;
}
.wtr-item:hover {
  border-color: rgba(255, 145, 0, 0.5);
}
.wtr-item-body {
  flex: 1 1 200px;
  min-width: 0;
}
.wtr-item-actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
  width: 100%;
}
@media (min-width: 480px) {
  .wtr-item-actions {
    width: auto;
  }
}
.wtr-item-actions .btn {
  flex: 1;
  white-space: nowrap;
  padding: 8px 14px;
  font-size: 12px;
}

/* ---------- Fullscreen POI photo viewer ---------- */
.poi-image-modal-overlay {
  z-index: 620;
  flex-direction: column;
  background: rgba(3, 4, 6, 0.94);
  padding: 0;
}
.poi-image-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  flex-shrink: 0;
}
.poi-image-modal-header h3 {
  margin: 0;
  font-size: 15px;
  color: #fff;
}
.poi-image-modal-body {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  padding: 0 12px;
}
.poi-image-modal-body img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: 8px;
}
.poi-image-modal-arrow {
  background: rgba(0, 0, 0, 0.5);
  border: none;
  color: #fff;
  font-size: 28px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  cursor: pointer;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2;
}
.poi-image-modal-arrow-prev {
  position: absolute;
  left: 12px;
}
.poi-image-modal-arrow-next {
  position: absolute;
  right: 12px;
}
.poi-image-modal-footer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 14px 20px calc(14px + env(safe-area-inset-bottom, 0px));
  flex-shrink: 0;
}
.poi-image-modal-dots {
  display: flex;
  gap: 6px;
}
.poi-image-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.3);
  cursor: pointer;
}
.poi-image-dot.active {
  background: #ff9100;
}
.poi-image-modal-counter {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-muted, #94a3b8);
}

/* ---------- Floating turn-by-turn directions button + modal ---------- */
.maps-fab-directions {
  position: fixed;
  left: 50%;
  bottom: 96px;
  transform: translateX(-50%);
  z-index: 510;
  display: none; /* shown only while a route is active */
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  border-radius: 999px;
  background: rgba(255, 145, 0, 0.94);
  color: #1a0f05;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 13px;
  border: none;
  cursor: pointer;
  box-shadow: 0 8px 20px rgba(255, 145, 0, 0.35);
}
.maps-fab-directions.is-visible {
  display: flex;
}
.maps-directions-modal-overlay {
  z-index: 610;
}
.maps-directions-modal-box {
  max-width: 480px;
}
.maps-directions-list {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.maps-directions-step {
  display: flex;
  gap: 12px;
  padding: 12px 4px;
  border-bottom: 1px solid var(--border-subtle);
  font-size: 13px;
  color: var(--text-primary);
  line-height: 1.5;
}
.maps-directions-step:last-child {
  border-bottom: none;
}
.maps-directions-step-num {
  font-family: var(--font-mono);
  font-weight: 700;
  color: #ff9100;
  flex-shrink: 0;
  width: 22px;
}
.maps-directions-step-dist {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 3px;
}

/* ==========================================================================
   Menu Button Clearance & Compact Button Styling
   ========================================================================== */
/* Ensure the performance full-screen header bar leaves a left gutter so the
   fixed menu-btn never overlaps its controls (.header-status-bar is already
   positioned with its own left:64px offset, so it doesn't need this; the
   maps view uses floating buttons instead of a header bar, offset directly
   via .maps-fab-back's own left:64px). */
.perf-header-bar {
  padding-left: 64px !important;
}

/* Compact buttons inside the full-screen performance header bar only —
   dashboard buttons use the glove-friendly .btn sizing defined above. */
.perf-header-bar .btn {
  padding: 4px 10px !important;
  font-size: 12px !important;
  height: 30px !important;
}

/* ==========================================================================
   Apex Performance Center — Premium Dark Racing Redesign
   ========================================================================== */
#performanceView {
  background: linear-gradient(135deg, #050811 0%, #0a0f1d 50%, #03060c 100%) !important;
  color: #f8fafc !important;
  overflow-y: auto !important;
}

.perf-header-bar {
  display: flex !important;
  align-items: center !important;
  justify-content: space-between !important;
  padding: 10px 18px 10px 64px !important;
  background: rgba(15, 23, 42, 0.95) !important;
  border-bottom: 1px solid rgba(0, 229, 255, 0.25) !important;
  backdrop-filter: blur(14px) !important;
  z-index: 510 !important;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.6) !important;
}

.perf-title {
  margin: 0 !important;
  font-family: 'Rajdhani', 'Orbitron', sans-serif !important;
  font-weight: 800 !important;
  font-size: 20px !important;
  letter-spacing: 1px !important;
  background: linear-gradient(90deg, #00e5ff, #ff9100, #00ff88) !important;
  -webkit-background-clip: text !important;
  -webkit-text-fill-color: transparent !important;
  text-transform: uppercase !important;
}

.perf-main-grid {
  display: grid !important;
  grid-template-columns: 1fr 1.2fr !important;
  gap: 20px !important;
  padding: 20px !important;
  max-width: 1400px !important;
  margin: 0 auto !important;
  width: 100% !important;
  box-sizing: border-box !important;
}

@media (max-width: 900px) {
  .perf-main-grid {
    grid-template-columns: 1fr !important;
  }
}

.perf-card {
  background: rgba(15, 23, 42, 0.85) !important;
  border: 1px solid rgba(255, 255, 255, 0.12) !important;
  border-radius: 16px !important;
  padding: 20px !important;
  backdrop-filter: blur(14px) !important;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5) !important;
  display: flex !important;
  flex-direction: column !important;
  gap: 16px !important;
}

.perf-card-header {
  display: flex !important;
  align-items: center !important;
  justify-content: space-between !important;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08) !important;
  padding-bottom: 12px !important;
}

.perf-card-header h3 {
  margin: 0 !important;
  font-family: 'Rajdhani', sans-serif !important;
  font-weight: 700 !important;
  font-size: 18px !important;
  color: #00e5ff !important;
  letter-spacing: 0.5px !important;
}

.perf-hero-digits {
  display: flex !important;
  align-items: center !important;
  justify-content: space-around !important;
  background: rgba(2, 6, 23, 0.85) !important;
  border: 1px solid rgba(0, 229, 255, 0.2) !important;
  border-radius: 14px !important;
  padding: 24px 16px !important;
}

.perf-digit-group {
  display: flex !important;
  flex-direction: column !important;
  align-items: center !important;
}

.perf-digit-group .v {
  font-family: 'JetBrains Mono', 'Rajdhani', monospace !important;
  font-weight: 900 !important;
  font-size: 42px !important;
  color: #ffffff !important;
  text-shadow: 0 0 14px rgba(0, 229, 255, 0.5) !important;
}

.perf-digit-group .k {
  font-size: 11px !important;
  font-weight: 700 !important;
  color: #94a3b8 !important;
  letter-spacing: 1px !important;
}

.perf-controls {
  display: flex !important;
  flex-wrap: wrap !important;
  gap: 10px !important;
  align-items: center !important;
}

.perf-launch-btn {
  background: linear-gradient(135deg, #e11d48, #be123c) !important;
  color: #fff !important;
  font-weight: 800 !important;
  font-size: 13px !important;
  padding: 8px 18px !important;
  border-radius: 10px !important;
  box-shadow: 0 4px 15px rgba(225, 29, 72, 0.4) !important;
  flex: 1 !important;
  min-width: 160px !important;
}
.perf-launch-btn:hover {
  background: linear-gradient(135deg, #f43f5e, #e11d48) !important;
  transform: translateY(-1px) !important;
}

/* Proximity & Recent Runs Log List */
.proximity-section {
  display: flex !important;
  flex-direction: column !important;
  gap: 14px !important;
}

.proximity-badge {
  display: inline-flex !important;
  align-items: center !important;
  gap: 6px !important;
  padding: 8px 14px !important;
  background: rgba(0, 229, 255, 0.12) !important;
  border: 1px solid rgba(0, 229, 255, 0.3) !important;
  border-radius: 10px !important;
  color: #00e5ff !important;
  font-weight: 700 !important;
  font-size: 12px !important;
  letter-spacing: 0.5px !important;
}

.proximity-badge.alt {
  background: rgba(255, 145, 0, 0.12) !important;
  border-color: rgba(255, 145, 0, 0.3) !important;
  color: #ff9100 !important;
}

.social-share-img {
  width: 100% !important;
  border-radius: 12px !important;
  border: 1px solid rgba(0, 229, 255, 0.3) !important;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6) !important;
  transition: transform 0.2s ease !important;
}
.social-share-img:hover {
  transform: scale(1.01) !important;
}

.proximity-runs-list {
  display: flex !important;
  flex-direction: column !important;
  gap: 10px !important;
  max-height: 420px !important;
  overflow-y: auto !important;
  padding-right: 4px !important;
}

.log-run-item {
  display: flex !important;
  align-items: center !important;
  justify-content: space-between !important;
  background: rgba(30, 41, 59, 0.6) !important;
  border: 1px solid rgba(255, 255, 255, 0.1) !important;
  border-radius: 10px !important;
  padding: 10px 14px !important;
  transition: all 0.15s ease !important;
}
.log-run-item:hover {
  background: rgba(30, 41, 59, 0.9) !important;
  border-color: rgba(0, 229, 255, 0.4) !important;
}

.log-run-item strong {
  font-family: 'JetBrains Mono', monospace !important;
  font-size: 15px !important;
  color: #00e5ff !important;
}

.log-run-item small {
  display: block !important;
  font-size: 11px !important;
  color: #94a3b8 !important;
  margin-top: 3px !important;
}

/* ---------- ride replay: 3D map wrap + status card ---------- */
.replay-map-wrap{
  position:relative;
  border-radius:18px;
  overflow:hidden;
  border:1px solid var(--border-strong);
  background:#0a0c11;
  margin:0 -16px; /* bleeds past the parent .panel's 16px side padding so the map spans its full width */
}
.replay-map-wrap #map{
  width:100%; height:min(60vh, 460px); min-height:320px;
}
.replay-loading-overlay{
  position:absolute; inset:0; z-index:20;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:12px;
  background:#0a0c11;
  transition:opacity 0.4s ease;
}
.replay-loading-overlay.hidden{
  opacity:0; pointer-events:none;
}
.replay-loading-spinner{
  width:34px; height:34px;
  border:3px solid rgba(255,255,255,0.15);
  border-top-color:#4f8cff;
  border-radius:50%;
  animation:replay-spin 0.85s linear infinite;
}
@keyframes replay-spin{ to{ transform:rotate(360deg); } }
.replay-loading-text{
  font-family:var(--font-mono); font-size:12.5px; color:rgba(255,255,255,0.7);
  letter-spacing:0.02em;
}
.replay-loading-bar{
  width:min(220px, 60%); height:4px;
  background:rgba(255,255,255,0.12);
  border-radius:2px;
  overflow:hidden;
}
.replay-loading-bar-fill{
  height:100%; width:0%;
  background:#4f8cff;
  border-radius:2px;
  transition:width 0.25s ease;
}
.replay-status{
  position:absolute; left:10px; right:10px; bottom:10px; z-index:5;
  background:linear-gradient(180deg, rgba(13,17,24,0.72), rgba(9,12,17,0.94));
  backdrop-filter:blur(10px);
  border:1px solid rgba(255,255,255,0.08);
  border-radius:16px;
  padding:12px 14px;
  box-shadow:0 12px 30px rgba(0,0,0,0.45);
  color:#eef1f5;
}
.replay-status-top{
  display:flex; align-items:flex-end; justify-content:space-between; gap:12px;
}
.replay-status-label{
  font-family:var(--font-display); font-size:10px; letter-spacing:0.1em; text-transform:uppercase;
  color:#8b93a3; margin-bottom:2px;
}
.replay-status-value{
  font-family:var(--font-mono); font-weight:800; font-size:32px; line-height:1; color:#fff;
  display:flex; align-items:baseline; gap:4px;
}
.replay-status-unit{ font-size:13px; font-weight:600; color:#8b93a3; }
.replay-status-weather{
  display:flex; align-items:center; gap:8px;
  background:rgba(255,255,255,0.06);
  border:1px solid rgba(255,255,255,0.08);
  border-radius:12px;
  padding:6px 10px;
  font-family:var(--font-mono); font-size:13px; color:#dfe4ea;
  flex-shrink:0;
}
.replay-weather-icon{ font-size:20px; line-height:1; }
.replay-status-location{
  margin-top:10px; padding-top:10px;
  border-top:1px solid rgba(255,255,255,0.08);
  font-size:13px; color:#c3cad6;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}

@media (max-width:480px){
  .replay-status-value{ font-size:26px; }
  .replay-status-weather{ font-size:12px; padding:5px 8px; }
}

/* ---------- ride replay: rider badge marker ---------- */
.replay-3d-marker{
  position:relative;
  width:44px; height:44px;
  transform:translateY(-6px);
}
.rider-marker-shadow{
  position:absolute; left:50%; bottom:-4px; transform:translateX(-50%);
  width:30px; height:10px; border-radius:50%;
  background:rgba(0,0,0,0.5); filter:blur(3px);
}
.rider-marker-pulse{
  position:absolute; inset:-8px; border-radius:50%;
  background:radial-gradient(circle, rgba(79,140,255,0.35) 0%, rgba(79,140,255,0) 70%);
  animation:riderPulse 1.8s ease-out infinite;
}
@keyframes riderPulse{
  0%{ transform:scale(0.7); opacity:0.9; }
  100%{ transform:scale(1.9); opacity:0; }
}
.rider-marker-badge{
  position:relative; width:44px; height:44px;
  filter:drop-shadow(0 4px 10px rgba(0,0,0,0.5));
}
.rider-marker-svg{ width:100%; height:100%; }
.rider-marker-heading{
  position:absolute; left:50%; top:-16px;
  width:14px; height:14px;
  transform:translateX(-50%);
  transform-origin:50% 28px;
  transition:transform 0.2s linear;
  filter:drop-shadow(0 0 3px rgba(79,140,255,0.8));
}
.rider-marker-heading svg{ width:100%; height:100%; fill:#4f8cff; }

.replay-3d-stop-marker{
  width:16px; height:16px; border-radius:50%;
  background:#ef4444; border:2px solid #0a0c11;
  box-shadow:0 0 0 3px rgba(239,68,68,0.25);
}

/* ---------- share ride modal ---------- */
.share-card-preview{
  display:flex; align-items:center; justify-content:center;
  background:#0a0c11; border-radius:14px; overflow:hidden;
  min-height:280px; border:1px solid var(--border-subtle);
}
.share-card-preview img{ display:block; width:100%; height:auto; }
.share-card-spinner{
  color:var(--text-muted); font-size:13px; font-family:var(--font-mono);
  padding:40px 0;
}
.share-type-toggle{
  display:flex; gap:4px; margin-bottom:12px;
  background:var(--bg-panel-raised); border:1px solid var(--border-subtle);
  border-radius:999px; padding:3px;
}
.share-type-btn{
  flex:1; border:none; background:transparent; color:var(--text-muted);
  font-family:var(--font-display); font-weight:600; font-size:12px; letter-spacing:0.02em;
  padding:8px 10px; border-radius:999px; cursor:pointer;
}
.share-type-btn.active{ background:var(--bg-panel); color:var(--neon-green); }
.share-gfx-preview{
  background:#0a0c11; border-radius:14px; border:1px solid var(--border-subtle);
  padding:22px; text-align:center;
}
.share-gfx-preview .gfx-icon{ font-size:40px; margin-bottom:8px; }
.share-gfx-preview .gfx-name{ font-family:var(--font-display); font-weight:600; font-size:15px; color:var(--text-primary); }
.share-gfx-preview .gfx-meta{ font-family:var(--font-mono); font-size:12px; color:var(--text-muted); margin-top:4px; }
.share-gfx-preview .gfx-desc{ font-family:var(--font-body); font-size:12px; color:var(--text-dim); margin-top:10px; }

.ride-share-type-option{
  display:flex; align-items:center; gap:12px; width:100%;
  background:var(--bg-panel-raised); border:1px solid var(--border-subtle);
  border-radius:14px; padding:14px 16px; cursor:pointer; text-align:left;
  font-family:var(--font-body); color:var(--text-primary);
}
.ride-share-type-option:active{ background:var(--bg-panel); }
.ride-share-type-option .icon{ font-size:24px; flex-shrink:0; }
.ride-share-type-option .label{ font-family:var(--font-display); font-weight:600; font-size:14px; }
.ride-share-type-option .sub{ font-family:var(--font-body); font-size:12px; color:var(--text-muted); margin-top:2px; }

.ride-card-share-btn, .ride-card-edit-btn{
  position:absolute; top:16px; z-index:2;
  width:32px; height:32px; border-radius:50%;
  border:1px solid var(--border-subtle); background:var(--bg-panel-raised);
  color:var(--text-muted); font-size:14px; cursor:pointer;
  display:flex; align-items:center; justify-content:center;
}
.ride-card-share-btn{ right:14px; }
.ride-card-edit-btn{ right:54px; }
.ride-card-share-btn:active, .ride-card-edit-btn:active{ background:var(--bg-panel); color:var(--neon-green); }
.ride-card.combine-mode .ride-card-share-btn, .ride-card.combine-mode .ride-card-edit-btn{ display:none; }

/* ---------- Labs (labs.html) ---------- */
/* The page-wide console card at the top of this page is
   js/page-console.js (RydRPageConsole) — a self-contained, reusable
   component that injects its own scoped styles (prefixed "rydr-pgc-"),
   same pattern as js/debug-console.js. Nothing to style here. */

.labs-grid{
  display:grid; grid-template-columns:repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap:16px;
}
.labs-card{ display:flex; flex-direction:column; gap:10px; }
.labs-card-desc{ font-family:var(--font-body); font-size:13px; color:var(--text-muted); line-height:1.5; margin:0; }

.labs-model-wrap{
  position:relative; width:100%; height:280px;
  border-radius:var(--radius-md); overflow:hidden;
  background:var(--bg-panel);
}
.labs-model-canvas{ position:absolute; inset:0; width:100%; height:100%; display:block; touch-action:none; }
.labs-status{
  position:absolute; inset:0; z-index:3; display:none;
  flex-direction:column; align-items:center; justify-content:center; text-align:center; gap:10px; padding:16px;
  background:var(--bg-panel); color:var(--text-primary);
  font-family:var(--font-display); font-size:12px; letter-spacing:0.02em;
}
.labs-status-retry{
  font-family:var(--font-display); font-weight:700; font-size:12px; letter-spacing:0.04em; text-transform:uppercase;
  padding:8px 18px; border-radius:999px; cursor:pointer;
  background:var(--neon-green); color:#02110a; border:none;
}
.labs-status-retry:hover{ filter:brightness(1.1); }
.labs-debug-mount{ margin-top:2px; }
.labs-trailreplay-map{ height:360px; }
.labs-trailreplay-controls{ display:flex; flex-wrap:wrap; gap:8px; align-items:center; justify-content:space-between; }
.labs-trailreplay-presets{ display:flex; gap:6px; flex-wrap:wrap; }
.labs-preset-btn{
  font-family:var(--font-display); font-weight:600; font-size:11.5px; letter-spacing:0.03em; text-transform:uppercase;
  padding:6px 12px; min-height:32px; border-radius:999px; cursor:pointer;
  background:var(--bg-panel-raised); border:1px solid var(--border-subtle); color:var(--text-muted);
}
.labs-preset-btn.active{ background:var(--neon-green); border-color:var(--neon-green-dim); color:#02110a; }
.labs-download-link{
  display:flex; align-items:center; justify-content:center; gap:6px;
  font-family:var(--font-display); font-weight:600; font-size:12.5px; letter-spacing:0.03em;
  padding:10px 14px; border-radius:var(--radius-sm);
  background:var(--bg-panel-raised); border:1px solid var(--border-subtle);
  color:var(--text-primary); text-decoration:none;
}
.labs-download-link:active{ background:var(--bg-panel); }

.labs-spec-row{
  display:flex; align-items:baseline; justify-content:space-between; gap:10px;
  padding:7px 0;
  border-bottom:1px solid var(--border-subtle);
  font-family:var(--font-body); font-size:13px;
}
.labs-spec-row:last-child{ border-bottom:none; }
.labs-spec-row span:first-child{ color:var(--text-muted); }
.labs-spec-row span:last-child{ font-family:var(--font-mono); color:var(--text-primary); font-weight:600; text-align:right; }

.labs-check-list{ display:flex; flex-direction:column; }
.labs-check-row{
  display:flex; align-items:center; gap:10px;
  padding:8px 0;
  border-bottom:1px solid var(--border-subtle);
  font-family:var(--font-body); font-size:13px;
}
.labs-check-row:last-child{ border-bottom:none; }
.labs-check-dot{ width:9px; height:9px; border-radius:50%; flex:0 0 auto; background:var(--text-dim); }
.labs-check-dot.labs-check-pending{ background:var(--text-dim); animation:labs-check-pulse 1.2s ease-in-out infinite; }
.labs-check-dot.labs-check-ok{ background:#22c55e; box-shadow:0 0 6px rgba(34,197,94,0.6); }
.labs-check-dot.labs-check-fail{ background:var(--alert-red); box-shadow:0 0 6px var(--alert-red-glow); }
@keyframes labs-check-pulse{ 0%,100%{ opacity:1; } 50%{ opacity:0.35; } }
.labs-check-name{ flex:1; color:var(--text-primary); }
.labs-check-result{ color:var(--text-muted); font-family:var(--font-mono); font-size:12px; }


