/* ============================================================
   HOPPINGSPOON — APPLE-INSPIRED PREMIUM DESIGN SYSTEM
   ============================================================ */

/* DESIGN TOKENS */
:root, [data-theme="light"] {
  /* Surfaces — warm ivory and pure crisp white */
  --color-bg: #F8F6F2;
  --color-surface: #FFFEFC;
  --color-surface-glass: rgba(255, 254, 252, 0.86);
  --color-surface-glass-subtle: rgba(255, 254, 252, 0.72);
  --color-surface-offset: #F1ECE4;
  --color-surface-offset-2: #EAE3D9;
  --color-surface-dynamic: #E2D9CC;
  --color-border: #E7E0D7;
  --color-border-subtle: #F0EAE1;
  --color-divider: #ECE4D8;

  /* Typography — deep espresso and warm stone */
  --color-text: #26221E;
  /* Darker than --color-text-muted below, so the three text levels read in
     the right order; also clears 4.5:1 on --color-surface-offset, which
     .vibe-tag and #resultCount sit on (#766E66 was 4.26:1 there). */
  --color-text-secondary: #645C54;
  /* Retuned for AA: #9E958C was 2.92:1 on --color-surface, and this token
     carries real text (.discovery-helper-note, .wheel-item, .sidebar-subtitle,
     the search placeholder), not just icons. 4.80:1 worst case across bg,
     surface and surface-offset. */
  --color-text-muted: #6F6659;
  --color-text-faint: #B5ABA0;
  --color-text-inverse: #FFFFFF;

  /* Brand Accent — Restrained Burnt Orange */
  --color-primary: #BE5A36;
  --color-primary-hover: #A94B2C;
  --color-primary-active: #8E3D21;
  --color-primary-tint: #F8ECE7;
  --color-primary-highlight: #F5DFD5;
  /* Solid (filled) buttons only. --color-primary stays #BE5A36 as brand ink
     for text, icons, borders and map markers; as a *fill* behind white label
     text it measures 4.46:1, just under AA, so filled buttons take a darker
     step. Markers keep --color-primary - non-text graphics only owe 3:1. */
  --color-primary-solid: #A94B2C;
  --color-primary-solid-hover: #8E3D21;
  --color-on-primary: #FFFFFF;

  /* Quiet Sage (Saved / Open States) */
  --color-sage: #4E6B50;
  --color-sage-hover: #3E5740;
  --color-sage-tint: #EBF2EC;

  /* Gold (Ratings & Stars) */
  --color-gold: #C68218;
  --color-gold-tint: #FBF2E2;
  /* --color-gold is a 3:1 graphic (the rating star). Where gold is the
     LABEL - .vibe-tag-popular sits on --color-gold-tint at 2.86:1 - it owes
     4.5:1 and needs its own darker step. */
  --color-gold-strong: #96600E;

  /* Error / Warnings */
  --color-error: #B3392E;
  --color-error-tint: #FBECE9;

  /* Spacing */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;

  /* Radii */
  --radius-xs: 0.375rem;
  --radius-sm: 0.5rem;
  --radius-md: 0.75rem;
  --radius-lg: 1rem;
  --radius-xl: 1.25rem;
  --radius-2xl: 1.5rem;
  --radius-full: 9999px;

  /* Shadows (Apple-style multi-layer diffuse) */
  --shadow-xs: 0 1px 2px rgba(38, 34, 30, 0.04);
  --shadow-sm: 0 2px 6px rgba(38, 34, 30, 0.05), 0 1px 2px rgba(38, 34, 30, 0.03);
  --shadow-md: 0 6px 18px rgba(38, 34, 30, 0.06), 0 2px 4px rgba(38, 34, 30, 0.03);
  --shadow-lg: 0 12px 36px rgba(38, 34, 30, 0.08), 0 4px 10px rgba(38, 34, 30, 0.04);
  --shadow-xl: 0 20px 48px rgba(38, 34, 30, 0.12), 0 6px 16px rgba(38, 34, 30, 0.05);

  /* Transitions */
  --ease-apple: cubic-bezier(0.16, 1, 0.3, 1);
  --transition-fast: 150ms var(--ease-apple);
  --transition-normal: 240ms var(--ease-apple);
  --transition-slow: 380ms var(--ease-apple);

  /* Fonts */
  --font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", "Inter", "Switzer", "Segoe UI", Roboto, sans-serif;
  --font-display: "Boska", Georgia, serif;
}

[data-theme="dark"] {
  --color-bg: #141210;
  --color-surface: #1E1B18;
  --color-surface-glass: rgba(30, 27, 24, 0.86);
  --color-surface-glass-subtle: rgba(30, 27, 24, 0.72);
  --color-surface-offset: #292420;
  --color-surface-offset-2: #332E29;
  --color-surface-dynamic: #3D3731;
  --color-border: #3D352F;
  --color-border-subtle: #2C2622;
  --color-divider: #2C2622;

  --color-text: #F5EFE9;
  /* Lighter than --color-text-muted below - dark mode's hierarchy runs the
     other way. */
  --color-text-secondary: #B4AAA0;
  /* AA retune, see the light-theme note. Was 3.79:1; now 5.29:1 worst case. */
  --color-text-muted: #A0968B;
  --color-text-faint: #5C544B;
  --color-text-inverse: #1E1B18;

  --color-primary: #E07852;
  --color-primary-hover: #EC8D6A;
  --color-primary-active: #F4A586;
  --color-primary-tint: #3B241B;
  --color-primary-highlight: #4D2D21;
  /* Dark mode inverts the pair: the accent is bright enough that white label
     text was 3.01:1, while the near-black ink is 5.70:1 on the same fill. */
  --color-primary-solid: #E07852;
  --color-primary-solid-hover: #EC8D6A;
  --color-on-primary: #1E1B18;

  --color-sage: #81A884;
  --color-sage-hover: #96BD99;
  --color-sage-tint: #233125;

  --color-gold: #E5A33D;
  --color-gold-tint: #3B2D18;
  /* Already 6.12:1 on the dark tint; aliased so the rule can be one line. */
  --color-gold-strong: #E5A33D;

  --color-error: #D96357;
  --color-error-tint: #3D211F;

  --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.2);
  --shadow-sm: 0 2px 6px rgba(0, 0, 0, 0.3);
  --shadow-md: 0 6px 18px rgba(0, 0, 0, 0.4);
  --shadow-lg: 0 12px 36px rgba(0, 0, 0, 0.5);
  --shadow-xl: 0 20px 48px rgba(0, 0, 0, 0.65);
}

/* BASE & LAYOUT RESET */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html, body {
  height: 100%;
  width: 100%;
  overflow: hidden;
  font-family: var(--font-sans);
  background-color: var(--color-bg);
  color: var(--color-text);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

button, input, select, textarea {
  font-family: inherit;
  font-size: inherit;
  color: inherit;
}

a {
  color: inherit;
  text-decoration: none;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* APP SHELL */
.app-shell {
  display: flex;
  flex-direction: column;
  height: 100vh; /* fallback for browsers without dvh */
  height: 100dvh;
  width: 100vw;
  overflow: hidden;
  background-color: var(--color-bg);
}

/* TOP NAVIGATION (Slim 70px) */
.topbar {
  height: 70px;
  background: var(--color-surface-glass);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border-bottom: 1px solid var(--color-border);
  position: relative;
  /* Higher than .discovery-overlay (900): the location popover lives inside
     the topbar and overflows down past its 70px height, and as a
     descendant it can never out-rank the topbar's own stacking context, so
     the topbar itself has to sit above anything on the map it might cover. */
  z-index: 950;
  flex-shrink: 0;
}

.topbar-inner {
  height: 100%;
  max-width: 100%;
  padding: 0 var(--space-6);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}

/* BRAND (see public/lib/logo.js - the nav renders one <span class="logo">
   per lockup variant, this file only styles the markup that module emits) */
.brand {
  display: flex;
  align-items: center;
  /* 28px icon + 8px padding on every side = a 44px touch target at the
     390px icon-only breakpoint, and doubles as the mark's clear space at
     every wider breakpoint too. */
  padding: 8px;
  margin: -8px;
  text-decoration: none;
  cursor: pointer;
  user-select: none;
}

.brand:hover .logo-icon {
  transform: scale(1.05);
}

.logo {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--logo-size, 28px) * 0.32);
}

.logo-icon {
  display: block;
  flex-shrink: 0;
  transition: transform var(--transition-fast);
}

.logo-word {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.01em;
  white-space: nowrap;
  font-size: calc(var(--logo-size, 28px) * 0.68);
}

.logo--compact .logo-word {
  font-size: calc(var(--logo-size, 28px) * 0.5);
}

/* Themes: `brand` rides the live design tokens (so it repaints for dark
   mode automatically); `charcoal` and `white` are fixed, for placing the
   mark on a surface that ignores the app's own light/dark state. */
.logo--brand {
  color: var(--color-primary);
}

.logo--brand .logo-word {
  color: var(--color-text);
}

.logo--charcoal,
.logo--charcoal .logo-word {
  color: #26221E;
}

.logo--white,
.logo--white .logo-word {
  color: #FFFFFF;
}

/* The nav renders all three lockup variants and lets these breakpoints
   pick which one is visible (native display:none, not a JS resize
   listener) - see the 900px/640px media queries below for the switch.
   display:none also drops the other two out of the accessibility tree, so
   nothing gets announced twice. */
.brand-lockup {
  display: inline-flex;
}

.brand-lockup[data-logo-slot="compact"],
.brand-lockup[data-logo-slot="icon"] {
  display: none;
}

/* TOPBAR CENTER (Location Pill & Compact Search) */
.topbar-center {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex: 1;
  max-width: 580px;
  margin: 0 auto;
}

.location-pill-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: 42px;
  padding: 0 var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--color-text);
  box-shadow: var(--shadow-xs);
  cursor: pointer;
  transition: all var(--transition-fast);
  white-space: nowrap;
}

.location-pill-btn:hover {
  background: var(--color-surface-offset);
  border-color: var(--color-border-subtle);
  box-shadow: var(--shadow-sm);
}

.location-pill-btn svg {
  width: 16px;
  height: 16px;
  color: var(--color-primary);
}

.location-pill-chevron {
  width: 14px !important;
  height: 14px !important;
  color: var(--color-text-muted) !important;
}

/* LOCATION PILL POPOVER */
.location-pill-wrap {
  position: relative;
  display: flex;
  align-items: center;
}

.location-popover {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  width: 300px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xl);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  z-index: 10;
}

.location-popover.hidden {
  display: none;
}

.location-popover-form {
  display: flex;
  gap: var(--space-2);
}

.location-popover-input {
  flex: 1;
  height: 40px;
  min-width: 0;
  background: var(--color-surface-offset);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 0 var(--space-3);
  font-size: 0.88rem;
  color: var(--color-text);
  outline: none;
}

.location-popover-input:focus {
  border-color: var(--color-primary);
}

.location-popover-go-btn {
  height: 40px;
  padding: 0 var(--space-4);
  border: none;
  border-radius: var(--radius-md);
  background: var(--color-primary-solid);
  color: var(--color-on-primary);
  font-size: 0.86rem;
  font-weight: 600;
  cursor: pointer;
  flex-shrink: 0;
  transition: background var(--transition-fast);
}

.location-popover-go-btn:hover {
  background: var(--color-primary-solid-hover);
}

.location-popover-geo-btn {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  height: 40px;
  padding: 0 var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-offset);
  color: var(--color-text);
  font-size: 0.86rem;
  font-weight: 500;
  cursor: pointer;
  transition: all var(--transition-fast);
}

.location-popover-geo-btn:hover {
  background: var(--color-surface-dynamic);
}

.location-popover-geo-btn svg {
  width: 16px;
  height: 16px;
  color: var(--color-primary);
}

.location-popover-presets {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px solid var(--color-border-subtle);
}

.location-popover-presets-label {
  font-size: 0.76rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  /* text-muted on the popover surface is 2.92:1 (light) - text-secondary
     clears 4.5:1 in both themes. */
  color: var(--color-text-secondary);
}

.location-popover-preset-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.location-popover-preset-btn {
  text-align: left;
  padding: var(--space-2) var(--space-2);
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-text);
  font-size: 0.86rem;
  cursor: pointer;
  transition: background var(--transition-fast);
}

.location-popover-preset-btn:hover {
  background: var(--color-surface-offset);
}

/* TOPBAR SEARCH BAR */
.topbar-search-form {
  display: flex;
  align-items: center;
  flex: 1;
  height: 42px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  padding: 0 4px 0 var(--space-3);
  box-shadow: var(--shadow-xs);
  transition: all var(--transition-fast);
}

.topbar-search-form:focus-within {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-tint);
}

.search-icon-inline {
  width: 16px;
  height: 16px;
  color: var(--color-text-muted);
  margin-right: var(--space-2);
  flex-shrink: 0;
}

.topbar-search-input {
  flex: 1;
  border: none;
  background: transparent;
  font-size: 0.88rem;
  color: var(--color-text);
  outline: none;
  min-width: 0;
}

.topbar-search-input::placeholder {
  color: var(--color-text-muted);
}

.search-submit-btn {
  height: 34px;
  padding: 0 var(--space-4);
  border: none;
  border-radius: var(--radius-full);
  background: var(--color-primary-solid);
  color: var(--color-on-primary);
  font-size: 0.84rem;
  font-weight: 600;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  transition: background var(--transition-fast);
  flex-shrink: 0;
}

.search-submit-btn:hover {
  background: var(--color-primary-solid-hover);
}

/* TOPBAR ACTIONS */
.topbar-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.nav-icon-btn {
  width: 42px;
  height: 42px;
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: var(--shadow-xs);
  transition: all var(--transition-fast);
}

.nav-icon-btn:hover {
  background: var(--color-surface-offset);
  color: var(--color-text);
  box-shadow: var(--shadow-sm);
}

.nav-icon-btn.active {
  background: var(--color-sage-tint);
  color: var(--color-sage);
  border-color: var(--color-sage);
}

.nav-icon-btn svg {
  width: 18px;
  height: 18px;
}

.discover-nav-btn {
  height: 42px;
  padding: 0 var(--space-4);
  border-radius: var(--radius-full);
  border: 1px solid var(--color-primary-highlight);
  background: var(--color-primary-tint);
  /* 3.86:1 as --color-primary on its own tint. */
  color: var(--color-primary-hover);
  font-size: 0.88rem;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  cursor: pointer;
  box-shadow: var(--shadow-xs);
  transition: all var(--transition-fast);
}

.discover-nav-btn:hover {
  background: var(--color-primary-solid);
  color: var(--color-on-primary);
  border-color: var(--color-primary);
  box-shadow: var(--shadow-sm);
}

.discover-nav-btn svg {
  width: 16px;
  height: 16px;
}

/* STATUS BANNER */
.status-banner {
  position: absolute;
  top: 78px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 150;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  padding: var(--space-2) var(--space-5);
  border-radius: var(--radius-full);
  box-shadow: var(--shadow-lg);
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--color-text);
  animation: slideDown 200ms var(--ease-apple);
}

@keyframes slideDown {
  from { opacity: 0; transform: translate(-50%, -10px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}

/* MAIN DUAL-PANE LAYOUT */
.main-layout {
  flex: 1;
  display: grid;
  /* The map was taking roughly three quarters of a wide screen to show what is
     mostly context, while the results - the thing being read - were squeezed
     into a fixed 430px. A proportion rather than a constant, so the list grows
     with the window; floored so it never gets narrower than it used to be, and
     capped so the map does not become a strip on an ultrawide display. */
  grid-template-columns: minmax(0, 1fr) clamp(430px, 36%, 660px);
  min-height: 0;
  position: relative;
  overflow: hidden;
}

/* MAP CONTAINER */
.map-pane {
  position: relative;
  height: 100%;
  width: 100%;
  background-color: #E6E2D8;
}

.map-pane .leaflet-tile-pane {
  filter: saturate(0.85) contrast(0.98) brightness(1.02);
}

[data-theme="dark"] .map-pane .leaflet-tile-pane {
  filter: invert(100%) hue-rotate(180deg) brightness(88%) contrast(92%) saturate(75%);
}

/* MAP ZOOM & LOCATE CONTROLS */
/* z-index must clear Leaflet's own .leaflet-pane (400) and .leaflet-popup-pane
   (700) - both are siblings of this element inside #map, and without this the
   live map tiles/markers/popups paint on top and swallow every click here. */
.map-controls-group {
  position: absolute;
  bottom: var(--space-6);
  left: var(--space-6);
  z-index: 800;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.map-control-btn {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-md);
  background: var(--color-surface-glass);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid var(--color-border);
  color: var(--color-text);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: var(--shadow-md);
  transition: all var(--transition-fast);
}

.map-control-btn:hover {
  background: var(--color-surface);
  transform: translateY(-1px);
  box-shadow: var(--shadow-lg);
}

.map-control-btn svg {
  width: 18px;
  height: 18px;
}

/* FLOATING COMPACT FILTER BAR OVER MAP */
/* Same z-index reasoning as .map-controls-group above - must clear Leaflet's
   own panes (up to 700) or the "Help me choose" pill and filter chips become
   unclickable wherever a marker/tile happens to sit underneath them. */
.compact-filter-bar {
  position: absolute;
  top: var(--space-4);
  left: var(--space-6);
  right: var(--space-6);
  z-index: 800;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  overflow: visible;
  padding: 4px;
  pointer-events: none;
}

.compact-filter-bar > * {
  pointer-events: auto;
}

/* OPTIONS DISCLOSURE
   Price, Mode, Units, Distance, Open now and Reset used to sit in the bar as
   six capsules floating across the top of the map. They live in one panel now,
   behind a single "Options" button: a popout anchored under that button on
   desktop, and a static panel inside the results sheet on phones. One element,
   moved between the two by syncFilterBarPlacement - so there is a single set of
   controls, with all their state and event wiring intact, not two copies. */
.filters-disclosure {
  position: relative;
}

.filters-summary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 38px;
  padding: 0 var(--space-3);
  background: var(--color-surface-glass);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  font-size: 0.84rem;
  font-weight: 500;
  color: var(--color-text);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  white-space: nowrap;
  list-style: none;
}

/* Safari paints its own disclosure triangle without this. */
.filters-summary::-webkit-details-marker {
  display: none;
}

.filters-summary::after {
  content: "";
  width: 6px;
  height: 6px;
  margin-left: 2px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
}

.filters-disclosure[open] .filters-summary::after {
  transform: rotate(-135deg) translate(-2px, -2px);
}

/* Closed, this button is the only sign that filters are narrowing the list. */
.filters-summary.has-active {
  background: var(--color-primary-tint);
  border-color: var(--color-primary-highlight);
  color: var(--color-primary-hover);
  font-weight: 600;
}

/* The browser hides a closed <details>'s non-summary children with
   display:none, which any display of our own silently overrides - so the panel
   has to be hidden explicitly and shown only when open. */
.filters-disclosure > .filter-controls {
  display: none;
}

.filters-disclosure[open] > .filter-controls {
  position: absolute;
  top: calc(100% + var(--space-2));
  left: 0;
  /* Above the bar's own 800 so the panel is never behind a sibling pill. */
  z-index: 810;
  width: 340px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-3);
  padding: var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xl);
}

/* Inside a panel, on a solid surface, the glass treatment has nothing to
   frost and the shadows read as noise. The group also stops being a capsule:
   it is a pill wrapping a pill of chips, and at any chip height above its own
   the inner one overhangs the outer, which looks like a rendering fault. Its
   label is plain text here and the chips are the only pill. */
.filter-controls .filter-bar-group {
  display: flex;
  justify-content: space-between;
  background: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: none;
  box-shadow: none;
  padding: 0;
  height: auto;
  min-height: 0;
  max-width: 100%;
  flex-wrap: wrap;
}

.filter-controls .filter-glass-pill {
  background: var(--color-surface-offset);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
}

.filter-controls .segmented-chips {
  flex-wrap: wrap;
}


.filter-glass-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 38px;
  padding: 0 var(--space-3);
  background: var(--color-surface-glass);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  font-size: 0.84rem;
  font-weight: 500;
  color: var(--color-text);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  white-space: nowrap;
  transition: all var(--transition-fast);
}

.filter-glass-pill:hover {
  background: var(--color-surface);
  border-color: var(--color-border-subtle);
  box-shadow: var(--shadow-md);
}

.filter-glass-pill.active {
  background: var(--color-primary-tint);
  border-color: var(--color-primary-highlight);
  /* color-primary against this tint is only 3.86:1 (light) - color-primary-active
     keeps the terracotta family while clearing 4.5:1 in both themes. */
  color: var(--color-primary-active);
  font-weight: 600;
}

.filter-chip-remove {
  width: 16px;
  height: 16px;
  border-radius: var(--radius-full);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.08);
  color: inherit;
  margin-left: 2px;
  cursor: pointer;
  transition: background var(--transition-fast);
}

.filter-chip-remove:hover {
  background: rgba(0, 0, 0, 0.2);
}

.filter-chip-remove svg {
  width: 10px;
  height: 10px;
}

/* One level up from muted: this pill's background is --color-surface-glass
   over live map tiles, so its effective backdrop swings with whatever is
   underneath - muted measured 3.84:1 over a light tile. */
.filter-reset-pill {
  color: var(--color-text-secondary);
}

.filter-reset-pill:hover {
  color: var(--color-error);
}

.filter-discover-pill {
  background: var(--color-primary-solid);
  color: var(--color-on-primary) !important;
  border: none;
  font-weight: 600;
}

.filter-discover-pill:hover {
  background: var(--color-primary-solid-hover);
  color: var(--color-on-primary) !important;
}

.filter-toggle-pill.active {
  background: var(--color-primary-tint);
  border-color: var(--color-primary-highlight);
  /* color-primary against this tint is only 3.86:1 (light) - color-primary-active
     keeps the terracotta family while clearing 4.5:1 in both themes. */
  color: var(--color-primary-active);
  font-weight: 600;
}

/* PERSISTENT FILTER BAR: PRICE & WALK TIME GROUPS */
/* Same glass-pill look as the rest of the bar, wrapping the segmented-chips
   control shared with the discovery card (see JS: any [data-price]/
   [data-radius] button, in either place, is wired to the same state). */
.filter-bar-group {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: 38px;
  padding: 0 var(--space-3);
  background: var(--color-surface-glass);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  box-shadow: var(--shadow-sm);
  flex-shrink: 0;
}

/* Same glass-over-tiles reasoning as .filter-reset-pill; secondary measured
   4.44:1 in dark. */
.filter-bar-group-label {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--color-text);
  white-space: nowrap;
}

/* Drive-mode disclosure: we only hold straight-line distance, never a
   driving route. Lives in the sidebar header (under the sort row), not the
   horizontally-scrolling map filter bar - at 1440/1024/390px that bar's
   scrollWidth exceeds its visible width and the note used to scroll off
   past the last chip. Same glass background/border/radius as the sibling
   .filter-bar-group so its contrast is fixed against the sidebar surface,
   never against whatever map tile happens to be underneath. */
.filter-bar-note {
  display: inline-flex;
  align-items: center;
  margin-top: var(--space-3);
  min-height: 34px;
  padding: 0 var(--space-3);
  background: var(--color-surface-glass);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  box-shadow: var(--shadow-sm);
  font-size: 0.78rem;
  color: var(--color-text-secondary);
  white-space: normal;
}

/* GUIDED DISCOVERY CARD ("WHAT ARE YOU FEELING?") */
/* Same z-index reasoning as .map-controls-group above, and higher still so
   the modal stays above the filter bar/controls - Leaflet's own panes
   (up to 700) are siblings of this element inside #map and would otherwise
   paint over the wheel pickers, making them impossible to click or drag. */
/* A light scrim, not a heavy one: the map behind the card should stay
   readable (streets, pins) while the card still reads clearly as the
   foreground layer via its own shadow (--shadow-xl on .discovery-card). */
.discovery-overlay {
  position: absolute;
  inset: 0;
  z-index: 900;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  background: rgba(38, 34, 30, 0.10);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  opacity: 1;
  visibility: visible;
  transition: opacity var(--transition-normal), visibility var(--transition-normal);
}

.discovery-overlay.hidden {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.discovery-card {
  width: 100%;
  max-width: 520px;
  /* .discovery-overlay is inset:0 on #map (a definite height) with padding
     and centers this card with align-items/justify-content, so 100% here
     resolves against the overlay's real content-box height - whatever phone
     and browser-chrome state that turns out to be, the card can never
     measure taller than what's actually on screen (872px/overflow-visible
     was the owner's "takes up the whole screen and I can't get past it").
     overflow-y makes the excess scrollable in place instead of clipped. */
  max-height: 100%;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-2xl);
  box-shadow: var(--shadow-xl);
  padding: var(--space-8);
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  position: relative;
  transform: translateY(0) scale(1);
  transition: transform var(--transition-normal);
}

.discovery-overlay.hidden .discovery-card {
  transform: translateY(20px) scale(0.96);
}

.discovery-close-btn {
  position: absolute;
  top: var(--space-5);
  right: var(--space-5);
  width: 32px;
  height: 32px;
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border);
  background: var(--color-surface-offset);
  color: var(--color-text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all var(--transition-fast);
}

.discovery-close-btn:hover {
  background: var(--color-surface-dynamic);
  color: var(--color-text);
}

.discovery-close-btn svg {
  width: 16px;
  height: 16px;
}

.discovery-card-header {
  text-align: center;
}

.discovery-sparkle-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: var(--radius-full);
  background: var(--color-primary-tint);
  color: var(--color-primary);
  margin-bottom: var(--space-3);
}

.discovery-sparkle-badge svg {
  width: 20px;
  height: 20px;
}

.discovery-title {
  font-size: 1.55rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--color-text);
  margin-bottom: var(--space-1);
}

.discovery-subtitle {
  font-size: 0.92rem;
  color: var(--color-text-secondary);
  line-height: 1.4;
}

/* 3-WHEEL PICKER CONTAINER */
.wheel-picker-group {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
  background: var(--color-surface-offset);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  padding: var(--space-2);
}

.wheel-column {
  display: flex;
  flex-direction: column;
  background: var(--color-surface);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-lg);
  overflow: hidden;
  position: relative;
}

.wheel-header {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  padding: var(--space-2) var(--space-1);
  border-bottom: 1px solid var(--color-border-subtle);
  background: var(--color-surface-glass-subtle);
}

.wheel-icon {
  width: 14px;
  height: 14px;
  color: var(--color-primary);
}

.wheel-title {
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-secondary);
}

/* Holds the lens/fade overlays outside the scrolling element. A position:
   absolute child of a scrolling position:relative container is positioned
   in that container's *content* coordinate space, not its visible window -
   it scrolls along with everything else instead of staying put, so an
   overlay meant to stay fixed while the list scrolls under it has to live
   here instead of inside .wheel-viewport. This is what let the highlight
   band (and the edge fades) end up scrolled out of place on any wheel whose
   default selection isn't the first row, like the Moment wheel. */
.wheel-viewport-wrap {
  position: relative;
  height: 220px;
}

.wheel-viewport {
  height: 100%;
  overflow-y: scroll;
  scrollbar-width: none;
  scroll-snap-type: y mandatory;
  user-select: none;
  cursor: grab;
  outline: none;
  /* The drag gesture is owned by WheelPicker's own pointer handlers (they
     set scrollTop directly); without this, touch browsers also start a
     native scroll gesture on the same drag and either fight it or cancel
     the pointer sequence outright, so the wheel doesn't reliably spin. */
  touch-action: none;
}

.wheel-viewport:active {
  cursor: grabbing;
}

.wheel-viewport::-webkit-scrollbar {
  display: none;
}

.wheel-lens {
  position: absolute;
  /* True center of the viewport, not a px figure tied to one breakpoint's
     height - .wheel-viewport's height changes at 640px (220px -> 140px) and
     a fixed top here previously matched only the desktop figure, so the
     lens sat over the wrong row everywhere else. The matching JS fix is in
     WheelPicker.layout() (wheel-picker.js), which centers the selected item
     on this same axis by measuring the real viewport/row height instead of
     assuming it. */
  top: 50%;
  transform: translateY(-50%);
  left: 4px;
  right: 4px;
  height: 44px;
  background: var(--color-primary-tint);
  border: 1px solid var(--color-primary-highlight);
  border-radius: var(--radius-md);
  pointer-events: none;
  z-index: 1;
}

.wheel-fade {
  position: absolute;
  left: 0;
  right: 0;
  height: 70px;
  pointer-events: none;
  z-index: 2;
}

.wheel-fade-top {
  top: 0;
  background: linear-gradient(to bottom, var(--color-surface) 10%, rgba(255, 254, 252, 0) 100%);
}

.wheel-fade-bottom {
  bottom: 0;
  background: linear-gradient(to top, var(--color-surface) 10%, rgba(255, 254, 252, 0) 100%);
}

[data-theme="dark"] .wheel-fade-top {
  background: linear-gradient(to bottom, var(--color-surface) 10%, rgba(30, 27, 24, 0) 100%);
}

[data-theme="dark"] .wheel-fade-bottom {
  background: linear-gradient(to top, var(--color-surface) 10%, rgba(30, 27, 24, 0) 100%);
}

.wheel-list {
  display: flex;
  flex-direction: column;
}

.wheel-item {
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 var(--space-2);
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--color-text-muted);
  scroll-snap-align: center;
  transition: all 180ms ease;
  position: relative;
  z-index: 3;
}

/* --color-primary-hover, not --color-primary: as *text* on the wheel's white
   column the brand ink is 4.43:1, just under AA. Same substitution the inline
   review and rating links already make. */
.wheel-item.selected {
  color: var(--color-primary-hover);
  font-weight: 700;
  font-size: 0.96rem;
  transform: scale(1.04);
}

/* SEGMENTED CHIPS (persistent filter bar's Price / Walk time groups - the
   discovery card's own Price/Distance chips were removed since the bar now
   owns both and applies them immediately, unlike the card's three wheels
   which defer to "Find places"). */
.segmented-chips {
  display: inline-flex;
  flex-wrap: nowrap;
  background: var(--color-surface-offset);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  padding: 2px;
}

.segmented-chip-btn {
  flex: 0 0 auto;
  white-space: nowrap;
  height: 28px;
  padding: 0 10px;
  border: none;
  background: transparent;
  border-radius: var(--radius-full);
  font-size: 0.8rem;
  font-weight: 500;
  /* text-secondary against the offset track is 4.26:1 (light) - text is
     already the hover color below and clears 4.5:1 with margin in both
     themes, so the resting state now matches it. */
  color: var(--color-text);
  cursor: pointer;
  transition: all var(--transition-fast);
}

.segmented-chip-btn:hover {
  color: var(--color-text);
}

.segmented-chip-btn.active {
  background: var(--color-surface);
  /* color-primary against the surface chip is 4.43:1 (light) - color-primary-active
     keeps the terracotta family while clearing 4.5:1 in both themes. */
  color: var(--color-primary-active);
  font-weight: 600;
  box-shadow: var(--shadow-xs);
}

/* DISCOVERY ACTION BUTTONS */
.discovery-actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.discovery-primary-btn {
  flex: 2;
  height: 48px;
  background: var(--color-primary-solid);
  color: var(--color-on-primary);
  border: none;
  border-radius: var(--radius-xl);
  font-size: 0.98rem;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(190, 90, 54, 0.3);
  transition: all var(--transition-fast);
}

.discovery-primary-btn:hover {
  background: var(--color-primary-solid-hover);
  transform: translateY(-1px);
  box-shadow: 0 6px 18px rgba(190, 90, 54, 0.38);
}

.discovery-surprise-btn {
  flex: 1;
  height: 48px;
  background: var(--color-surface-offset);
  border: 1px solid var(--color-border);
  color: var(--color-text);
  border-radius: var(--radius-xl);
  font-size: 0.92rem;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  cursor: pointer;
  transition: all var(--transition-fast);
}

.discovery-surprise-btn:hover {
  background: var(--color-surface-dynamic);
}

.discovery-helper-note {
  text-align: center;
  font-size: 0.8rem;
  color: var(--color-text-muted);
}

/* Structural wrappers around the wheels and the actions. These are
   unconditional on purpose. Gating them on a breakpoint is what left the
   primary action below the fold at 561-593px tall (just outside a
   max-height:560px query) on any window wider than a phone: the exact bug
   the phone rules were written to kill, surviving in a 33px band that a
   laptop with docked devtools lands in. Stated as pure flex, they are inert
   wherever the card fits - the scroll region has nothing to scroll and the
   footer sits exactly where it would have anyway - and they engage on their
   own the moment it doesn't, at any width or height. The card itself keeps
   its base overflow-y:auto as a backstop for the pathological case where
   even the header alone overflows. */
.discovery-card-header {
  flex-shrink: 0;
}

.discovery-card-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  scrollbar-width: none;
}

.discovery-card-scroll::-webkit-scrollbar {
  display: none;
}

/* The footer keeps its own gap so sitting outside the card's direct flex
   flow doesn't collapse the space between the buttons and the helper note. */
.discovery-card-footer {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  flex-shrink: 0;
}

/* RIGHT RESULTS SIDEBAR */
.sidebar {
  background: var(--color-bg);
  border-left: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  min-height: 0;
  position: relative;
  overflow: hidden;
}

.sidebar-view {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
}

.sidebar-view.hidden {
  display: none !important;
}

/* SIDEBAR HEADER */
.sidebar-header {
  padding: var(--space-5) var(--space-6) var(--space-4);
  background: var(--color-surface-glass);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border-bottom: 1px solid var(--color-border);
  flex-shrink: 0;
}

.sidebar-header-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-2);
  margin-bottom: var(--space-1);
}

.sidebar-title {
  font-size: 1.3rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--color-text);
}

/* MOMENT SWITCHER (chevron + menu next to the sidebar heading) */
.sidebar-title-group {
  position: relative;
  display: flex;
  align-items: center;
  gap: 2px;
  min-width: 0;
}

.moment-chevron-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border: none;
  border-radius: var(--radius-full);
  background: transparent;
  /* text-muted on the header's glass surface is ~2.90:1 (light), below even
     the 3:1 graphical floor - text-secondary clears 4.5:1 in both themes. */
  color: var(--color-text-secondary);
  cursor: pointer;
  flex-shrink: 0;
  transition: all var(--transition-fast);
}

.moment-chevron-btn:hover {
  background: var(--color-surface-offset);
  color: var(--color-text);
}

.moment-chevron-btn svg {
  width: 16px;
  height: 16px;
}

.moment-menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  min-width: 190px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
  padding: var(--space-2);
  display: flex;
  flex-direction: column;
  gap: 1px;
  z-index: 20;
}

.moment-menu.hidden {
  display: none;
}

.moment-menu-item {
  text-align: left;
  padding: var(--space-2) var(--space-3);
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-text);
  font-size: 0.86rem;
  font-weight: 500;
  cursor: pointer;
  transition: background var(--transition-fast);
}

.moment-menu-item:hover {
  background: var(--color-surface-offset);
}

.moment-menu-item.active {
  background: var(--color-primary-tint);
  /* color-primary against this tint is only 3.86:1 (light) - color-primary-active
     keeps the terracotta family while clearing 4.5:1 in both themes. */
  color: var(--color-primary-active);
  font-weight: 600;
}

.sidebar-count-badge {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--color-text-secondary);
  background: var(--color-surface-offset);
  padding: 3px var(--space-3);
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border-subtle);
  white-space: nowrap;
}

.sidebar-subtitle {
  font-size: 0.84rem;
  color: var(--color-text-muted);
  margin-bottom: var(--space-4);
  line-height: 1.4;
}

.sidebar-controls-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.sidebar-sort-select {
  height: 36px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 0 var(--space-3);
  font-size: 0.84rem;
  font-weight: 500;
  color: var(--color-text);
  outline: none;
  cursor: pointer;
}

.sidebar-filter-input {
  flex: 1;
  height: 36px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 0 var(--space-3);
  font-size: 0.84rem;
  color: var(--color-text);
  outline: none;
}

.sidebar-filter-input:focus {
  border-color: var(--color-primary);
}

/* SIDEBAR RESTAURANT LIST */
/* Held-over results while a new search runs (see renderCards). Not
   pointer-events:none - these are still real places and tapping one is
   reasonable - just visibly not current. */
.sidebar-list.is-stale {
  opacity: 0.5;
  transition: opacity var(--transition-fast);
}

.sidebar-list {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-4) var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

/* APPLE-STYLE RESTAURANT CARD */
.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-sm);
  padding: var(--space-4);
  display: flex;
  gap: var(--space-4);
  cursor: pointer;
  position: relative;
  transition: transform var(--transition-fast), box-shadow var(--transition-fast), border-color var(--transition-fast);
  user-select: none;
}

.card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
  border-color: var(--color-primary-highlight);
}

.card.card-highlighted {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 2px var(--color-primary-tint), var(--shadow-md);
  background: var(--color-surface);
}

/* CARD THUMBNAIL */
.card-thumb-slot {
  width: 86px;
  height: 86px;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--color-surface-offset);
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}

.card-thumb-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.card-thumb-fallback {
  width: 100%;
  height: 100%;
  background: linear-gradient(135deg, var(--color-surface-offset), var(--color-surface-dynamic));
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-primary);
}

.card-thumb-fallback svg {
  width: 30px;
  height: 30px;
}

/* CARD CONTENT */
.card-content {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.card-name-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-2);
}

.card-name {
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--color-text);
  line-height: 1.25;
}

.card-price {
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--color-text-secondary);
}

.card-meta-line {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  font-size: 0.82rem;
  color: var(--color-text-secondary);
}

.card-meta-line .dot {
  color: var(--color-text-muted);
}

.card-rating-badge {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-weight: 600;
  color: var(--color-text);
}

.card-rating-badge svg {
  width: 13px;
  height: 13px;
  color: var(--color-gold);
}

.card-walk-badge {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  color: var(--color-text-secondary);
}

.card-walk-badge svg {
  width: 13px;
  height: 13px;
}

/* "WHY IT FITS" EDITORIAL LINE */
.card-fit-summary {
  font-size: 0.81rem;
  color: var(--color-text-secondary);
  line-height: 1.35;
  margin-top: 2px;
}

/* CARD TAGS ROW */
.card-tags-row {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 6px;
  flex-wrap: wrap;
}

.vibe-tag {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: var(--radius-full);
  background: var(--color-surface-offset);
  font-size: 0.74rem;
  font-weight: 500;
  color: var(--color-text-secondary);
}

.vibe-tag-trending {
  background: #FCE8E6;
  color: #C5221F;
  font-weight: 600;
}

.vibe-tag-popular {
  background: var(--color-gold-tint);
  color: var(--color-gold-strong);
  font-weight: 600;
}

/* BOOKMARK BUTTON */
.card-bookmark-btn {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  width: 28px;
  height: 28px;
  border-radius: var(--radius-full);
  border: none;
  background: transparent;
  color: var(--color-text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all var(--transition-fast);
}

/* Saving a place is a primary action and the visible chip is 28px, under the
   44px touch floor. A transparent inset overlay grows the hit area to 44px
   without growing the button box, which would also grow the hover circle. */
.card-bookmark-btn::before {
  content: "";
  position: absolute;
  inset: -8px;
  border-radius: inherit;
}

.card-bookmark-btn:hover {
  background: var(--color-surface-offset);
  color: var(--color-primary);
}

.card-bookmark-btn.bookmarked {
  color: var(--color-primary);
}

.card-bookmark-btn svg {
  width: 15px;
  height: 15px;
}

/* MAP MARKERS */
.marker-wrapper {
  background: transparent;
  border: none;
}

.marker {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-full);
  background: var(--color-primary);
  color: #FFFFFF;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 10px rgba(190, 90, 54, 0.4);
  border: 2px solid #FFFFFF;
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
  cursor: pointer;
}

.marker:hover {
  transform: scale(1.15);
  box-shadow: 0 6px 14px rgba(190, 90, 54, 0.55);
}

.marker-active {
  transform: scale(1.22);
  background: #A94B2C;
  box-shadow: 0 0 0 5px rgba(190, 90, 54, 0.35), 0 8px 20px rgba(190, 90, 54, 0.5);
  z-index: 9999 !important;
}

.marker svg {
  width: 17px;
  height: 17px;
}

.marker-origin {
  background: var(--color-text);
  border-color: #FFFFFF;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.35);
}

.marker-cluster-wrapper {
  background: transparent;
  border: none;
}

/* The border is a graphic and keeps the brand ink, but the count inside is
   text on --color-surface: 4.43:1 as --color-primary, just under AA. */
.marker-cluster-icon {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-full);
  background: var(--color-surface);
  color: var(--color-primary-hover);
  border: 2px solid var(--color-primary);
  font-size: 0.88rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--shadow-md);
}

/* DETAIL VIEW */
.sidebar-detail-view {
  background: var(--color-surface);
  overflow-y: auto;
}

.detail-nav-bar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--color-surface-glass);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border-bottom: 1px solid var(--color-border);
  padding: var(--space-3) var(--space-6);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.back-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--color-primary);
  border: none;
  background: var(--color-primary-tint);
  padding: 6px 14px;
  border-radius: var(--radius-full);
  cursor: pointer;
  transition: all var(--transition-fast);
}

.back-btn:hover {
  background: var(--color-primary-solid);
  color: var(--color-on-primary);
}

.back-btn svg {
  width: 15px;
  height: 15px;
}

.detail-hero-section {
  padding: var(--space-6);
  border-bottom: 1px solid var(--color-divider);
}

.detail-title {
  font-size: 1.55rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--color-text);
  margin-bottom: var(--space-2);
}

.detail-badges-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

.detail-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  border-radius: var(--radius-full);
  background: var(--color-surface-offset);
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--color-text-secondary);
}

.detail-badge svg {
  width: 13px;
  height: 13px;
}

.detail-section {
  padding: var(--space-5) var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.detail-block-title {
  font-size: 0.82rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-muted);
  margin-bottom: var(--space-2);
}

.detail-actions-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-3);
}

.detail-action-btn {
  height: 42px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text);
  font-size: 0.88rem;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  cursor: pointer;
  box-shadow: var(--shadow-xs);
  transition: all var(--transition-fast);
}

.detail-action-btn:hover {
  background: var(--color-surface-offset);
  border-color: var(--color-border-subtle);
  transform: translateY(-1px);
}

.detail-action-btn.primary {
  background: var(--color-primary-solid);
  color: var(--color-on-primary);
  border: none;
  box-shadow: 0 4px 12px rgba(190, 90, 54, 0.25);
}

.detail-action-btn.primary:hover {
  background: var(--color-primary-hover);
}

.detail-action-btn svg {
  width: 16px;
  height: 16px;
}

.dish-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.dish-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  background: var(--color-surface-offset);
  border-radius: var(--radius-md);
  font-size: 0.88rem;
  color: var(--color-text);
}

.dish-item svg {
  width: 16px;
  height: 16px;
  color: var(--color-primary);
  flex-shrink: 0;
}

/* PHOTO STRIP */
.photo-strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-2);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.photo-strip img {
  width: 100%;
  height: 100px;
  object-fit: cover;
}

/* RATINGS ROW */
.ratings-row {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.rating-item {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font-size: 0.86rem;
}

.rating-source {
  font-weight: 600;
}

.rating-value {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-weight: 700;
  color: var(--color-gold);
}

.rating-count {
  color: var(--color-text-secondary);
}

.rating-item a {
  margin-left: auto;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--color-primary-hover);
  text-decoration: none;
}

.rating-item a:hover {
  color: var(--color-primary-active);
}

/* .rating-count is more specific than the rule above when the Tripadvisor
   review count renders as a link (it's a plain <span> otherwise, which
   correctly stays styled as a muted count); override color only. */
.rating-item a.rating-count {
  color: var(--color-primary-hover);
}

.rating-item a.rating-count:hover {
  color: var(--color-primary-active);
}

.yelp-logo {
  height: 16px;
  width: auto;
  vertical-align: middle;
}

.ta-bubbles {
  height: 14px;
  width: auto;
  vertical-align: middle;
}

/* Card-level Yelp/Tripadvisor rating badge: the whole badge becomes the
   link (see renderCardNodes in app.js), styled to keep reading as a badge
   rather than a plain text link. */
.card-rating-badge a {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  color: inherit;
  text-decoration: none;
}

/* PROVIDER ATTRIBUTION */
.attribution {
  margin-top: var(--space-5);
  text-align: right;
  font-size: 0.78rem;
  color: var(--color-text-secondary);
}

/* Google Places attribution: official logo, light/dark variants swapped by
   theme. Policy requires the logo (or "Google Maps" text) whenever Places
   data is shown without a Google map. */
.google-logo {
  height: 18px;
  width: auto;
  display: inline-block;
  padding: 10px 10px 5px;
  box-sizing: content-box;
}

.google-logo-dark {
  display: none;
}

[data-theme="dark"] .google-logo-light {
  display: none;
}

[data-theme="dark"] .google-logo-dark {
  display: inline-block;
}

/* VIEW MORE PLACES (end of list, wired to the Load more/nextPageToken path) */
.view-more-btn {
  width: 100%;
  margin: var(--space-2) 0 var(--space-4);
  padding: var(--space-3);
  background: transparent;
  border: none;
  border-top: 1px solid var(--color-border);
  /* color-primary on the sidebar background is 4.13:1 (light) - color-primary-active
     keeps the terracotta family while clearing 4.5:1 in both themes. */
  color: var(--color-primary-active);
  font-size: 0.9rem;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  transition: color var(--transition-fast);
}

.view-more-btn:hover:not(:disabled) {
  color: var(--color-primary-hover);
}

.view-more-btn:disabled {
  /* text-muted on the sidebar background is 2.73:1 (light) - text-secondary
     clears 4.5:1 in both themes. */
  color: var(--color-text-secondary);
  cursor: default;
}

/* EMPTY STATE */
.empty-state {
  text-align: center;
  padding: var(--space-10) var(--space-4);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  color: var(--color-text-secondary);
}

.empty-state-icon {
  width: 48px;
  height: 48px;
  border-radius: var(--radius-full);
  background: var(--color-surface-offset);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text-muted);
}

/* REVIEWS FOLD (collapsed by default - Terra/Yelp display requirements) */
.reviews-fold {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 0 var(--space-3);
}

.reviews-fold > summary {
  display: flex;
  align-items: center;
  min-height: 44px;
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--color-text);
  cursor: pointer;
  list-style: none;
}

.reviews-fold > summary::-webkit-details-marker {
  display: none;
}

.reviews-fold > summary::before {
  content: '';
  width: 7px;
  height: 7px;
  margin-right: var(--space-3);
  border-right: 2px solid var(--color-text-muted);
  border-bottom: 2px solid var(--color-text-muted);
  transform: rotate(-45deg);
  transition: transform var(--transition-fast);
  flex-shrink: 0;
}

.reviews-fold[open] > summary::before {
  transform: rotate(45deg);
}

.review-item {
  padding: var(--space-3) 0;
  border-top: 1px solid var(--color-border-subtle);
  font-size: 0.86rem;
}

.review-item:last-child {
  padding-bottom: var(--space-4);
}

.review-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-1);
}

.review-author {
  font-weight: 600;
  color: var(--color-text);
}

.review-time {
  font-size: 0.78rem;
  /* text-muted here measured 2.92:1 (light) / 3.79:1 (dark) on this surface,
     below AA - text-secondary clears 4.97:1 / 6.42:1 on the same surface. */
  color: var(--color-text-secondary);
}

.review-title {
  font-weight: 600;
  color: var(--color-text);
  margin: var(--space-1) 0;
}

.review-text {
  color: var(--color-text-secondary);
  line-height: 1.5;
}

.review-text a {
  color: var(--color-primary-hover);
  font-weight: 600;
  text-decoration: none;
}

.review-text a:hover {
  color: var(--color-primary-active);
}

/* TRENDING ON TIKTOK */
.tiktok-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-2);
}

.tiktok-card {
  position: relative;
  aspect-ratio: 9 / 16;
  padding: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-surface-offset);
  cursor: pointer;
  transition: transform var(--transition-fast);
}

.tiktok-card:hover {
  transform: translateY(-1px);
}

.tiktok-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.tiktok-card-placeholder {
  width: 100%;
  height: 100%;
  background: var(--color-surface-offset-2);
}

.tiktok-card-caption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--space-2);
  text-align: left;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.75), rgba(0, 0, 0, 0));
}

.tiktok-card-title {
  font-size: 0.7rem;
  font-weight: 600;
  color: #FFFFFF;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.tiktok-card-author {
  font-size: 0.66rem;
  color: rgba(255, 255, 255, 0.85);
}

.tiktok-player {
  aspect-ratio: 9 / 16;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-surface-offset-2);
}

.tiktok-player iframe {
  width: 100%;
  height: 100%;
  border: 0;
}

.tiktok-suggest {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--space-3);
  margin-top: var(--space-3);
  font-size: 0.8rem;
  color: var(--color-text-secondary);
  text-decoration: none;
}

.tiktok-suggest:hover {
  color: var(--color-primary-hover);
  text-decoration: underline;
}

/* RESPONSIVE DESIGN (TABLET & MOBILE) */

/* Nav lockup: full above tablet width, compact at tablet width (this is a
   wider threshold than the .main-layout reflow below - a 1024px iPad
   landscape is already "tablet" for the brand mark even though the sidebar
   doesn't reflow to a single column until 900px), icon-only at 640px (see
   below). */
@media (max-width: 1100px) {
  .brand-lockup[data-logo-slot="full"] {
    display: none;
  }

  .brand-lockup[data-logo-slot="compact"] {
    display: inline-flex;
  }
}

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

  /* One source of truth for the sheet's height: .map-controls-group and the
     Leaflet attribution both have to clear it exactly, and three hand-synced
     copies of 45vh is a bug waiting for the first time it changes. */
  :root {
    /* At 45vh the sheet's own header (title, count, sort, find, filters) left
       about 120px of list below it - one card. The map stays large enough to
       place the results while browsing, but the list is what a phone is
       actually for here. */
    --sheet-height: 58vh;
  }

  /* Opening the filters must not evict the list they filter. The sheet is a
     fixed height with overflow hidden, so an expanded panel pushed #sidebarList
     clean off the bottom - 0px visible at 320x660, and unreachable, since
     nothing there scrolls. The sheet grows instead, the way a real bottom
     sheet does. Everything keyed off --sheet-height follows automatically. */
  :root:has(#filtersDisclosure[open]) {
    --sheet-height: 88vh;
  }

  /* At 88vh there is ~12vh of map left. The controls stack is taller than
     that, and the "Help me choose" pill ends up half behind the sheet's
     rounded top edge, which reads as broken. Both come straight back when the
     panel closes. */
  :root:has(#filtersDisclosure[open]) .map-controls-group,
  :root:has(#filtersDisclosure[open]) .compact-filter-bar {
    display: none;
  }

  .sidebar {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: var(--sheet-height);
    border-left: none;
    border-top: 1px solid var(--color-border);
    border-radius: var(--radius-2xl) var(--radius-2xl) 0 0;
    box-shadow: var(--shadow-xl);
    /* 25 was fine at desktop width, where the sidebar is a separate grid
       column that never overlaps the map. Here it becomes a bottom-sheet
       overlay on top of the map, and #map/.main-layout/.app-shell never
       establish their own stacking context (position:relative with no
       z-index), so Leaflet's internal panes - already documented above as
       reaching z-index 700 - compared directly against 25 and won: the
       entire results list was rendering underneath the map, present and
       tappable (DOM order and hit-testing were fine) but never visible.
       850 clears Leaflet's panes and the floating map controls/filter bar
       (800) the same way .discovery-overlay (900) already does, while
       staying below it so the discovery modal still wins when both exist. */
    z-index: 850;
    transition: height var(--transition-normal);
  }

  /* The sidebar becomes an opaque bottom sheet here, and it is drawn
     above these (z-index 850 vs 800) precisely so the results list is
     visible at all - which left locate-me and both zoom buttons sitting
     underneath it, invisible and untappable on every phone. Raising the
     z-index would not help: the sheet is opaque and geometrically on top,
     so the group has to move above it. */
  /* A full duplicate of the "Help me choose" pill, and it wraps to two lines
     in the crowded sub-900px topbar. */
  .discover-nav-btn {
    display: none;
  }

  /* Header compaction: every row above the list competes with the list itself
     for a phone's vertical space. The subtitle is the same location the topbar
     pill already names, so it goes first. */
  .sidebar-header {
    padding: var(--space-4) var(--space-4) var(--space-3);
  }

  .sidebar-title {
    font-size: 1.15rem;
  }

  .sidebar-subtitle {
    display: none;
  }

  /* An input with flex:1 still refuses to go below its intrinsic size without
     min-width:0, so at 320px "Find in these results..." was pushed past the
     sheet's edge and silently clipped by its overflow-x:hidden. Both children
     may now shrink, and wrap to a second row rather than clip. */
  .sidebar-controls-row {
    flex-wrap: wrap;
  }

  .sidebar-sort-select,
  .sidebar-filter-input {
    min-width: 0;
    flex: 1 1 140px;
  }

  /* A caveat, not a control - it does not need a pill of its own alongside
     them. Every part of the pill treatment has to come off, the
     backdrop-filter and shadow included. */
  .filter-bar-note {
    display: block;
    min-height: 0;
    margin-top: var(--space-2);
    padding: 0;
    border: none;
    background: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    box-shadow: none;
    font-size: 0.75rem;
  }

  /* On phones the disclosure is a static panel inside the results sheet, not a
     popout: there is nothing to anchor a popout to that would not cover the
     list it filters. */
  .filters-disclosure {
    margin-top: var(--space-3);
  }

  .filters-summary {
    min-height: 44px;
    padding: 0 var(--space-4);
    background: var(--color-surface-offset);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    box-shadow: none;
    font-size: 0.86rem;
    font-weight: 600;
    width: max-content;
  }

  /* Capped and scrollable rather than unbounded. At 320x660 every group wraps
     onto two rows and the panel wants ~316px, which even an 88vh sheet cannot
     spare without squeezing the list back down to nothing. Capping it keeps a
     usable list on the smallest phones while leaving every control reachable;
     on anything 390 and wider the panel is shorter than the cap and this never
     applies. */
  .filters-disclosure[open] > .filter-controls {
    position: static;
    width: auto;
    max-height: 34vh;
    overflow-y: auto;
    overscroll-behavior: contain;
    /* Row-wrapped, not the popout's single column: Mode and Units pair up on
       one line, which is two fewer rows of the sheet's scarce height. */
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3) 0 0;
    background: none;
    border: none;
    border-radius: 0;
    box-shadow: none;
  }

  .filters-disclosure > .filter-controls .filter-bar-group {
    justify-content: flex-start;
    width: auto;
  }

  .filter-controls .filter-bar-group-label {
    font-size: 0.75rem;
  }

  .map-controls-group {
    bottom: calc(var(--sheet-height) + var(--space-4));
  }

  /* Leaflet's attribution control is z-index 1000, above the sheet, so the
     OSM credit was painting as a stray bar across the bottom of the results
     list. It has to stay visible (it is the required map credit), so it
     moves onto the map with the rest of the controls. */
  .leaflet-bottom.leaflet-right {
    bottom: var(--sheet-height);
    /* Leaflet's own 1000 also beat .discovery-overlay (900), so lifting the
       credit off the sheet dropped it straight onto the discovery card. It
       only has to clear the map itself now that it sits above the sheet. */
    z-index: 700;
  }
}

/* Discovery card structure. Keyed on EITHER a phone-width viewport OR a short
   one: a landscape phone (844x390, 736x414) is wider than 640px but has less
   vertical room than any portrait phone, and without the height clause it fell
   back to the desktop rules and put "Find places" ~200px below the fold - the
   exact bug the portrait fix was for, on the other orientation. */
/* Phone/short-window cosmetics only. The scroll and pin behaviour itself is
   unconditional above, so nothing here decides whether the primary action is
   reachable - only how the card looks once it is. */
@media (max-width: 640px), (max-height: 600px) {
  /* Bottom padding moves onto .discovery-card-footer (below); the card's own
     padding-bottom would double up with the footer's. */
  .discovery-card {
    padding: var(--space-5) var(--space-5) 0;
    border-radius: var(--radius-xl);
    overflow: hidden;
  }

  .discovery-card-scroll {
    padding-bottom: var(--space-2);
  }

  /* The hairline plus matching card-surface background is what makes the
     wheels read as passing behind a fixed layer instead of the card just
     stopping short. Tighter gap than desktop's space-6 keeps the footer
     compact enough to leave real room for the scroll area above it. */
  .discovery-card-footer {
    flex-shrink: 0;
    gap: var(--space-4);
    background: var(--color-surface);
    border-top: 1px solid var(--color-border);
    /* The env() term is deliberately inert today: index.html has no
       viewport-fit=cover, so iOS keeps the visual viewport clear of the
       home indicator on its own and the inset resolves to 0px. It is here
       so this padding stays correct if cover is ever turned on. */
    padding: var(--space-4) 0 calc(var(--space-4) + env(safe-area-inset-bottom));
  }

  .wheel-viewport-wrap {
    height: 132px;
  }
}

/* 44px touch targets. Keyed on the same 900px breakpoint the bottom-sheet
   layout uses, OR a short viewport: below 900px this is a thumb on glass, not
   a mouse. Keying it on 640px alone left landscape phones (812x375, 844x390)
   with a 32px close button on a modal that opens by itself and has no backdrop
   dismissal, and left tablets holding the relocated filter controls at 27px
   chips - the same ones that mis-selected a neighbour in portrait. */
@media (max-width: 900px), (max-height: 560px) {
  /* 44px touch targets for the persistent filter bar's controls, which live
     over the map, not inside .topbar-center. min-height (not a fixed height)
     on the group: it wraps .segmented-chips, whose own 2px padding needs a
     couple more px than the 44px chip button alone to avoid clipping it. */
  .filter-glass-pill,
  .filter-bar-group {
    min-height: 44px;
  }

  /* Chips abutted inside one track at 40px tall with ~27px of width each
     ("$" vs "$$") mis-selected a neighbour; both dimensions now clear the
     44px minimum touch target. */
  .segmented-chip-btn {
    min-height: 44px;
    min-width: 44px;
  }

  .moment-chevron-btn {
    width: 44px;
    height: 44px;
  }

  /* The discovery card auto-opens on load and backdrop dismissal was
     removed, so this close button is the only way out on phones - it can no
     longer be a 32px target. */
  .discovery-close-btn {
    width: 44px;
    height: 44px;
  }

  .view-more-btn {
    min-height: 44px;
  }

  /* Saved places / theme toggle stay in the topbar at every width, and the
     location pill becomes the sole way to change location on phones - both
     were 42px, under the touch floor. */
  .nav-icon-btn {
    width: 44px;
    height: 44px;
  }

  .location-pill-btn {
    min-height: 44px;
  }
}

/* Landscape phones (844x390, 736x414) have ~290px of card to work with. The
   full header - badge, 1.55rem title, subtitle - plus the pinned footer left
   the wheels a ~28px slot, so all three were scrolled out of sight even
   though the card technically worked. The title alone carries the card here. */
@media (max-height: 560px) {
  .discovery-sparkle-badge,
  .discovery-subtitle,
  .discovery-helper-note {
    display: none;
  }

  .discovery-title {
    font-size: 1.15rem;
  }

  .discovery-card {
    gap: var(--space-2);
  }

  /* Just under two rows: still centers the selection with a slice of its
     neighbours visible above and below, and keeps the 44px row height
     WheelPicker measures its snap targets from. With the scroll region's own
     bottom padding dropped, this is what takes the last ~20px of overflow out
     of the shortest landscape phone, so nothing needs panning at all. */
  .wheel-viewport-wrap {
    height: 76px;
  }

  .discovery-card-scroll {
    padding-bottom: 0;
  }
}

@media (max-width: 640px) {
  .topbar {
    height: 62px;
  }

  .topbar-inner {
    padding: 0 var(--space-4);
  }

  /* The location pill is the owner's original "dead button" complaint, so it
     has to stay reachable on phones, not disappear with the rest of the
     center column - the topbar-search-form duplicates the pill popover's own
     search (both geocode through the same path), so that's what compacts
     away instead. */
  .topbar-center {
    flex: 0 1 auto;
    max-width: none;
    margin: 0;
  }

  .topbar-search-form {
    display: none;
  }

  #locationPillLabel {
    max-width: 34vw;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* Making room for the now-visible pill: the wordmark still works as a
     home link via its icon alone, and the topbar's "Help me choose" is a
     full duplicate of #barDiscoverBtn, which already floats over the map on
     phones - hiding these two here is what actually keeps saved-places and
     the theme toggle from being pushed off-screen, not just the pill. */
  .brand-lockup[data-logo-slot="compact"] {
    display: none;
  }

  .brand-lockup[data-logo-slot="icon"] {
    display: inline-flex;
  }

  /* Anchored to the viewport, not the pill, so a 300px-wide popover never
     overflows off the right edge of a narrow phone regardless of where the
     pill sits in the compacted header. */
  .location-popover {
    position: fixed;
    top: 70px;
    left: var(--space-4);
    right: var(--space-4);
    width: auto;
  }

  /* Stacked wheels never fit a phone: three 132px columns plus their titles
     is ~500px of content in a ~260px scroll region, so the Moment wheel sat
     entirely off-screen. Worse, it could only be reached by dragging one of
     the ~44px title strips - .wheel-viewport owns its drag gesture via
     touch-action:none (a drag on a wheel must spin that wheel, not scroll the
     card), which left ~70% of the scroll region un-pannable. Keeping the
     desktop's three columns is both the iOS picker convention and what makes
     all three wheels fit with no card scrolling at all in portrait. */
  .wheel-picker-group {
    gap: 4px;
    padding: 4px;
  }

  .wheel-title {
    font-size: 0.6rem;
    letter-spacing: 0.02em;
  }

  /* ~90px of label width per column at 320px wide, so long labels wrap inside
     the 44px row rather than truncating - two lines for "Middle Eastern",
     three for the longest in the taxonomy ("Wings / Fried Chicken"). The row
     height must stay 44px: WheelPicker measures it and derives its centering
     pad and snap targets from it. */
  .wheel-item {
    font-size: 0.72rem;
    line-height: 1.15;
    padding: 0 4px;
  }

  .wheel-item.selected {
    font-size: 0.76rem;
  }

  /* The label wrapped to two lines inside the button at every phone width.
     Scoped here so the roomier desktop footer is untouched. */
  .discovery-surprise-btn {
    font-size: 0.85rem;
    padding: 0 var(--space-2);
  }

  .discovery-surprise-btn span {
    white-space: nowrap;
  }

  /* Both buttons are flex containers and their Lucide SVGs are flex items, so
     once the labels stop wrapping the icons become the only thing left that
     can absorb the squeeze - the sparkle was shrinking to 9px against the
     arrow's 24px. */
  .discovery-surprise-btn svg,
  .discovery-primary-btn svg {
    flex-shrink: 0;
    width: 18px;
    height: 18px;
  }

}
