:root {
  /* Light only. Paris street-sign blue as the accent, cool slate neutrals.
     Free, sold out, saved and special keep their own meaning colours. */
  --bg: #fffcf7; /* cream, copper and serif titles: look B (Felix 2026-10-26) */
  --bg-soft: #f6efe3;
  --text: #1f1a17;
  --lm-glow: rgba(255, 196, 61, 0.95);
  --muted: #6a5f55;
  --border: #e9dfcf;
  --accent: #9b5530; /* the splash's copper (look B; was navy #24427a) */
  --brand: var(--accent);
  --act-bg: #e9eef7; /* the round buttons under a name: pale blue, navy icons (Felix picked A) */
  --status: #24427a; /* Now and Open stay navy (Felix: copper looked odd on them) */
  --serif: Georgia, "Times New Roman", serif; /* names of events and places, headings of the brand */
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; /* everything else */
  --logo: #a3653f; /* the Eiffel mark and "ce soir" in the wordmark, as on the splash */
  --gold: #c9a227; /* picks */
  --gold-mid: #b08a12; /* theme weeks: tints */
  --gold-deep: #b8860b; /* theme weeks: pins and icons */
  --gold-ink: #2b2100; /* text on gold */
  --shadow-1: 0 1px 3px rgba(60, 36, 20, 0.22); /* small things floating on the map */
  --shadow-2: 0 4px 18px rgba(60, 36, 20, 0.22); /* menus */
  --r-float: 16px; /* cards, panels and menus over the map */
  --r-inner: 12px; /* photos, notes and tiles inside them */
  --live: #ff4b4b; /* happening now: the red dot, as on a camera recording */
  --open-dot: #3ad57e; /* open now (places): a green one */
  --accent-text: #ffffff;
  --shadow: 0 6px 24px rgba(60, 36, 20, 0.14);
  /* The map, in Google Maps colours: light grey land, white streets with faint edges, mint parks,
     clear blue water; soft yellow along busy shopping streets, pink hospitals, grey campuses. */
  --land: #f4f2ee; /* (a touch warm, so the map meets the cream sheet without a seam) */
  --street-major: #e3e2e9;
  --street-minor: #ffffff;
  --street-casing: #c9c7d1; /* the thin edge of the big streets (sharper, like Google Maps) */
  --street-edge: #d5d3db; /* the thin edge of the small white streets */
  --building: #e9e7ee; /* buildings, from close in (as on Google Maps) */
  --building-edge: #d9d6df;
  --street-outer: #e3e2e9;
  --water: #9fcbf3;
  --park: #c4ecd0;
  --area-busy: #fdf0c6;
  --area-hospital: #f9e0df;
  --area-campus: #ebe8f0;
  --area-school: #eeecf2;
  --area-cemetery: #d7ebdc;
  --area-sport: #cdeedb;
  --rail-track: #c6c3cd; /* train tracks, thin lines (as on Google Maps) */
  --rail-platform: #f8f1dc; /* station platforms, cream */
  --label-street: #4d5156;
  --label-street-halo: #ffffff;
  --label-hood: #3c4043;
  --label-park: #2b7a45;
  --label-park-halo: #ffffff;
  --label-water: #3a74b0; /* river and lake names out of town (bike tours) */
  --boundary: #857d70;
  --map-text: #202124;
  --label-arr: #5f6368;
  /* Names on the map: a thin sharp outline in the ground's colour (as on Google Maps), not a
     blurred glow, so they read crisp. */
  --halo: -1px -1px 0 var(--land), 0px -1px 0 var(--land), 1px -1px 0 var(--land), -1px 0px 0 var(--land), 1px 0px 0 var(--land), -1px 1px 0 var(--land), 0px 1px 0 var(--land), 1px 1px 0 var(--land);
  /* Saved (My list): the accent (copper) (look A, Felix 2026-10-26); gold is
     kept for picks, theme weeks and famous scenes. */
  --star: var(--accent);
  --star-fill: var(--accent); /* behind white text (My list when on) */
  --on-star: #fff;
  --raised: var(--bg); /* a selected tab or segment, above its track */
  --special: #0f766e;
  --free: #1d7a46;
  --event-glyph: #fff; /* the icon inside an event's dot */
  --sold: #b42318;
  --wait: #8a5a00;
  --g-music: #b5267a;
  --g-stage: #6b3fd1;
  --g-art: #d2553a; /* coral: exhibitions stand apart from the teal landmarks and libraries */
  --g-film: #2f62c8;
  --g-food: #b8730a;
  --g-kids: #0f8487;
  --g-learn: #1e8a57;
  --g-other: #5f6b7a;
  --lm: #0b7f8a;
  --lm-text: #086670;
  --panel-width: 380px;
  color-scheme: light;
}

/* Light by default, whatever the device or viewer theme; the map's Dark toggle adds .app-dark.
   (The app's own class, so the claude.ai viewer's theme setting doesn't flip it.) */
:root.app-dark { /* warm: brown-black like the cream's night side, not blue-grey (Felix, 2026-10-26) */
  --bg: #17130f;
  --bg-soft: #221c17;
  --text: #ece6df;
  --lm-glow: rgba(255, 210, 110, 0.85);
  --muted: #a89c8f;
  --border: #3a3029;
  --accent: #e0a27a;
  --status: #9db8f2;
  --act-bg: color-mix(in srgb, var(--accent) 16%, var(--bg));
  --brand: var(--accent);
  --accent-text: #1a1310;
  --shadow: 0 6px 24px rgba(0, 0, 0, 0.55);
  --land: #1f1c19;
  --street-major: #34302b;
  --street-minor: #2e2a26;
  --street-casing: #17140f;
  --street-edge: #191612;
  --building: #2a2622;
  --building-edge: #35302a;
  --street-outer: #34302b;
  --water: #163450;
  --park: #1f3a2b;
  --area-busy: #2f2b24;
  --area-hospital: #3d2b2e;
  --area-campus: #292a33;
  --area-school: #292a33;
  --area-cemetery: #223128;
  --area-sport: #1f3a2b;
  --rail-track: #423b34;
  --rail-platform: #2e2c26;
  --label-street: #b9bec7;
  --label-street-halo: #30353e;
  --label-hood: #dde0e5;
  --label-park: #8fcf9f;
  --label-park-halo: #1f3a2b;
  --label-water: #8ab8e6;
  --boundary: #8a7a6a;
  --map-text: #ece6df;
  --label-arr: #d2cbc2;
  --star: var(--accent);
  --star-fill: var(--accent);
  --on-star: #17130f;
  --raised: #2d251f;
  --special: #5ccfc0;
  --free: #5fd18f;
  --sold: #ff7b6b;
  --wait: #f2b632;
  --g-music: #f07ab8;
  --g-stage: #b49cff;
  --g-art: #ff8f75;
  --g-film: #8ab4f8;
  --g-food: #f2b94b;
  --g-kids: #5fd0d0;
  --g-learn: #5fd18f;
  --g-other: #a3acb9;
  --event-glyph: #13161b; /* dark icons on the lighter dots */
  --lm: #4cc0cb;
  --lm-text: #7fd6de;
  --logo: #e0a878;
  --shadow-1: 0 1px 3px rgba(0, 0, 0, 0.5);
  --shadow-2: 0 4px 18px rgba(0, 0, 0, 0.55);
  color-scheme: dark;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; } /* beats display: flex on hidden blocks */

/* Type sizes: 1rem is 14px (87.5% of the browser's 16px, and it follows the reader's own text
   size setting); every rem in this file counts from it. Body text is 0.875rem (12.25px).
   (It used to read "html, body { font: 0.875rem … }", which gave the same two sizes by accident.) */
html {
  height: 100%;
  font-size: 87.5%;
}
@media (max-width: 720px) { html { font-size: 93.75%; } } /* phones: a touch bigger (15 px), Felix 2026-10-26 */
/* The map always fills the window: the page itself never scrolls (no scrollbar over the map's
   buttons); the panel's list and the cards scroll inside. */
html, body { overflow: hidden; overscroll-behavior: none; }
body {
  margin: 0;
  height: 100%;
  font: 0.875rem/1.45 var(--sans);
  color: var(--text);
  background: var(--bg);
}

#map { position: fixed; inset: 0 0 0 var(--panel-width); z-index: 0; } /* (its panes stay under the panel) */

.muted { color: var(--muted); }
/* Links in the app's own navy, not the browser's blue and purple (any class of theirs wins). */
:where(a) { color: var(--accent); }

/* ---------- panel ---------- */

/* Computers: one flat panel from top to bottom on the left edge, the map right beside it and the
   search bar floating on its top, as Google Maps (no rounded card on a second white layer). */
.panel {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: var(--panel-width);
  display: flex;
  flex-direction: column;
  background: var(--bg);
  box-shadow: 1px 0 6px rgba(60, 36, 20, 0.12);
  z-index: 1000;
  overflow: hidden;
  overflow: clip; /* not even scrolled by code: a chip row's hidden label once slid the whole sheet sideways */
}

.sheet-grip, .view-switch { display: none; }

.panel-header { padding: 16px 16px 8px; }
.title-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.panel-header h1 { margin: 0; font-size: 1.25rem; letter-spacing: -0.01em; text-wrap: balance; }

.banner {
  margin: 10px 0 0;
  padding: 8px 10px;
  border-radius: 8px;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  font-size: 0.8125rem;
}
.banner code { font-size: 0.75rem; }

/* One scrolling line per chip row keeps the list visible; the fade hints there's more. */
.chip-row {
  display: flex;
  flex-wrap: nowrap;
  gap: 6px;
  padding: 0 16px 8px;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
  mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
}
.chip-row::-webkit-scrollbar { display: none; }
.chip { flex: none; }

.chip:focus-visible, .button:focus-visible, .seg:focus-visible,
.event-list li:focus-visible, .star:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.chip, .button {
  border: 1px solid var(--border);
  background: var(--bg-soft);
  color: var(--text);
  border-radius: 999px;
  padding: 5px 11px;
  font: inherit;
  font-size: 0.8125rem;
  cursor: pointer;
  white-space: nowrap;
}
.chip[aria-checked="true"], .chip[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-text);
}
.chip { position: relative; } /* keeps its screen-reader text (.sr-only) inside the chip row */
.chip .n { opacity: 0.7; font-size: 0.7188rem; margin-left: 3px; font-variant-numeric: tabular-nums; }
.chip.empty { opacity: 0.45; }
.button[aria-expanded="true"] { border-color: var(--accent); }

.filter-bar { display: flex; gap: 8px; padding: 0 16px 10px; border-bottom: 1px solid var(--border); }
.filter-bar input { flex: 1; min-width: 0; }

input[type="search"] {
  width: 100%;
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-soft);
  color: var(--text);
  font: inherit;
}

.more-filters {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 10px 16px 12px;
  border-bottom: 1px solid var(--border);
}

.toggles { display: flex; flex-wrap: wrap; gap: 4px 16px; }

/* Two modes: events or places. Controls that only make sense in one are hidden in the other. */
body[data-mode="places"] .events-only, body[data-mode="places"] #open-chat { display: none !important; }
body:not([data-mode="places"]) .places-only { display: none !important; }

/* Events | Places: tabs as on Google Maps' place cards (Felix picked B, 2026-10-25): an icon and
   a word, a line in the accent colour under the one picked, a thin rule across the panel. */
.mode-switch {
  display: flex;
  margin: 10px -16px 0;
  border-bottom: 1px solid var(--border);
}
.mode-switch button {
  flex: 1;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  border: none;
  background: none;
  color: var(--muted);
  padding: 10px 10px 11px;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.mode-switch button:hover { color: var(--text); }
.mode-switch button[aria-selected="true"] { color: var(--brand); }
.mode-switch button[aria-selected="true"]::after {
  content: ""; position: absolute; left: 22%; right: 22%; bottom: -1px; height: 3px;
  border-radius: 3px 3px 0 0; background: var(--brand);
}
.mode-switch .tab-ic { width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.mode-switch button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: 6px; }
.chip[aria-pressed] .swatch, .chip .swatch { width: 8px; height: 8px; display: inline-block; vertical-align: 0; }
.event-list .title .swatch { display: inline-block; vertical-align: 1px; margin-right: 2px; }

/* Landmarks: colour icons in the style of emoji, under the events; name on hover/tap.
   The drawn shape and an unseen box in the middle catch the pointer (.lm-hit), so a thin tower
   is easy to hit and the empty corners never block the map. */
.leaflet-marker-icon.landmark { pointer-events: none !important; cursor: default; }
/* On the Places tab a monument is a place you can open: a soft glow, gently breathing. */
body[data-mode="places"] .leaflet-marker-icon.landmark .lm-icon {
  cursor: pointer;
  filter: drop-shadow(0 0.5px 0.5px rgba(0, 0, 0, 0.45)) drop-shadow(0 0 3px var(--lm-glow)) drop-shadow(0 0 6px var(--lm-glow));
  animation: lm-glow 2.8s ease-in-out 1; /* (once, then still: no pulse that never stops) */
}
@keyframes lm-glow { 50% { filter: drop-shadow(0 0.5px 0.5px rgba(0, 0, 0, 0.45)) drop-shadow(0 0 1px var(--lm-glow)) drop-shadow(0 0 2px var(--lm-glow)); } }
@media (prefers-reduced-motion: reduce) { body[data-mode="places"] .leaflet-marker-icon.landmark .lm-icon { animation: none; } }
.lm-icon {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
  filter: drop-shadow(0 0.5px 0.5px rgba(0, 0, 0, 0.45));
  pointer-events: visiblePainted;
}
/* On the dark map, a pale halo keeps darker icons (the tower, the column) visible. */
.app-dark .lm-icon { filter: drop-shadow(0 0 1px rgba(255, 255, 255, 0.7)) drop-shadow(0 1px 2px rgba(0, 0, 0, 0.6)); }
.lm-icon .lm-hit { fill: transparent; stroke: none; }
.lm-tip { font-weight: 600; }
/* The monument's name under its drawing (closer in), in the map's own text grey, like Google Maps. */
.lm-name {
  position: absolute;
  left: 50%;
  top: 100%;
  transform: translateX(-50%);
  margin-top: 1px;
  white-space: nowrap;
  pointer-events: none;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.15;
  color: var(--label-hood);
  text-shadow: var(--halo);
}

.section-label {
  margin: 0;
  font-size: 0.7188rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--muted);
}

/* ---------- map display: neutral switches on the map, apart from the event filters ---------- */

.map-tools {
  position: fixed;
  top: calc(12px + env(safe-area-inset-top, 0px));
  right: 56px;
  z-index: 1001;
  display: flex;
  gap: 6px;
  align-items: center;
}
.map-btn {
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  border-radius: 8px;
  padding: 6px 11px;
  font: inherit;
  font-size: 0.8125rem;
  box-shadow: var(--shadow);
  cursor: pointer;
  white-space: nowrap;
}
a.map-btn { text-decoration: none; display: inline-block; } /* (About: a link that looks like the buttons) */
.map-btn[aria-expanded="true"] { background: var(--bg-soft); }
.map-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* EN | FR: event text translated or original */
.lang-switch { display: flex; padding: 2px; gap: 2px; cursor: default; }
.lang-switch[hidden] { display: none; }
.lang-switch button {
  border: 0; background: none; color: var(--muted); font: inherit; font-size: 0.75rem; font-weight: 600;
  padding: 4px 7px; border-radius: 6px; cursor: pointer;
}
.lang-switch button[aria-pressed="true"] { background: var(--accent); color: var(--accent-text); }
.lang-switch button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.tr-status { margin: 0; padding: 0 16px 8px; font-size: 0.7812rem; }
/* Short notes from the map buttons, under them (so a longer one never squeezes the row). */
.map-tools { position: fixed; pointer-events: none; } /* the empty part lets the map through */
.map-tools > * { pointer-events: auto; }
/* The buttons never run under the panel (tablets) or off the screen (French, large text):
   they wrap onto a second line instead. */
@media (min-width: 721px) {
  .map-tools { left: calc(var(--panel-width) + 12px); flex-wrap: wrap; justify-content: flex-end; }
  /* As on phones: every button an icon with its word under it. */
  .map-tools .map-btn:not(.lang-switch) { display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px; padding: 4px 10px; min-width: 52px; line-height: 1.1; }
  .map-tools .map-btn .cap { display: block; font-size: 0.6875rem; font-weight: 400; color: var(--muted); white-space: nowrap; }
  .map-tools .map-btn .btn-text { display: none; }
  .map-tools .lang-switch { align-self: stretch; } /* as tall as the buttons beside it */
  .map-tools .saved-btn { position: relative; }
  .map-tools .saved-btn .n { position: absolute; top: 2px; right: 8px; margin: 0; font-size: 0.6875rem; font-weight: 700; }
  /* The zoom buttons in the same style as the toolbar beside them. */
  .leaflet-top.leaflet-right .leaflet-control-zoom { margin-top: 12px; border: 1px solid var(--border) !important; border-radius: 8px; overflow: hidden; box-shadow: var(--shadow); }
  .leaflet-control-zoom a { width: 34px; height: 34px; line-height: 34px; }
}
.map-status {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  max-width: min(320px, calc(100vw - 32px));
  font-size: 0.7812rem;
  color: var(--text);
  background: var(--bg);
  border-radius: 8px;
  padding: 6px 10px;
  box-shadow: var(--shadow);
}
.map-status:empty { display: none; }
/* Notes (location, toilets, water…) start left of the button card, never under it. */
.map-tools .map-status { right: 58px; max-width: min(420px, calc(100vw - 88px)); white-space: normal; }
@media (max-width: 720px) { .map-tools .map-status { right: 56px; max-width: calc(100vw - 76px); } }

.layers-panel {
  position: fixed;
  top: calc(52px + env(safe-area-inset-top, 0px));
  right: 56px;
  z-index: 1001;
  width: min(300px, calc(100vw - 32px));
  max-height: calc(100% - 120px);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 14px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow);
}
.layers-panel .note { margin: 0; }
.layers-panel .poi-categories { grid-template-columns: 1fr; gap: 4px; padding: 2px 0 0 4px; }
.layers-panel input[type="checkbox"]:not([role="switch"]) { accent-color: var(--boundary); }

/* On/off switches in neutral grey: they change the drawing, not the results. */
.switch { display: flex; align-items: center; gap: 10px; }
.switch input {
  appearance: none;
  flex: none;
  width: 34px;
  height: 20px;
  margin: 0;
  border-radius: 999px;
  background: var(--border);
  position: relative;
  cursor: pointer;
  transition: background 0.15s;
}
.switch input::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--bg);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
  transition: transform 0.15s;
}
.switch input:checked { background: var(--accent); }
.switch input:checked::after { transform: translateX(14px); }
.switch input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
label { cursor: pointer; }
input[type="checkbox"] { accent-color: var(--accent); }


.poi-categories {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px 12px;
  padding: 8px 0 0 2px;
}
.poi-categories label { display: flex; align-items: center; gap: 6px; }

.swatch {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex: none;
  border: 1.5px solid #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);
}


.note { margin: 6px 0 0; font-size: 0.7812rem; }

/* ---------- event details (phones) ---------- */

.panel.has-detail > :not(#detail):not(.sheet-grip) { display: none; }
.detail { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior-x: contain; }
.detail-bar {
  position: sticky;
  top: 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 16px;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
}
.detail-body { padding: 12px 16px 24px; }
.detail-body img { display: block; width: 100%; height: 210px; object-fit: cover; border-radius: 12px; }
.detail-body h2 { margin: 12px 0 4px; font-size: 1.25rem; line-height: 1.25; text-wrap: balance; }
.detail-body h3 {
  margin: 16px 0 4px;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}
.detail-body p { margin: 4px 0; }
.detail-when { font-weight: 600; font-size: 0.9375rem; }
.detail-body .tags { color: var(--muted); font-size: 0.7812rem; margin-top: 12px; }
.date-list { list-style: none; margin: 0; padding: 0; font-variant-numeric: tabular-nums; }
.date-list li { display: flex; justify-content: space-between; gap: 12px; padding: 5px 0; border-bottom: 1px solid var(--border); }
.detail-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 18px; }
.detail-actions .button { text-decoration: none; display: inline-flex; align-items: center; }
.detail .save {
  border: 1px solid var(--border);
  background: var(--bg-soft);
  color: var(--text);
  border-radius: 999px;
  padding: 5px 11px;
  font: inherit;
  font-size: 0.8125rem;
  cursor: pointer;
}
.detail .save[aria-pressed="true"] { border-color: var(--star); color: var(--star); }

/* ---------- chat ---------- */

.ask {
  flex: none;
  border: none;
  border-radius: 999px;
  padding: 5px 12px;
  background: var(--accent);
  color: var(--accent-text);
  font: inherit;
  font-size: 0.8125rem;
  font-weight: 600;
  cursor: pointer;
}
.ask:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }
.title-row h1 { flex: 1; min-width: 0; }

.panel.has-chat > :not(#chat):not(.sheet-grip):not(#detail) { display: none; }
.chat { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.chat .detail-bar { position: static; }
.chat-log { flex: 1; min-height: 0; overflow-y: auto; padding: 12px 16px; display: flex; flex-direction: column; gap: 10px; }
.bubble { max-width: 92%; padding: 8px 12px; border-radius: 14px; line-height: 1.45; }
.bubble p { margin: 4px 0; }
.bubble ul { margin: 4px 0; padding-left: 18px; }
.bubble li { margin: 4px 0; }
.bubble.user { align-self: flex-end; background: var(--accent); color: var(--accent-text); border-bottom-right-radius: 4px; }
.bubble.assistant { align-self: flex-start; background: var(--bg-soft); border-bottom-left-radius: 4px; }
.bubble .link { font-weight: 600; }
.bubble a { color: var(--accent); }
.thinking { color: var(--muted); }
.thinking::after { content: ""; animation: dots 1.2s steps(4) infinite; }
@keyframes dots { 0% { content: ""; } 25% { content: "."; } 50% { content: ".."; } 75% { content: "..."; } }

.chat-suggestions { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 16px 10px; }
.chat-suggestions p { width: 100%; margin: 0 0 4px; font-size: 0.7812rem; }
.chat-suggestions .chip { white-space: normal; text-align: left; }

.chat-form { display: flex; gap: 8px; align-items: flex-end; padding: 10px 16px 4px; border-top: 1px solid var(--border); }
.chat-form textarea {
  flex: 1;
  min-width: 0;
  resize: none;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg-soft);
  color: var(--text);
  font: inherit;
}
.send {
  border: none;
  border-radius: 999px; /* (a pill, as Details and every other main button) */
  padding: 9px 14px;
  background: var(--accent);
  color: var(--accent-text);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.chat-note { margin: 0; padding: 0 16px 10px; font-size: 0.7188rem; }
.link {
  border: none;
  background: none;
  padding: 0;
  font: inherit;
  color: var(--accent);
  text-align: left;
  cursor: pointer;
  text-decoration: underline;
}

@media (prefers-reduced-motion: reduce) { .thinking::after { animation: none; content: "…"; } }

/* ---------- results ---------- */

.results { flex: 1; overflow-y: auto; padding: 4px 0 8px; }
.results h2 {
  margin: 0;
  padding: 10px 16px 6px;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}

.event-list { list-style: none; margin: 0; padding: 0; }
.event-list li {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  padding: 10px 8px 10px 16px;
  border-top: 1px solid var(--border);
  cursor: pointer;
}
.event-list .body { flex: 1; min-width: 0; }
/* Hover only with a mouse: on touch screens a tapped row would stay grey. */
@media (hover: hover) { .event-list li:hover { background: var(--bg-soft); } }
.event-list li:focus { outline: none; }
.event-list li:focus-visible { background: var(--bg-soft); }
.event-list li:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.event-list .title { font-weight: 600; font-size: 1.0625rem; }
/* Names of events and places in the serif everywhere: list, card, picks (Felix, 2026-10-26). */
.event-list .title .ttl, .preview-title, .pick-card-title { font-family: var(--serif); font-weight: 700; letter-spacing: -0.005em; }
.event-list .meta { font-size: 0.7812rem; color: var(--muted); font-variant-numeric: tabular-nums; }
/* Titles: one look whatever the organiser typed. A small "series" label, then the title,
   two lines at most in lists (the details show it whole). */
.kicker {
  display: block;
  margin-bottom: 1px;
  font-size: 0.6562rem;
  font-weight: 650;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
}
.ttl { font-weight: 650; }
.event-list .title .ttl, .preview-title .ttl {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}
.event-list .title .ttl { -webkit-line-clamp: 1; line-clamp: 1; } /* (a list row's title: one line) */
/* Times and hours in figures of one width, so they line up from row to row. */
table.week-hours td, .preview-meta, .facts .when-line, .pick-card-text { font-variant-numeric: tabular-nums; }
/* Short last lines: no lone word left on the last line of a note or a pick's reason. */
.hidden-note span, .welcome, .facts p, .pick-why, .ed-why { text-wrap: pretty; }
.pick-card-why > span { text-wrap: balance; }
/* "Getting there": a line breaks only between its pieces ("· 4 min walk · exit 2, pl. Saint-Michel"), never inside one. */
.stations-row .nw { white-space: nowrap; }
.event-list .meta .badge, .preview-meta .badge { margin-left: 0; } /* (a space before each: see badges()) */
.price { margin: 4px 0; }
/* Descriptions keep their paragraphs; in popups a long one folds after six lines. */
.about { white-space: pre-line; }
.about.folded { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 6; line-clamp: 6; overflow: hidden; }
button.link.more { border: 0; background: none; padding: 0; font: inherit; font-size: 0.8125rem; color: var(--accent); cursor: pointer; }
.note { font-size: 0.7812rem; margin: 2px 0 4px; }
/* Claude's compact line of days and hours, under the next date. */
.times { margin: 2px 0 4px; font-weight: 500; }

.price strong { color: var(--text); font-weight: 700; }
.event-list .when, .when-line .when, .preview-meta .when { color: var(--text); font-weight: 650; }
/* "● Now" and "Free" tags in front of the time. */
.pill {
  display: inline-block;
  margin-right: 6px;
  padding: 0 7px;
  border-radius: 999px;
  font-size: 0.6875rem;
  font-weight: 700;
  line-height: 17px;
  vertical-align: 1px;
  white-space: nowrap;
}
.pill.now { background: var(--status); color: #fff; }
.pill.free { background: var(--free); color: var(--bg); }

.star {
  flex: none;
  width: 36px;
  height: 36px;
  border: none;
  border-radius: 50%;
  background: none;
  color: var(--muted);
  font-size: 1.188rem;
  line-height: 1;
  cursor: pointer;
}
.star[aria-pressed="true"] { color: var(--star); }
@media (hover: hover) { .star:hover { background: var(--bg-soft); } }
.event-list .empty { cursor: default; color: var(--muted); }
/* Sold out: grey text, but keep the badge at full strength so it stands out. */
.event-list li.is-sold-out .title, .event-list li.is-sold-out .meta, .event-list li.is-sold-out .when { color: var(--muted); }
.event-list li.more-row { justify-content: center; cursor: default; }
.event-list li.more-places { padding-right: 16px; }
.event-list li.list-divider { cursor: default; padding-top: 14px; font-size: 0.75rem; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.event-list li.list-divider:hover { background: none; }

.badge {
  display: inline-block;
  margin-left: 0; /* spaced by a space before it (badges()), so it lines up when it starts a line */
  padding: 0 6px;
  border-radius: 4px;
  font-size: 0.6875rem;
  font-weight: 600;
  background: var(--free);
  color: var(--bg);
  vertical-align: 1px;
}

.badge.sold { background: var(--sold); color: var(--bg); }
.badge.wait { background: var(--wait); color: var(--bg); }
/* Free only with a paid entry ticket: grey, not the green Free. */
.badge.cond { background: transparent; color: var(--muted); box-shadow: inset 0 0 0 1px var(--border); }
/* The booking page after the booking line: "Booking required · Book ↗", the line's own size. */
.book-link { color: var(--muted); white-space: nowrap; }
.book-link a { color: var(--accent); font-weight: 600; text-decoration: none; }
.book-link a:hover, .book-link a:focus-visible { text-decoration: underline; }
.tickets a { color: var(--accent); }
.badge.special { background: var(--special); color: var(--bg); }
.badge.now { background: var(--status); color: #fff; }
/* "Now": a red dot before the word in its tag; "Open" (places): a green one. */
.badge.now::before, .pill.now::before {
  content: ""; display: inline-block; width: 0.55em; height: 0.55em; border-radius: 50%;
  background: var(--live); margin-right: 0.35em; vertical-align: 0.08em;
}
.badge.now.open::before { background: var(--open-dot); }
.late-museums { margin: 6px 16px 4px; padding: 10px 12px; border-radius: 10px; background: var(--bg-soft); font-size: 0.8125rem; }
.late-museums h3 { margin: 0 0 4px; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--special); }
.late-museums p { margin: 4px 0; }
.late-museums .small { font-size: 0.7188rem; }
/* The info boxes above the Places list: the title folds the box (the first one starts open). */
.kind-boxes .kind-box > summary { list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.kind-boxes .kind-box > summary::-webkit-details-marker { display: none; }
.kind-boxes .kind-box > summary::after { content: ""; width: 7px; height: 7px; border: solid var(--muted); border-width: 0 2px 2px 0; transform: rotate(45deg); margin: -4px 4px 0 0; flex: none; }
.kind-boxes .kind-box[open] > summary::after { transform: rotate(-135deg); margin-top: 4px; }
.kind-boxes .kind-box:not([open]) > summary h3 { margin: 0; }
.kind-boxes .kind-box > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.badge.lang { background: var(--muted); color: var(--bg); letter-spacing: 0.03em; }


/* ---------- markers & popups ---------- */

.hit { width: 100%; height: 100%; display: grid; place-items: center; cursor: pointer; }
.dot {
  width: var(--dot, 14px);
  height: var(--dot, 14px);
  border-radius: 50%;
  border: 1.5px solid #fff;
  box-shadow: 0 1px 3px rgba(40, 32, 20, 0.3);
}
.dot.event { background: var(--g-other); }
/* The icon in the middle of each dot (as on Google Maps), once the dots are big enough to hold
   one: events and places from zoom 13 (.ev-glyphs / .pl-glyphs, set in applyZoomScale). */
.dot { display: grid; place-items: center; }
.dot .glyph { display: none; width: 64%; height: 64%; fill: #fff; pointer-events: none; }
.dot.event .glyph { fill: var(--event-glyph); }
.ev-glyphs .dot.event .glyph, .pl-glyphs .dot.place .glyph { display: block; }
/* The Key's dots, bigger, with the same icons. */
.legend > span > i.key-dot.key-dot { width: 18px; height: 18px; display: grid; place-items: center; border-radius: 50%; border: 1.5px solid #fff; box-shadow: 0 0 0 1px rgba(0, 0, 0, .12); }
.legend > span > i.key-dot .glyph { width: 12px; height: 12px; fill: #fff; }
.legend > span > i.tip-group.key-dot .glyph { fill: var(--event-glyph); }
.dot.place { width: var(--place-dot, 11px); height: var(--place-dot, 11px); }
.g-music { --g: var(--g-music); }
.g-stage { --g: var(--g-stage); }
.g-art { --g: var(--g-art); }
.g-kids { --g: var(--g-kids); }
.g-learn { --g: var(--g-learn); }
.g-film { --g: var(--g-film); }
.g-food { --g: var(--g-food); }
.g-other { --g: var(--g-other); }
.dot.event[class*="g-"] { background: var(--g); }
/* Free: a green ring outside the white edge. On now (open now): a still ring in the dot's own
   colour, on single dots and groups alike. It pulses once as it appears, then keeps still
   (Felix, 2026-10-25: a pulse that never stops is tiring, older people most). */
.dot.live { position: relative; }
.dot.live::after, .place-pin.live::before {
  content: "";
  position: absolute;
  inset: -5px;
  border-radius: 50%;
  border: 2px solid var(--g); /* (in the dot's own colour) */
  opacity: 0.75;
  animation: live-once 1.6s ease-out -1.6s; /* (drawn already finished: still) */
  pointer-events: none;
}
/* After a step forward (app.js, playRings) the rings drawn then pulse; rings already there
   don't play again, as their pulse counts from when they were drawn. */
.rings-play .dot.live::after, .rings-play .place-pin.live::before { animation-delay: 0s; }
/* A place's photo pin: the ring round its photo (34 px; 28 small; 24 tiny). */
.place-pin.live::before { --pp: 34px; inset: auto; left: -6px; top: 50%; width: calc(var(--pp) + 12px); height: calc(var(--pp) + 12px); margin-top: calc(var(--pp) / -2 - 6px); box-sizing: border-box; border-color: var(--ring); }
.place-pin.small.live::before { --pp: 28px; }
.place-pin.tiny.live::before { --pp: 24px; }
.place-pin.few.live::before { display: none; } /* (its dot has the ring) */
@keyframes live-once {
  from { transform: scale(0.6); opacity: 0; }
  45% { transform: scale(1.3); opacity: 0.6; }
  to { transform: scale(1); opacity: 0.75; }
}
@media (prefers-reduced-motion: reduce) {
  .dot.live::after, .place-pin.live::before { animation: none; }
}
/* Saved events: gold stars, a little bigger than the dots. */
.star-mark {
  width: calc(max(var(--dot, 14px), 14px) * 1.5);
  height: calc(max(var(--dot, 14px), 14px) * 1.5);
  fill: var(--star);
  stroke: #fff;
  stroke-width: 1.6;
  stroke-linejoin: round;
  filter: drop-shadow(0 1px 1.5px rgba(40, 32, 20, 0.35));
  overflow: visible;
}
.star-mark.live { animation: star-pulse 1.6s ease-in-out -1.6s; } /* (once, as the rings) */
.rings-play .star-mark.live { animation-delay: 0s; }
@keyframes star-pulse { 50% { transform: scale(1.15); } }
@media (prefers-reduced-motion: reduce) { .star-mark.live { animation: none; } }
/* Saved view: the date and filter chips don't apply, so they step back (a tap leaves the view). */
.saved-view .chip[data-when], .saved-view #type-chips .chip:not([data-saved-chip]), .saved-view #filters-toggle { opacity: 0.45; }
.saved-view .chip[data-when][aria-checked="true"] { background: transparent; color: var(--text); border-color: var(--border); }
/* The ★ map button: gold when only saved events are shown. */
.saved-btn { color: var(--star); font-weight: 650; }
.saved-btn .n { color: var(--text); font-weight: 600; }
.saved-btn[aria-pressed="true"] { background: var(--star-fill); border-color: var(--star-fill); color: var(--on-star); }
.saved-btn[aria-pressed="true"] .n { color: var(--on-star); }
.saved-sample { font-style: normal; color: var(--star); margin-right: 6px; }
/* Toilets and drinking water: small icons, growing a little with zoom. */
.amenity { display: grid; place-items: center; cursor: pointer; }
.amenity svg { width: var(--amenity, 18px); height: var(--amenity, 18px); filter: drop-shadow(0 1px 1.5px rgba(40, 32, 20, 0.35)); }
.am-popup .actions { margin-top: 6px; }
.am-key { display: inline-flex; gap: 3px; vertical-align: -3px; margin-right: 6px; }
.am-key svg { width: 15px; height: 15px; }
/* You are here: a small figure (the SVG in app.js) with a pulse on the ground under its feet.
   The ◎ button is blue while following you. */
.you-are-here { pointer-events: none !important; }
.you-pulse { transform-origin: 18px 32.5px; animation: here-pulse 2s ease-out infinite; }
@keyframes here-pulse { from { transform: scale(0.5); opacity: 0.55; } to { transform: scale(1.6); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .you-pulse { animation: none; opacity: 0.3; } }
/* Same marks in the key. */
.tip-group.ring-free { box-shadow: 0 0 0 2px var(--free); }
.tip-group.ring-live { box-shadow: 0 0 0 2px var(--bg), 0 0 0 3.5px var(--g); }
.tip-group { display: inline-block; width: 9px; height: 9px; margin-right: 6px; border-radius: 50%; background: var(--g); vertical-align: 0; }

/* Hover previews (desktop) */
.leaflet-tooltip.event-tip {
  width: max-content;
  max-width: 260px;
  white-space: normal;
  padding: 6px 9px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
  color: var(--text);
  box-shadow: var(--shadow);
  font-size: 0.7812rem;
  line-height: 1.35;
}
.leaflet-tooltip.event-tip::before { display: none; }
/* The hover card (computers): photo down the left, text beside it, a pointer to the dot. */
.leaflet-tooltip.hover-tip { max-width: none; padding: 8px; border: 0; border-radius: 12px; font-size: 0.78rem; }
.leaflet-tooltip.hover-tip::after {
  content: ""; position: absolute; left: 50%; bottom: -6px; width: 12px; height: 12px;
  background: var(--bg); transform: translateX(-50%) rotate(45deg); border-radius: 0 0 3px 0;
}
.hover-card { display: flex; gap: 12px; width: 304px; } /* (wide enough for Now · Ends in … · Free · ♿ on one line) */
.hover-card .row-thumb {
  position: relative; flex: none; width: 76px; min-height: 64px; align-self: stretch;
  border-radius: 8px; overflow: hidden; display: grid; place-items: center;
  background: color-mix(in srgb, var(--g, var(--g-other)) 14%, var(--bg));
}
.hover-card .row-thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hover-card .hc-text { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 2px; }
.hover-card strong { font-size: 0.86rem; line-height: 1.25; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.hover-card .hc-sub { color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hover-card .hc-sub .when { color: inherit; }
.hover-card .tip-group { width: 8px; height: 8px; margin-right: 5px; }
.hover-card .hc-text { gap: 3px; }
/* The marks: a little room between them, and between two lines if they still wrap. */
.hover-card .marks-row { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 5px; margin: 0; } /* (the same ~6 px between all the lines' letters, the badges too; Felix, 2026-10-26) */
:root.app-dark .leaflet-tooltip.hover-tip, :root.app-dark .leaflet-tooltip.hover-tip::after { background: var(--raised); } /* (dark: the card and its pointer stand off the dark map) */

/* Short names next to single events once zoomed in */
.event-label span {
  display: inline-block;
  max-width: calc(var(--label, 11.5px) * 13);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: var(--label, 11.5px);
  font-weight: 550;
  color: var(--map-text);
  text-shadow: var(--halo);
  cursor: pointer;
}

/* The place's name above several events at one spot, once zoomed in (a small note with a tail
   pointing down at the group; taps go through to the dots) */
.spot-label { pointer-events: none; }
.spot-label span {
  position: absolute;
  left: 0;
  bottom: var(--lift, 14px);
  transform: translateX(-50%);
  max-width: calc(var(--label, 11.5px) * 15);
  padding: 2px 8px 3px;
  border-radius: 999px;
  background: var(--bg);
  border: 1px solid var(--border);
  box-shadow: 0 1px 3px rgba(40, 32, 20, 0.18);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: calc(var(--label, 11.5px) * 0.82);
  font-weight: 650;
  line-height: 1.3;
  color: var(--map-text);
}
.spot-label span::before { content: "📍"; font-size: 0.85em; margin-right: 3px; }

/* A busy place close in: a round photo dot on the spot, ringed in its events' colour, with
   the number as a badge and the name beside it (like a place on Google Maps, like the dots) */
.place-pin-icon { overflow: visible; }
.place-pin {
  --ring: var(--g, var(--accent));
  position: absolute;
  left: 0;
  top: 0;
  transform: translate(-17px, -50%);
  display: flex;
  align-items: center;
  gap: 9px; /* (past the 4.5 px ring, as far from the name as a plain dot) */
  max-width: 220px;
  color: var(--map-text);
  white-space: nowrap;
  cursor: pointer;
}
:is(.place-pin, .sc-ban) .row-thumb {
  position: relative; overflow: hidden; display: grid; place-items: center;
  background: color-mix(in srgb, var(--g, var(--g-other)) 14%, var(--bg));
}
:is(.place-pin, .sc-ban) .row-thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.place-pin .row-thumb {
  width: 34px; height: 34px; flex: none; border-radius: 50%;
  box-shadow: 0 0 0 2px var(--bg), 0 0 0 4.5px var(--ring), 0 1px 5px rgba(0, 0, 0, 0.35);
}
.place-pin.small { transform: translate(-14px, -50%); max-width: 180px; }
.place-pin.small .row-thumb { width: 28px; height: 28px; }
/* Two or three places together: a small dot on the spot, the busiest one's name and "+1" */
.place-pin.few { transform: translate(calc(var(--dot, 14px) / -2), -50%); gap: 6px; }
.place-pin .pp-ico { background: var(--ring); }
.place-pin .pp-ico .glyph { display: block; width: 58%; height: 58%; fill: var(--event-glyph); }
.place-pin .pp-stack { position: relative; flex: none; display: grid; }
:is(.place-pin .pp-stack, .ev-stack)::before {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: var(--dot, 14px); height: var(--dot, 14px); border-radius: 50%; box-sizing: border-box;
  background: color-mix(in srgb, var(--g) 55%, var(--bg)); border: 1.5px solid #fff;
  transform: translate(calc(-50% + 4px), calc(-50% - 4px));
}
.place-pin .pp-stack .dot { position: relative; }
.place-pin .pp-t { min-width: 0; display: flex; flex-direction: column; line-height: 1.2; }
.place-pin :is(b, small, .pp-more) {
  overflow: hidden; text-overflow: ellipsis;
  text-shadow: var(--halo);
}
.place-pin b { font-size: 0.8125rem; font-weight: 650; }
.place-pin.small b { font-size: 0.75rem; }
.place-pin small { font-size: 0.6875rem; color: var(--muted); }
.place-pin .pp-more { flex: none; color: var(--muted); font-size: 0.6875rem; font-weight: 650; }
.place-pin .pp-n {
  position: absolute;
  left: 22px;
  top: -9px;
  padding: 0 5px;
  border: 1.5px solid var(--bg);
  border-radius: 999px;
  background: var(--ring);
  color: var(--event-glyph);
  font-size: 0.65625rem;
  font-weight: 700;
  line-height: 15px;
}
.place-pin.small .pp-n { left: 17px; top: -8px; }
.place-pin.tiny { transform: translate(-12px, -50%); }
.place-pin.tiny .row-thumb { width: 24px; height: 24px; box-shadow: 0 0 0 1.5px var(--bg), 0 0 0 3.5px var(--ring), 0 1px 4px rgba(0, 0, 0, 0.35); }
.place-pin.tiny .pp-n { left: 14px; top: -9px; }
/* Events at a few places close together: a dot with another peeking out behind, and the number */
.ev-stack { position: relative; width: 100%; height: 100%; display: grid; place-items: center; cursor: pointer; }
.ev-stack .dot { position: relative; }
.pl-stack .dot.place { width: var(--dot, 14px); height: var(--dot, 14px); }
.pl-stack .dot.place .glyph { display: block; }
.ev-stack .pp-n {
  position: absolute; left: calc(50% + var(--dot, 14px) / 2 - 6px); top: calc(50% - var(--dot, 14px) / 2 - 9px);
  padding: 0 5px; border: 1.5px solid var(--bg); border-radius: 999px;
  background: var(--g); color: var(--event-glyph); font-size: 0.65625rem; font-weight: 700; line-height: 15px;
}
.place-pin.few .pp-n { left: calc(var(--dot, 14px) - 6px); top: calc(50% - var(--dot, 14px) / 2 - 9px); }

/* Its card on a tap: photo with the name, kind and address, what's on there, the place */
.spot-card {
  position: fixed;
  left: 12px;
  right: 12px;
  bottom: calc(var(--peek-h, 186px) + env(safe-area-inset-bottom, 0px) + 10px);
  z-index: 1002;
  border-radius: 14px;
  background: var(--bg);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.spot-card[hidden] { display: none; }
.spot-pop .leaflet-popup-content-wrapper { padding: 0; overflow: hidden; border-radius: 14px; }
.spot-pop .leaflet-popup-content { margin: 0; width: 320px !important; }
.spot-pop .leaflet-popup-close-button { display: none; }
.spot-card-in { color: var(--text); font-size: 0.8125rem; }
.sc-ban { position: relative; height: 92px; background: color-mix(in srgb, var(--map-text) 75%, #000); }
.sc-ban[data-spot-place] { cursor: pointer; }
.sc-ban .row-thumb.sc-photo { position: absolute; inset: 0; width: auto; height: auto; border-radius: 0; }
.sc-ban .row-thumb.sc-photo::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to top, rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0) 60%); }
.sc-ban b { position: absolute; left: 12px; right: 12px; bottom: 8px; color: #fff; font-size: 1.125rem; line-height: 1.2; text-shadow: 0 1px 6px rgba(0, 0, 0, 0.5); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sc-ban .sc-n { position: absolute; left: 10px; top: 8px; padding: 2px 8px; border-radius: 999px; background: rgba(0, 0, 0, 0.55); color: #fff; font-size: 0.6875rem; }
.sc-ban .sc-close { position: absolute; right: 6px; top: 4px; width: 32px; height: 32px; border: 0; border-radius: 50%; background: rgba(0, 0, 0, 0.45); color: #fff; font-size: 0.875rem; cursor: pointer; }
.spot-card-in .sc-sub { margin: 8px 12px 4px; color: var(--muted); font-size: 0.75rem; }
.spot-card-in .sc-list { list-style: none; margin: 0; padding: 0 4px; }
.sc-list button {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 40px;
  padding: 6px 8px;
  border: 0;
  border-top: 1px solid var(--border);
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.sc-list button:hover { background: color-mix(in srgb, var(--accent) 6%, var(--bg)); }
.sc-list .tip-group { flex: none; }
.sc-when { flex: none; min-width: 92px; color: var(--muted); font-size: 0.75rem; font-variant-numeric: tabular-nums; }
.sc-ttl { min-width: 0; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* More than 4: the list scrolls in place (4 and a half rows show, so the cut row says "more"),
   with a soft shadow at an edge while there is more that way */
.sc-list.scrolls {
  max-height: min(184px, 30vh); overflow-y: auto; overscroll-behavior: contain;
  background:
    linear-gradient(var(--bg) 30%, transparent) top / 100% 24px no-repeat local,
    linear-gradient(transparent, var(--bg) 70%) bottom / 100% 24px no-repeat local,
    radial-gradient(farthest-side at 50% 0, rgba(0, 0, 0, 0.14), transparent) top / 100% 8px no-repeat scroll,
    radial-gradient(farthest-side at 50% 100%, rgba(0, 0, 0, 0.14), transparent) bottom / 100% 8px no-repeat scroll;
}
.spot-card-in .sc-list.scrolls { padding-bottom: 0; border-bottom: 1px solid var(--border); }
.sc-place { display: block; width: calc(100% - 24px); margin: 8px 12px 12px; padding: 9px; border: 0; border-radius: 999px; background: var(--accent); color: #fff; font: inherit; font-weight: 600; cursor: pointer; }

/* Phone: tap a dot for a compact card above the bottom panel */
.preview {
  position: fixed;
  left: 10px; /* (the same edge as the search bar and the chips) */
  right: 10px;
  bottom: calc(var(--peek-h, 186px) + env(safe-area-inset-bottom, 0px) + 10px);
  z-index: 1002;
  padding: 12px 16px;
  border-radius: var(--r-float);
  background: var(--bg);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  gap: 4px;
}
/* The event's photo as a banner across the top of the card. */
.preview-photo {
  display: block;
  margin: -12px -16px 8px;
  width: calc(100% + 32px);
  height: 118px;
  object-fit: cover;
  border-radius: var(--r-float) var(--r-float) 0 0;
}
.preview-photo[hidden] { display: none; }
.preview-photo, .preview-title, .preview-meta { cursor: pointer; }
.preview-group { font-size: 0.7188rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; }
.preview-title { font-weight: 700; line-height: 1.3; font-size: 1.0625rem; }
.preview-meta { font-size: 0.7812rem; color: var(--muted); }
.preview-actions { display: flex; gap: 8px; align-items: center; margin-top: 4px; }
.preview-actions #preview-close { margin-left: auto; width: 38px; padding: 0; justify-content: center; } /* (a circle, not an oval) */
.preview .save {
  border: 1px solid var(--border);
  background: var(--bg-soft);
  color: var(--text);
  border-radius: 999px;
  padding: 5px 11px;
  font: inherit;
  font-size: 0.8125rem;
  cursor: pointer;
}
.preview .save[aria-pressed="true"] { border-color: var(--star); color: var(--star); }

.legend { display: grid; grid-template-columns: 1fr 1fr; gap: 3px 10px; font-size: 0.7812rem; }
.legend i { font-style: normal; }

.cluster {
  display: grid;
  place-items: center;
  border-radius: 50%;
  color: #fff;
  font-weight: 700;
  font-size: 0.75rem;
  border: 2px solid #fff;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.35);
}
/* Clusters stay quiet (a cream disc with a warm edge, events and places alike) so single,
   colour-coded dots stand out; the edge is 3:1 against the map. */
.cluster.events, .cluster.pois {
  background: var(--bg);
  color: #5a3420;
  border: 1.5px solid #968576;
  box-shadow: 0 1px 3px rgba(40, 32, 20, 0.22);
  font-size: 0.75rem;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}
.cluster .cl-n { display: block; line-height: 1; } /* (the number alone in the disc's middle) */
:root.app-dark :is(.cluster.events, .cluster.pois) { background: var(--raised); color: var(--map-text); border-color: var(--boundary); } /* (raised, so the disc shows on the dark land) */

.leaflet-popup-content-wrapper, .leaflet-popup-tip {
  background: var(--bg);
  color: var(--text);
}
.leaflet-popup-content { margin: 12px 14px; font-size: 0.8438rem; }
.popup h3 { margin: 0 0 4px; font-size: 0.9375rem; }
.popup p { margin: 4px 0; }
.popup img { display: block; width: 100%; height: 150px; object-fit: cover; border-radius: 8px; margin-bottom: 8px; }
.popup .tags { color: var(--muted); font-size: 0.75rem; }
.popup a { color: var(--accent); }
.popup .sessions { margin: 4px 0; padding-left: 16px; font-size: 0.7812rem; font-variant-numeric: tabular-nums; }
.popup .actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 8px; }
.popup .save {
  border: 1px solid var(--border);
  background: var(--bg-soft);
  color: var(--text);
  border-radius: 999px;
  padding: 4px 10px;
  font: inherit;
  font-size: 0.7812rem;
  cursor: pointer;
}
.popup .save[aria-pressed="true"] { border-color: var(--star); color: var(--star); }

.leaflet-container { background: var(--land); font: inherit; }


.arr-label {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  line-height: 1.1;
  color: var(--label-arr);
  text-shadow: var(--halo);
  cursor: pointer;
}
/* Outside Paris zoomed out: a town's dots as one number, in the same pill as Paris's. */
.town-group { color: var(--label-arr); } /* the same as the arrondissements (.arr-label) */
.town-group .arr-count { display: block; }
.arr-label b { font-size: 0.7188rem; font-weight: 600; letter-spacing: 0.02em; white-space: nowrap; }
.arr-count { display: none; font-weight: 700; font-size: 0.8125rem; color: var(--text); font-variant-numeric: tabular-nums; }
.arr-label:focus-visible { outline: 2px solid var(--accent); border-radius: 6px; }

/* Towns around Paris: small grey italics, centred on their point, under everything else. */
.town-label { pointer-events: none; }
.town-label span {
  display: block; transform: translate(-50%, -50%); white-space: nowrap;
  font-size: 0.6875rem; font-style: italic; color: var(--muted); opacity: 0.95;
  text-shadow: var(--halo);
}

/* Zoomed out: counts become the main mark, in pills so they read over any shading. */
.overview .arr-label { text-shadow: none; }
.overview .arr-label b { font-weight: 600; font-size: 0.6875rem; }
.overview .arr-close { color: var(--muted); font-weight: 600; }
/* Zoomed out the numbers are the controls, so they sit above any dots they've opened.
   Zoomed in the names are just labels: taps go through to the dots. */
.overview .leaflet-areaLabels-pane, .overview .leaflet-areaPicked-pane { z-index: 610 !important; } /* beats the pane's inline 450 */
/* Zoomed in, the name takes a tap (its events or places only, and its outline); the rest of the
   label's box lets taps through to the dots. */
body:not(.overview) .arr-label { pointer-events: none; }
body:not(.overview) .arr-label b { pointer-events: auto; padding: 4px 6px; margin: -4px -6px; }
@media (hover: hover) { body:not(.overview) .arr-label b:hover { text-decoration: underline; text-underline-offset: 2px; } }
.arr-label.arr-picked { color: var(--accent); }
.arr-label.arr-picked b { font-weight: 800; }
/* Only the name and number take taps: the dots they've opened around them stay tappable. */
.overview .arr-label { pointer-events: none; }
.overview .arr-label > * { pointer-events: auto; }
.overview .arr-count {
  display: block;
  min-width: 28px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--bg);
  color: var(--map-text);
  font-weight: 650;
  box-shadow: 0 1px 3px rgba(40, 32, 20, 0.2);
  text-align: center;
}

/* "Paris Centre" stands in for the 1st–4th when zoomed far out. */
.arr-centre { display: none; }
.merge-centre .arr-centre { display: flex; }
.merge-centre .arr-in-centre { display: none; }

.map-hint {
  margin-top: 12px !important;
  padding: 6px 12px;
  border-radius: 999px;
  background: var(--bg);
  color: var(--text);
  box-shadow: var(--shadow);
  font-size: 0.7812rem;
}

/* ---------- mobile: the panel becomes a draggable bottom sheet ---------- */

@media (max-width: 720px) {
:root { --peek-h: 252px; }
  /* (Cards over the map sit just over the sheet: lower with it all the way down, at the bottom
     while a dropped pin's card stands in for it.) */
  body[data-sheet="mini"] { --peek-h: 76px; }
  body.pin-down[data-sheet="peek"], body.pin-down[data-sheet="mini"] { --peek-h: 0px; }
  body.home-open[data-sheet="peek"], body.home-open[data-sheet="mini"] { --peek-h: 0px; }
  #map { inset: 0; }
  .leaflet-control-zoom { display: none; }
  .map-tools, .layers-panel { right: 12px; }
  .map-tools { top: calc(56px + env(safe-area-inset-top, 0px)); }
  /* Room for longer (French) labels: "Near me" and the theme button become icons. */
  #locate .btn-text, #theme-toggle .btn-text, #layers-toggle .btn-text { display: none; }
  .map-tools { left: 8px; flex-wrap: wrap; justify-content: flex-end; }
  /* With the panel at full height, the buttons move up into the strip above it. */
  body[data-sheet="full"] .map-tools { top: calc(10px + env(safe-area-inset-top, 0px)); }
  body[data-sheet="full"] .map-tools .map-btn { padding-top: 2px; padding-bottom: 2px; }
  /* (Key & layers opens over the list too: its button is there.) */
  .layers-panel { top: calc(96px + env(safe-area-inset-top, 0px)); max-height: calc(100% - 96px - 200px); }

  .panel {
    --peek: calc(252px + env(safe-area-inset-bottom, 0px));
    --mini: calc(76px + env(safe-area-inset-bottom, 0px)); /* the lowest: just the grip and the tabs */
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    width: auto;
    height: 55%;
    max-height: calc(100% - 48px - env(safe-area-inset-top, 0px));
    padding-bottom: env(safe-area-inset-bottom, 0px);
    border-radius: 16px 16px 0 0;
    box-shadow: var(--shadow);
    transition: height 0.3s cubic-bezier(.2, .8, .2, 1); /* settles softly, no bounce */
  }
  .panel[data-sheet="peek"] { height: var(--peek); }
  .panel[data-sheet="mini"] { height: var(--mini); }
  .panel[data-sheet="half"] { height: 55%; }
  .panel[data-sheet="full"] { height: calc(100% - 58px - env(safe-area-inset-top, 0px)); }
  .panel.dragging { transition: none; }

  .sheet-grip {
    display: block;
    flex: none;
    padding: 8px 0 2px;
    cursor: grab;
    touch-action: none;
  }
  .sheet-grip span {
    display: block;
    width: 44px;
    height: 5px;
    margin: 0 auto;
    border-radius: 3px;
    background: var(--border); /* (quiet, Felix) */
  }
  .panel-header { padding: 4px 16px 8px; touch-action: none; }
  /* The filter rows pull the sheet up and down too; chip rows still scroll sideways. */
  .panel > .chip-row { touch-action: pan-x; }
  .panel > .filter-bar { touch-action: none; }
  .mode-switch { margin-top: 4px; }
  .mode-switch button { padding: 8px 10px 9px; }
  .panel-header h1 { font-size: 1.125rem; }

  .view-switch {
    display: flex;
    flex: none;
    padding: 2px;
    border-radius: 999px;
    background: var(--bg-soft);
    border: 1px solid var(--border);
  }
  .seg {
    border: none;
    background: none;
    color: var(--muted);
    border-radius: 999px;
    padding: 4px 12px;
    font: inherit;
    font-size: 0.8125rem;
    cursor: pointer;
  }
  .seg[aria-pressed="true"] { background: var(--raised); color: var(--text); box-shadow: 0 1px 3px rgba(60, 36, 20, 0.15); }

  .results { flex: 1; min-height: 0; }
}

@media (max-width: 720px) {
  body[data-sheet="full"] .map-hint { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .panel, .switch input, .switch input::after { transition: none; }
}

/* ---------- one event: the same layout in phone details and map popups ---------- */
.ev-title { margin: 12px 0 4px; font-size: 1.188rem; line-height: 1.25; }
/* The name of an event or a place (and its kind above it) in the brand's serif, as on the
   opening screen: exactly as in mockup B. */
.detail h2 { font-family: var(--serif); font-weight: 600; letter-spacing: -0.01em; }
.detail h2 .kicker { font-family: var(--sans); font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.05em; } /* (the kind label: plain, the name alone in the serif) */
.popup .ev-title { font-size: 1rem; margin-top: 8px; }
.ev-title .ttl { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; }
.detail .ev-title .ttl { display: block; -webkit-line-clamp: unset; line-clamp: none; overflow: visible; text-wrap: balance; } /* (the details show the name whole) */
.ev-badges { margin: 2px 0 6px; }
.ev-badges .badge { margin: 0 6px 0 0; }
.facts { list-style: none; margin: 8px 0 0; padding: 0; }
.facts > li { display: grid; grid-template-columns: 22px 1fr; gap: 8px; align-items: start; padding: 8px 0; border-top: 1px solid var(--border); }
.facts > li:first-child { border-top: 0; padding-top: 2px; }
.facts .ico { font-size: 0.9375rem; line-height: 1.3; text-align: center; color: var(--muted); } /* (on the middle of the first line of text) */
/* Line icons (LINE_ICONS in app.js): drawn in the text's colour, as big as a line of text. */
svg.lic { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; vertical-align: -4px; flex: none; }
.facts .ico svg.lic { display: block; margin: calc((0.875rem * 1.45 - 20px) / 2) auto 0; } /* (its middle on the first line's: that line is 0.875rem × 1.45) */
.facts .traffic-row .ico { color: var(--wait, #b06000); }
.am-row .button svg.lic, .st-fact svg.lic, .hsum-walk svg.lic { width: 16px; height: 16px; vertical-align: -3px; margin-right: 2px; }
.home-chip .home-ic svg.lic { width: 18px; height: 18px; display: block; color: var(--accent); }
.home-chip[aria-expanded="true"] .home-ic svg.lic { color: currentColor; } /* (on: white on the navy chip) */
.home-card .home-big svg.lic { width: 26px; height: 26px; display: block; color: var(--accent); }
.home-card .hs-ico svg.lic { display: block; margin: 0 auto; color: var(--muted); }
.facts p { margin: 0; }
.facts .when-line { font-weight: 600; }
.facts .times::before { content: none; }
.times.folded, .price.folded {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; cursor: pointer;
}
.cta { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0 4px; }
/* In popups, Save · Share (· I went) start their own row, for events and places alike. */
.cta-break { flex-basis: 100%; height: 0; margin-top: -8px; }
@media (max-width: 480px) { .cta-break { margin-top: -5px; } }
.tags a { color: inherit; }
.cta .button { text-decoration: none; display: inline-flex; align-items: center; }
.cta .button.primary { background: var(--accent); border-color: var(--accent); color: var(--bg); font-weight: 600; }
.popup .cta .button { padding: 5px 10px; font-size: 0.8125rem; }
/* Four buttons on one row on a phone. */
#detail-map .short, #station-map .short { display: none; }
@media (max-width: 480px) {
  .cta { gap: 5px; }
  .cta .button { padding: 6px 8px; font-size: 0.7812rem; }
  #detail-map .long, #station-map .long { display: none; }
  #detail-map .short, #station-map .short { display: inline; }
  #detail-map .short::before, #station-map .short::before { content: "🗺\FE0F  "; }
}
details.more-dates summary { cursor: pointer; color: var(--accent); font-size: 0.8438rem; padding: 6px 0; }
/* ---------- feedback dialog ---------- */
.feedback {
  width: min(440px, calc(100vw - 32px)); padding: 20px 20px 18px; border: 1px solid var(--border);
  border-radius: 14px; background: var(--bg); color: var(--text); box-shadow: var(--shadow);
}
/* About as a pop-up: about.html's text, scrolling under a fixed top bar (title and ×). Set like
   a short paper, after econphdplacements.com's privacy notice (Felix, 2026-10-25): serif text,
   a big title, a hairline, quiet subheads, "Last updated" in italics at the end. */
.about-dialog {
  --about-serif: var(--serif); /* (the wordmark's serif, as in the search bar) */
  width: min(640px, calc(100vw - 24px)); max-height: min(88vh, 820px); padding: 0; border-radius: 18px;
  overflow: hidden; font-family: var(--about-serif);
}
.about-dialog[open] { display: flex; flex-direction: column; }
.about-dialog:focus { outline: none; }
.about-head { display: flex; align-items: center; gap: 12px; padding: 22px 20px 22px 32px; border-bottom: 1px solid var(--border); flex: none; }
/* The title as the search bar writes it (Felix): "About" in the app's font, then the wordmark. */
.about-head h1 { flex: 1; margin: 0; font: 400 1.875rem/1.2 var(--about-serif); }
.about-head h1 .pre { font: 500 1.625rem/1.2 var(--sans); }
.about-head h1 .mark i { color: var(--logo); }
.about-x { flex: none; display: grid; place-items: center; width: 40px; height: 40px; margin: -4px 0; border: 0; border-radius: 50%; background: none; color: var(--muted); font: 300 2rem/1 var(--sans); cursor: pointer; }
.about-x:hover { color: var(--text); background: rgba(127,127,127,.12); }
.about-dialog #about-body { overflow: auto; padding: 18px 32px 26px; font-size: 1.0625rem; line-height: 1.6; }
.about-dialog #about-body > div > * { margin: 0 0 14px; font-size: inherit; }
.about-dialog #about-body p { font-size: inherit; }
.about-dialog #about-body a { color: inherit; text-decoration-color: var(--muted); text-underline-offset: 3px; text-decoration-thickness: 1px; }
.about-dialog #about-body a:focus:not(:focus-visible) { outline: none; }
.about-dialog #about-body > div > .fine { margin-top: 26px; padding-top: 0; border-top: 1px solid var(--border); }
/* A thin line over each section (Felix, 2026-10-26): the same space above and below each line. */
.about-dialog #about-body .fine h2 { font: 400 1.1875rem/1.3 var(--about-serif); margin: 0 0 8px; padding-top: 22px; }
.about-dialog #about-body .fine h2:not(:first-child) { margin-top: 22px; border-top: 1px solid var(--border); }
.about-dialog #about-body .fine p { margin: 0 0 12px; }
.about-dialog #about-body .fine ul { margin: 0 0 12px; padding-left: 22px; }
.about-dialog #about-body .fine li { font-size: inherit; }
.about-dialog #about-body .fine li + li { margin-top: 6px; }
.about-dialog .nowrap { white-space: nowrap; }
/* The imprint: one small grey paragraph under a line, no heading (Felix's pick C). */
.about-dialog #about-body .fine .imprint { margin: 22px 0 12px; padding-top: 22px; border-top: 1px solid var(--border); font: 0.8125rem/1.6 var(--sans); color: var(--muted); }
.about-dialog #about-body .imprint a { color: inherit; }
.about-dialog #about-body .fine .updated { font-style: italic; margin-top: 12px; }
@media (max-width: 520px) {
  .about-head { padding: 16px 12px 16px 20px; }
  .about-head h1 { font-size: 1.5rem; }
  .about-head h1 .pre { font-size: 1.3125rem; }
  .about-dialog #about-body { padding: 14px 20px 22px; font-size: 1rem; line-height: 1.7; }
  .about-dialog #about-body .fine h2 { font-size: 1.1875rem; } /* (above the bold labels under it) */
}
.feedback::backdrop { background: rgba(0, 0, 0, 0.35); }
.feedback h2 { margin: 0 0 4px; font-size: 1.125rem; }
.feedback p { margin: 0 0 10px; font-size: 0.8438rem; }
.feedback textarea, .feedback input {
  display: block; width: 100%; box-sizing: border-box; margin: 0 0 8px; padding: 8px 10px;
  border: 1px solid var(--border); border-radius: 8px; background: var(--bg-soft); color: var(--text); font: inherit;
}
.feedback textarea { resize: vertical; min-height: 96px; }
.fb-status { font-size: 0.8125rem; }
/* The feedback form, set like About (Felix picked mockup A, 2026-10-25): the same top bar (serif
   title, ×), a serif intro, plain white fields, small print and a round Send at the bottom. */
.fb-paper {
  --about-serif: var(--serif);
  width: min(560px, calc(100vw - 24px)); padding: 0; border-radius: 18px; font-family: var(--about-serif);
}
.fb-paper:focus { outline: none; }
.fb-paper .about-head h1 { margin: 0; }
.fb-paper .fb-body { padding: 20px 32px 6px; }
.fb-paper .fb-intro { margin: 0 0 18px; font-size: 1.0625rem; line-height: 1.7; }
.fb-paper textarea, .fb-paper input {
  margin: 0 0 12px; padding: 12px 14px; border-radius: 10px; background: var(--bg);
  font: 1rem/1.5 var(--sans);
}
.fb-paper textarea { min-height: 140px; }
.fb-paper textarea:focus, .fb-paper input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.fb-paper .fb-status { margin: 0 0 8px; font: 0.9375rem/1.5 var(--sans); }
/* What a report is about: its photo and name, between two hairlines. */
.fb-about:not([hidden]) { display: flex; align-items: center; gap: 12px; margin: 0 0 14px; padding: 10px 0; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); font-family: var(--sans); }
.fb-about img { width: 44px; height: 44px; flex: none; border-radius: 8px; object-fit: cover; }
.fb-about div { min-width: 0; }
.fb-about small { display: block; color: var(--muted); font-size: 0.8125rem; }
.fb-about b { display: block; overflow: hidden; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.fb-foot { display: flex; align-items: center; gap: 16px; padding: 8px 32px 24px; }
.fb-fine { flex: 1; color: var(--muted); font: italic 0.875rem/1.4 var(--about-serif); }
.fb-paper .send { padding: 11px 26px; border-radius: 999px; font: 600 0.9375rem var(--sans); }
@media (max-width: 640px) {
  .fb-paper .fb-body { padding: 16px 20px 4px; }
  .fb-paper .fb-intro { font-size: 1rem; }
  .fb-foot { padding: 6px 20px 20px; }
}
/* Narrow phones: a little less air between the map buttons so the whole row fits. */
@media (max-width: 400px) {
  .map-tools { gap: 4px; right: 8px; }
  .map-tools .map-btn { padding-left: 8px; padding-right: 8px; }
}
.feedback .hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; } /* bots fill it, people never see it */

/* On computers: the browser's usual cursors: the arrow, the pointing hand over things to click,
   the open hand to drag the map and the closed hand while dragging. Text fields keep their
   text cursor. */
@media (hover: hover) and (pointer: fine) {
  .leaflet-grab, .leaflet-grab * { cursor: grab !important; }
  .leaflet-dragging .leaflet-grab, .leaflet-dragging .leaflet-grab *, .leaflet-dragging .leaflet-marker-draggable { cursor: grabbing !important; }
  :is(a[href], button, [role="button"], [role="tab"], [role="radio"], [role="switch"], [role="checkbox"], summary, label, select,
      input[type="checkbox"], input[type="radio"], input[type="range"], .leaflet-interactive, .leaflet-marker-icon, .cluster,
      .event-list li[tabindex], .preview-photo, .preview-title, .preview-meta, .photo-c):not(:disabled),
  :is(a[href], button, [role="button"], [role="tab"], [role="radio"], summary, label, .leaflet-marker-icon,
      .event-list li[tabindex]):not(:disabled) *:not(input, textarea) { cursor: pointer !important; }
  input[type="text"], input[type="search"], textarea, [contenteditable] { cursor: text !important; }
}

/* The map's OpenStreetMap credit, small and quiet. */
.leaflet-control-attribution.leaflet-control {
  background: transparent; font-size: 0.5938rem; opacity: .8; padding: 0 4px; color: var(--muted);
}
.leaflet-control-attribution a { color: var(--muted); }
.leaflet-control-attribution:hover { opacity: 1; background: var(--bg); }
/* The zoom buttons in the app's colours (Leaflet's own are white in dark mode too). */
.leaflet-bar a, .leaflet-bar a:hover { background: var(--bg); color: var(--text); border-bottom-color: var(--border); }
.leaflet-bar { border-color: var(--border) !important; }
/* The search's hint text, in the app's muted grey (the browser's is too light on the field). */
input::placeholder { color: var(--muted); opacity: 1; }

/* Chip rows on computers: ‹ › arrows at the ends with more chips (app.js), the fade on the
   side(s) that continue. */
.chip-arrow {
  position: sticky; z-index: 2; flex: none; align-self: center;
  width: 28px; height: 28px; border-radius: 50%; padding: 0;
  border: 1px solid var(--border); background: var(--bg); color: var(--text);
  font-size: 1.125rem; line-height: 1; box-shadow: 0 1px 4px rgba(60, 36, 20, .15);
}
.chip-arrow.left { left: 0; margin-right: -22px; }
.chip-arrow.right { right: 0; margin-left: -22px; outline: 18px solid var(--bg); clip-path: inset(-4px -24px -4px -24px); } /* (covers the chip beyond it) */
.chip-arrow:hover { background: var(--bg-soft); }
.chip-row[data-fade], .chip-row.at-end { -webkit-mask-image: none; mask-image: none; }
.chip-row.dragging, .chip-row.dragging * { user-select: none; -webkit-user-select: none; }

/* "Pick dates": From / To under the date chips. */
.date-pop {
  display: flex; flex-wrap: wrap; align-items: end; gap: 8px 12px;
  margin: 0 16px 10px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 12px; background: var(--bg-soft);
}
.date-pop[hidden] { display: none; }
.date-pop label { display: flex; flex-direction: column; gap: 3px; font-size: 0.75rem; color: var(--muted); }
.date-pop input[type="date"] {
  font: inherit; font-size: 0.875rem; color: var(--text); background: var(--bg);
  border: 1px solid var(--border); border-radius: 8px; padding: 5px 8px;
}
.date-pop-actions { display: flex; gap: 6px; margin-left: auto; }
.detail-actions { display: flex; align-items: center; gap: 6px; margin: 0 !important; }
.detail-bar .button span { display: inline; }

/* List rows: the same event at other places, indented under the first; distance and price. */
.event-list li.in-group { padding-left: 32px; background: var(--bg-soft); }
.event-list .more-same { display: block; margin-top: 3px; font-size: 0.7812rem; }
.event-list .dist { font-weight: 600; }
.event-list .price-short { font-weight: 600; }

/* Touch screens: buttons and chips big enough for a fingertip. */
@media (pointer: coarse) {
  .chip, .button, .seg, .send { min-height: 38px; }
  .map-btn { min-height: 40px; min-width: 40px; }
  .lang-switch button { min-height: 34px; min-width: 38px; }
}
.button.share, .cta .button, .detail-actions .button { gap: 0.3em; }
/* A skip link for keyboards: to the list, past the map. */
.skip-link { position: absolute; left: 8px; top: -60px; z-index: 3000; padding: 8px 12px; border-radius: 8px; background: var(--accent); color: var(--bg); font-weight: 600; }
.skip-link:focus { top: 8px; }
.legend-emoji { font-style: normal; display: inline-block; width: 16px; text-align: center; }

/* Details bar: Back, Share and Save the same height, on one line. */
.detail-bar .button, .detail-bar .save {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.3em;
  min-height: 36px; padding: 0 14px; margin: 0; font-size: 0.875rem; line-height: 1;
  box-sizing: border-box; vertical-align: middle;
}
.near-clear { margin: 2px 16px 2px; background: var(--accent); border-color: var(--accent); color: var(--bg); font-weight: 600; }
.event-list .age { color: var(--accent); font-weight: 600; }
.share-saved { margin: 8px 16px 0; }
.results > .near-clear + .welcome { margin-top: 12px; } /* (the same room above and below the chip) */
.link.report { display: block; margin: 14px 0 4px; font-size: 0.8125rem; color: var(--muted); }
#am-card .link.report, #bus-card .link.report, #film-card .link.report { margin: 10px 0 0; padding: 0; }
.theme-note .link.report { margin: 6px 0 0; padding: 0; }
.link.hours-wrong { display: block; margin-top: 4px; font-size: 0.8125rem; color: var(--muted); } /* (under a place's unknown hours: as "Report a mistake") */

/* Loading: a small turning ring before the events arrive. */
.event-list .empty.loading { display: flex; align-items: center; gap: 10px; }
.spinner { width: 18px; height: 18px; border-radius: 50%; border: 2px solid var(--border); border-top-color: var(--accent); animation: spin 0.8s linear infinite; flex: none; }
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 2.4s; } }
/* Tablets: the map buttons take two lines over the narrow map; the hint goes under them. */
@media (min-width: 721px) and (max-width: 1100px) {
  .map-hint { margin-top: 112px !important; }
}
/* A popup's ✕ big enough to hit with a finger. */
.leaflet-container a.leaflet-popup-close-button { width: 36px; height: 36px; font: 24px/34px Tahoma, Verdana, sans-serif; top: 0; right: 0; }
/* Read out, not shown. */
/* A range dash drawn at half the figures' height (see app.js): the box runs from the baseline
   (an inline-block that hides its overflow sits on its bottom edge) up to the capitals' height,
   the line across its middle; the "–" inside is kept but not painted. */
.range { white-space: nowrap; }
.dash { display: inline-block; position: relative; height: 0.7em; height: 1cap; overflow: hidden; vertical-align: baseline; width: 0.7em; /* (a hair of space each side of the line, see ::after) */
  -webkit-text-fill-color: transparent; line-height: 1; --t: max(1px, 0.085em); /* the line's thickness */ }
/* The line: a whole number of screen pixels thick (--px is one screen pixel, set by app.js), and
   placed on whole pixels, which the browser snaps the same way for every dash: equally crisp,
   never one smeared over an extra row of pixels that makes it look bolder than the next. */
.dash::after { content: ""; position: absolute; left: 0.14em; right: 0.14em; /* the line 0.42em long, apart from the figures */
  --tt: var(--t); --tt: max(var(--px, 1px), round(nearest, var(--t), var(--px, 1px)));
  height: 0; border-top: var(--tt) solid currentColor; /* (a border, not a background: Chrome painted the
     odd background twice as thick at 2.625 or 2.75 pixels per point, a border never) */
  bottom: calc(0.35em - var(--tt) / 2); bottom: round(nearest, calc(0.5cap - var(--tt) / 2), var(--px, 1px)); }
strong .dash, b .dash, h1 .dash, h2 .dash, h3 .dash, .when .dash { --t: max(1px, 0.095em); } /* (barely heavier: on a phone the bolder one rounded to a block) */
/* (One dash for every range, prices too.) */
/* Bold figures sit a hair lower than their box says (measured on Android): follow them. */
strong .dash::after, b .dash::after, h1 .dash::after, h2 .dash::after, h3 .dash::after, .when .dash::after {
  bottom: calc(0.35em - var(--tt) / 2 - 0.025em); bottom: round(nearest, calc(0.5cap - var(--tt) / 2 - 0.025em), var(--px, 1px)); }
.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; }
/* The rows at the top of the panel keep their height; when Filters open in a short panel, the
   filters scroll inside themselves and the list keeps the rest. */
.panel > header, .panel > .chip-row, .panel > .filter-bar, .panel > .date-pop { flex-shrink: 0; }
.more-filters { flex-shrink: 1; min-height: 0; overflow-y: auto; }
/* The "● Now" / "Free" pill and the time on one centred line in the event details. */
.when-line { display: flex; align-items: center; flex-wrap: wrap; row-gap: 4px; }
.when-line .pill { vertical-align: baseline; }
.when-line .run-end { margin-left: 0.3em; font-weight: 400; } /* "On now until midnight · until Sun 11 Oct" */
/* List view on phones: the buttons sit in their own strip above the list, a little smaller,
   evenly spaced, with room above and below (no overlap with the sheet's edge); the map key
   button is only for the map, so it waits until the map is back. */
@media (max-width: 720px) {
  body[data-sheet="full"] .map-tools { left: 12px; right: 12px; justify-content: space-between; gap: 6px; }
  body[data-sheet="full"] .map-tools .map-btn { min-height: 36px; height: 36px; flex: 1 1 0; min-width: 0; box-shadow: none; }
  body[data-sheet="full"] .map-tools .lang-switch { flex: 0 0 auto; padding: 2px; }
  body[data-sheet="full"] .map-tools .lang-switch button { min-height: 30px; padding-top: 0; padding-bottom: 0; }
  body[data-sheet="full"] #layers-toggle { display: none; }
}
/* The arrows sit on a soft band of the panel's colour, so a chip running under one fades out
   instead of being overprinted ("7 prochai›urs"). */
.chip-arrow.right { box-shadow: 0 1px 4px rgba(60, 36, 20, .15), -16px 0 14px 8px var(--bg); }
.chip-arrow.left { box-shadow: 0 1px 4px rgba(60, 36, 20, .15), 16px 0 14px 8px var(--bg); }
/* "Open on…" in the places chip row: a chip-shaped menu, filled in when a day is picked. */
.chip-select {
  -webkit-appearance: none; appearance: none; flex: none;
  padding-right: 26px;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 14px) 52%, calc(100% - 9px) 52%;
  background-size: 5px 5px; background-repeat: no-repeat;
}
.chip-select.on { background-color: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.chip-select option { color: var(--text); background: var(--bg); }
/* Words under the icons on phones (an icon alone left people guessing what ◎ or ★ do);
   computers have room for the full labels and hide them. */
.map-btn .cap { display: none; }
@media (max-width: 720px) {
  .map-tools .map-btn:not(.lang-switch) { display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px; padding: 3px 6px; min-width: 44px; line-height: 1.1; }
  .map-tools .map-btn .cap { display: block; font-size: 0.625rem; font-weight: 400; color: var(--muted); white-space: nowrap; }
  .map-tools .saved-btn .n { position: absolute; top: 2px; right: 6px; margin: 0; font-size: 0.6875rem; font-weight: 700; }
  .map-tools .saved-btn { position: relative; }
  /* In the list view's strip they stay compact: icons only. */
  body[data-sheet="full"] .map-tools .map-btn .cap { display: none; }
}
@media (max-width: 400px) {
  .map-tools .lang-switch button { min-width: 30px; padding-left: 5px; padding-right: 5px; }
  .map-tools .map-btn:not(.lang-switch) { padding-left: 4px; padding-right: 4px; min-width: 42px; }
}
/* Filters that are on (Free, English-friendly, Evening…): small pills under the search box,
   each one tap to remove. */
.active-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 0 16px 10px; margin-top: -2px; border-bottom: 1px solid var(--border); }
.active-filters[hidden] { display: none; }
.pill-filter {
  border: 1px solid var(--accent); background: var(--accent); color: var(--accent-text);
  border-radius: 999px; padding: 3px 9px; font: inherit; font-size: 0.75rem; font-weight: 600; cursor: pointer;
}
.pill-filter span { opacity: 0.8; margin-left: 2px; }
.active-filters .link { font-size: 0.75rem; }
.filter-bar:has(+ .active-filters:not([hidden])) { border-bottom: 0; }
.chip.empty[aria-pressed="true"] { opacity: 1; } /* switched on, even with nothing left to show */
.event-list .empty .link { white-space: nowrap; }
/* ✦ Special leads the kinds row, set apart in gold: late museum nights, festivals, open days. */
.chip.special-chip:not([aria-pressed="true"]) { border-color: var(--gold); background: color-mix(in srgb, var(--gold) 12%, var(--bg-soft)); }
.more-filters .chip-row { padding-left: 0; padding-right: 0; } /* in line with their headings */
/* Sharing a list: its name, then which saved events go in. */
.share-pop { margin: 4px 16px 10px; padding: 12px; border: 1px solid var(--border); border-radius: 12px; background: var(--bg); box-shadow: var(--shadow); }
.share-pop[hidden] { display: none; }
.share-pop .list-name { display: block; font-size: 0.8125rem; font-weight: 600; }
.share-pop .list-name input { display: block; width: 100%; box-sizing: border-box; margin-top: 4px; padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-soft); color: var(--text); font: inherit; font-weight: 400; }
.share-pick-head { display: flex; justify-content: space-between; align-items: baseline; margin: 12px 0 4px; font-size: 0.8125rem; font-weight: 600; }
.share-pick { list-style: none; margin: 0 0 10px; padding: 0; max-height: 40vh; overflow-y: auto; }
.share-pick li { border-top: 1px solid var(--border); }
.share-pick label { display: flex; gap: 10px; align-items: flex-start; padding: 8px 2px; font-size: 0.875rem; cursor: pointer; }
.share-pick input { margin-top: 3px; flex: none; }
.share-pick .muted { font-size: 0.75rem; }
/* A list shared with you. */
.shared-box h3 { text-transform: none; letter-spacing: 0; font-size: 1rem; }
.shared-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0 0; }
/* Phones: the buttons keep one place at the top in every view (map, half, list), with their
   words; the map hint and the key sit under them, and the full list stops just below them. */
@media (max-width: 720px) {
  .map-tools, body[data-sheet="full"] .map-tools { top: calc(10px + env(safe-area-inset-top, 0px)); left: 8px; right: 8px; justify-content: flex-end; gap: 4px; }
  body[data-sheet="full"] .map-tools .map-btn { height: auto; min-height: 40px; flex: none; min-width: 44px; padding-top: 3px; padding-bottom: 3px; box-shadow: var(--shadow); }
  body[data-sheet="full"] .map-tools .map-btn .cap { display: block; }
  body[data-sheet="full"] #layers-toggle { display: inline-flex; }
  body[data-sheet="full"] .map-tools .lang-switch { padding: 2px; }
  body[data-sheet="full"] .map-tools .lang-switch button { min-height: 34px; }
  .map-hint { margin-top: 62px !important; }
  .layers-panel { top: calc(64px + env(safe-area-inset-top, 0px)); }
  .panel { max-height: calc(100% - 64px - env(safe-area-inset-top, 0px)); }
  .panel[data-sheet="full"] { height: calc(100% - 64px - env(safe-area-inset-top, 0px)); }
}
/* Empty stand-ins the sheet's heights are measured on (app.js): never seen. */
.sheet-probe { visibility: hidden; pointer-events: none; transition: none !important; z-index: -1; box-shadow: none; }
@media (min-width: 721px) { .sheet-probe { display: none; } }
/* A note under the buttons takes the hint's place while it shows (they overlapped). */
.status-on .map-hint { visibility: hidden; }
/* Nothing matches: three short lines, not one crowded row. */
.event-list li.empty-box { display: block; padding: 18px 16px; }
.empty-box p { margin: 0 0 10px; }
.empty-box .empty-title { color: var(--text); font-weight: 600; }
.empty-box .empty-on { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; }
.empty-box .empty-on span { color: var(--text); }
.empty-box .empty-hint { font-size: 0.8125rem; margin-bottom: 0; }
/* The kind chips' icons: the icon alone, in its dots' colour (Google Maps' chips). */
/* The icon is its own box, centred in the chip with the words (not sat on the text's line, which
   left it a pixel or two low). */
.chip .ic:has(.chip-glyph) { display: inline-flex; align-self: center; }
.chip-glyph { display: inline-grid; place-items: center; width: 18px; height: 18px; vertical-align: middle; }
.chip-glyph .glyph { width: 18px; height: 18px; fill: var(--g); }
.chip[aria-pressed="true"] .chip-glyph .glyph { fill: currentColor; }
.chip .ic svg.mime { vertical-align: -0.18em; margin: -0.15em 0; } /* centred like the emoji beside it */
/* Phones: the sheet always has the list's height; map, middle and list are how far it's slid
   down. Moving between them only changes the slide (smooth, no re-layout), never the height,
   so the sheet can't flash to full height when it lands. The list, details and chat get room
   at the bottom for the part that's off screen, so their ends can still be scrolled into view. */
@media (max-width: 720px) {
  .panel {
    --full-h: calc(100vh - 64px - env(safe-area-inset-top, 0px));
    --half-h: 55vh;
    max-height: none;
    transition: transform 0.3s cubic-bezier(.25, .7, .3, 1);
  }
  @supports (height: 100dvh) {
    .panel { --full-h: calc(100dvh - 64px - env(safe-area-inset-top, 0px)); --half-h: 55dvh; }
  }
  .panel, .panel[data-sheet="mini"], .panel[data-sheet="peek"], .panel[data-sheet="half"], .panel[data-sheet="full"] { height: var(--full-h); }
  .panel[data-sheet="full"] { --off: 0px; transform: none; }
  .panel[data-sheet="half"] { --off: calc(var(--full-h) - var(--half-h)); transform: translate3d(0, var(--off), 0); }
  .panel[data-sheet="peek"] { --off: calc(var(--full-h) - var(--peek)); transform: translate3d(0, var(--off), 0); }
  .panel[data-sheet="mini"] { --off: calc(var(--full-h) - var(--mini)); transform: translate3d(0, var(--off), 0); }
  /* A dropped pin: its card is the sheet (as Google Maps'), so the list slides away under it. */
  body:is(.pin-down, .home-open) .panel:not(.sheet-probe)[data-sheet="peek"], body:is(.pin-down, .home-open) .panel:not(.sheet-probe)[data-sheet="mini"] { --off: calc(var(--full-h) + 24px); transform: translate3d(0, var(--off), 0); }
  .panel.dragging { transition: none; }
  .panel .results, .panel .detail, .panel .chat-log { scroll-padding-bottom: var(--off, 0px); }
  .panel .results::after, .panel .detail::after { content: ""; display: block; height: var(--off, 0px); }
}
/* What a chip means, said under its row after a tap. */
.chip-hint { margin: -2px 16px 8px; font-size: 0.75rem; color: var(--muted); }
.chip-hint[hidden] { display: none; }
.more-filters .chip-hint { margin: -4px 0 0; }
/* Active top buttons: their word as readable as their icon (white on the colour). */
.map-btn[aria-pressed="true"] .cap, .map-btn[aria-pressed="true"] .btn-text { color: inherit; }
.saved-btn[aria-pressed="true"] span[aria-hidden] { color: var(--on-star); }
/* Distances stay on one line ("50 m"), and badges keep their distance from them. */
.event-list .dist { white-space: nowrap; }
/* (badges: no left margin; a space before each lines one up when it starts a line) */
/* Computers and tablets: the map hint sits below the top buttons, never under them. */
@media (min-width: 721px) { .map-hint { margin-top: 60px !important; } }
@media (min-width: 721px) and (max-width: 1100px) { .map-hint { margin-top: 112px !important; } }
/* Rows of chips that shouldn't hide anything behind a scroll: the choices in Filters wrap onto
   more lines (with large text too). The rows on top of the list (dates, kinds of event) scroll
   sideways on one line, with a › arrow on computers. */
.more-filters .chip-row { flex-wrap: wrap; overflow: visible; -webkit-mask-image: none; mask-image: none; }
.more-filters .chip-row .chip-arrow { display: none; }
.more-filters .price-row { gap: 5px; } .more-filters .price-row .chip { padding-left: 9px; padding-right: 9px; } /* (the five prices on one line on a phone, French too) */

/* "Show N events" at the foot of Filters: stays in reach while the chips scroll. */
.more-filters .filters-done {
  position: sticky;
  bottom: 0;
  align-self: stretch;
  margin-top: 4px;
  padding: 10px 14px;
  box-shadow: 0 -8px 12px var(--bg), 0 24px 0 12px var(--bg); /* (and a solid band under it: no row shows through below) */
}

/* Searching: "3 places match too" above the events; a place's coming events. */
.event-list li.list-places { padding: 6px 16px; border-bottom: 1px solid var(--border); font-size: 0.875rem; cursor: default; }
.place-events ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.place-events li { font-size: 0.8438rem; line-height: 1.35; }
.place-events .muted { display: block; font-size: 0.75rem; }

/* The name: the opening screen's wordmark, small (the tower, "Paris", "ce soir" in copper). */
.panel-header h1.brand {
  display: inline-flex; align-items: flex-end; gap: 6px;
  font: 400 1.5rem/1 var(--serif); letter-spacing: 0; color: var(--accent);
  white-space: nowrap;
}
.brand i { font-style: italic; color: var(--logo); }
.brand-mark { width: auto; height: 1.45em; flex: none; margin-bottom: .02em; }
@media (max-width: 720px) { .panel-header h1.brand { font-size: 1.375rem; } }

/* Price and ages in a list row: small outlined tags after the place, not bold text in the line. */
/* Rows: status and time on one line, then where · price · age · marks in grey on one line of
   its own (a long venue ends in "…"); price and age as plain text, only status gets pills. */
.event-list .meta .tag { color: var(--muted); white-space: nowrap; }
.event-list .meta.sub { line-height: 1.5; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: flex; }
/* A long venue gives way; the price and ages after it stay in sight. */
.event-list .meta.sub .venue { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.event-list .meta.sub .info { flex: none; white-space: pre; }
/* The marks (Now, Free, Open day, ♿…) on a line of their own under the title, as on the details. */
.marks-row { margin: 3px 0 2px; line-height: 1.35; font-size: 0.7812rem; color: var(--muted); }
.marks-row .badge { margin: 0; vertical-align: 0; }
/* "Open on…": only as wide as what it says, wider once a day is picked. */
.chip-select { field-sizing: content; }
/* Place colours in Key & layers: the same dots as on the map. */
.legend i.swatch { display: inline-block; width: 11px; height: 11px; border-width: 1.5px; box-shadow: 0 0 0 1px rgba(0, 0, 0, .12); margin-right: 6px; vertical-align: -1px; flex: none; }

/* List rows: the event's photo (or its kind's icon on a tile in its colour) at the left. */
.event-list .row-thumb {
  position: relative; flex: none; width: 52px; height: 52px; margin-top: 2px;
  border-radius: 10px; overflow: hidden;
  background: color-mix(in srgb, var(--g, var(--g-other)) 14%, var(--bg));
  display: grid; place-items: center;
}
.event-list .row-thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.event-list li { gap: 12px; }
.event-list li.in-group .row-thumb { width: 40px; height: 40px; margin-left: 12px; }

/* Place photos: one shared colour grade, so photos from many cameras look like one set: a little
   warmer, a little softer in colour, a touch more contrast. Light enough that places stay easy to
   know. To try another look, change --place-grade; "none" turns it off. */
:root { --place-grade: sepia(.12) saturate(.88) contrast(1.06) brightness(1.02); }
:root.app-dark { --place-grade: sepia(.12) saturate(.85) contrast(1.04) brightness(.92); }
.photo-wrap.place img, .row-thumb.place img { filter: var(--place-grade); }

/* Place photos: "©" in the corner shows the credit its licence asks for, over the photo. */
.photo-wrap { position: relative; }
.photo-wrap img[hidden] ~ .photo-c { display: none; }
.photo-c {
  position: absolute; right: 8px; bottom: 8px; width: 22px; height: 22px; padding: 0;
  border: none; border-radius: 50%; background: rgba(0, 0, 0, .45); color: #fff;
  font: 600 12px/22px var(--sans); cursor: pointer; z-index: 1; /* above the credit, so it closes it too */
}
.photo-c[aria-expanded="true"] { background: rgba(0, 0, 0, .7); }
/* "Don't like this photo?" just under a place's photo, at its right (on the line of the kind above
   the title), as small and grey as "Report a mistake". */
.photo-dislike { position: absolute; right: 0; top: calc(100% + 10px); z-index: 1; font-size: 0.75rem; color: var(--muted); }
.photo-dislike:disabled { text-decoration: none; cursor: default; }
.photo-wrap img[hidden] ~ .photo-dislike { display: none; }
.photo-wrap:has(.photo-dislike) + .ev-title .kicker { padding-right: 13.5rem; } /* (a long kind never runs under it) */
.photo-credit {
  position: absolute; left: 0; right: 0; bottom: 0; margin: 0; padding: 8px 38px 8px 10px;
  border-radius: 0 0 12px 12px; background: rgba(0, 0, 0, .6); color: #fff; font-size: 0.6875rem; line-height: 1.35; cursor: pointer;
}
.popup .photo-credit { border-radius: 0 0 8px 8px; bottom: 8px; }
.popup .photo-c { bottom: 16px; }
.photo-credit a { color: inherit; text-decoration: underline; }
/* "On here soon" on a place: each event with its small picture. */
.place-events li { display: flex; gap: 10px; align-items: center; }
.place-events .row-thumb { position: relative; flex: none; width: 40px; height: 40px; border-radius: 8px; overflow: hidden;
  background: color-mix(in srgb, var(--g, var(--g-other)) 14%, var(--bg)); display: grid; place-items: center; }
.place-events .row-thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 0; margin: 0; }
.place-events li[hidden] { display: none; }
.place-events .pe-all { margin-top: 8px; }
/* "More like this": photo tiles to swipe through, as Google Maps' "People also search for" (Felix, look B). */
.more-like .ml-tiles { display: flex; gap: 10px; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; padding-bottom: 4px;
  touch-action: pan-x pan-y; overscroll-behavior-x: contain; } /* (swipes itself, never the browser's Back) */
.more-like .ml-wrap { position: relative; }
.more-like .ml-arrow { display: none; }
@media (hover: hover) and (pointer: fine) {
  .more-like .ml-arrow { display: flex; align-items: center; justify-content: center; position: absolute; top: 30px; z-index: 1; width: 36px; height: 36px; padding: 0;
    border: 0; border-radius: 50%; background: var(--bg); color: var(--text); box-shadow: 0 1px 4px rgba(60, 36, 20, .3); cursor: pointer; }
  .more-like .ml-arrow svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
  .more-like .ml-arrow:hover { background: var(--bg-soft); }
  .more-like .ml-arrow.left { left: 6px; }
  .more-like .ml-arrow.right { right: 6px; }
  .more-like.at-start .ml-arrow.left, .more-like.at-end .ml-arrow.right { display: none; }
}
.more-like .ml-tiles::-webkit-scrollbar { display: none; }
.more-like .ml-tile { flex: 0 0 44%; max-width: 180px; scroll-snap-align: start; display: flex; flex-direction: column; padding: 0; text-align: left;
  font: inherit; color: var(--text); background: var(--bg); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; cursor: pointer; }
.more-like .ml-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.more-like .ml-tile .row-thumb { position: relative; display: flex; align-items: center; justify-content: center; background: color-mix(in srgb, var(--g, var(--accent)) 14%, transparent); width: 100%; height: 96px; margin: 0; border-radius: 0; flex: none; }
.more-like .ml-tile .row-thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 0; margin: 0; }
.more-like .ml-tile b { padding: 8px 10px 2px; font-family: var(--serif); font-weight: 700; letter-spacing: -0.005em; font-size: 0.875rem; line-height: 1.25; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.more-like .ml-tile .ml-when { padding: 0 10px 10px; font-size: 0.75rem; color: var(--muted); }

/* Key & layers: each entry as its symbol in a fixed column and its words beside it, wrapping
   under the words (not under the symbol); the longer explanations take the full width. */
.legend { gap: 6px 14px; }
.legend { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } /* (the two columns stay inside the card) */
.legend > span { display: grid; grid-template-columns: 18px minmax(0, 1fr); column-gap: 7px; align-items: center; line-height: 1.3; } /* (a long French label wraps, not clipped) */
.legend > span > i { justify-self: center; position: relative; top: -1px; } /* (on the text's middle) */
.legend > span > i.legend-emoji { width: auto; }
.legend > span.wide { grid-column: 1 / -1; }
@media (min-width: 721px) { .legend { grid-template-columns: auto auto; justify-content: start; column-gap: 24px; } } /* (computers: each name on one line) */

/* A row's description: room between its lines, so a tag on the second line doesn't touch the badge above. */
.event-list .meta { line-height: 1.75; }
.legend .legend-star { width: 15px; height: 15px; justify-self: center; }

/* Preview card of a group tapped on the map: where you are among its ones (swipe for the others). */
.preview-group { display: flex; align-items: baseline; gap: 4px; }
.preview-group .preview-step { align-self: center; margin-block: -10px; } /* (its tap-sized arrows overhang: the line keeps the label's height) */
/* The kind's dot on the capitals' middle, whatever the phone's font: exactly as tall as a capital,
   standing on the baseline (an empty box's baseline is its bottom). */
.preview-group .tip-group { width: 0.72em; height: 0.72em; width: 1cap; height: 1cap; margin: 0 3px 0 0; }
.preview-step {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  color: var(--text);
}
.preview-step button {
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  font-size: 1.1rem;
  line-height: 1;
  padding: 0 8px;
  min-width: 40px;
  min-height: 40px; /* a fingertip, also for quick taps */
  cursor: pointer;
}
.preview-step button:disabled { opacity: 0.25; cursor: default; }
/* The dot a card or page is about: a little bigger, its own white edge then a thin accent line,
   and a soft shadow. */
.leaflet-marker-icon.current .dot { transform: scale(1.35); box-shadow: 0 0 0 2px var(--bg), 0 0 0 4.5px var(--accent), 0 2px 6px rgba(0, 0, 0, 0.35); } /* (the open one: bigger, a cream gap, then a copper ring: clear on every colour) */
/* A place's preview: its photo as the banner, with the "©" credit over it. */
.preview .photo-wrap { margin: -12px -16px 8px; }
.preview .photo-wrap .preview-photo { margin: 0; width: 100%; }
.preview .photo-credit { border-radius: 0; }
.leaflet-marker-icon.current .star-mark { transform: scale(1.3); filter: drop-shadow(0 0 1.5px var(--text)) drop-shadow(0 0 1px var(--text)); }

/* Above the list: its count, and "On the map / All" (what the list covers). */
.list-head { display: flex; align-items: center; gap: 8px; padding: 8px 16px 8px 0; }
.list-head h2 { flex: 1; min-width: 0; }
/* The count stays on one line; on a narrow phone it gets a bit tighter, and a very long one
   (a date range, a near-me note) ends in "…" (the full text is in its tooltip). */
.list-head #result-count { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.list-head #result-count { letter-spacing: 0.03em; padding-top: 8px; padding-bottom: 8px; } /* (a bit tighter than other headings: "65 aujourd’hui · +2 en cours" fits beside On the map / All) */
@media (max-width: 480px) { .list-head #result-count { padding-right: 0; } }
.list-scope { display: inline-flex; flex: none; padding: 2px; border-radius: 999px; background: var(--bg-soft); border: 1px solid var(--border); }
.list-scope[hidden] { display: none; }
.list-scope button {
  border: 0; background: none; color: var(--muted); font: inherit; font-size: 0.75rem;
  padding: 4px 10px; border-radius: 999px; cursor: pointer; white-space: nowrap;
}
.list-scope button[aria-pressed="true"] { background: var(--raised); color: var(--text); font-weight: 600; box-shadow: 0 1px 2px rgba(60, 36, 20, 0.15); }

/* "Larger text" (Key & layers): sizes are in rem, so this scales the panel, cards and popups. */

/* A tapped photo, big. */

/* The popup's ✕ on a round chip, so it shows on top of a light photo too. */
.leaflet-container a.leaflet-popup-close-button {
  top: 6px; right: 6px; width: 30px; height: 30px; border-radius: 50%;
  font: 600 20px/29px var(--sans); text-align: center;
  background: rgba(255, 255, 255, .92); color: #1d2433; box-shadow: 0 1px 4px rgba(0, 0, 0, .35);
}
.leaflet-container a.leaflet-popup-close-button:hover { background: #fff; color: #000; }

/* A place's week: one row per day (or run of days alike), today's row marked. */
table.week-hours { border-collapse: collapse; margin: 4px 0 0; font-size: 0.8125rem; color: var(--muted); }
table.week-hours th { min-width: 4.5rem; text-align: left; font-weight: 600; padding: 1px 16px 1px 0; white-space: nowrap; vertical-align: top; } /* (each table as wide as its own labels, then a fixed gap) */
table.week-hours td { padding: 1px 0; }
table.week-hours tr.today { color: var(--text); }
/* Today's row: a small arrow pointing at it, in the margin so the days stay lined up. One indent
   for every week table (event and place, card and page) and the notes under it; prices never. */
:root { --week-indent: 0px; --week-mark: 18px; } /* (the days start where the words do; today in bold, as Google Maps) */
table.week-hours { margin-left: var(--week-indent); }
table.week-hours tr.today th { position: relative; }
table.week-hours tr.today :is(th, td) { font-weight: 700; }
.hours-status { margin: 4px 0 0; font-size: 0.8125rem; color: var(--muted); }
.hours-status.closed { margin: 0; color: var(--text); font-weight: 600; }
table.week-hours.price-table { margin-left: 0; } /* (prices start where the words do) */
/* Without "Paid" over it, the table starts on the 💶 line, where the words begin. */
.facts li > div > table.price-table:first-child, .facts .price-lead + table.price-table { margin-left: 0; margin-top: 0; }
.facts .price-lead { margin: 0 0 2px; font-size: 0.8125rem; }
table.price-table th { white-space: nowrap; max-width: 60%; }
table.price-table th.wrap { white-space: normal; } /* (long labels only) */
table.price-table td { color: var(--text); }
table.price-table td .aside { font-size: 0.9em; } /* (a long name's brackets, after its amount: see labelAside) */
.price-note { margin: 2px 0 0; font-size: 0.8125rem; }
.week-hours-note { margin: 2px 0 0; font-size: 0.75rem; }

/* Small phones (360 px): the zoomed-out names and numbers overlapped ("9e10e"): smaller and
   tighter, so each arrondissement's pair stays apart. */
@media (max-width: 380px) {
  .overview .arr-label b { font-size: 0.5625rem; letter-spacing: 0; }
  .overview .arr-label .arr-word { display: none; }
  .overview .arr-count { min-width: 22px; padding: 0 5px; font-size: 0.6875rem; }
}
.am-popup > :first-child { padding-right: 30px; } /* clear of the ✕ */
/* My list: Share and Archive side by side; the archive's rows and buttons. */
.saved-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 16px 0; }
.saved-actions .share-saved { margin: 0; }
.saved-actions:not(:has(button:not([hidden]))) { display: none; }
.event-list li[data-arch] { flex-wrap: wrap; }
.arch-actions { display: flex; gap: 6px; align-items: center; }
.event-list li[data-arch] .arch-actions { width: 100%; justify-content: flex-end; }
.button.went { white-space: nowrap; }
.button.went[aria-pressed="true"] { border-color: var(--free, #2e7d32); color: var(--free, #2e7d32); }
/* Big screens: a little wider side panel (long titles); the chips are on the map now, so the
   map gets the rest, as on Google Maps (about 410 px there). */
@media (min-width: 1500px) { :root { --panel-width: 410px; } }
@media (min-width: 1800px) { :root { --panel-width: 430px; } }
/* A laptop is read from further away than a phone: 1rem is 16px there (the browser's own size),
   the panel as much wider. */
@media (min-width: 1101px) and (hover: hover) and (pointer: fine) {
  html { font-size: 100%; }
  :root { --panel-width: 400px; }
}
@media (min-width: 1500px) and (hover: hover) and (pointer: fine) { :root { --panel-width: 420px; } }
@media (min-width: 1800px) and (hover: hover) and (pointer: fine) { :root { --panel-width: 440px; } }
/* Details bar with "✓ I went" too: on a narrow phone the buttons wrap under each other on the
   right, Back staying at the top left. */
.detail-bar { flex-wrap: wrap; gap: 8px; align-items: flex-start; }
.detail-bar .detail-actions { flex-wrap: wrap; justify-content: flex-end; flex: 1 1 auto; }
.am-text { padding-right: 30px; } /* clear of the ✕ */

/* Photos: not draggable or long-pressable (no "open image" menu); those in details and popups
   aren't buttons. (The preview card's photo still opens the details.) */
img.photo, .row-thumb img { -webkit-user-drag: none; user-select: none; -webkit-touch-callout: none; }
.detail img.photo, .popup img.photo { pointer-events: none; }
/* Wheelchair access, in lists and on cards: one light ♿ (the details say full or partial). */
/* The wheelchair sign: our own drawing, white on the sign's blue, a badge's height (not the emoji). */
.access-mark, .access-sign { display: inline-grid; place-items: center; flex: none; width: 1.25em; height: 1.25em; border-radius: 3px;
  background: #1f5fb4; color: #fff; vertical-align: -0.22em; font-size: 1em; }
.access-mark svg, .access-sign svg { width: 88%; height: 88%; }
.access-mark.limited { opacity: 0.45; } /* (limited access: the sign faded, its tooltip says "limited") */
/* In a row of badges: a badge itself (Felix, 2026-10-26): their height, corners and side room,
   the sign in its middle. */
.access-mark { box-sizing: border-box; height: 0.9rem; width: auto; padding: 0 2px; border-radius: 4px; font-size: 0.6875rem; vertical-align: -0.2em; }
.access-mark svg { width: 1.2em; height: 1.2em; }
/* A venue's (a place's) name on one line, the address below it. */
.facts .venue-name { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.facts li > div { min-width: 0; } /* (so a line in it can end in "…" rather than run past the edge) */

/* A photo that failed to load takes its © with it. */
.photo-wrap:not(:has(img, .photo)) { display: none; }
.ph-only > :is(.photo-c, .photo-credit, .photo-dislike) { display: none; }

/* No photo yet: a soft tint of the kind's colour with its icon in that colour in the middle, the
   same size and corners as a photo (app.js phIcon on tiles, phPhoto on banners). */
.row-thumb .ph { display: grid; place-items: center; height: 46%; aspect-ratio: 1; }
.row-thumb .ph .glyph { display: block; width: 100%; height: 100%; fill: var(--g, var(--g-other)); }
.event-list .pick-card .row-thumb .ph { height: 40px; }
.sc-ban .row-thumb.sc-photo .ph { height: 40px; margin-bottom: 18px; }
.ph-only > div.photo {
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--g, var(--g-other)) 14%, var(--bg));
}
.ph-only > div.photo .glyph { width: 56px; height: 56px; fill: var(--g, var(--g-other)); }
/* (dark mode: places' colours are the same as by day, so their icon is lifted to stay clear) */
:root.app-dark :is(.row-thumb.place .ph, .ph-only.place > div.photo) .glyph { fill: color-mix(in srgb, var(--g) 70%, #fff); }
.detail-body .ph-only > div.photo { height: 210px; border-radius: 12px; }
.popup .ph-only > div.photo { height: 150px; border-radius: 8px; margin-bottom: 8px; }
.popup .ph-only > div.photo .glyph, .ph-only > div.preview-photo .glyph { width: 44px; height: 44px; }


/* My list: its two tabs at the top (coming up / archive). */
.saved-tabs { display: flex; margin: 10px 16px 0; width: fit-content; }
.saved-tabs[hidden] { display: none; }
.saved-tabs button { font-size: 0.8125rem; padding: 6px 14px; }

/* Details: a slim toolbar centred between the sheet's handle and the photo. Back is a round
   chevron on the left; I went, Share and Save soft pills on the right, drawn icon and word;
   Save fills gold and I went turns green once on. Narrow phones: the icons alone. */
.detail-bar { padding: 8px 16px 6px; background: var(--bg); border-bottom: none; box-shadow: none; flex-wrap: nowrap; align-items: center; }
/* (The gap under the bar is the bar's own: the same while the page scrolls under it.) */
.detail-bar + .detail-body { padding-top: 0; }
.detail-bar .detail-actions { flex-wrap: nowrap; gap: 6px; }
.detail-bar .bar-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  min-height: 32px; padding: 0 12px 0 10px; margin: 0; border: none; border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 8%, var(--bg)); color: var(--accent);
  font-size: 0.8125rem; font-weight: 600; line-height: 1; box-shadow: none; cursor: pointer;
  transition: background-color 0.15s, color 0.15s;
}
.detail-bar .bar-btn:hover { background: color-mix(in srgb, var(--accent) 15%, var(--bg)); }
.detail-bar .bar-btn:active { transform: scale(0.97); }
.bar-icon { width: 16px; height: 16px; flex: none; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.detail-bar .bar-back { width: 34px; min-height: 34px; padding: 0; }
.detail-bar .bar-back .bar-icon { width: 18px; height: 18px; stroke-width: 2.4; }
.detail-bar .bar-save[aria-pressed="true"] { background: color-mix(in srgb, var(--star) 16%, var(--bg)); color: color-mix(in srgb, var(--star) 75%, var(--text)); }
.detail-bar .bar-save[aria-pressed="true"] .bar-icon { fill: var(--star); stroke: var(--star); }
.detail-bar .bar-went[aria-pressed="true"] { background: color-mix(in srgb, #2e8b57 14%, var(--bg)); color: color-mix(in srgb, #2e8b57 80%, var(--text)); }
@media (pointer: coarse) { .detail-bar .bar-btn { min-height: 34px; } }
/* On computers: "‹ 3 / 41 ›" in the middle, between Back and the pills, for the one before or after in the list
   (phones swipe instead). */
.detail-bar .detail-step { display: none; margin: 0 auto; font-size: 0.8125rem; color: var(--muted); }
@media (hover: hover) and (pointer: fine) { .detail-bar .detail-step { display: inline-flex; } .detail-bar .detail-step + .detail-actions { flex: none; } }
.detail-bar .detail-step button { min-width: 32px; min-height: 32px; padding: 0 6px; border-radius: 999px; color: var(--accent); }
.detail-bar .detail-step button:not(:disabled):hover { background: color-mix(in srgb, var(--accent) 12%, var(--bg)); }

/* Details, Google Maps style (Felix picked it, 2026-10-25): no toolbar. Back (and "‹ 3 / 41 ›" on
   computers) float as white round buttons on the photo's top left, like the map's own buttons,
   and stay there while the page scrolls. With no photo, the page starts lower to make room. */
#detail .detail-bar { position: sticky; top: 0; z-index: 5; display: block; height: 0; padding: 0; overflow: visible; background: none; }
#detail .detail-bar + .detail-body { padding-top: 12px; }
#detail .detail-body:not(:has(> .photo-wrap:first-child > :is(img.photo:not([hidden]), div.photo), > .st-hero:first-child)) { padding-top: 58px; }
/* (no photo: Back sits on the text's own left edge, flat, not floating on nothing) */
#detail:not(:has(.detail-body > .photo-wrap:first-child > :is(img.photo:not([hidden]), div.photo), .detail-body > .st-hero:first-child)) .detail-bar .bar-back { top: 12px; left: 16px; box-shadow: none; background: var(--bg-soft); }
#detail .detail-bar .bar-back {
  position: absolute; top: 22px; left: 26px; width: 38px; min-height: 38px; height: 38px;
  background: var(--bg); color: var(--text); box-shadow: 0 1px 4px rgba(60, 36, 20, 0.3);
}
#detail .detail-bar .bar-back:hover { background: var(--bg-soft); }
#detail .detail-bar::before { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 56px; background: var(--bg); box-shadow: 0 1px 0 var(--border); opacity: 0; pointer-events: none; transition: opacity .15s; }
#detail.scrolled .detail-bar::before { opacity: 1; }
/* Scrolled: the name beside Back, in the serif, one line (phones; computers have "‹ 3 / 41 ›" there). */
#detail .detail-bar::after { content: attr(data-name); position: absolute; left: 62px; right: 16px; top: 0; height: 56px; line-height: 56px;
  font: 700 1rem/56px var(--serif); color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; opacity: 0; pointer-events: none; transition: opacity .15s; }
#detail.scrolled .detail-bar::after { opacity: 1; }
@media (hover: hover) and (pointer: fine) { #detail .detail-bar::after { display: none; } }
#detail.scrolled .detail-bar .bar-back { top: 9px; left: 16px; box-shadow: none; background: var(--bg-soft); }
#detail.scrolled .detail-bar .detail-step { top: 9px; left: 62px; box-shadow: none; }
#detail .detail-bar .detail-step {
  position: absolute; top: 22px; left: 72px; height: 38px; margin: 0; padding: 0 4px; align-items: center;
  border-radius: 19px; background: var(--bg); box-shadow: 0 1px 4px rgba(60, 36, 20, 0.3);
}

/* The round buttons under the name: Directions, Save, Share, Calendar or Nearby, Website, Map.
   An accent circle with its word under it; Saved fills in the accent colour (the one "on" look).
   More than fit (narrow phones, long French words): the row scrolls sideways. */
.act-row {
  display: flex; justify-content: space-between; gap: 0; margin: 16px 0 0; padding: 0 0 16px;
  border-bottom: 1px solid var(--border); overflow-x: auto; scrollbar-width: none;
}
.act-row::-webkit-scrollbar { display: none; }
/* Only two or three (a station): side by side from the left, not spread across the width. */
.act-row:not(:has(> :nth-child(4))) { justify-content: flex-start; gap: 14px; }
.act-row:not(:has(> :nth-child(4))) > .act { flex: 0 0 auto; }
.act {
  flex: 1 1 0; display: flex; flex-direction: column; align-items: center; gap: 6px; /* (equal columns, whatever the words) */
  min-width: max-content; padding: 2px 3px 0; border: 0; background: none; color: var(--text); /* (labels in ink; the circles pale blue with navy icons, Felix picked A) */
  font: inherit; font-size: 0.75rem; font-weight: 600; line-height: 1.2; text-decoration: none; text-align: center;
  white-space: nowrap; cursor: pointer;
}
.act .act-c {
  width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center;
  background: var(--act-bg); border: 1px solid color-mix(in srgb, var(--status) 22%, var(--act-bg)); color: var(--status);
  transition: background-color 0.15s, color 0.15s;
}
.act .bar-icon { width: 20px; height: 20px; }
.act:hover .act-c { background: color-mix(in srgb, var(--act-bg) 82%, var(--status)); }
.act:active .act-c { transform: scale(0.95); }
.act:focus-visible { outline: none; }
.act:focus-visible .act-c { outline: 2px solid var(--accent); outline-offset: 2px; }
.act[aria-pressed="true"] .act-c { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.act[aria-pressed="true"] .bar-icon { fill: currentColor; }

/* Key: every symbol centred in the same 22 px box, every row the same height, so the words line
   up down both columns whatever the symbol (dot, ring, star, emoji). */
.legend { gap: 4px 14px; }
.legend > span { grid-template-columns: 22px 1fr; column-gap: 8px; min-height: 22px; }
.legend > span > i, .legend > span > svg { margin: 0 !important; justify-self: center; align-self: center; vertical-align: middle; }
.legend > span > i.tip-group, .legend > span > i.swatch { width: 10px; height: 10px; }
.legend > span > i.tip-group.ring-free { box-shadow: 0 0 0 2px var(--free); }
.legend > span > i.tip-group.ring-live { box-shadow: 0 0 0 2px var(--bg), 0 0 0 3.5px var(--g); }
.legend > span > i.legend-emoji, .legend > span > i.saved-sample { width: 22px; font-size: 15px; line-height: 22px; text-align: center; }
.legend > span > i.swatch.dot.live::after { inset: -4px; }
/* Free and On now: a plain grey dot with the white edge, as on the map, so the green ring and the
   pulse stand out (a dark blue middle was hard to tell from the ring). */
.legend > span > i.key-plain { --g: #9ba1ad; width: 14px; height: 14px; background: var(--g); border: 1.5px solid #fff; border-radius: 50%; box-sizing: border-box; }
.legend > span > i.tip-group.key-plain.ring-free { box-shadow: 0 0 0 2.5px var(--free); }
:root.app-dark .legend > span > i.key-plain { --g: #7d8492; }
.legend > span > i.key-plain.live::after { border-color: #4f5562; }
:root.app-dark .legend > span > i.key-plain.live::after { border-color: #d3d7de; }
.legend .legend-star { width: 15px; height: 15px; }
/* The toilets switch: its words where the other switches have theirs, the two symbols after. */
.switch .am-key { order: 2; margin: 0 0 0 2px; }
/* Details on a phone: the browser scrolls them up and down itself; sideways is the swipe to the
   next one, handled by the page. */
@media (max-width: 760px) { .detail { touch-action: pan-y; } }

/* My list: the dates, kinds and Filters don't apply there, so they step aside (search stays);
   the two tabs and Share on one row, Share a soft pill like the details' toolbar; each tab's
   count a small badge. */
.saved-view .chip-row:has(> .chip[data-when]), .saved-view #type-chips, .saved-view #filters-toggle,
.saved-view #when-chip, .saved-view #open-chip { display: none; } /* (My list shows everything saved, any day) */
.saved-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 14px 16px 6px; }
.saved-head:not(:has(:is(#saved-tabs, button):not([hidden]))) { display: none; }
.saved-head .saved-tabs, .saved-head .saved-actions { margin: 0; }
.saved-head .saved-tabs { padding: 3px; }
.saved-head .saved-tabs button { display: inline-flex; align-items: center; gap: 6px; font-size: 0.875rem; padding: 6px 14px; }
.tab-count {
  display: inline-block; min-width: 18px; padding: 1px 6px; border-radius: 999px; font-size: 0.6875rem; font-weight: 700;
  line-height: 16px; text-align: center; background: color-mix(in srgb, var(--star) 18%, var(--bg)); color: color-mix(in srgb, var(--star) 80%, var(--text));
}
.tab-count.due { background: color-mix(in srgb, var(--accent) 12%, var(--bg)); color: var(--accent); }
.saved-head .share-saved {
  display: inline-flex; align-items: center; gap: 5px; min-height: 34px; padding: 0 14px 0 11px; border: none; border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 8%, var(--bg)); color: var(--accent); font-size: 0.8125rem; font-weight: 600;
}
.saved-head .share-saved:hover { background: color-mix(in srgb, var(--accent) 15%, var(--bg)); }
/* The Key's samples stand still (the map's rings pulse once as they appear). */
.legend .dot.live::after { animation: none; }
.price-verdict { margin-bottom: 2px; }
/* The toolbar stays above the photo as the details scroll under it. */
.detail-bar { z-index: 3; }

/* A place's "Source ↗" right under its About text (it is the About's source, not the page's). */
.place-about { margin-bottom: 0; }
.tags.about-src { margin-top: 3px; }
/* A fact starts with a capital ("Ages 4–10", "Collation incluse"), whatever wrote it. */
.facts li > div > p::first-letter, .facts .price-note::first-letter { text-transform: uppercase; }
/* A note under a week or price table lines up with the table's rows, not with the line above it. */
table.week-hours:not(.price-table) + :is(.price-note, .week-hours-note, .hours-status, p.muted) { margin-left: var(--week-indent); }
/* A ticket's rates side by side ("€25 adult · €23 reduced"): they wrap between rates, not inside one. */
td.price-group { white-space: normal; }
td.price-group .rate { white-space: nowrap; }
td.price-group .kind { color: var(--muted); font-weight: 400; }
tr.kinds td { font-size: 0.75rem; padding-bottom: 2px; } /* the kinds named once, above the prices */

/* List rows (events and places): the photo and the ☆ centred on the row's lines; the four lines
   (title, marks, time, where) a little closer together, still easy to read. */
.event-list li[tabindex] { align-items: center; padding-top: 9px; padding-bottom: 9px; }
.event-list li[tabindex] .title { line-height: 1.3; margin-bottom: 1px; }
.event-list li[tabindex] .marks-row { margin: 0 0 1.5px; line-height: 1.3; } /* (the same ~3px between all four lines) */
.event-list li[tabindex] .meta { line-height: 1.45; }
.event-list li[tabindex] .meta.sub { line-height: 1.4; }
/* Cards: the same space between each of their lines (kind, title, marks, time). */
#preview .marks-row { margin: 0 0 1px; }

/* ---------- One rhythm on the details pages and cards (final layout pass) ---------- */
/* Location: the venue's line, then the address or the meeting point, no empty line between. */
.facts .venue-name + br { display: none; }
/* Price tables start where the words do, after a verdict line as after a note (2px under it). */
.facts .price-verdict + table.price-table { margin-left: 0; margin-top: 2px; }
.facts .price-lead + table.price-table { margin-top: 2px; }
/* Week and price tables all start where the words do; today's ▸ hangs in the icon column. */
/* The second, grey lines of a fact in one size (the listing's notes, price notes). */
.facts .note, .facts .price-note, .facts .price-lead { font-size: 0.8125rem; }
/* The badges under a title: as far from the title as from the facts below. */
.ev-badges { margin: 6px 0 2px; line-height: 1.3; }
/* "All 12 dates" right under the About text: set apart as a section of its own. */
.detail-body .about + details.more-dates, .detail-body button.more + details.more-dates { margin-top: 12px; }
button.link.more { display: block; margin-top: 2px; }
/* Date rows: their text in the middle of the row (the border is under it). */
.date-list li { padding: 5px 0 4px; }
/* Card buttons: Details, Save and ✕ the same height. */
.preview .save { min-height: 38px; display: inline-flex; align-items: center; gap: 6px; padding: 0 14px; }
.save .flag-ic { flex: none; width: 16px; height: 16px; fill: currentColor; } /* (the same drawn flag as on the rows and the round button) */
/* List rows: the photo exactly in the middle (no leftover nudge); the ☆ as far from the right
   edge as the photo from the left. */
.event-list li[tabindex] .row-thumb { margin-top: 0; }
.event-list li[tabindex] { padding-right: 5px; }

.ev-badges + .facts { margin-top: 3px; } /* (the badges as far from the facts as from the title) */
/* Badges: the capitals in the middle of the pill whatever the font (trimmed to cap height and
   baseline, then padded evenly). */
@supports (text-box: trim-both cap alphabetic) {
  .badge { text-box: trim-both cap alphabetic; padding-top: 3px; padding-bottom: 3px; }
  /* (numbers in the middle of their bubbles, not 1-2 px high) */
  .cluster .cl-n { text-box: trim-both cap alphabetic; } /* (on the number itself: on the disc it didn't reach the text on Android) */
  .place-pin .pp-n, .ev-stack .pp-n { text-box: trim-both cap alphabetic; height: 15px; box-sizing: content-box; display: grid; place-items: center; }
}
/* A marks line holding only ♿: no taller than the glyph, so it doesn't look like a half-empty line. */
.marks-row:has(> .access-mark:only-child) { line-height: 1; }
/* Cards: the badges as far from the title as from the time line. */
#preview .marks-row { margin: -1px 0 1px; }
#preview .marks-row:has(> .access-mark:only-child) { margin: 2px 0 3px; }
/* A week table as close under its time line as an "Every Thu" line. */
.facts table.week-hours.event-week, .facts .when-line + table.week-hours, .facts p + table.week-hours:not(.price-table) { margin-top: 1px; }
/* Dark mode: badges as tinted chips with coloured words, not bright blocks that glow. */
:root.app-dark .badge { background: color-mix(in srgb, var(--free) 22%, var(--bg)); color: var(--free); }
:root.app-dark .badge.now { background: color-mix(in srgb, var(--status) 22%, var(--bg)); color: var(--status); }
:root.app-dark .badge.special { background: color-mix(in srgb, var(--special) 24%, var(--bg)); color: color-mix(in srgb, var(--special) 70%, white); }
:root.app-dark .badge.pick { background: color-mix(in srgb, var(--gold) 26%, var(--bg)); color: #e2c25a; } /* (not the green of Free) */
:root.app-dark .badge.cond { background: transparent; color: var(--muted); } /* (free with a ticket: grey, not the green of Free) */
:root.app-dark .badge.sold { background: color-mix(in srgb, var(--sold) 26%, var(--bg)); color: color-mix(in srgb, var(--sold) 70%, white); }
:root.app-dark .badge.wait { background: color-mix(in srgb, var(--wait) 26%, var(--bg)); color: color-mix(in srgb, var(--wait) 70%, white); }
:root.app-dark .badge.lang { background: color-mix(in srgb, var(--boundary) 30%, var(--bg)); color: var(--text); }
/* A "venue" that is really directions ("Devant la statue équestre de Louis XIV…"): in full. */
.facts .venue-name.directions { white-space: normal; }
/* Cards: Details a pill like Save and ✕ beside it. */
#preview .preview-actions .send { border-radius: 999px; }
/* Prices are never cut: their labels are kept short instead (see labelAside, event_facts.py). */
/* Metro, RER and tram lines, in their official colours: a round badge for the metro, a square
   one for the RER, a pill for trams ("T3b"). */
.line-badge {
  display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box;
  min-width: 1.45em; height: 1.45em; padding: 0 0.25em; margin-right: 2px; border-radius: 999px;
  min-width: round(1.45em, 1px); height: round(1.45em, 1px); /* (whole pixels: no half-pixel edge) */
  background: var(--lc); color: var(--lt); font-size: 0.75rem; font-weight: 700; line-height: 1;
  font-variant-numeric: normal; vertical-align: 0.1em; /* (a list row's tabular figures put the "1" off centre) */
}
.line-badge.rer { border-radius: 4px; }
.line-badge.tram { padding: 0 0.35em; }
.line-badge.bus { border-radius: 4px; padding: 0 0.3em; } /* Noctilien night buses */
.stations-row .station { display: inline-block; margin: 1px 0; }
/* Metro and RER stations on the map (zoomed in): the street sign's navy "M", the name closer in.
   A tap opens the station's card. */
.station-mark { display: flex; align-items: center; justify-content: center; }
.station-tap { background: none; border: 0; } /* the clear tap spot under the "M" */
.st-m {
  display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box;
  width: 18px; height: 18px; padding: 0; border-radius: 999px;
  background: #1d2b4f; color: #fff; border: 1.5px solid #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
  font: 800 11px/1 system-ui, -apple-system, sans-serif; letter-spacing: 0;
}
.st-m.rer { width: auto; min-width: 18px; padding: 0 2px; border-radius: 5px; font-size: 8.5px; }
.station-mark .st-name {
  display: none; position: absolute; left: calc(50% + 12px); top: 50%; transform: translateY(-50%);
  white-space: nowrap; font: 600 11.5px/1 system-ui, -apple-system, sans-serif; color: #1d2b4f;
  text-shadow: -1px -1px 0 #fff, 0px -1px 0 #fff, 1px -1px 0 #fff, -1px 0px 0 #fff, 1px 0px 0 #fff, -1px 1px 0 #fff, 0px 1px 0 #fff, 1px 1px 0 #fff; pointer-events: none;
}
.leaflet-stations-pane.named .st-name { display: block; }
:root.app-dark .station-mark .st-name { color: #dfe6f3; text-shadow: -1px -1px 0 #111, 0px -1px 0 #111, 1px -1px 0 #111, -1px 0px 0 #111, 1px 0px 0 #111, -1px 1px 0 #111, 0px 1px 0 #111, 1px 1px 0 #111; }
.station-mark .st-m.rer + .st-name { left: calc(50% + 14.5px); } /* (the wider RER badge) */
.leaflet-marker-icon.current .st-m { background: #c2185b; transform: scale(1.25); }
.kicker .st-m { width: 16px; height: 16px; font-size: 10px; box-shadow: none; vertical-align: -3px; margin-right: 2px; }
/* A station card's "M  METRO STATION": the badge in line with the middle of the capitals (the
   label's box trimmed to them, then both centred), not hanging below them. */
.st-kicker { display: flex; align-items: center; gap: 6px; }
.st-kicker .st-m { flex: none; margin: 0; vertical-align: 0; }
@supports (text-box: trim-both cap alphabetic) { .st-kicker > span { text-box: trim-both cap alphabetic; } }
.kicker .st-m.rer { width: auto; min-width: 16px; font-size: 7.5px; }
.st-key { display: inline-flex; vertical-align: -3px; margin-right: 6px; }
.switch .st-key { order: 2; margin: 0 0 0 2px; }
.st-key .st-m { box-shadow: none; }
.station-lines .station-line { display: inline-block; margin: 1px 12px 1px 0; white-space: nowrap; }
.station-events { margin: 0 -4px 8px; padding: 0; }
/* The last metro (event cards, station cards): one line per metro or RER line. */
.last-line { display: block; margin: 3px 0; }
.last-line .nowrap { white-space: nowrap; }
.last-more summary { cursor: pointer; color: var(--muted); font-size: 0.875rem; text-decoration: underline; list-style: none; }
.last-more summary::-webkit-details-marker { display: none; }
.last-more[open] summary { margin-bottom: 2px; }
.last-more p, .station-last { font-size: 0.9rem; margin: 0; }
.stations-row .line-badges { white-space: nowrap; }
.stations-row .station-name { font-weight: 500; }
.event-list .meta.sub .row-lines { flex: none; display: inline-flex; align-items: center; gap: 2px; margin-left: 6px; }
.event-list .meta.sub .row-lines + .info { margin-left: 3px; } /* (a space plus 3 px: the same ~6 px on both sides of the line circles; Felix, 2026-10-26) */
.event-list .meta.sub .row-lines .line-badge { font-size: 0.625rem; margin: 0; vertical-align: 0; }
/* Filters › Along a line: every line's badge, a tap picks it (and again to drop it). */
.line-filter[hidden] { display: none; }
.line-picker { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 12px; }
.line-pick { border: 2px solid transparent; background: none; padding: 2px; border-radius: 999px; cursor: pointer; line-height: 0; }
.line-pick .line-badge { font-size: 0.875rem; margin: 0; vertical-align: 0; }
.line-pick[aria-checked="true"] { border-color: var(--text); }
.line-pick:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
@media (pointer: coarse) { .line-pick .line-badge { font-size: 1rem; } }
/* "Starts in 20 min", "Ends in 10 min", "Closes in 40 min": amber, beside "Now"/"Open". */
.badge.soon { background: #fbe7bf; color: #7a4b00; }
:root.app-dark .badge.soon { background: color-mix(in srgb, #f0a830 26%, var(--bg)); color: #f6c46a; }
.event-list li.list-station .link .line-badges { display: inline-flex; gap: 2px; margin-right: 6px; vertical-align: -0.1em; }
.event-list li.list-station .line-badge { font-size: 0.6875rem; margin: 0; }
/* Line badges and the "M": the number or letter in the middle of its circle whatever the font
   (its box trimmed to the capitals' top and the baseline, then centred). */
@supports (text-box: trim-both cap alphabetic) {
  .line-badge > span, .st-m > span { text-box: trim-both cap alphabetic; }
}

/* Our picks tonight (data/picks.json): gold rows on top of the list, each with a short reason. */
.event-list li.picks-head { color: var(--brand); font-family: var(--serif); text-transform: none; letter-spacing: 0; font-size: 1.05rem; font-weight: 400; line-height: 1.3; align-items: baseline; padding-top: 18px; padding-bottom: 8px; padding-right: 16px; }
.event-list li.picks-head .other-picks { margin-left: auto; font-family: var(--sans); font-style: normal; font-weight: 600; }
.event-list li.picked { background: color-mix(in srgb, var(--gold) 10%, var(--bg)); box-shadow: inset 4px 0 0 var(--gold); }
.event-list li.picked:hover { background: color-mix(in srgb, var(--gold) 16%, var(--bg)); }
.pick-why { margin: 1px 0 2px; font-size: 0.78rem; line-height: 1.3; color: #7a5f00; }
:root.app-dark .pick-why { color: #e2c25a; }
.badge.pick { background: var(--gold); color: var(--gold-ink); } /* ✦ Pick: first of the marks, gold like the row */

/* First visit: one line of welcome above the list (closes for good). */
.welcome.off { display: none; }
.welcome { position: relative; margin: 10px 16px 2px; padding: 10px 36px 10px 12px; border-radius: 12px; background: color-mix(in srgb, var(--accent) 8%, var(--bg)); font-size: 0.86rem; line-height: 1.4; }
.welcome p { margin: 0; }
.welcome-close { position: absolute; top: 6px; right: 6px; width: 28px; height: 28px; border: 0; border-radius: 50%; background: none; color: var(--muted); font-size: 0.9rem; cursor: pointer; }
.welcome-close:hover { background: color-mix(in srgb, var(--accent) 10%, var(--bg)); }

/* Smart search: how the words in the box were read ("Showing: Free · Concerts · Tonight"). */
.query-read { margin: 6px 16px 0; font-size: 0.8rem; color: var(--muted); line-height: 1.35; }
.query-read b { color: var(--text, inherit); font-weight: 600; }

/* Our picks on a phone: photo cards in a row that swipes sideways, on a gold band. */
.event-list li.picks-cards { display: block; padding: 10px 0 14px; cursor: default; background: color-mix(in srgb, var(--gold) 8%, var(--bg)); }
.event-list li.picks-cards:hover { background: color-mix(in srgb, var(--gold) 8%, var(--bg)); }
.picks-cards-head { display: flex; align-items: baseline; margin: 0 16px 8px; font: 400 1.05rem/1.3 var(--serif); color: var(--brand); } /* (regular: Georgia's bold drew too much attention, Felix) */ /* (the brand's serif and copper, as on the opening screen) */
.picks-row { display: flex; gap: 10px; overflow-x: auto; padding: 0 16px 2px; scroll-snap-type: x mandatory; scroll-padding-inline: 16px; scrollbar-width: none; touch-action: pan-x pan-y; }
.picks-row::-webkit-scrollbar { display: none; }
.pick-card { position: relative; flex: none; display: flex; flex-direction: column; justify-content: flex-start; width: 168px; padding: 0; border: 0; border-radius: 12px; overflow: hidden; text-align: left; font: inherit; color: inherit; background: var(--bg); box-shadow: 0 1px 4px rgba(60, 36, 20, .12); scroll-snap-align: start; cursor: pointer; }
.pick-card-photo { position: relative; display: block; flex: none; height: 132px; }
.event-list .pick-card .row-thumb { width: 100%; height: 100%; margin: 0; border-radius: 0; }
.pick-card-why { position: absolute; left: 6px; top: 6px; max-width: calc(100% - 12px); box-sizing: border-box; background: var(--gold); color: var(--gold-ink); font-size: 0.68rem; font-weight: 700; line-height: 1.25; padding: 2px 6px; border-radius: 6px; }
/* The clamp sits on the inner span, so the padding around it never shows a third line. A long
   reason wraps to a second line instead of being cut. */
.pick-card-why > span { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* (one line, always: Felix 2026-10-26; tools/picks.py keeps reasons to 24 characters) */
/* The title at the photo's foot: white on a fade to dark, at most two lines. */
.pick-card-title { position: absolute; left: 0; right: 0; bottom: 0; padding: 28px 10px 8px; background: linear-gradient(transparent, rgba(0,0,0,.72)); color: #fff; font-size: 0.88rem; line-height: 1.25; text-shadow: 0 1px 2px rgba(0,0,0,.4); }
.pick-card-title > span { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.pick-card-text { display: block; padding: 7px 10px 9px; font-size: 0.78rem; line-height: 1.3; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* "Other picks ↻ 2/3", at the right of the picks' heading */
.other-picks { float: right; font: inherit; font-size: 0.75rem; letter-spacing: 0; text-transform: none; color: inherit; text-decoration: underline; text-underline-offset: 2px; cursor: pointer; background: none; border: 0; padding: 0; }
.other-picks .muted { text-decoration: none; opacity: .7; }
.picks-cards-head .other-picks { margin-left: auto; font-family: var(--sans); font-style: normal; font-weight: 600; }

/* The new map engine (MapLibre, glmap.js): its box shows the land colour; the app's dots lie on a
   see-through Leaflet layer on top, which lets taps through except on dots, pop-ups and buttons. */
.maplibregl-map { background: var(--land); }
.gl-overlay { position: absolute; inset: 0; }
.gl-overlay.leaflet-container { background: none; pointer-events: none; }
.gl-overlay .leaflet-popup { pointer-events: auto; }
/* The compass on a turned map (web/glmap.js), round like Google Maps': a tap turns north back up. */
.gl-compass[hidden] { display: none !important; }
.gl-compass.leaflet-bar { border: 0 !important; box-shadow: none; background: none; }
.gl-compass button { display: grid; place-items: center; width: 40px; height: 40px; border: 0; border-radius: 50%; background: var(--bg); cursor: pointer; padding: 0; box-shadow: 0 1px 4px rgba(60, 36, 20, .25); }
.gl-compass svg { width: 24px; height: 24px; }
@media (max-width: 720px) { .gl-overlay .leaflet-top.leaflet-right { top: calc(64px + env(safe-area-inset-top, 0px)); } }

/* ---------- toilets / water: the card for the nearest one (app.js) ---------- */
@media (max-width: 720px) { body[data-sheet="full"] .am-card { display: none; } } /* (phones: the list covers the map) */
.am-card {
  position: fixed; z-index: 1000; left: 8px; right: 8px; bottom: calc(var(--peek-h, 252px) + env(safe-area-inset-bottom, 0px) + 10px); /* just over the sheet, pulled down */
  background: var(--bg); color: var(--text); border: 1px solid var(--border); border-radius: 16px;
  box-shadow: var(--shadow); padding: 12px 44px 12px 14px; font-size: 0.875rem; line-height: 1.4;
}
.am-card[hidden] { display: none; }
:is(.am-card, .film-panel) .am-head { display: flex; gap: 10px; align-items: flex-start; }
:is(.am-card, .film-panel) .am-head .am-ico svg { width: 26px; height: 26px; display: block; margin-top: 1px; }
:is(.am-card, .film-panel) .am-text strong { font-size: 1rem; }
:is(.am-card, .film-panel) .am-row { display: flex; align-items: center; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
:is(.am-card, .film-panel) .am-row .button { display: inline-flex; align-items: center; min-height: 36px; padding: 0 14px; border-radius: 18px; text-decoration: none; font-weight: 600; }
:is(.am-card, .film-panel) .am-row .button.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.am-card .am-of { margin-left: auto; font-size: 0.8125rem; }
.am-card .am-x { position: absolute; top: 6px; right: 6px; width: 36px; height: 36px; border: 0; background: none; color: var(--muted); font-size: 18px; cursor: pointer; border-radius: 18px; }
.am-card .am-x:hover { background: var(--bg-soft); }
/* Shut now: faint; the one on the card: bigger. */
.amenity.closed { opacity: 0.4; filter: grayscale(1); }
.amenity.picked svg { transform: scale(1.6); transform-origin: center; }
.amenity.picked { z-index: 1000 !important; }
@media (min-width: 721px) {
  .am-card { left: calc(var(--panel-width) + 16px); right: auto; bottom: 24px; width: 380px; }
}
/* Just for fun views (Film locations, Day trips, Bike tours, Demonstrations) and Best baguettes are
   views of their own: no Events / Places tabs either, only what the view is about (Felix,
   2026-10-25). ✕ in the search bar brings them back. */
body.film-focus .mode-switch, body.tour-focus .mode-switch, body.trip-focus .mode-switch,
body.demo-focus .mode-switch, body.bread-focus .mode-switch, body.theme-focus .mode-switch { display: none !important; }
/* Filmed here (Key & layers, ☰): a clapper on each street. While it's on, a focus: no chips and
   no list, only the film spots, and the film locations in the list's place (app.js, setFilmFocus;
   not a card over the map: Felix, 2026-10-25). */
body.film-focus #map-chips, body.film-focus .list-head, body.film-focus #event-list, body.film-focus #welcome,
body.film-focus #hidden-note, body.film-focus #theme-note, body.film-focus #picks { display: none !important; }
/* Bike tours (Key & layers): orange route lines with their names at the start; a focus like the
   film locations (app.js, setTourFocus), the routes in the list's place (#tour-card). */
body.tour-focus #map-chips, body.tour-focus .list-head, body.tour-focus #event-list, body.tour-focus #welcome,
body.tour-focus #hidden-note, body.tour-focus #theme-note, body.tour-focus #picks { display: none !important; }
/* Day trips (Key & layers): the trips on their rings, a focus like the bike tours (app.js,
   setTripFocus), the trips by train time in the list's place (#trip-card). */
body.trip-focus #map-chips, body.trip-focus .list-head, body.trip-focus #event-list, body.trip-focus #welcome,
body.trip-focus #hidden-note, body.trip-focus #theme-note, body.trip-focus #picks, body.trip-focus #late-museums { display: none !important; }
.trip-panel .trip-tile { position: relative; overflow: hidden; background: var(--bg-soft); }
.trip-panel .trip-tile img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.trip-panel .film-row-text .muted + .muted { margin-top: 2px; }
.trip-panel .trip-week { margin: 10px 0 4px; }
.film-panel.tour-panel .tour-tile { background: #fde6d8; }
/* The list: two folding parts (nice trips open, speed loops folded), a photo on each row. */
.film-panel .tour-sec { margin-top: 12px; }
.film-panel .tour-sec > summary { display: flex; align-items: baseline; gap: 8px; padding: 8px 0; cursor: pointer; list-style: none; }
.film-panel .tour-sec > summary::-webkit-details-marker { display: none; }
.film-panel .tour-sec > summary::before { content: "›"; display: inline-block; width: 12px; color: var(--muted); transition: transform .15s; }
.film-panel .tour-sec[open] > summary::before { transform: rotate(90deg); }
.film-panel .tour-sec-name { font-weight: 700; font-size: 0.9375rem; }
.tour-sec-name svg.lic { width: 18px; height: 18px; color: var(--accent); margin-right: 5px; }
.film-panel .tour-sec > summary .muted { font-size: 0.8125rem; }
.tour-panel .tour-thumb { position: relative; flex: none; width: 64px; height: 64px; border-radius: 10px; overflow: hidden; background: #fde6d8; display: grid; place-items: center; }
.tour-panel .tour-thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.tour-panel .tour-thumb-ico svg { width: 28px; height: 28px; display: block; }
/* A route's page: the details fold, their first line says the gist. */
.tour-panel .tour-folds { margin-top: 14px; border-top: 1px solid var(--border); }
.tour-panel .tour-fold { border-bottom: 1px solid var(--border); }
.tour-panel .tour-fold > summary { display: flex; gap: 10px; align-items: flex-start; padding: 10px 0; cursor: pointer; list-style: none; }
.tour-panel .tour-fold > summary::-webkit-details-marker { display: none; }
.tour-panel .tour-fold > summary::after { content: "›"; margin-left: auto; padding-left: 8px; color: var(--muted); transition: transform .15s; }
.tour-panel .tour-fold[open] > summary::after { transform: rotate(90deg); }
.tour-panel .tour-fold > summary .ico { flex: none; width: 20px; text-align: center; }
.tour-panel .tour-fold-body { padding: 0 0 10px 30px; }
.tour-panel .tour-fold-body p { margin: 0 0 6px; }
.tour-panel .tour-kind { display: inline-block; margin: 10px 0 0; padding: 3px 10px; border-radius: 12px; font-size: 0.8125rem; font-weight: 600; background: #fde6d8; color: #8a3306; }
.tour-panel .tour-kind.speed { background: #fde2e1; color: #a50e0e; }
:root.app-dark .tour-panel .tour-kind { background: #4a2a17; color: #f7b98c; }
:root.app-dark .tour-panel .tour-kind.speed { background: #4d1f1e; color: #f6aea9; }
.film-panel.tour-panel .tour-tile svg { width: 28px; height: 28px; fill: initial; stroke: none; }
.tour-panel .film-row-text .muted + .muted { margin-top: 2px; }
:root.app-dark .film-panel.tour-panel .tour-tile { background: #4a2a17; }
:root.app-dark .tour-panel .tour-thumb { background: #4a2a17; }
.tour-start { display: flex; align-items: center; gap: 4px; width: auto !important; height: 22px !important; white-space: nowrap; pointer-events: auto; }
.tour-start svg { width: 16px; height: 16px; flex: none; filter: drop-shadow(0 1px 1.5px rgba(0,0,0,.3)); }
.tour-start span { font-size: 12px; font-weight: 600; color: #b8460a; text-shadow: 0 0 2px #fff, 0 0 2px #fff, 0 0 3px #fff; }
.tour-start.picked span { color: #8a3306; }
.tour-start.picked svg { width: 22px; height: 22px; }
.map-far .tour-start span { display: none; }
.tour-panel .tour-profile { margin: 10px 0 2px; }
.tour-panel .tour-profile svg { display: block; width: 100%; height: 64px; }
.tour-panel .tour-tags { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0 0; }
.tour-panel .tour-tags .tour-kind { margin: 0; }
.tour-panel .tour-level-why { margin: 4px 0 0; font-size: 0.8125rem; }
.tour-level { display: inline-block; padding: 1px 8px; border-radius: 10px; font-size: 0.75rem; font-weight: 700; line-height: 1.5; vertical-align: 1px; }
.tour-tags .tour-level { padding: 3px 10px; font-size: 0.8125rem; border-radius: 12px; }
.tour-level.easy { background: #e3f1e5; color: #1e6b2f; }
.tour-level.medium { background: #fdf0d3; color: #8a5a00; }
.tour-level.hard { background: #fde2e1; color: #a50e0e; }
.tour-level.pace { background: #e8eaed; color: #3c4043; }
:root.app-dark .tour-level.easy { background: #1f3a25; color: #a8dab5; } :root.app-dark .tour-level.medium { background: #43361a; color: #f3cf86; } :root.app-dark .tour-level.hard { background: #4d1f1e; color: #f6aea9; } :root.app-dark .tour-level.pace { background: #3c4043; color: #e8eaed; }
.tour-panel .tour-surf-key { display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: center; margin: 6px 0 0; font-size: 0.75rem; }
.tour-panel .tour-surf-key span { display: inline-flex; align-items: center; gap: 4px; }
.tour-panel .tour-surf-key svg { width: 22px; height: 6px; }
.tour-panel .tour-steep-key { float: right; display: inline-flex; gap: 10px; align-items: center; }
.tour-panel .tour-steep-key i { display: inline-block; width: 14px; height: 4px; border-radius: 2px; margin-right: 4px; vertical-align: middle; }
.tour-panel .tour-profile figcaption { font-size: 0.75rem; margin-top: 2px; }
.tour-panel .tour-facts { margin: 8px 0 0; }
.tour-panel .am-row { flex-wrap: wrap; }
/* Demonstrations (app.js, setDemoFocus): as the bike tours, in the list's place (#demo-card). */
body.demo-focus #map-chips, body.demo-focus .list-head, body.demo-focus #event-list, body.demo-focus #welcome,
body.demo-focus #hidden-note, body.demo-focus #theme-note, body.demo-focus #picks { display: none !important; }
.film-panel.demo-panel .demo-tile { background: #fce8e6; }
.film-panel.demo-panel .demo-tile.past { background: #ece8f4; color: #4a3d73; }
.film-panel.demo-panel .demo-tile b { font-size: 0.8125rem; font-variant-numeric: tabular-nums; }
.film-panel.demo-panel .demo-tile svg { width: 28px; height: 28px; fill: initial; stroke: none; }
.film-panel.demo-panel .demo-tile.row-thumb { position: relative; overflow: hidden; }
.film-panel.demo-panel .demo-tile img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* (A march photo has the crowd in its lower part, under the sky: keep that part in view.) */
.film-panel.demo-panel img.photo, .film-panel.demo-panel .demo-tile img { object-position: 50% 75%; }
:root.app-dark .film-panel.demo-panel .demo-tile { background: #4d1f1e; }
:root.app-dark .film-panel.demo-panel .demo-tile.past { background: #34304a; color: #d6cfee; }
.demo-panel .demo-row-about { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.demo-pin { display: flex; align-items: center; gap: 4px; width: auto !important; height: 22px !important; white-space: nowrap; pointer-events: auto; }
.demo-pin svg { width: 22px; height: 22px; flex: none; filter: drop-shadow(0 1px 1.5px rgba(0,0,0,.3)); }
.demo-pin.past svg { width: 18px; height: 18px; }
.demo-pin span { font-size: 12px; font-weight: 600; color: #b3261e; text-shadow: 0 0 2px #fff, 0 0 2px #fff, 0 0 3px #fff; }
.demo-pin.past span { color: #4a3d73; font-weight: 500; }
.demo-pin.picked span { font-weight: 700; }
.demo-end { width: 10px !important; height: 10px !important; border-radius: 50%; background: #fff; border: 3px solid #6b5b95; box-sizing: border-box; }
.demo-end.coming { width: 12px !important; height: 12px !important; border-color: #d93025; }
.film-panel.demo-panel .demo-tile.day { background: #feefc3; color: #8a3c00; }
:root.app-dark .film-panel.demo-panel .demo-tile.day { background: #4a3a10; color: #fdd663; }
.demo-station { display: flex; align-items: center; gap: 4px; width: auto !important; height: 14px !important; white-space: nowrap; }
.demo-station::before { content: ""; flex: none; width: 10px; height: 10px; border-radius: 50%; background: #fff; border: 2.5px solid #a50e0e; }
.demo-station span { font-size: 11px; font-weight: 600; color: #a50e0e; text-shadow: 0 0 2px #fff, 0 0 2px #fff, 0 0 3px #fff; }
.alert-march { margin: 2px 0 8px; font-size: 0.875rem; line-height: 1.4; }
.film-mark svg { width: 100%; height: 100%; display: block; filter: drop-shadow(0 1px 1.5px rgba(0,0,0,.3)); }
.film-mark.picked svg { transform: scale(1.5); transform-origin: center; }
.film-mark.picked { z-index: 1000 !important; }
.film-card .film-q { width: 100%; box-sizing: border-box; margin-top: 10px; min-height: 40px; padding: 0 14px; border: 1px solid var(--border); border-radius: 20px; background: var(--bg-soft); color: var(--text); font: inherit; font-size: 1rem; }
.film-card .film-hits { display: flex; flex-direction: column; margin-top: 8px; max-height: 236px; overflow-y: auto; }
.film-card .film-hit { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; text-align: left; padding: 7px 8px; margin: 0 -8px; border: 0; border-radius: 10px; background: none; color: var(--text); font: inherit; cursor: pointer; }
.film-card .film-hit:hover, .film-card .film-hit.on { background: var(--bg-soft); }
.film-card .film-hit > span:first-child { font-weight: 600; }
.film-card .film-hit .muted { font-size: 0.8125rem; }
.film-card .film-none, .film-card .film-note { margin: 8px 0 0; font-size: 0.8125rem; }
.film-card .film-sub { margin: 12px 0 0; font-size: 0.8125rem; font-weight: 700; color: #9a7208; }
.film-card .film-scene { margin: 10px 0 0; font-size: 0.9375rem; }
.film-card .photo-wrap { margin: -12px -44px 10px -14px; border-radius: 16px 16px 0 0; overflow: hidden; max-height: 180px; }
.film-card .photo-dislike { top: auto; bottom: 8px; left: 10px; right: auto; padding: 3px 9px; border-radius: 999px; background: rgba(0, 0, 0, 0.55); color: #fff; text-decoration: none; } /* (the card clips its photo: the link sits on it) */
.film-mark.scene { z-index: 900 !important; }
@media (pointer: coarse) { .film-mark:not(.picked) svg { transform: scale(0.7); } } /* (a phone: the tap area stays big, the clapper smaller, so they crowd less) */
/* (In the panel, after the card rules above: these win.) */
/* All the titles, and a title's spots: rows as in Google Maps' lists (a tile, the name and its line, the spots on the right). */
.film-panel .film-all-head { margin: 16px 0 2px; color: var(--muted); font-weight: 600; text-transform: uppercase; letter-spacing: .03em; font-size: 0.75rem; }
.film-panel .film-rows { display: flex; flex-direction: column; margin: 0 -16px; }
.film-panel .film-row { display: flex; align-items: center; gap: 12px; padding: 10px 16px; border: 0; border-bottom: 1px solid var(--border); background: none; color: var(--text); font: inherit; text-align: left; cursor: pointer; }
.film-panel .film-row:hover, .film-panel .film-row:focus-visible { background: var(--bg-soft); }
.film-panel .film-tile { flex: none; display: grid; place-items: center; width: 40px; height: 40px; border-radius: 10px; background: #e9e6f2; color: #3d3654; }
.film-panel .film-tile.gold { background: #f6ecd2; color: #8a6406; }
.film-panel .film-tile svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linejoin: round; stroke-linecap: round; }
.film-panel .film-row-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.film-panel .film-row-name { font-weight: 600; font-size: 0.9375rem; overflow-wrap: anywhere; }
.film-panel .film-row-text .muted { font-size: 0.8125rem; }
.film-panel .film-row-famous { font-size: 0.75rem; font-weight: 700; color: #9a7208; }
.film-panel .film-row-n { flex: none; color: var(--muted); font-size: 0.75rem; white-space: nowrap; }
.film-panel .film-more { height: 1px; }
/* Famous scenes: a row each, with its photo (Felix, 2026-10-25: "should look nicer"). */
.film-panel .scene-tile { position: relative; overflow: hidden; width: 56px; height: 56px; }
.film-panel .scene-tile img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.film-panel .scene-row { align-items: flex-start; }
.film-panel .scene-row .film-row-famous { display: block; }
.film-panel .scene-row .film-row-famous::first-letter { text-transform: uppercase; }
.film-panel .scene-row .scene-text { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.film-panel .film-show { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin: 18px 0 2px; }
.film-panel .film-open { margin: 10px 0 0; font-weight: 600; }
.film-panel .film-others span { color: var(--muted) !important; font-weight: 400; } /* (gold is for the famous scenes only: Felix, 2026-10-25) */
.film-panel .film-show b { font-size: 1rem; color: var(--text); }
.film-panel .film-show span { flex: none; font-size: 0.8125rem; font-weight: 600; color: #9a7208; }
:root.app-dark .film-panel .film-show span { color: #e0b84a; }
:root.app-dark .film-panel .film-tile { background: #34304a; color: #d9d4ee; }
:root.app-dark .film-panel .film-tile.gold { background: #4a3d17; color: #f0cf72; }
.film-panel { margin: 0; padding: 14px 16px 24px; font-size: 0.875rem; line-height: 1.4; color: var(--text); }
.film-panel:has(> .view-bar.on-photo) { padding-top: 0; } /* (its photo as high as a place page's) */
.film-panel[hidden] { display: none; }
.film-panel .film-hits { max-height: none; overflow: visible; }
/* (The photo as on a place's page: inset, rounded, 210 px high, cropped round its middle. It
   used to show only the top of the photo at its full height, so a tall one looked "zoomed in";
   and its Back sat lower than a place's: Felix, 2026-10-26.) */
.film-panel .photo-wrap { margin: 0 0 12px; border-radius: 12px; overflow: hidden; }
.film-panel .photo-wrap img.photo { display: block; width: 100%; height: 210px; object-fit: cover; border-radius: 12px; }
.film-panel .film-tip { margin: 18px 0 0; padding-top: 14px; border-top: 1px solid var(--border); color: var(--muted); font-size: 0.875rem; line-height: 1.45; }
.film-panel .film-tip .link { padding: 0; border: 0; background: none; color: var(--accent); font: inherit; font-weight: 600; cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
/* Bikes (Key & layers): each Vélib' station's bikes, as a small green rounded square with the
   number; grey when it has none or is shut. */
.bike-mark { display: flex; align-items: center; justify-content: center; }
.bike-mark b, .bike-key {
  display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box;
  min-width: 17px; height: 17px; padding: 0 3px; border-radius: 5px; border: 1.5px solid #fff;
  background: #3a9a3f; color: #fff; font: 700 10px/1 system-ui, -apple-system, sans-serif;
  box-shadow: 0 1px 2px rgba(40, 32, 20, 0.35); cursor: pointer;
}
.bike-mark.empty b { background: #9a9a9a; }
.bike-key { box-shadow: none; cursor: inherit; vertical-align: -3px; }
.switch .bike-key { order: 2; margin: 0 0 0 2px; }
/* The Key's Vélib' tile: a fine white bicycle on a green square the size of the bus one (Felix, 2026-10-25). */
.bike-key.bike-tile { width: 16px; height: 16px; min-width: 0; padding: 1px; border-radius: 4px; }
.bike-key.bike-tile svg { width: 100%; height: 100%; }
.bike-key.big { width: 26px; height: 26px; font-size: 13px; border: 0; margin-top: 1px; }
.bike-mark.picked b { transform: scale(1.5); }
.bikes-row strong { font-weight: 600; }
/* Buses (Key & layers): a small blue bus square at each stop from street level, the name closer
   in, as on Google Maps; a tap opens the stop's card (its lines and live times). A picked line:
   its route, and each bus on its way as a dot in the line's colour with its minutes. */
.bus-stop-mark { display: flex; align-items: center; justify-content: center; }
.bus-m {
  display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box;
  width: 16px; height: 16px; border-radius: 4px; background: #1a6fd6; color: #fff;
  border: 1.5px solid #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}
.bus-m svg { width: 11px; height: 11px; display: block; }
.bus-stop-mark .st-name {
  display: none; position: absolute; left: calc(50% + 10px); top: 50%; transform: translateY(-50%);
  white-space: nowrap; font: 600 11px/1 system-ui, -apple-system, sans-serif; color: #1a5bb0; pointer-events: none;
  text-shadow: -1px -1px 0 #fff, 0px -1px 0 #fff, 1px -1px 0 #fff, -1px 0px 0 #fff, 1px 0px 0 #fff, -1px 1px 0 #fff, 0px 1px 0 #fff, 1px 1px 0 #fff;
}
.leaflet-busStops-pane.named .st-name { display: block; }
:root.app-dark .bus-stop-mark .st-name { color: #a9c8f5; text-shadow: -1px -1px 0 #111, 0px -1px 0 #111, 1px -1px 0 #111, -1px 0px 0 #111, 1px 0px 0 #111, -1px 1px 0 #111, 0px 1px 0 #111, 1px 1px 0 #111; }
.bus-stop-mark.picked .bus-m { transform: scale(1.5); }
.bus-stop-mark.picked { z-index: 1000 !important; }
.bus-key { display: inline-flex; }
.bus-key .bus-m { box-shadow: none; }
.bus-ico .bus-m { width: 26px; height: 26px; border: 0; border-radius: 6px; margin-top: 1px; }
.bus-ico .bus-m svg { width: 18px; height: 18px; }
.bus-card .bus-rows { display: flex; flex-direction: column; gap: 2px; margin-top: 10px; max-height: 40vh; overflow-y: auto; }
.bus-row {
  display: flex; align-items: flex-start; gap: 10px; width: 100%; padding: 7px 6px; border: 0; border-radius: 10px;
  background: none; color: inherit; font: inherit; text-align: left; cursor: pointer;
}
.bus-row:hover { background: var(--bg-soft); }
.bus-row.picked { background: color-mix(in srgb, var(--accent) 8%, var(--bg)); }
.bus-row .line-badge { flex: none; width: 3em; min-width: 3em; height: 1.7em; font-size: 0.8125rem; margin-top: 1px; } /* (one width: N01 and 24 start their rows' text at the same place) */
.line-badge.bus.picked { outline: 2px solid var(--accent); outline-offset: 1px; }
.bus-dirs { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.bus-dir { display: flex; justify-content: space-between; gap: 8px; min-height: 1.7em; align-items: baseline; }
.bus-dir.muted { align-items: center; }
.bus-arrow { display: inline-block; width: 1.25em; }
.bus-dir.muted { padding-left: 1.25em; } /* ("No bus…" starts where the destination names start) */
.bus-to { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The times in one column: each row's dot and first time start at the same place. */
.bus-when { flex: none; display: flex; flex-direction: column; align-items: flex-start; width: 8.6em; white-space: nowrap; color: #1e8e3e; }
.bus-when strong { font-weight: 700; }
.bus-later { opacity: 0.8; }
.bus-late { color: #c26401; font-weight: 600; font-size: 0.75rem; }
:root.app-dark .bus-late { color: #f6ad55; }
.bus-news { margin-top: 8px; padding: 0 6px; } /* (same left edge, gap and badge as the bus rows above) */
.bus-news summary { display: flex; align-items: center; gap: 10px; text-decoration: none; }
.bus-news summary .bus-news-t { text-decoration: underline; }
.bus-news summary .line-badge { flex: none; width: 3em; min-width: 3em; height: 1.7em; margin: 0 2px 0 0; font-size: 0.8125rem; }
.bus-news > :not(summary) { margin-left: calc(2.4375rem + 12px); }
:root.app-dark .bus-when { color: #81c995; }
/* "Live": the little waves Google Maps puts by real-time minutes. */
.bus-live { display: inline-block; width: 7px; height: 7px; margin-right: 5px; border-radius: 50%; background: currentColor; vertical-align: 1px; animation: bus-live 1.6s ease-in-out infinite; }
@keyframes bus-live { 50% { opacity: 0.25; } }
@media (prefers-reduced-motion: reduce) { .bus-live { animation: none; } }
.bus-others { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 8px 0 0; }
.bus-chip { padding: 0; border: 0; background: none; cursor: pointer; }
.bus-all { border: 1px solid var(--border); background: var(--bg); color: inherit; border-radius: 14px; padding: 3px 10px; font: inherit; font-size: 0.8125rem; cursor: pointer; }
.bus-note { margin: 8px 0 0; font-size: 0.75rem; }
@media (max-width: 720px) { .bus-card .bus-rows { max-height: 28vh; } }
.bus-dot { display: flex; align-items: center; justify-content: center; }
.bus-dot b {
  display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box;
  width: 26px; height: 26px; border-radius: 50%; background: var(--lc); color: var(--lt);
  border: 2px solid #fff; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
}
.bus-dot b svg { width: 15px; height: 15px; }
.bus-dot span {
  position: absolute; left: calc(50% + 15px); top: 50%; transform: translateY(-50%); white-space: nowrap;
  padding: 2px 6px; border-radius: 9px; background: var(--bg); color: var(--text); font: 700 11px/1.2 system-ui, -apple-system, sans-serif;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}
.bus-dot.later b { width: 20px; height: 20px; opacity: 0.85; }
.bus-dot.later b svg { width: 11px; height: 11px; }
.bus-dot.later span { font-weight: 600; opacity: 0.9; }
/* Live traffic (cards, station cards): one message per line, its full text one tap away. */
.traffic-item { display: block; margin: 2px 0 6px; }
.traffic-item:first-child { margin-top: 0; } /* (the first one on the row icon's line: Felix, 2026-10-26) */
.traffic-item.blocked strong { color: #c62828; }
.traffic-item.disrupted strong { color: #d35400; }
.traffic-item .last-more summary { white-space: normal; }
/* A message about a station or two: the stations in bold, what happens in the level's colour. */
.traffic-item.at-st .tr-what { font-weight: 600; }
.traffic-item.blocked.at-st .tr-what { color: #c62828; }
.traffic-item.disrupted.at-st .tr-what { color: #d35400; }
.traffic-item .tr-st { font-weight: 700; color: var(--text, #202124); }
:root.app-dark .traffic-item.blocked.at-st .tr-what { color: #f28b82; }
:root.app-dark .traffic-item.disrupted.at-st .tr-what { color: #fcad70; }
.station-traffic { margin: 0 0 8px; }
/* "Within 20 min" (Near me on): a chip under the list's top; filled while it's on. */
.reach-chip { margin: 8px 0 0 16px; font-weight: 600; }
.reach-mode { margin: 8px 16px 0 6px; }
.reach-mode[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: var(--bg); font-weight: 600; }
.reach-chip[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: var(--bg); }
/* "Within 20 min": circles fully filled on one canvas; the pane makes them see-through as one. */
.leaflet-reach-pane { opacity: 0.14; pointer-events: none; }

/* Key › Map display as tiles (as Google Maps' "Map details"): an icon over a short name; the
   switch itself is hidden but still there for keyboards and screen readers. */
/* (Four to a row: with seven switches one row was too tight for their names.) */
/* Three across, as Google Maps' "Map details", so every name fits on one line (Felix, 2026-10-25). */
.layer-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; margin-bottom: 4px; }
.layer-tiles .switch.tile { min-width: 0; flex-direction: column; justify-content: flex-start; gap: 6px; padding: 9px 2px 7px; border: 1.5px solid var(--border); border-radius: 10px; font-size: 0.7rem; line-height: 1.15; text-align: center; hyphens: manual; position: relative; }
.layer-tiles .switch.tile[hidden] { display: none; }
.layer-tiles .switch.tile input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; margin: 0; border-radius: 10px; }
.layer-tiles .switch.tile:has(input:checked) { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--bg)); font-weight: 600; }
.layer-tiles .switch.tile:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.layer-tiles .switch.tile > span[aria-hidden] { order: 0; flex: none; align-self: center; margin: 3px 0; transform: scale(1.3); vertical-align: 0; }
/* (each icon in a row of its own fixed height, so the five names start on one line) */
.layer-tiles .switch.tile { display: grid; grid-template-rows: 22px auto; grid-template-columns: minmax(0, 1fr); row-gap: 6px; justify-items: center; align-content: start; } /* (one full-width column: each icon and name in the tile's middle) */
.theme-tiles .theme-key svg { width: 15px; height: 15px; fill: #9a7208; display: block; }
.theme-tiles .switch.tile small { display: block; margin-top: 2px; font-weight: 400; color: var(--muted); font-size: 0.65rem; }
.theme-tiles .switch.tile.soon > span[aria-hidden] { opacity: 0.6; } /* (only the icon fades: the words stay readable) */
/* (on now or this week: a gold ring and a gold line, like the chip at the top) */
.theme-tiles .switch.tile.live { border-color: var(--gold); box-shadow: inset 0 0 0 1px var(--gold); }
.theme-tiles .switch.tile.live small { color: #7a5f00; font-weight: 700; }
/* A week before: a light gold wash and its first day in gold, no ring. */
.theme-tiles .switch.tile.next { background: color-mix(in srgb, var(--gold) 8%, var(--bg)); }
.theme-tiles .switch.tile.next small { color: #7a5f00; font-weight: 600; }
:root.app-dark .theme-tiles .switch.tile.next small { color: #e0b84a; }
:root.app-dark .theme-tiles .switch.tile.live small { color: #e0b84a; }
.theme-tiles .switch.tile.past:not(:has(input:checked)) > span[aria-hidden] { opacity: 0.6; } /* last year’s, shown so you know what to expect (Design Week) */
.theme-tiles .switch.tile small { white-space: nowrap; }
.theme-tiles .switch.tile:has(input:checked) { border-color: var(--gold); background: color-mix(in srgb, var(--gold) 12%, var(--bg)); }
.layer-tiles .switch.tile > span[aria-hidden] { margin: 0; }
.layer-tiles .lanes-key svg { width: 15px; height: 15px; display: block; }
.layer-tiles .arr-key { width: 15px; height: 15px; border: 1.5px dashed #7a86a8; border-radius: 3px; box-sizing: border-box; }
.layers-panel.layers-panel { width: min(380px, calc(100vw - 32px)); } /* (wide enough for each name on one row) */

/* The station card, line by line (as Google Maps): badges under the name, short facts as chips,
   then one small card per line with its status and its last trains each way. */
/* A station with no photo: a band in its lines' soft colours, the big "M" and its line badges in
   the middle, a strip of the lines' own colours along the bottom (Back floats on it, as on a photo). */
.st-hero {
  position: relative; display: flex; align-items: center; justify-content: center; gap: 14px;
  height: 150px; border-radius: 12px; overflow: hidden; background: var(--st-tint);
}
.st-hero::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 6px; background: var(--st-strip); }
.st-hero .st-m { width: 56px; height: 56px; font-size: 32px; border-width: 3px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25); }
.st-hero .st-m.rer { width: auto; min-width: 56px; padding: 0 8px; border-radius: 12px; font-size: 22px; }
.st-hero-lines { display: flex; flex-wrap: wrap; gap: 6px; max-width: 55%; }
.st-hero-lines .line-badge { transform: scale(1.5); margin: 6px; box-shadow: 0 0 0 2px var(--bg); }
.st-hero + .ev-title { margin-top: 14px; }
.st-hero ~ .st-badges { display: none; } /* (the band shows them, bigger) */
.st-hero ~ .st-facts { margin-top: 10px; }
.st-badges { display: flex; flex-wrap: wrap; gap: 4px; margin: 6px 0 10px; }
.st-badges .line-badge { transform: scale(1.15); margin-right: 3px; }
.st-facts { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 12px; }
.st-fact { display: inline-flex; align-items: center; gap: 4px; padding: 5px 8px; border-radius: 999px; background: color-mix(in srgb, var(--text) 6%, var(--bg)); font-size: 0.82rem; line-height: 1.3; }
.st-fact .line-badges { display: inline-flex; gap: 2px; }
.st-fact .access-sign { margin-right: 2px; } /* (the same space as a line icon's: 16 px sign, 6 px to its words) */
.walk-link { color: var(--accent); font-weight: 600; text-decoration: none; white-space: nowrap; }
.walk-link:hover { text-decoration: underline; }
details.st-fact { display: block; }
details.st-fact[open] { border-radius: 12px; flex-basis: 100%; }
.st-fact summary { cursor: pointer; list-style: none; }
.st-fact summary::-webkit-details-marker { display: none; }
.st-fact .station-exits { margin: 6px 0 2px; }
.detail-body .section-label.st-section { margin: 22px 0 8px; }
.st-line { border: 1px solid var(--border); border-radius: 12px; padding: 10px 12px; margin-bottom: 8px; }
.st-line-head { display: flex; align-items: center; gap: 8px; font-weight: 600; }
.st-status { margin-left: auto; font-size: 0.8rem; font-weight: 600; display: inline-flex; align-items: center; gap: 5px; }
.st-status::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
.st-status.ok { color: #2e9e48; }
.st-status.bad { color: #d35400; }
.st-note { font-size: 0.82rem; padding-top: 5px; }
.st-note.blocked summary, .st-note.disrupted summary { color: #c04a00; }
.st-last { display: flex; justify-content: space-between; gap: 8px; font-size: 0.86rem; color: var(--muted); padding-top: 5px; }
.st-last strong { color: var(--text); font-variant-numeric: tabular-nums; white-space: nowrap; }
.st-night { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; margin: 4px 0 0; font-size: 0.85rem; color: var(--muted); }

/* ---------- drop a pin: the red pin and its card (app.js, "drop a pin") ---------- */
.dropped-pin { cursor: grab; }
.dropped-pin .pin-svg { display: block; width: 22px; height: 32px; transform-origin: 11px 31px; animation: pin-drop .35s cubic-bezier(.3, 1.4, .6, 1); filter: drop-shadow(0 1px 1px rgba(0, 0, 0, .3)); }
@keyframes pin-drop { from { transform: translateY(-24px) scale(.8); opacity: 0; } to { transform: none; opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .dropped-pin .pin-svg { animation: none; } }
#pin-drop[aria-pressed="true"] .cap { color: #fff; }
body.pin-picking #map, body.pin-picking #map canvas { cursor: crosshair !important; }
/* (an arrondissement's name doesn't catch the click meant for the pin: the pin goes there) */
body.pin-picking .leaflet-areaLabels-pane, body.pin-picking .leaflet-areaLabels-pane * { pointer-events: none !important; }
.pin-card { z-index: 1001; padding-bottom: 10px; }
.pin-card .pin-ico svg { width: 20px; height: 29px; display: block; animation: none; }
.pin-card .pin-station { margin: 6px 0 0 30px; font-size: 0.8125rem; }
.pin-card .am-row { margin-left: 30px; gap: 6px; }
.pin-card .am-row .button { min-height: 34px; padding: 0 12px; }
.pin-card .am-row .button.on { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.pin-card .am-row .button[data-pin-metro][aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.pin-card .pin-near-head { margin: 10px 0 2px 30px; color: var(--muted); font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: .03em; }
.pin-card .pin-near { list-style: none; margin: 0 -6px 0 18px; padding: 0; }
.pin-card .pin-near button { gap: 8px; }
.pin-card .pin-walk { flex: none; margin-left: auto; font-size: 0.75rem; }
.pin-card .pin-near-head { display: flex; align-items: center; gap: 8px; }
.pin-card .pin-all { margin-left: auto; padding: 4px 0; border: 0; background: none; color: var(--accent); font: inherit; font-weight: 600; text-transform: none; letter-spacing: 0; cursor: pointer; }
/* While the area loads, the buttons keep their words (no width jumping about) and fade a little. */
.pin-card .button.busy, .reach-chip.busy, .reach-mode.busy { opacity: .65; cursor: progress; }
/* At the top of the list (computers; phones with the list up), as Google Maps shows a dropped pin
   in its side panel; its buttons stand in for the list's own pin chips. */
.results > .pin-card { position: relative; inset: auto; z-index: auto; margin: 4px 12px 8px; padding: 12px 44px 10px 12px; box-shadow: none; }
body.pin-down .results > #near-clear, body.pin-down .results > #reach-chip, body.pin-down .results > #reach-mode { display: none; }
/* Phones, the list pulled down: the card is the bottom sheet, with a grip (swipe it up for the
   list). With the list up it heads the list, as on computers (below). */
@media (max-width: 720px) {
  body > .pin-card { left: 0; right: 0; bottom: 0; border-width: 1px 0 0; border-radius: 16px 16px 0 0; touch-action: none; box-shadow: 0 -2px 12px rgba(0, 0, 0, .15); }
  body > .pin-card::before { content: ""; position: absolute; top: 7px; left: 50%; width: 36px; height: 4px; margin-left: -18px; border-radius: 2px; background: var(--border); }
  body > .pin-card .am-x { top: 14px; }
  body:not([data-sheet="peek"]):not([data-sheet="mini"]) > .pin-card { display: none; }
  /* A card of its own on top (a toilet's, a place's group, an event's): the pin's waits under it. */
  body:has(#am-card:not([hidden]), #spot-card:not([hidden]), #preview:not([hidden])) > .pin-card { display: none; }
  #pin-drop .btn-text { display: none; }
  body > .pin-card { padding: 18px 40px calc(6px + env(safe-area-inset-bottom, 0px)) 12px; }
  .pin-card .am-row { margin-top: 8px; gap: 6px; }
  .pin-card .pin-near-head { margin-top: 6px; }
  .pin-card .pin-near button { padding-top: 6px; padding-bottom: 6px; }
}

/* The map's own corner buttons and the hint stay below the clock and the notch too. */
.leaflet-top { top: env(safe-area-inset-top, 0px); }
/* iPhone home-screen app: the map runs up under the clock, whose text is white there. A soft
   shade behind it keeps the clock readable on the light map. (Nothing elsewhere: the space is 0.) */
@media (display-mode: standalone) {
  body::after { content: ""; position: fixed; top: 0; left: 0; right: 0; z-index: 1002; pointer-events: none;
    height: calc(env(safe-area-inset-top, 0px) * 1.5);
    background: linear-gradient(rgba(0, 0, 0, .32), rgba(0, 0, 0, .12) 66%, rgba(0, 0, 0, 0)); }
}

/* ---------- The top of the map, as in Google Maps ----------
   A search bar (⋯ at its end opens the rest), one row of chips under it (Filters, when or
   opening hours, the kinds; My list and the pin too while they're on), and round buttons:
   layers on the right, your location just above the sheet. On computers the search bar sits at
   the top of the panel and the chips run along the top of the map. */
.map-tools, body[data-sheet="full"] .map-tools {
  display: flex; flex-direction: column; align-items: stretch; flex-wrap: nowrap; gap: 8px; justify-content: flex-start;
}
.search-pill {
  display: flex; align-items: center; gap: 8px; height: 48px; padding: 0 13px 0 4px; box-sizing: border-box;
  border-radius: 24px; background: var(--bg); box-shadow: 0 1px 2px rgba(60, 36, 20, .2), 0 2px 8px rgba(60, 36, 20, .12);
  pointer-events: auto;
}
.search-pill:focus-within { box-shadow: 0 0 0 2px var(--accent), 0 2px 8px rgba(0, 0, 0, .12); }
.pill-go { margin-right: -9px; } /* (the 🔍 stays where it was; the button around it is bigger) */
.search-pill .pill-ic { width: 22px; height: 22px; flex: none; fill: none; stroke: var(--muted); stroke-width: 2; stroke-linecap: round; }
.search-pill input[type="search"] {
  flex: 1; min-width: 0; height: 100%; padding: 0; border: 0; border-radius: 0; background: none;
  color: var(--text); font: inherit; font-size: 1rem; outline: none;
}
.pill-btn {
  display: grid; place-items: center; flex: none; width: 40px; height: 40px; padding: 0;
  border: 0; border-radius: 50%; background: none; color: var(--text); cursor: pointer;
}
.pill-btn svg { width: 22px; height: 22px; fill: currentColor; }
@media (hover: hover) { .pill-btn:hover { background: var(--bg-soft); } } /* (a phone tap leaves no grey circle behind) */
.pill-btn:focus-visible { outline: 2px solid var(--accent); }
.search-pill { position: relative; }
/* The placeholder with the name as on the loading screen: one grey for all of it, "Paris ce soir"
   in the serif on the same line, "ce soir" in copper. It stays when the bar is tapped, until you
   type (Felix, 2026-10-25: the font went away on a tap, and the mix looked unsettled). */
.pill-brand { display: none; position: absolute; left: 52px; right: 52px; top: 0; bottom: 0; align-items: center; overflow: hidden;
  white-space: pre; color: var(--muted); font-size: 1rem; line-height: 1; pointer-events: none; }
.pill-brand > span { overflow: hidden; text-overflow: ellipsis; }
.pill-brand b { font: 400 1.125rem/1 var(--serif); color: inherit; }
@media (max-width: 380px) { .pill-brand { font-size: 0.95em; } .pill-brand b { font-size: 1.07rem; } } /* (a small phone: the longer French line still fits) */
.pill-brand i { color: var(--logo); }
.search-pill.branded:has(#search:placeholder-shown) .pill-brand { display: flex; }
.search-pill.branded #search::placeholder { color: transparent; }
.pill-menu svg { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; } /* ☰ */

/* One row of chips, swiped sideways (dragged or ‹ › on computers). */
.map-tools .map-chips { margin: 0 -10px; padding: 2px 10px 6px; gap: 8px; pointer-events: auto; }
.map-chips .chip-set { display: contents; }
.map-chips .chip {
  flex: none; display: inline-flex; align-items: center; gap: 6px; height: 36px; padding: 0 14px;
  border: 0; background: var(--bg); color: var(--text); box-shadow: var(--shadow-1); font-size: 0.875rem;
}
/* One "on" look for everything that opens or switches on: the chip (or button) is filled in the
   accent colour, so it's clear another tap turns it off. Filters, My list, the pin, the Today /
   Open now menus while open, layers and ☰. */
.map-chips .chip[aria-pressed="true"], .map-chips .chip[aria-expanded="true"], .map-chips .drop-chip[aria-expanded="true"],
.ctl-card .fab[aria-expanded="true"], .ctl-card .fab[aria-expanded="true"]:hover, .ctl-card .fab-pin[aria-pressed="true"], .ctl-card .fab-pin[aria-pressed="true"]:hover,
.ctl-card .fab-list[aria-pressed="true"], .ctl-card .fab-list[aria-pressed="true"]:hover,
.pill-btn[aria-expanded="true"], .pill-btn[aria-expanded="true"]:hover { background: var(--accent); color: var(--accent-text); }
.map-chips .chip.empty { opacity: 1; } /* (same text as the others, Felix: one look for the row; the 0 says it) */
.map-chips .chip.empty :is(.ic, .chip-glyph) { opacity: 0.45; }
.map-chips .chip-arrow { box-shadow: var(--shadow-1); outline: 0; clip-path: none; margin: 0; }
.map-chips .on-chip[aria-pressed="false"] { display: none; } /* My list and the pin: only while they're on */
.map-chips .on-chip .x { margin-left: 2px; opacity: 0.75; font-size: 0.75rem; }
/* Small line icons, drawn in the text's colour. */
.map-chips .filt::before, .drop-chip .clock, .drop-chip::after {
  content: ""; display: inline-block; flex: none; width: 18px; height: 18px; background: currentColor;
  -webkit-mask: var(--ic) center / contain no-repeat; mask: var(--ic) center / contain no-repeat;
}
.map-chips .filt::before { --ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M4 7h10M18 7h2M4 17h4M12 17h8'/%3E%3Ccircle cx='16' cy='7' r='2'/%3E%3Ccircle cx='10' cy='17' r='2'/%3E%3C/svg%3E"); }
.drop-chip .clock { --ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='8.5'/%3E%3Cpath d='M12 7.5V12l3 2'/%3E%3C/svg%3E"); }
.drop-chip::after { width: 14px; height: 14px; margin-right: -4px; --ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 9l6 6 6-6z'/%3E%3C/svg%3E"); }
/* Filters, Today / Open now and Home stand out a little: a soft copper tint, copper icons,
   dark words (Felix picked 1 of six; the other chips stay white). */
.map-chips :is(.filt, .drop-chip, .home-chip):not([aria-expanded="true"]) { background: color-mix(in srgb, var(--accent) 12%, var(--bg)); }
.map-chips :is(.filt, .drop-chip, .home-chip) { font-weight: 600; } /* (open too: the row doesn't shift) */
.map-chips .drop-chip:not([aria-expanded="true"]) .clock, .map-chips .filt:not([aria-expanded="true"])::before { background: var(--accent); }

/* The menus under "Today ▾" and "Open now ▾", the dates panel, and ⋯. */
.drop-menu:not([hidden]), .map-tools .more-menu:not([hidden]), .map-tools .date-pop:not([hidden]) {
  position: fixed; z-index: 1004; display: flex; flex-direction: column; min-width: 200px; padding: 6px 0; margin: 0;
  border: 0; border-radius: 12px; background: var(--bg); box-shadow: var(--shadow-2); pointer-events: auto;
}
.drop-menu .chip {
  display: flex; align-items: center; gap: 8px; height: auto; min-height: 42px; padding: 0 18px;
  border: 0; border-radius: 0; background: none; color: var(--text); font-size: 0.9375rem; text-align: left;
}
.drop-menu .chip[aria-checked="true"] { background: color-mix(in srgb, var(--accent) 13%, var(--bg)); color: var(--accent); font-weight: 600; }
.drop-menu .chip:hover { background: var(--bg-soft); }
.drop-menu #pick-day { margin-top: 4px; border-top: 1px solid var(--border); }
#pick-day .pick-ic { display: inline-flex; color: var(--muted); }
#pick-day[aria-checked="true"] .pick-ic { color: currentColor; }
#pick-day .pick-ic svg.lic { width: 18px; height: 18px; }
.drop-menu .chip-select { margin: 4px 12px; min-height: 38px; border: 1px solid var(--border); border-radius: 8px; padding: 0 10px; }
.drop-menu .chip-select.on { border-color: var(--accent); color: var(--accent); font-weight: 600; background: none; }
.map-tools .date-pop:not([hidden]) { flex-direction: row; flex-wrap: wrap; align-items: end; gap: 8px 12px; padding: 12px; max-width: calc(100vw - 20px); box-sizing: border-box; }
.map-tools .more-menu:not([hidden]) { min-width: 180px; }
.more-menu button, .more-menu .menu-lang {
  display: flex; align-items: center; gap: 12px; min-height: 44px; padding: 0 16px;
  border: 0; background: none; color: var(--text); font: inherit; font-size: 0.9375rem; text-align: left; cursor: pointer;
}
.more-menu button[hidden] { display: none; }
.more-menu button:hover, .more-menu button:focus-visible { background: var(--bg-soft); }
.more-menu svg { width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linejoin: round; }
.more-menu .ico { width: 20px; height: 20px; flex: none; text-align: center; font-size: 18px; line-height: 20px; } /* (the glyphs as big as the line icons) */
.more-menu .lbl { flex: 1; }
.more-menu .n { color: var(--muted); font-variant-numeric: tabular-nums; }
.more-menu hr { width: 100%; height: 1px; margin: 4px 0; border: 0; background: var(--border); }
.more-menu .menu-lang { cursor: default; padding: 4px 18px 6px 52px; } /* EN | FR alone, under the names */
.more-menu .lang-switch { display: flex; padding: 2px; border: 1px solid var(--border); border-radius: 999px; }
.more-menu .lang-switch button { min-height: 30px; padding: 0 10px; border-radius: 999px; font-weight: 600; }
.more-menu .lang-switch button[aria-pressed="true"] { background: var(--accent); color: var(--accent-text); }

/* The map's buttons in white cards, as in Apple Maps: layers and near me under the chips at
   the top right, + and − at the bottom right on computers. */
.ctl-card {
  position: fixed; z-index: 1001; display: flex; flex-direction: column; width: 44px;
  border-radius: 12px; background: var(--bg); box-shadow: 0 1px 4px rgba(60, 36, 20, .3); overflow: hidden;
}
.leaflet-control-zoom { display: none !important; } /* (Leaflet's own + and −: the card has them; also hides them from an older app.js still in a browser's cache) */
.ctl-card hr { width: 60%; height: 1px; margin: 0 auto; border: 0; flex: none; background: var(--border); }
.fab {
  display: grid; place-items: center; width: 44px; height: 44px; padding: 0;
  border: 0; background: none; color: var(--text); cursor: pointer;
}
.fab svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linejoin: round; }
.fab:hover { background: var(--bg-soft); }
.fab:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; }
.fab-locate { color: var(--muted); }
.fab-locate .dot { fill: none; }
.fab-locate[aria-pressed="true"] { color: #1a73e8; }
.fab-locate[aria-pressed="true"] .dot { fill: currentColor; }
:root.app-dark .fab-locate[aria-pressed="true"] { color: #8ab4f8; }

/* The panel's own title row goes (the name is in the search bar); the Ask button keeps it. */
.panel .title-row:not(:has(.ask:not([hidden]))) { display: none; }
.panel .title-row .view-switch { display: none; }
/* The welcome note: as much space above it as below. */
.saved-head:not(:has(#saved-tabs:not([hidden]), .saved-actions > button:not([hidden]))) { display: none; } /* (its tab buttons counted while their row was hidden) */
.results > .welcome { margin-top: 8px; margin-bottom: 12px; }

@media (max-width: 720px) {
  .map-tools, body[data-sheet="full"] .map-tools { top: calc(10px + env(safe-area-inset-top, 0px)); left: 10px; right: 10px; }
  .ctl-card { top: calc(122px + env(safe-area-inset-top, 0px)); right: 10px; }
  .zoom-card { display: none; } /* (fingers zoom) */
  body[data-sheet="full"] .ctl-card { display: none; }
  .layers-panel.layers-panel { top: calc(122px + env(safe-area-inset-top, 0px)); right: 66px; width: calc(100vw - 76px); }
  .gl-overlay .leaflet-top.leaflet-right { top: calc(313px + env(safe-area-inset-top, 0px)); right: 3px; } /* the compass, under the card (4 buttons since My list), centred under it */
  .map-hint { margin-top: 116px !important; max-width: calc(100vw - 90px); white-space: normal; }
  /* The sheet, pulled up, stops under the search bar and the chips. */
  .panel { --full-h: calc(100vh - 116px - env(safe-area-inset-top, 0px)); max-height: none; }
  @supports (height: 100dvh) {
    .panel { --full-h: calc(100dvh - 116px - env(safe-area-inset-top, 0px)); }
  }
  .panel[data-sheet="full"] { height: var(--full-h); }
}
@media (min-width: 721px) {
  .map-tools, body[data-sheet="full"] .map-tools { top: calc(16px + env(safe-area-inset-top, 0px)); left: calc(var(--panel-width) + 16px); right: 16px; } /* (the chips on the search bar's middle line) */
  .map-tools .map-chips { margin: 0 -2px; padding: 2px 2px 6px; }
  .search-pill { position: fixed; top: calc(12px + env(safe-area-inset-top, 0px)); left: 16px; width: calc(var(--panel-width) - 32px); } /* (the panel's own 16 px edges) */
  .panel .panel-header { padding-top: 52px; }
  /* An open event or place (or the chat) starts under the search bar, as Google's place panel. */
  .panel.has-detail, .panel.has-chat { padding-top: 64px; }
  .ctl-card { top: calc(70px + env(safe-area-inset-top, 0px)); right: 16px; } /* (16 px under the chips, as on phones) */
  .zoom-card { top: auto; bottom: calc(24px + env(safe-area-inset-bottom, 0px)); }
  .leaflet-top.leaflet-right { top: calc(212px + env(safe-area-inset-top, 0px)); right: 3px; } /* the compass, under the card */
  .gl-overlay .leaflet-top.leaflet-right { top: calc(262px + env(safe-area-inset-top, 0px)); right: 8px; } /* (4 buttons since My list; centred under them) */
  .layers-panel { top: calc(70px + env(safe-area-inset-top, 0px)); right: 72px; }
  .map-hint { margin-top: 76px !important; }
  /* Bigger list photos on computers: square, the row's height (Felix picked A, 2026-10-25). */
  .event-list li:not(.in-group) .row-thumb { width: 76px; height: 76px; border-radius: 12px; margin-top: 0; }
  .event-list li { gap: 14px; }
}

/* A theme week's chip (Paris Photo, Fashion Week…) and its note over the list. */
.map-chips .theme-chip { background: color-mix(in srgb, var(--gold-mid) 16%, var(--bg)); color: #8a6a00; font-weight: 600; }
:root.app-dark .map-chips .theme-chip { color: #e3c25a; }
.map-chips .theme-chip .ic svg { width: 16px; height: 16px; fill: currentColor; }
.map-chips .theme-chip[aria-pressed="true"] { background: var(--accent); color: var(--accent-text); }
.theme-note { margin: 0 16px 10px; padding: 0; border-radius: 16px; overflow: hidden;
  background: color-mix(in srgb, var(--gold-mid) 12%, var(--bg)); font-size: 0.875rem; line-height: 1.45; }
/* Its title: the theme's icon in a gold disc, the name big, the days under it. */
.theme-title { display: flex; gap: 12px; align-items: center; margin-bottom: 10px; }
.theme-badge { flex: none; width: 44px; height: 44px; border-radius: 50%; background: var(--gold-deep); display: grid; place-items: center; }
.theme-badge svg { width: 24px; height: 24px; fill: #fff; }
.theme-title h2 { margin: 0; font-size: 1.375rem; line-height: 1.2; font-weight: 700; letter-spacing: -0.01em; text-transform: none; color: var(--text); padding: 0; }
.theme-title .theme-site { display: inline-flex; vertical-align: -0.12em; margin: -8px -8px -8px -2px; padding: 8px; border-radius: 50%; color: var(--accent); } /* (the official site: a web icon after the name; Felix, 2026-10-26) */
.theme-title .theme-site svg { width: 0.85em; height: 0.85em; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.theme-title .theme-site:hover { background: var(--act-bg); }
.theme-days { margin: 2px 0 0; color: #8a6a0c; font-weight: 600; }
.theme-text, .theme-more, .theme-links { margin: 0 0 6px; }
/* "More to come": a gold box near the top, so it's seen (Felix, 2026-10-26). */
.theme-note .theme-more { display: flex; gap: 8px; align-items: flex-start; margin: 0 0 10px; padding: 8px 10px; border-radius: 10px;
  background: color-mix(in srgb, var(--gold-mid) 18%, var(--bg)); border: 1px solid color-mix(in srgb, var(--gold-mid) 45%, transparent); color: var(--text); font-weight: 600; }
.theme-note .theme-more .lic { flex: none; width: 18px; height: 18px; margin-top: 1px; color: #8a6a0c; }
.theme-links a { font-weight: 600; }
.theme-related { margin: 4px 0 6px; padding: 0 16px; } /* (in line with the list's own headings) */
/* Its photo on top, full width of the box, and what it shows under it. */
.theme-note .theme-hero { margin: 0; overflow: hidden; max-height: 200px; }
.theme-note .theme-hero img { width: 100%; height: 200px; object-fit: cover; display: block; }
.theme-cap { margin: 4px 14px 0; font-size: 0.75rem; color: var(--muted); }
.theme-related[hidden] { display: none; }
.theme-note[hidden] { display: none; }
/* Laid out like a place's page (Felix, 2026-10-25: "it should all be in the golden thing"): round
   buttons, where and when, the way there, what it is, then its places when it has many. */
.theme-body { padding: 14px 14px 10px; }
.theme-note .act-row { margin: 2px 0 10px; }
.theme-note .facts { margin: 0 0 10px; }
.theme-note .facts > li { border-top-color: color-mix(in srgb, var(--gold-mid) 25%, transparent); }
.theme-note .facts .to-map { cursor: pointer; }
.theme-note .facts .to-map:hover p { text-decoration: underline; }
.theme-sub { margin: 12px 0 6px; font-weight: 700; font-size: 0.9375rem; }
.theme-rows { display: flex; flex-direction: column; gap: 6px; margin-bottom: 8px; }
.theme-note .theme-more-rows { display: block; margin: 0 0 10px; padding: 4px 0; font-weight: 600; font-size: 0.875rem; }
.theme-row { background: var(--bg); border-radius: 12px; }
.theme-row.picked { box-shadow: 0 0 0 2px var(--gold-deep); }
.theme-row-head { display: flex; gap: 10px; align-items: center; width: 100%; padding: 8px 10px; border: 0; background: none; color: inherit; font: inherit; text-align: left; cursor: pointer; }
.theme-row-ico { flex: none; width: 40px; height: 40px; border-radius: 50%; background: var(--gold-deep); display: grid; place-items: center; }
.theme-row-ico svg { width: 18px; height: 18px; fill: #fff; }
.theme-row-ico.photo { width: 40px; height: 40px; border-radius: 10px; overflow: hidden; background: color-mix(in srgb, var(--gold-mid) 25%, var(--bg)); }
.theme-row-ico.photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* (A place's photo fills its row's height on the left edge, the row as tall as before: Felix, 2026-10-26, mockup A.) */
.theme-row:has(.theme-row-ico.photo) { overflow: hidden; }
.theme-row-head:has(.photo) { padding: 0 10px 0 0; min-height: 56px; gap: 12px; align-items: stretch; }
.theme-row-head:has(.photo) .theme-row-text { justify-content: center; padding: 6px 0; }
.theme-row-ico.photo { position: relative; width: 70px; height: auto; min-height: 56px; border-radius: 0; }
.theme-row-ico.photo img { position: absolute; inset: 0; border-radius: 0; } /* (the row sets the height, not the photo) */
.theme-row:has(.theme-row-ico.photo) .theme-row-body { padding-left: 82px; }
.theme-row.picked .theme-row-ico.photo { border-bottom-right-radius: 10px; } /* (an open row: the photo ends neatly above the text) */
.theme-row-credit { font-size: 0.75rem; color: var(--muted); }
.theme-row-credit a { color: inherit; }
/* Last edition's facts (a short list under the note). */
.theme-last { margin: 0 0 8px; padding-left: 18px; }
.theme-last li { margin: 0 0 4px; }
.theme-row-text { display: flex; flex-direction: column; min-width: 0; }
.theme-row-name { font-weight: 600; }
.theme-row-text .muted { font-size: 0.8125rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.theme-row-body { padding: 0 12px 8px 60px; }
.theme-row-body p { margin: 0 0 6px; white-space: pre-line; }
.theme-row-body .act-row { margin: 4px 0 8px; }
.theme-row-body .theme-links { display: flex; flex-wrap: wrap; gap: 6px 18px; margin: 8px 0 4px; font-size: 0.875rem; } /* (quiet line-icon links in a place's row: Felix, 2026-10-26) */
.theme-links a { display: inline-flex; align-items: center; gap: 6px; color: var(--text); text-decoration: none; font-weight: 600; }
.theme-links a:hover span { text-decoration: underline; }
.theme-links svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; color: var(--muted); }
/* While a theme week is on: no date, Filters, Home or ⚠ chips, no "On the map / All" (like the
   film locations' focus). */
body.theme-focus #map-chips, body.theme-focus .list-head, body.theme-focus #welcome,
body.theme-focus #hidden-note, body.theme-focus #picks { display: none !important; }
.theme-note .ic svg { width: 16px; height: 16px; margin-top: 2px; fill: var(--gold-mid); }

/* Tonight's weather: a small "⛅ 12°" inside the search bar, by the magnifier (Felix picked it,
   2026-10-25: it never moves, list open or hidden). Its icon turns blue when rain is likely before
   01:00. A tap opens the card under the search bar: the sky in words and the next hours. */
.wx-pill {
  display: inline-flex; align-items: center; gap: 4px; flex: none; height: 32px; padding: 0 9px 0 7px;
  border: 0; border-radius: 999px; background: var(--bg-soft); color: var(--text);
  font: inherit; font-size: 0.875rem; cursor: pointer;
}
.wx-pill[hidden], .search-pill.has-kind .wx-pill, .search-pill:not(:has(#search:placeholder-shown)) .wx-pill { display: none; }
.search-pill.has-wx .pill-brand { right: 118px; } /* (room for it) */
.search-pill:has(.wx-pill:focus) { box-shadow: 0 1px 2px rgba(60, 36, 20, .2), 0 2px 8px rgba(60, 36, 20, .12); } /* (no search ring: it is not the search) */
.wx-pill svg, .wx-card svg { width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.wx-pill svg { width: 18px; height: 18px; stroke-width: 2; }
.wx-pill .wx-t { font-variant-numeric: tabular-nums; }
.wx-pill .wx-d { color: var(--muted); font-size: 0.8125rem; margin-right: 1px; }
.wx-pill[aria-expanded="true"] .wx-d { color: inherit; }
.search-pill.has-wx:has(.wx-pill.other-day) .pill-brand { right: 150px; }
/* On an event's card: the forecast for its time. */
.facts .wx-ico svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; vertical-align: -4px; }
.facts .wx-row.wet .wx-ico, .facts .wx-rain { color: #1a73e8; }
:root.app-dark .facts .wx-row.wet .wx-ico, :root.app-dark .facts .wx-rain { color: #8ab4f8; }
.wx-pill.wet svg { color: #1a73e8; }
:root.app-dark .wx-pill.wet svg { color: #8ab4f8; }
.wx-pill:hover { background: color-mix(in srgb, var(--text) 10%, var(--bg)); }
.wx-pill:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.wx-pill[aria-expanded="true"] { background: var(--accent); color: var(--accent-text); }
.wx-pill[aria-expanded="true"] svg { color: inherit; }
.wx-card {
  position: fixed; z-index: 1004; width: 272px; padding: 12px 14px; box-sizing: border-box;
  border-radius: 12px; background: var(--bg); box-shadow: var(--shadow-2);
}
.wx-card[hidden] { display: none; }
.wx-card h3 { margin: 0 0 6px; font-size: 0.9375rem; }
.wx-hours { list-style: none; margin: 0; padding: 0; }
.wx-now { display: flex; align-items: center; gap: 8px; margin: 0 0 8px; line-height: 1.3; }
.wx-now svg { width: 28px; height: 28px; }
.wx-now-line { color: #1a73e8; font-size: 0.8125rem; }
.wx-sun { display: flex; align-items: center; gap: 5px; margin: -2px 0 8px; color: var(--muted); font-size: 0.8125rem; font-variant-numeric: tabular-nums; }
.wx-sun svg { width: 18px; height: 18px; color: #e37400; }
.wx-sun svg + span { margin-right: 10px; }
:root.app-dark .wx-sun svg { color: #fbbc04; }
:root.app-dark .wx-now-line { color: #8ab4f8; }
.wx-hours li { display: grid; grid-template-columns: 44px 24px 34px 1fr auto; gap: 0 4px; align-items: center; min-height: 28px; font-variant-numeric: tabular-nums; }
.wx-hours .wx-h { color: var(--muted); text-align: right; padding-right: 8px; } /* ("9 h" and "10 h" line up on the h) */
.wx-hours .wx-t { font-weight: 600; }
.wx-hours .wx-say { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); font-size: 0.8125rem; }
.wx-hours .wx-pct { color: #1a73e8; font-size: 0.8125rem; }
:root.app-dark .wx-hours .wx-pct { color: #8ab4f8; }
.wx-src { margin: 8px 0 0; font-size: 0.75rem; line-height: 1.35; }
/* Strikes and demonstrations: an amber chip first in the chip row, its card under it. */
.map-chips .alert-chip { background: #fef7e0; color: #8a5300; font-weight: 600; }
.map-chips .alert-chip[hidden] { display: none; }
.map-chips .alert-chip[aria-expanded="true"] { background: #f9ab00; color: #202124; }
:root.app-dark .map-chips .alert-chip { background: #4a3a10; color: #fdd663; }
.alert-chip .alert-ic { font-size: 1rem; line-height: 1; }
.alert-card { width: min(340px, calc(100vw - 16px)); max-height: min(70vh, 520px); overflow-y: auto; }
.alert-card h3 { margin: 0 0 6px; font-size: 0.9375rem; }
.alert-group { margin: 10px 0 4px; font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: #8a5300; }
:root.app-dark .alert-group { color: #fdd663; }
.alert-items .traffic-item { display: block; padding: 4px 0; font-size: 0.875rem; }
/* The one "i" info icon (INFO_ICON in app.js): a thin grey outline, blue while open. */
.info-ic { display: inline-grid; place-items: center; width: 20px; height: 20px; color: var(--muted); }
.info-ic svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
details[open] > summary .info-ic { color: var(--accent); }
/* A row folds open on a tap: the headline, then a small "i" for the message itself. */
.tr-fold > summary { list-style: none; cursor: pointer; }
.tr-fold > summary::-webkit-details-marker { display: none; }
.tr-i { display: inline-grid; vertical-align: -4px; margin-left: 2px; }
/* (the message, in a soft grey box, as the other small "i" notes) */
.tr-more { margin: 4px 0 2px; padding: 8px 10px; border-radius: 10px; background: var(--bg-soft); line-height: 1.4; }
.tr-more p { margin: 0 0 4px; }
.tr-mode { margin: 8px 0 2px; font-size: 0.75rem; font-weight: 600; color: var(--muted); }
.tr-station { padding: 4px 0; }
.tr-station + .tr-station { border-top: 1px solid var(--border); }
.tr-station > .tr-st { margin: 0 0 2px; font-weight: 700; font-size: 0.9375rem; }
.alert-items .tr-fold { padding: 2px 0; }
.alert-items .tr-fold .tr-what { font-weight: 600; }
.alert-items .tr-fold.blocked .tr-what { color: #c62828; }
.alert-items .tr-fold.disrupted .tr-what { color: #d35400; }
:root.app-dark .alert-items .tr-fold.blocked .tr-what { color: #f28b82; }
:root.app-dark .alert-items .tr-fold.disrupted .tr-what { color: #fcad70; }
.alert-src { margin: 10px 0 0; font-size: 0.75rem; line-height: 1.35; }

/* Restaurants and bars (data/eatdrink.geojson): style · price, and "Why it's here" on the card. */
.ed-style { margin: 10px 0 0; }
.ed-price { font-weight: 700; color: var(--text); letter-spacing: .02em; }
.ed-ter { display: flex; align-items: center; gap: 6px; margin: 6px 0 0; font-size: 0.875rem; }
.ed-ter .ic { display: inline-flex; color: var(--muted); }
.ed-ter .glyph { width: 18px; height: 18px; fill: currentColor; }
.ed-why { margin: 10px 0 2px; padding: 10px 12px; border-radius: 12px; background: color-mix(in srgb, var(--accent) 12%, var(--bg)); } /* (the same tint as the top chips) */
.ed-why p { margin: 0; line-height: 1.4; }
.ed-why p + p { margin-top: 4px; }
.ed-why .ed-why-head { font-weight: 700; font-size: 0.85rem; }
.ed-why .muted { font-size: 0.8rem; }
/* Your own rating on a restaurant's or bar's card: Loved it / Fine / Not for me, then sometimes
   "which was better?" against another place you loved. */
.ed-rate { margin: 10px 0 0; }
.ed-rate-head { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; margin: 0 0 6px; font-size: 0.85rem; font-weight: 700; }
.ed-info { display: contents; }
.ed-info summary { list-style: none; display: inline-grid; place-items: center; width: 24px; height: 24px; border-radius: 50%; cursor: pointer; color: var(--muted); }
.ed-info summary::-webkit-details-marker { display: none; }
.ed-info summary svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
.ed-info[open] summary { color: var(--accent); }
.ed-info p { flex-basis: 100%; margin: 2px 0 4px; padding: 8px 10px; border-radius: 10px; background: var(--bg-soft); font-weight: 400; color: var(--muted); line-height: 1.4; }
.ed-rate-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.ed-rate-row .ed-to-list { margin-left: auto; padding: 6px 0; border: 0; background: none; color: var(--accent); font: inherit; font-size: 0.875rem; font-weight: 600; cursor: pointer; }
.ed-rate-btn { min-height: 36px; padding: 0 12px; border-radius: 18px; border: 1px solid var(--border); background: var(--bg); color: var(--text); font: inherit; font-size: 0.9rem; cursor: pointer; }
.ed-rate-btn[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.ed-duel { --copper: var(--logo); margin-top: 12px; padding: 14px; border-radius: 16px; border: 1px solid color-mix(in srgb, var(--copper) 30%, transparent);
  background: color-mix(in srgb, var(--copper) 9%, var(--bg)); animation: ed-duel-in .35s ease-out; }
@keyframes ed-duel-in { from { opacity: 0; transform: translateY(8px) scale(.98); } }
.ed-duel p { margin: 0; }
.ed-duel-kick { font-size: 0.72rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--copper); }
.ed-duel-q { margin-top: 4px !important; font: 400 1.3rem/1.2 var(--serif); color: var(--text); }
.ed-duel-pick { display: flex; align-items: stretch; gap: 8px; margin: 12px 0 10px; }
.ed-duel-or { align-self: center; flex: none; font: italic 400 1rem var(--serif); color: var(--copper); }
.ed-duel-tile { position: relative; flex: 1 1 0; min-width: 0; min-height: 168px; display: flex; flex-direction: column; justify-content: flex-end; padding: 0; overflow: hidden;
  border-radius: 14px; border: 0; color: #fff; font: inherit; text-align: left; cursor: pointer; isolation: isolate;
  background: linear-gradient(160deg, color-mix(in srgb, var(--g) 55%, #2a2522), color-mix(in srgb, var(--g) 30%, #1a1614));
  box-shadow: 0 2px 10px rgba(60, 36, 20, .12); transition: transform .12s, box-shadow .12s; }
/* Both tiles always look the same (a tap left the first one ringed on phones): the ring only for a
   mouse hovering or the keyboard. */
@media (hover: hover) { .ed-duel-tile:hover { box-shadow: 0 0 0 2px var(--copper), 0 6px 18px rgba(60, 36, 20, .18); } }
.ed-duel-tile:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--copper), 0 6px 18px rgba(60, 36, 20, .18); }
.ed-duel-tile:focus:not(:focus-visible) { outline: none; }
.ed-duel-tile:active { transform: scale(.97); }
.ed-duel-img { position: absolute; inset: 0; z-index: -2; width: 100%; height: 100%; object-fit: cover; filter: var(--place-grade, none); }
.ed-duel-tile::after { content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(to top, rgba(12, 10, 9, .82) 0%, rgba(12, 10, 9, .35) 45%, rgba(12, 10, 9, 0) 75%); }
.ed-duel-txt { display: flex; flex-direction: column; gap: 2px; padding: 12px; }
.ed-duel-txt b { font-size: 1rem; line-height: 1.2; text-shadow: 0 1px 2px rgba(0, 0, 0, .4); }
.ed-duel-txt span { font-size: 0.78rem; line-height: 1.3; opacity: .88; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.ed-duel-ico { position: absolute; top: 10px; left: 10px; display: grid; place-items: center; width: 26px; height: 26px; }
.ed-duel-ico .glyph { width: 18px; height: 18px; fill: rgba(255, 255, 255, .55); }
.ed-duel-foot { display: flex; justify-content: space-between; gap: 12px; font-size: 0.85rem; }
@media (prefers-reduced-motion: reduce) { .ed-duel { animation: none; } }
.ed-rate-btn { display: inline-flex; align-items: center; gap: 6px; }
.ed-rate-btn .glyph { width: 16px; height: 16px; fill: var(--muted); }
.ed-rate-btn[aria-pressed="true"] .glyph { fill: currentColor; }

/* Kinds switched off in "Show or hide": their chips come last, greyed (a tap still shows just
   that kind). The last chip opens the switches. */
.map-chips .chip.off:not([aria-pressed="true"]) { color: var(--muted); }
.map-chips .chip.off:not([aria-pressed="true"]) .chip-glyph .glyph,
.map-chips .chip.off:not([aria-pressed="true"]) .ic svg { fill: var(--muted); opacity: 0.6; filter: grayscale(1); }
.map-chips .kinds-chip { font-weight: 600; }
.map-chips .kinds-chip::before {
  content: ""; display: inline-block; flex: none; width: 18px; height: 18px; background: currentColor;
  -webkit-mask: var(--ic) center / contain no-repeat; mask: var(--ic) center / contain no-repeat;
  --ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 12S6 5.5 12 5.5 21.5 12 21.5 12 18 18.5 12 18.5 2.5 12 2.5 12z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E");
}
.drop-menu.kinds-menu:not([hidden]) {
  width: 320px; max-width: calc(100vw - 20px); max-height: calc(100vh - 130px); overflow-y: auto; overscroll-behavior: contain;
  padding: 14px 16px 12px; box-sizing: border-box;
}
.kinds-menu h3 { margin: 0; font-size: 1.0625rem; }
.kinds-menu .kinds-sub { margin: 4px 0 8px; color: var(--muted); font-size: 0.8125rem; line-height: 1.35; }
.kinds-menu .kind-row {
  display: flex; align-items: center; gap: 12px; width: 100%; min-height: 44px; padding: 0;
  border: 0; border-top: 1px solid var(--border); background: none; color: var(--text); font: inherit; font-size: 0.9375rem; text-align: left; cursor: pointer;
}
.kinds-menu .kind-row .ic { display: inline-flex; width: 20px; justify-content: center; }
.kinds-menu .kind-row .lbl { flex: 1; }
.kinds-menu .kind-row .n { color: var(--muted); font-size: 0.75rem; font-variant-numeric: tabular-nums; }
.kinds-menu .kind-row.off { color: var(--muted); }
.kinds-menu .kind-row.off .glyph, .kinds-menu .kind-row.off .ic svg { fill: var(--muted); opacity: 0.6; filter: grayscale(1); }
.kinds-menu .sw { position: relative; flex: none; width: 38px; height: 22px; border-radius: 11px; background: var(--border); transition: background .15s; }
.kinds-menu .sw::after { content: ""; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, .3); transition: left .15s; }
.kinds-menu [aria-checked="true"] .sw { background: var(--accent); }
.kinds-menu [aria-checked="true"] .sw::after { left: 19px; }
.kinds-menu .kind-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.kinds-menu .kinds-done {
  position: sticky; bottom: 0; /* always in reach, however long the list */
  display: block; margin: 10px 0 0 auto; padding: 8px 20px; border: 0; border-radius: 999px; box-shadow: 0 2px 10px rgba(60, 36, 20, .2);
  background: var(--accent); color: var(--accent-text); font: inherit; font-weight: 600; cursor: pointer;
}
@media (prefers-reduced-motion: reduce) { .kinds-menu .sw, .kinds-menu .sw::after { transition: none; } }
/* Phones: a sheet from the bottom, the map dimmed behind it (a tap there closes it). */
@media (max-width: 720px) {
  .drop-menu.kinds-menu:not([hidden]) {
    top: auto !important; left: 0 !important; right: 0; bottom: 0; width: auto; max-width: none; max-height: 78vh;
    border-radius: 18px 18px 0 0; padding: 16px 18px calc(14px + env(safe-area-inset-bottom, 0px));
    box-shadow: 0 0 0 100vmax rgba(0, 0, 0, .3); z-index: 2000;
  }
}
/* Over the list: which kinds are switched off, "Show", and ✕ (closes it for good). */
.hidden-note { /* a plain line, so the picks sit higher (Felix, 2026-10-26) */
  display: flex; align-items: center; gap: 12px; margin: 0 16px 4px; padding: 0;
  color: var(--muted); font-size: 0.75rem; line-height: 1.4;
}
.hidden-note .note-close { display: none; }
.hidden-note[hidden] { display: none; }
.hidden-note b { color: var(--text); font-weight: 600; }
.hidden-note span { flex: 1; padding: 4px 0; }
.hidden-note .link { flex: none; border: 0; background: none; padding: 0; font: inherit; font-weight: 700; color: var(--accent); text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
.hidden-note .note-close { flex: none; width: 32px; height: 32px; margin-left: -4px; border: 0; border-radius: 50%; background: none; color: var(--muted); font-size: 0.9rem; cursor: pointer; }
@media (hover: hover) { .hidden-note .note-close:hover { background: color-mix(in srgb, var(--text) 8%, transparent); } }

/* The address row: a tap shows the place on the map (a small map icon on the right says so). */
.facts > li.to-map { grid-template-columns: 22px 1fr auto; cursor: pointer; }
.facts > li.to-map:hover .to-map-ico { background: color-mix(in srgb, var(--act-bg) 82%, var(--status)); }
.facts > li.to-map:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.to-map-ico {
  align-self: center; width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center;
  background: var(--act-bg); border: 1px solid color-mix(in srgb, var(--status) 22%, var(--act-bg)); color: var(--status);
}
.to-map-ico .bar-icon { width: 17px; height: 17px; }
/* A kind picked in the chips, Google Maps style: "← [icon] Restaurants ✕" in the search bar, and
   the chips under it turn into that kind's filters (price, open now; Filters last). */
.search-pill.has-kind .pill-brand, .search-pill.has-kind .pill-go { display: none !important; }
.kind-tag {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; height: 100%;
  font-size: 1rem; font-weight: 600; white-space: nowrap; overflow: hidden; cursor: text;
}
.kind-tag .lbl { overflow: hidden; text-overflow: ellipsis; }
.kind-tag .ic { display: inline-flex; align-items: center; flex: none; font-size: 1.1rem; }
.kind-tag .ic svg { width: 20px; height: 20px; }
.kind-tag .more { flex: none; color: var(--muted); font-weight: 500; }
.search-pill.has-kind { padding-right: 4px; }
#map-chips.kind-on #type-chips, #map-chips.kind-on #place-chips, #map-chips.kind-on #kinds-chip { display: none; }
#map-chips.kind-on > #price-chip { order: 1; }
#map-chips.kind-on > #open-chip, #map-chips.kind-on > #when-chip { order: 2; }
#map-chips.kind-on > .filt { order: 4; }
#terrace-chip .ic { display: inline-flex; align-items: center; }
#terrace-chip .ic svg { width: 18px; height: 18px; fill: currentColor; }
.price-note { flex-basis: 100%; margin: 4px 2px 0; color: var(--muted); font-size: 0.75rem; line-height: 1.3; max-width: 220px; }

/* My list › Been: your mark where the star was (♥ loved it, ✓ fine, not for me). */
.been-mark { flex: none; align-self: center; display: inline-flex; align-items: center; gap: 5px; margin-left: 8px; padding: 4px 10px; border-radius: 99px; font-size: 0.8125rem; font-weight: 600; white-space: nowrap; }
.been-mark .glyph { width: 15px; height: 15px; fill: currentColor; }
.been-mark.love { background: color-mix(in srgb, #c0304a 12%, var(--bg)); color: #c0304a; }
:root.app-dark .been-mark.love { color: #f08ea0; }
.been-mark.fine { background: color-mix(in srgb, var(--accent) 12%, var(--bg)); color: var(--accent); }
.been-mark.no { background: var(--bg-soft); color: var(--muted); }
/* Live traffic in English: the French original, one tap further (web/traffic_en.js). */
.tr-orig { margin-top: 4px; }
.tr-orig summary { font-size: 0.8rem; }
.st-note .tr-orig summary, .traffic-item .tr-orig summary { color: var(--muted); }
/* Your ranking within "Loved it": 1, 2, 3… from the "which would you send a friend to?" answers. */
.been-rank { flex: none; align-self: center; display: grid; place-items: center; min-width: 26px; height: 26px; margin-left: 8px; padding: 0 6px; border-radius: 13px; background: var(--logo); color: #fff; font: 700 0.875rem/1 var(--serif); }
:root.app-dark .been-rank { background: var(--logo); color: #1d2330; }
/* "Share my list": the same soft, round look as the place card's buttons (Felix, 2026-10-25:
   the old box and its ⤴ looked out of date). Want to go and Loved it each under a small head. */
.share-pop { border: none; border-radius: 16px; padding: 14px 14px 12px; }
.share-pop .list-name input { border-radius: 10px; padding: 10px 12px; }
.share-pick-group { padding: 12px 2px 4px; font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); }
.share-pick li.share-pick-group { border-top: none; }
.share-pick input { width: 18px; height: 18px; margin-top: 1px; accent-color: var(--accent); }
.share-pop .date-pop-actions button { display: inline-flex; align-items: center; gap: 6px; min-height: 36px; padding: 0 16px; border-radius: 999px; font-weight: 600; }
.share-pop #share-cancel { border: none; background: color-mix(in srgb, var(--accent) 8%, var(--bg)); color: var(--accent); }

/* Zoomed out to the region (the day trips): no arrondissement names over the small city (app.js FAR_ZOOM). */
.map-far .leaflet-areaLabels-pane, .map-far .leaflet-areaPicked-pane { display: none; }

/* Computers: the tab on the panel's right edge folds the list away (the whole map), and back,
   as Google Maps. The search bar and the chips stay where they are; the weather button and a
   map card move to the free space on the left. */
.panel-fold { display: none; }
@media (min-width: 721px) {
  .panel { transition: transform .25s ease, visibility 0s; }
  .panel-fold {
    display: flex; align-items: center; justify-content: center; position: fixed; z-index: 1000;
    top: 50%; left: var(--panel-width); width: 22px; height: 48px; margin-top: -24px; padding: 0;
    border: 0; border-radius: 0 8px 8px 0; background: var(--bg); color: var(--muted); cursor: pointer;
    box-shadow: 2px 1px 4px rgba(0, 0, 0, .2); clip-path: inset(-8px -8px -8px 0); /* (no shadow on the panel's side) */
    transition: left .25s ease;
  }
  .panel-fold svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; transition: transform .25s ease; }
  .panel-fold:hover { color: var(--text); background: var(--bg-soft); }
  .panel-fold:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
  body.panel-folded .panel { transform: translateX(calc(-100% - 8px)); visibility: hidden; transition: transform .25s ease, visibility 0s .25s; }
  body.panel-folded .panel-fold { left: 0; clip-path: none; }
  body.panel-folded .panel-fold svg { transform: rotate(180deg); }
  body.map-full #map { left: 0; }
  body.panel-folded .am-card { left: 24px; }
}
@media (min-width: 721px) and (prefers-reduced-motion: reduce) {
  .panel, .panel-fold, .panel-fold svg, body.panel-folded .panel { transition: none; }
}
/* My list's bookmark fills in while My list is on. */
.fab-list[aria-pressed="true"] svg { fill: currentColor; }
/* My list's Want to go, Been and Share: chips like the map's (Felix picked B, 2026-10-25).
   White round chips with a line icon, the word and a count; the open tab fills in the accent
   colour (the one "on" look); Share a chip too, on the right. */
.saved-head { margin: 14px 16px 8px; }
.saved-head .saved-tabs { gap: 8px; padding: 0; border: 0; background: none; }
.saved-head .saved-tabs button, .saved-head .share-saved {
  display: inline-flex; align-items: center; gap: 7px; height: 40px; min-height: 40px; padding: 0 13px 0 11px;
  border: 1px solid var(--border); border-radius: 999px; background: var(--raised, var(--bg)); color: var(--text);
  font-size: 0.9rem; font-weight: 600; white-space: nowrap; box-shadow: 0 1px 3px rgba(60, 36, 20, 0.12);
}
.saved-head .saved-tabs button .bar-icon, .saved-head .share-saved .bar-icon { width: 18px; height: 18px; }
.saved-head .saved-tabs button[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: var(--accent-text); box-shadow: 0 1px 3px rgba(60, 36, 20, 0.2); }
.saved-head .saved-tabs .tab-count { background: var(--bg-soft); color: var(--muted); }
.saved-head .saved-tabs button[aria-pressed="true"] .tab-count { background: rgba(255, 255, 255, 0.22); color: var(--accent-text); }
.saved-head .share-saved { color: var(--accent); }
.saved-head .share-saved:hover { background: var(--bg-soft); }
@media (max-width: 360px) { .saved-head .saved-tabs button, .saved-head .share-saved { padding: 0 10px 0 9px; gap: 5px; } }
/* "Want to go" is a flag (Felix picked A, 2026-10-25): the list rows' flag button, outlined,
   filled in gold once it's on your list. */
.star .flag-ic { width: 20px; height: 20px; fill: currentColor; display: block; }
.star:not([aria-pressed="true"]) { color: var(--muted); }
/* The My list chip on the map: a bookmark, as its button in the map's card; no count beside the
   ✕ (Felix: it read as "x²"; the tabs below show the counts). */
#saved-count { display: none; }
.saved-btn .chip-bm { width: 17px; height: 17px; fill: currentColor; flex: none; }
.ed-rate-note { margin: -2px 0 8px; color: var(--muted); font-size: 0.85rem; }

/* Day trips far out, drawn on their rings round Paris (app.js tripIcon, renderTrips): a round
   photo with a thin blue ring and a small train badge, its name and train ride beside it as map
   text with a soft halo, no white box (Felix picked A, 2026-10-26), on the side towards Paris. */
/* (.leaflet-marker-icon is already absolute: the photo and name sit in it) */
.trip-ph { position: absolute; inset: 0; display: grid; place-items: center; border-radius: 50%; background: var(--bg-soft);
  box-shadow: 0 0 0 2px var(--accent), 0 2px 6px rgba(0, 0, 0, 0.35); font-size: 16px; }
/* (.leaflet-marker-pane: Leaflet's own "marker-pane img { width: auto }" beat a plainer rule, so tall
   photos (Rouen, Chartres) left white space and wide ones spilled out) */
.leaflet-marker-pane .trip-ph img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
.trip-ph b { position: absolute; right: -5px; bottom: -5px; width: 18px; height: 18px; display: grid; place-items: center; border-radius: 50%;
  color: var(--accent-text); background: var(--accent); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35); }
.trip-ph b svg.lic { width: 12px; height: 12px; stroke-width: 2.2; display: block; }
.trip-lb { position: absolute; top: 50%; left: 47px; width: max-content; transform: translateY(-50%); white-space: nowrap;
  color: var(--text); font-size: 13px; line-height: 1.25; --halo: var(--bg);
  text-shadow: 0 0 2px var(--halo), 0 0 2px var(--halo), 0 0 3px var(--halo), 0 0 4px var(--halo), 0 0 5px var(--halo); }
.trip-pin.left .trip-lb { left: auto; right: 47px; text-align: right; }
.trip-pin.below .trip-lb, .trip-pin.above .trip-lb { left: 50%; transform: translateX(-50%); text-align: center; }
.trip-pin.below .trip-lb { top: 45px; }
.trip-pin.above .trip-lb { top: auto; bottom: 45px; }
.trip-ph img:not([hidden]) + .trip-g { display: none; }
.trip-g { font-style: normal; color: var(--accent); }
.trip-lb strong { display: block; font-weight: 700; }
.trip-lb small { display: block; color: var(--muted); font-size: 11px; }
.trip-pin.current .trip-ph { box-shadow: 0 0 0 3px var(--accent), 0 0 0 6px color-mix(in srgb, var(--accent) 25%, transparent), 0 2px 6px rgba(0, 0, 0, 0.35); }
.trip-ring-label svg.lic { width: 13px; height: 13px; vertical-align: -2px; margin-right: 3px; }
.trip-ring-label span { position: absolute; transform: translate(calc(-100% - 6px), -50%); white-space: nowrap; padding: 2px 8px; border-radius: 10px;
  background: var(--bg); color: var(--accent); font-size: 11px; font-weight: 600; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); }
/* A theme week's places (themes.json "spots"): gold round pins with the theme's icon, the event
   itself a little bigger. */
.theme-mark { border-radius: 50%; background: var(--gold-deep); border: 2px solid #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35); display: grid; place-items: center; box-sizing: border-box; }
.theme-mark svg { width: 62%; height: 62%; fill: #fff; display: block; }
.theme-mark.picked { box-shadow: 0 0 0 5px rgba(184, 134, 11, 0.35); z-index: 1000 !important; }
/* A theme pin's details, in the panel above the theme's note (no card over the map). */
.theme-spot { position: relative; margin: 0 16px 10px; padding: 12px 44px 12px 14px; border: 1px solid var(--border); border-radius: 16px;
  background: var(--bg); font-size: 0.875rem; line-height: 1.4; }
.theme-spot[hidden] { display: none; }
.theme-spot .photo-wrap { margin: -12px -44px 10px -14px; border-radius: 16px 16px 0 0; overflow: hidden; max-height: 190px; }
.theme-spot .photo-wrap + .am-x { top: 8px; right: 8px; background: rgba(255, 255, 255, 0.9); color: #333; }
.theme-spot .am-head { display: flex; gap: 10px; align-items: flex-start; }
.theme-spot .theme-ico svg { width: 24px; height: 24px; fill: var(--gold-deep); display: block; }
.theme-spot .am-text strong { font-size: 1rem; }
.theme-spot .film-scene { margin: 10px 0 0; font-size: 0.9375rem; white-space: pre-line; }
.theme-spot .film-note { margin: 8px 0 0; }
.theme-spot .am-row { display: flex; align-items: center; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.theme-spot .am-row .button { display: inline-flex; align-items: center; min-height: 36px; padding: 0 14px; border-radius: 18px; text-decoration: none; font-weight: 600; }
.theme-spot .am-row .button.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.theme-spot .am-x { position: absolute; top: 6px; right: 6px; width: 36px; height: 36px; border: 0; background: none; color: var(--muted); font-size: 18px; cursor: pointer; border-radius: 18px; }
.theme-spot .am-x:hover { background: var(--bg-soft); }
:root.app-dark .theme-days { color: #e0b84a; }
.theme-card .theme-ico svg { width: 24px; height: 24px; fill: var(--gold-deep); display: block; }
.theme-card .film-scene { white-space: pre-line; }
/* My list shows everything on it: no "Show or hide" there (Felix, 2026-10-25). */
.saved-view #kinds-chip { display: none; }
/* Your ranking in Been, one list per kind (Felix, 2026-10-25, as Beli): the rank before the
   name, your score out of 10 in a round badge on the right, in your answer's colour. */
.been-kind { display: flex; justify-content: space-between; align-items: center; }
.been-kind .link { font-size: 0.8125rem; text-transform: none; letter-spacing: 0; font-weight: 600; }
.been-n { display: inline-grid; place-items: center; min-width: 22px; height: 22px; margin-right: 7px; padding: 0 5px; border-radius: 11px; background: var(--logo); color: #fff; font: 700 0.8125rem/1 var(--serif); vertical-align: 1px; }
:root.app-dark .been-n { background: var(--logo); color: #1d2330; }
.been-score { flex: none; align-self: center; position: relative; display: grid; place-items: center; width: 46px; height: 46px; margin-left: 8px; border-radius: 50%; border: 2px solid currentColor; background: var(--bg); }
.been-score b { font: 700 1rem/1 var(--serif); color: var(--text); }
.been-score > span { position: absolute; right: -4px; bottom: -4px; display: grid; place-items: center; width: 20px; height: 20px; border-radius: 50%; background: currentColor; }
.been-score .glyph { width: 12px; height: 12px; fill: var(--bg); }
.been-score.love { color: #c0304a; }
:root.app-dark .been-score.love { color: #f08ea0; }
.been-score.fine { color: var(--accent); }
.been-score.no { color: var(--muted); }
.title:has(> .been-n) { display: flex; align-items: center; }
.title:has(> .been-n) .ttl { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.been-score { margin-right: 4px; }
/* A kind's heading in Been folds its list. */
.been-fold { display: inline-flex; align-items: center; gap: 4px; min-width: 0; padding: 0; border: 0; background: none; color: inherit; font: inherit; letter-spacing: inherit; text-transform: inherit; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.been-fold svg { width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; transition: transform 0.15s; }
.been-fold[aria-expanded="false"] svg { transform: rotate(-90deg); }
.been-top { text-transform: none; letter-spacing: 0; font-weight: 500; overflow: hidden; text-overflow: ellipsis; }
/* "Did you know?" (app.js, TIPS): the same card as the toilets' and the buses', a bulb in front. */
.tip-card .tip-ico { flex: none; display: flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 18px; background: color-mix(in srgb, var(--accent) 12%, var(--bg)); }
.tip-card .tip-ico svg { width: 20px; height: 20px; fill: none; stroke: var(--accent); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.tip-card .tip-kicker { display: block; font-size: 0.75rem; font-weight: 600; color: var(--accent); letter-spacing: .02em; }
.tip-card .am-text p { margin: 2px 0 0; font-size: 0.9375rem; line-height: 1.35; }
.tip-card .tip-row { justify-content: flex-end; }
.tip-card .tip-row .button { cursor: pointer; }
/* Day trips on a phone: names only on the pins, no ring labels (the sheet lists both). */
@media (max-width: 720px) {
  body.trip-focus .trip-lb small, body.trip-focus .trip-ring-label { display: none; }
}
.trip-ev { display: block; color: var(--accent); font-size: 13px; }
.trip-unesco { display: block; color: var(--muted); font-size: 12px; font-weight: 600; }

/* Trust dots (?trust=1, app.js trustDot): green checked, amber one source, red not known. The
   dot sits at the line's right; hover or tap shows where the detail comes from. */
.trust-dot { display: inline-block; width: 22px; height: 22px; margin: -4px 0 -4px -4px; padding: 0; border: 0; background: none; cursor: help; position: relative; vertical-align: middle; }
.trust-dot::after { content: ""; position: absolute; inset: 7px; border-radius: 50%; background: var(--t); }
.trust-dot.t-g, .trust-key .t-g { --t: #1e8e3e; }
.trust-dot.t-a, .trust-key .t-a { --t: #f29900; }
.trust-dot.t-r, .trust-key .t-r { --t: #d93025; }
/* On a row of the details: on the corner of the row's icon, beside the line it rates. */
.facts > li:has(> div > .trust-dot) { position: relative; }
.facts > li > div > .trust-dot { position: absolute; left: 6px; top: 13px; margin: 0; }
.facts > li:first-child > div > .trust-dot { top: 8px; }
.facts > li > div > .trust-dot::after { inset: 6px; box-shadow: 0 0 0 2px var(--bg); }
/* The key, one line under the details. */
.trust-key { display: flex; flex-wrap: wrap; gap: 2px 12px; margin: 6px 0 0; padding-top: 8px; border-top: 1px solid var(--border); font-size: 0.75rem; color: var(--muted); }
.trust-key span { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.trust-key span::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--t); }
#trust-tip { position: fixed; z-index: 10000; padding: 6px 10px; border-radius: 8px; background: #303134; color: #fff; font-size: 0.8125rem; line-height: 1.35; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); pointer-events: none; }
#trust-tip[hidden] { display: none; }

/* ---------- Home: the best way home tonight (app.js, "Home") ---------- */
.map-chips .home-chip[aria-expanded="true"] { background: var(--accent); color: var(--accent-text); }
.home-chip .home-ic { display: inline-flex; line-height: 1; } /* (the chip's own 5px gap, as the clock's) */
.home-card { z-index: 1002; max-height: min(62vh, 560px); overflow-y: auto; }
.home-card .home-big { font-size: 1.5rem; line-height: 1; }
.home-card .home-time { font-size: 1.25rem; }
.home-card .home-sum { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; margin: 8px 0 0; font-size: 0.875rem; }
.home-card .home-sum .line-badge { margin: 0; }
.home-card .hsum-sep { color: var(--muted); }
.home-card .home-alts { display: flex; gap: 6px; margin-top: 8px; }
.home-card .home-alts .chip { min-height: 30px; padding: 0 10px; font-size: 0.8125rem; }
.home-card .home-alts .chip.on { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.home-card :is(.home-ok, .home-night, .home-news) { margin: 8px 0 0; padding: 7px 10px; border-radius: 10px; font-size: 0.8125rem; }
.home-card .home-ok { background: #e6f4ea; color: #1e6b34; }
.home-card .home-night { background: #e8eaf6; color: #283593; }
.home-card .home-news { background: #fef7e0; color: #8a5300; }
:root.app-dark .home-card .home-ok { background: #1e3a26; color: #a8dab5; }
:root.app-dark .home-card .home-night { background: #262b4a; color: #c5cae9; }
:root.app-dark .home-card .home-news { background: #4a3a10; color: #fdd663; }
.home-card .home-steps { list-style: none; margin: 8px 0 0; padding: 0; }
.home-card .home-steps li { display: flex; gap: 10px; align-items: flex-start; padding: 7px 0; border-top: 1px solid var(--border); }
.home-card .hs-ico { flex: none; width: 30px; text-align: center; }
.home-card .hs-ico .line-badge { margin: 0; }
.home-card .home-foot { margin: 8px 0 0; font-size: 0.8125rem; }
.home-card .linkish { padding: 0; border: 0; background: none; color: var(--accent); font: inherit; font-weight: 600; cursor: pointer; }
.home-card .home-find { width: 100%; box-sizing: border-box; margin-top: 10px; padding: 9px 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--bg); color: var(--text); font: inherit; font-size: 1rem; }
.home-card .home-found { list-style: none; margin: 6px 0 0; padding: 0; }
.home-card .home-found button { display: flex; align-items: center; gap: 8px; width: 100%; padding: 7px 4px; border: 0; border-top: 1px solid var(--border); background: none; color: var(--text); font: inherit; text-align: left; cursor: pointer; }
.home-card .home-found .line-badge { margin: 0 1px; }
.home-card .home-none { margin: 8px 0 0; }
/* (The box and the lock in one 18 px column, both lines' words starting 10 px after it: Felix, 2026-10-26.) */
.home-card .home-keep { display: flex; align-items: center; gap: 10px; margin-top: 12px; font-size: 0.8125rem; }
.home-card .home-keep input { flex: none; width: 16px; height: 16px; margin: 0 1px; }
.home-card .home-privacy { margin: 8px 0 0; font-size: 0.75rem; gap: 10px; }
.home-card .home-privacy > svg.lic { margin-left: 1px; margin-right: 1px; }
.home-card .home-last { margin: 10px 0 0; font-weight: 600; }
.home-card .home-lines { margin: 4px 0 0; font-size: 0.8125rem; }
.home-pin span { display: grid; place-items: center; width: 30px; height: 30px; border-radius: 50%; background: #1f3d7a; border: 2px solid #fff; box-shadow: 0 1px 4px rgba(0, 0, 0, .35); font-size: 15px; box-sizing: border-box; }
/* "Leave by 00:55 for the last metro home": over the map, just above the sheet (phones) or at the
   bottom of the map (computers). */
.home-bar { position: fixed; z-index: 1001; left: 8px; right: 8px; bottom: calc(var(--peek-h, 252px) + env(safe-area-inset-bottom, 0px) + 10px);
  display: flex; gap: 10px; align-items: center; padding: 10px 14px; border: 0; border-radius: 14px; background: #1f3d7a; color: #fff;
  font: inherit; font-size: 0.875rem; line-height: 1.35; text-align: left; box-shadow: var(--shadow); cursor: pointer; }
.home-bar[hidden] { display: none; }
.home-bar .home-moon { font-size: 1.25rem; }
.home-bar .home-bar-sub { opacity: .85; font-size: 0.8125rem; }
.home-bar .line-badge { margin: 0 1px; }
@media (min-width: 721px) {
  .home-card { left: calc(var(--panel-width) + 16px); right: auto; bottom: auto; top: 120px; width: 380px; max-height: calc(100vh - 150px); }
  body.panel-folded .home-card { left: 24px; }
  .home-bar { left: calc(var(--panel-width) + 16px); right: auto; bottom: 24px; width: 380px; }
  body.panel-folded .home-bar { left: 24px; }
}
/* Phones: the way home is the bottom sheet (as a dropped pin's card), the list slid away under it. */
@media (max-width: 720px) {
  body[data-sheet="full"] .home-bar { display: none; }
  body:has(#home-card:not([hidden])) > .pin-card { display: none; }
  body > .home-card { left: 0; right: 0; bottom: 0; max-height: 58vh; border-width: 1px 0 0; border-radius: 16px 16px 0 0; padding: 16px 40px calc(10px + env(safe-area-inset-bottom, 0px)) 14px; box-shadow: 0 -2px 12px rgba(0, 0, 0, .15); }
  body > .home-card .am-x { top: 10px; }
  body.home-open:not([data-sheet="peek"]):not([data-sheet="mini"]) > .home-card { display: none; }
  /* (An event's or a group's card tapped on the map goes on top: the way home waits under it, as the pin's card does.) */
  body:has(#spot-card:not([hidden]), #preview:not([hidden])) > .home-card { display: none; }
}
body:has(#am-card:not([hidden]), #bus-card:not([hidden])) .home-card { display: none; }

/* Best baguettes (Key › Just for fun): numbered pins for the year shown, small dots for the others. */
body.bread-focus #map-chips, body.bread-focus .list-head, body.bread-focus #event-list, body.bread-focus #welcome,
body.bread-focus #hidden-note, body.bread-focus #theme-note, body.bread-focus #picks { display: none !important; }
.bread-pin { display: inline-grid; place-items: center; flex: none; width: 26px; height: 26px; box-sizing: border-box; border-radius: 50%; border: 2px solid #fff; background: #8a5a2b; color: #fff; font: 700 0.8125rem/1 var(--sans); box-shadow: 0 1px 3px rgba(0,0,0,.35); }
.bread-pin.r1 { background: #c9971c; }
.bread-pin.r2 { background: #8c96a0; }
.bread-pin.r3 { background: #b06a33; }
.bread-mark .bread-pin { width: 100%; height: 100%; }
.bread-mark.picked { z-index: 1000 !important; }
.bread-mark.picked .bread-pin { transform: scale(1.35); }
.bread-dot { display: block; width: 100%; height: 100%; box-sizing: border-box; border-radius: 50%; border: 2px solid #fff; background: #c9a77c; box-shadow: 0 1px 2px rgba(0,0,0,.3); }
.bread-mark.other.picked .bread-dot { transform: scale(1.5); background: #8a5a2b; }
.bread-panel .bread-years { display: flex; gap: 6px; margin: 12px 0 4px; overflow-x: auto; scrollbar-width: none; }
.bread-panel .bread-year { flex: none; min-height: 32px; padding: 0 14px; border: 1px solid var(--border); border-radius: 16px; background: var(--bg); color: var(--text); font: inherit; font-weight: 600; font-size: 0.875rem; cursor: pointer; }
.bread-panel .bread-year.on { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.bread-panel .film-row .bread-pin { width: 32px; height: 32px; font-size: 0.9375rem; box-shadow: none; border: 0; }
.bread-panel .film-row-famous { color: #8a5a2b; }
.bread-panel .film-sub { color: var(--text); } /* (gold only for what matters most: Felix, 2026-10-25) */
.bread-panel .bread-wins { display: flex; flex-direction: column; margin-top: 4px; }
.bread-panel .bread-win { display: flex; align-items: center; gap: 10px; text-align: left; padding: 7px 8px; margin: 0 -8px; border: 0; border-radius: 10px; background: none; color: var(--text); font: inherit; cursor: pointer; }
.bread-panel .bread-win:hover { background: var(--bg-soft); }
.bread-panel .bread-win .bread-pin { border: 0; box-shadow: none; }
.bread-panel .bread-win .muted { font-size: 0.8125rem; }
:root.app-dark .bread-panel .film-row-famous { color: #e0b884; }
.bread-panel .bread-gone { cursor: default; }
.bread-panel .bread-gone:hover { background: none; }
.bread-panel .bread-gone .bread-pin { background: var(--border); color: var(--muted); }
.bread-panel .bread-gone .film-row-name { color: var(--muted); font-weight: 500; }
/* A prize bakery's place card: its prizes, each linked to the City's results. */
.bread-prizes { display: flex; flex-direction: column; gap: 6px; margin: 6px 0; }
.bread-prize { display: flex; align-items: center; gap: 8px; color: var(--text); text-decoration: none; }
.bread-prize:hover strong { text-decoration: underline; }
.bread-prize .bread-pin { width: 24px; height: 24px; font-size: 0.75rem; border: 0; box-shadow: none; }
.ed-why .bread-open { margin-top: 6px; padding: 0; }
/* A view's page (a film scene, a route, a march, a bakery): the round Back of a place's page
   (Felix, 2026-10-26). On the photo: white, floating, staying there while the page scrolls.
   With no photo: flat, above the name. */
.film-panel .view-bar { margin: 0 0 8px; }
.film-panel .view-bar.on-photo { position: sticky; top: 0; z-index: 5; height: 0; margin: 0; }
.film-panel .view-back { display: grid; place-items: center; width: 38px; height: 38px; padding: 0; border: 0; border-radius: 50%;
  background: var(--bg-soft); color: var(--text); cursor: pointer; }
.film-panel .view-back .bar-icon { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.film-panel .view-bar.on-photo .view-back { position: absolute; top: 10px; left: 10px; background: var(--bg); box-shadow: 0 1px 4px rgba(60, 36, 20, 0.3); }
.film-panel .view-back:hover { background: var(--bg-soft); }
.film-panel .view-back:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Phones: small buttons keep their look but take a fingertip (40 px or more): an invisible
   ring around each catches taps just outside it. */
@media (max-width: 720px) {
  .wx-pill, .hidden-note .link, .hidden-note .note-close, .list-scope button, #preview-close, .book-link a { position: relative; }
  :is(.wx-pill, .hidden-note .link, .hidden-note .note-close, .list-scope button, #preview-close, .book-link a,
    .welcome-close, .photo-c, .photo-dislike, .sc-ban .sc-close, #detail .detail-bar .bar-back)::after {
    content: ""; position: absolute; inset: -8px;
  }
  .list-scope button::after { inset: -9px 0; } /* (side by side: only up and down, or they'd overlap) */
  .list-scope button:last-child::after { right: -8px; }
  .photo-c::after { inset: -10px; }
  .hidden-note .link::after { inset: -12px 0 -12px -8px; }
  .hidden-note .note-close::after { inset: -8px -8px -8px 0; } /* (beside Show: not over it) */
  .book-link a::after { inset: -12px -6px; }
  .photo-dislike::after { inset: -12px -6px; }
}

/* Demonstrations: a peaceful march at the top of the panel, and the coming marches in big cards. */
.film-panel.demo-panel .demo-cover { position: relative; margin: 0 0 12px; }
.film-panel.demo-panel .demo-cover .photo-wrap { margin: 0; }
.film-panel.demo-panel .demo-cover figcaption { position: absolute; left: 0; right: 0; bottom: 0; padding: 22px 44px 9px 12px; border-radius: 0 0 12px 12px;
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.55)); color: #fff; font-size: 0.8125rem; pointer-events: none; }
.demo-coming { margin: 16px 0 14px; }
.demo-coming-head { margin: 0 0 8px; font-size: 1.0625rem; font-weight: 600; }
.demo-next { display: flex; gap: 12px; align-items: flex-start; width: 100%; margin: 0 0 8px; padding: 12px; text-align: left; font: inherit; color: inherit;
  background: #fce8e6; border: 1px solid #f6c7c2; border-radius: 14px; cursor: pointer; }
.demo-next:hover { border-color: #d93025; }
.demo-next-date { flex: none; display: grid; justify-items: center; width: 56px; padding: 6px 0; border-radius: 10px; background: #d93025; color: #fff; line-height: 1.1; }
.demo-next-date b { font-size: 1.5rem; font-variant-numeric: tabular-nums; }
.demo-next-date small { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.02em; }
.demo-next-text { display: grid; gap: 2px; min-width: 0; }
.demo-next-text strong { font-size: 1rem; }
.demo-next-when { color: #a50e0e; font-weight: 600; font-size: 0.875rem; }
.demo-next-way { font-size: 0.875rem; }
.demo-next-noroute { justify-self: start; margin-top: 4px; padding: 2px 9px; border-radius: 999px; background: #fef7e0; color: #8a5300; font-size: 0.8125rem; font-weight: 500; }
:root.app-dark .demo-next { background: #3a1d1b; border-color: #5c2b28; }
:root.app-dark .demo-next-when { color: #f28b82; }
:root.app-dark .demo-next-noroute { background: #4a3a10; color: #fdd663; }

/* Things to see near a bike route (app.js, TOUR_STOP_KINDS): a round line icon, its name beside it. */
.tour-stop { display: flex; align-items: center; gap: 4px; width: auto !important; height: 28px !important; white-space: nowrap; pointer-events: auto; cursor: pointer; }
.tour-stop svg { flex: none; filter: drop-shadow(0 1px 1.5px rgba(0,0,0,.3)); }
.tour-stop span { font-size: 12px; font-weight: 600; color: var(--map-text); text-shadow: 0 0 2px var(--land), 0 0 2px var(--land), 0 0 3px var(--land); }
.tour-stop.picked span { font-weight: 700; }
.film-panel .tour-stops-head { margin: 16px 0 4px; font-weight: 700; font-size: 0.9375rem; }
.film-panel .tour-stop-ico { flex: none; display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; }
.film-panel .tour-stop-route { margin-top: 12px; }

/* A place closed right now: those words in red, as on Google Maps (Open stays navy). */
.closed-now { color: var(--sold); }

/* The map's chip row on computers: the chips fade out just before a ‹ › arrow, so no cut chip or
   stray letters show around it (the arrow itself stays solid). */
@media (min-width: 721px) {
.map-chips[data-fade="r"] { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 72px), transparent calc(100% - 34px), #000 calc(100% - 33px)); mask-image: linear-gradient(to right, #000 calc(100% - 72px), transparent calc(100% - 34px), #000 calc(100% - 33px)); }
.map-chips[data-fade="l"] { -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 72px), transparent calc(100% - 34px), #000 calc(100% - 33px)); mask-image: linear-gradient(to left, #000 calc(100% - 72px), transparent calc(100% - 34px), #000 calc(100% - 33px)); }
.map-chips[data-fade="lr"] {
  -webkit-mask-image: linear-gradient(to right, #000 33px, transparent 34px, #000 72px, #000 calc(100% - 72px), transparent calc(100% - 34px), #000 calc(100% - 33px));
  mask-image: linear-gradient(to right, #000 33px, transparent 34px, #000 72px, #000 calc(100% - 72px), transparent calc(100% - 34px), #000 calc(100% - 33px));
}
}

/* Dark: a place's count bubble keeps its daytime colour, so its number stays white. */
:root.app-dark :is(.place-pin, .pl-stack) .pp-n { color: #fff; }
/* A map button that is on (copper) keeps a visible focus ring: outside it, not inside. */
.fab[aria-expanded="true"]:focus-visible, .fab[aria-pressed="true"]:focus-visible { outline-offset: 2px; }

/* French times have their own spaces ("12 h–21 h"): a tighter range line there. */
:lang(fr) .dash { width: 0.56em; }
:lang(fr) .dash::after { left: 0.07em; right: 0.07em; }

/* The Key: a soft fade at its foot while more is below, so a row cut in half reads as "scroll". */
.layers-panel::after { content: ""; position: sticky; bottom: -12px; flex: none; height: 24px; margin: -8px -14px -12px; background: linear-gradient(color-mix(in srgb, var(--bg) 0%, transparent), var(--bg)); pointer-events: none; }

/* A free event's dot: a green ring, as the Key says ("Free (green ring)"). */
.dot.event.free { box-shadow: 0 0 0 2px var(--free), 0 1px 3px rgba(40, 32, 20, 0.3); }

/* A line of text led by a line icon (the home card's notes, a shared list's name): the icon 16 px,
   6 px from its words, its middle on the first line's, as on the station card (Felix, 2026-10-26). */
.ic-line { display: flex; align-items: flex-start; gap: 6px; }
.ic-line > svg.lic { width: 16px; height: 16px; margin-top: calc((1lh - 16px) / 2); vertical-align: 0; }
/* (The moon in the line cards' badge column, its words where "Line 1" starts: border 1 + padding 12 + (18 - 16) / 2.) */
.st-night { padding-left: 14px; flex-wrap: nowrap; align-items: baseline; gap: 0; }
/* (One row on the words' baseline: the moon in the line cards' badge column, the words where
   "Line 1" starts, then the night-bus badges, a second row of them under the first badge. The
   moon's middle sits on the capitals' middle (0.36em above the baseline), as do the badges' letters.
   Felix, 2026-10-26.) */
.st-night-lbl { flex: none; white-space: nowrap; margin-right: 6px; }
.st-night-lbl svg.lic { width: 16px; height: 16px; margin-right: 11px; vertical-align: calc(0.36em - 8px); }
.st-night-buses { display: flex; flex-wrap: wrap; gap: 4px; min-width: 0; }
.st-night-buses .line-badge { margin: 0; vertical-align: 0; position: relative; top: -0.08em; } /* (a badge box is a touch low against its letters: measured on the pixels) */
.home-bar .home-moon svg.lic { width: 22px; height: 22px; display: block; }
.reach-chip svg.lic { width: 16px; height: 16px; vertical-align: -3px; margin-right: 6px; }
/* "Directions" (it was "Walk there"): the round button's arrow sign, 16 px, 6 px before its word. */
.dir-sign { display: inline-grid; place-items: center; flex: none; vertical-align: -3px; margin-right: 6px; }
.dir-sign .bar-icon { display: block; }
.st-fact .dir-sign { margin-right: 2px; } /* (the pill's own 4 px gap makes it 6) */
