/* Palette par defaut = theme sombre actuel (sidebar/ecrans fonces), pour ne
   rien changer au rendu existant pour les navigateurs sans support de
   prefers-color-scheme, ni pour une preference systeme sombre explicite.
   Seule une preference systeme *claire* explicite bascule ces tokens (voir
   @media plus bas) : le thème sombre reste la reference eprouvee.
   --paper est le seul token volontairement invariant entre les deux themes
   (utilise uniquement par .map, cf. son propre commentaire) : tout le reste
   de l'interface, y compris la vue liste, suit le theme normalement. */
:root {
  --ink: #12161d;
  --ink-soft: #1a212b;
  --ink-softer: #212a36;
  --border: rgba(255, 255, 255, 0.08);
  --text-light: #f3f2ec;
  --text-dim: #9aa4b2;
  --accent: #2fb8a6;
  --accent-text: var(--accent);
  --accent-strong: #24917f;
  --accent-soft: rgba(47, 184, 166, 0.16);
  --danger: #e5604d;
  --warn: #e8b23c;
  --paper: #f6f4ee;
  --dot-ring: rgba(255, 255, 255, 0.06);
  --radius: 12px;
  --font-display: "Space Grotesk", "Inter", system-ui, sans-serif;
  --font-body: "Inter", system-ui, sans-serif;
  color-scheme: dark;
}

/* Theme clair (EXI-PWA-*, issue #32) : soit une preference systeme claire
   explicite (Reglages > Apparence > Clair), soit un choix manuel "Clair"
   dans le selecteur de theme de l'app (EXI-PWA-7, ecrit `data-theme="light"`
   sur <html> par public/theme.js, prioritaire sur la preference systeme).
   --paper n'a pas besoin d'etre redefini ici : deja clair par defaut, il
   reste identique dans les deux themes - la carte Google elle-meme (tuiles
   + bulle d'info native) reste dans tous les cas rendue dans son style
   clair standard, un theme sombre cote Google necessitant un second Map ID
   configure dans Google Cloud Console (hors de
   portee du code de cette app, cf. limitation documentee similaire pour
   l'URI de redirection OAuth).
   IMPORTANT : les deux blocs ci-dessous (@media, puis [data-theme="light"])
   doivent rester synchronises - CSS pur, sans preprocesseur (cf. CLAUDE.md),
   pas de mixin possible pour factoriser. */
@media (prefers-color-scheme: light) {
  /* :not([data-theme="dark"]) : un choix manuel "Sombre" doit rester
     prioritaire sur une preference systeme claire. */
  :root:not([data-theme="dark"]) {
    --ink: #f6f4ee;
    --ink-soft: #ffffff;
    --ink-softer: #ece9e0;
    --border: rgba(18, 22, 29, 0.10);
    --text-light: #12161d;
    --text-dim: #5b6472;
    --dot-ring: rgba(0, 0, 0, 0.10);
    --danger: #a54537;
    --warn: #a15c07;
    --accent-text: #157567;
  }
}

/* Choix manuel "Clair" (EXI-PWA-7) : prioritaire sur la preference systeme,
   y compris quand celle-ci est sombre. Memes valeurs que le bloc @media
   ci-dessus - voir ses commentaires pour le detail de chaque token. */
:root[data-theme="light"] {
  --ink: #f6f4ee;
  --ink-soft: #ffffff;
  --ink-softer: #ece9e0;
  --border: rgba(18, 22, 29, 0.10);
  --text-light: #12161d;
  --text-dim: #5b6472;
  --dot-ring: rgba(0, 0, 0, 0.10);
  /* --danger et --warn : la teinte par defaut (pensee pour un fond fonce)
     tombe sous le ratio de contraste WCAG AA (4.5:1) sur fond clair -
     memes teintes assombries pour rester lisibles. --warn reutilise la
     couleur du badge "Local", deja pensee pour un texte lisible sur fond
     clair. */
  --danger: #a54537;
  --warn: #a15c07;
  /* --accent (#2fb8a6) n'offre que ~2.5:1 de contraste utilise comme
     couleur de texte sur un fond clair (il est concu pour un fond fonce,
     cf. usage par defaut ci-dessus) : sous le seuil WCAG AA (4.5:1) pour
     du texte. --accent-text est une teinte plus sombre, reservee aux
     usages textuels (liens, libelles de bouton actif) ; les usages
     non textuels (fonds, bordures, pastilles) continuent d'utiliser
     --accent tel quel. */
  --accent-text: #157567;
  color-scheme: light;
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
}

body {
  font-family: var(--font-body);
  color: var(--text-light);
  background: var(--ink);
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;
}

button, input {
  font-family: inherit;
}

.screen {
  height: 100dvh;
  width: 100%;
}

.screen[hidden] {
  display: none !important;
}

.loading-screen {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--ink);
}

.loading-pulse { animation: loading-pulse 1.1s ease-in-out infinite; }
@keyframes loading-pulse {
  0%, 100% { opacity: 0.35; }
  50% { opacity: 1; }
}

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

/* ---------- Selecteurs de theme et de langue ---------- */
/* .header-controls (coin fixe) n'existe que sur les ecrans de
   connexion/autorisation, ou rien d'autre ne flotte en haut de l'ecran :
   masque sur l'ecran carte (regle juste apres), ou les memes reglages sont
   repris dans l'accordeon "Parametres" de la sidebar - evite la
   superposition avec la bascule Carte/Liste/Les deux sur mobile (signalee
   par l'utilisateur, cf. historique des anomalies). */
.header-controls {
  position: fixed;
  top: 14px;
  right: 14px;
  z-index: 60;
  display: flex;
  gap: 8px;
}
body[data-active-screen="app-screen"] .header-controls {
  display: none;
}

.lang-switcher {
  /* Meme raison que .theme-switcher juste en dessous : evite un etirement
     sur toute la largeur de .panel dans l'accordeon "Parametres". */
  align-self: flex-start;
}

.lang-switcher select {
  /* --ink-soft, pas --ink : ce controle apparait toujours sur un fond
     --ink (coin fixe des ecrans de connexion, ou panneau "Parametres" de
     la sidebar) - il lui faut un fond distinct pour rester visible. */
  background: var(--ink-soft);
  color: var(--text-light);
  border: 1px solid var(--border);
  border-radius: 8px;
  height: 40px;
  padding: 0 10px;
  font-family: inherit;
  font-size: 0.85rem;
  cursor: pointer;
}

@media (max-width: 820px) {
  /* Uniquement dans le coin fixe (ecrans de connexion), ou la place est
     comptee : le selecteur ne garde que le drapeau. Dans l'accordeon
     "Parametres" de la sidebar, le libelle complet reste affiche (largeur
     disponible, pas de controle voisin). */
  .header-controls .lang-switcher select {
    width: 48px;
    padding: 0 6px;
    overflow: hidden;
    text-overflow: clip;
  }
}

.lang-switcher select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* Trois boutons icone (clair/sombre/auto), meme habillage "pilule
   segmentee" que .view-toggle/.view-btn (bascule carte/liste). Repete a
   l'identique dans le coin fixe (ecrans de connexion) et dans l'accordeon
   "Parametres" de la sidebar (ecran carte) : les deux jeux de boutons
   restent synchronises automatiquement via leur classe .theme-btn commune
   (voir theme.js), sans notion d'instance a gerer cote JS. */
.theme-switcher {
  display: flex;
  align-items: center;
  /* Ne prend que la largeur de son contenu (3 icones) : sans ça, place
     dans .panel (flex-direction: column, align-items: stretch par defaut
     - accordeon "Parametres"), la pilule s'etirait sur toute la largeur de
     la sidebar au lieu de rester compacte. */
  align-self: flex-start;
  height: 40px;
  background: var(--ink-soft);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0 3px;
  gap: 2px;
}

.theme-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  background: none;
  border: none;
  border-radius: 999px;
  color: var(--text-dim);
  cursor: pointer;
  transition: all 0.15s ease;
}
.theme-btn[aria-pressed="true"] {
  background: var(--accent-soft);
  color: var(--accent-text);
}
.theme-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* ---------- Login / autorisation Google (meme habillage) ---------- */
#login-screen, #google-auth-screen {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background:
    radial-gradient(circle at 15% 20%, rgba(47,184,166,0.16), transparent 45%),
    radial-gradient(circle at 85% 80%, rgba(47,184,166,0.10), transparent 40%),
    var(--ink);
}

.login-card {
  width: 100%;
  max-width: 360px;
  background: var(--ink-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 32px 28px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.35);
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--accent);
}

.brand-mark {
  display: inline-flex;
  color: var(--accent);
}

.brand-name {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.15rem;
  color: var(--text-light);
  letter-spacing: -0.01em;
}

.login-sub {
  margin: 0 0 6px;
  color: var(--text-dim);
  font-size: 0.92rem;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 0.85rem;
  color: var(--text-dim);
}

.field input {
  background: var(--ink-softer);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 11px 12px;
  color: var(--text-light);
  /* 16px minimum : en dessous, Safari iOS zoome automatiquement la page au
     focus du champ. */
  font-size: 16px;
  outline: none;
  transition: border-color 0.15s ease;
}

.field input:focus {
  border-color: var(--accent);
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 8px;
  padding: 11px 16px;
  font-size: 0.95rem;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  box-sizing: border-box;
  transition: background 0.15s ease, transform 0.05s ease;
}
.btn:active { transform: scale(0.98); }
.btn-block { width: 100%; }

.btn-primary {
  background: var(--accent);
  color: #08201c;
}
.btn-primary:hover { background: var(--accent-strong); color: var(--text-light); }

.btn-ghost {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-dim);
}
.btn-ghost:hover { color: var(--text-light); border-color: var(--text-dim); }

.login-error {
  color: var(--danger);
  font-size: 0.85rem;
  margin: 0;
}

.login-hint {
  margin: 4px 0 0;
  font-size: 0.78rem;
  color: var(--text-dim);
  text-align: center;
}

.version-badge {
  margin: 10px 0 0;
  font-size: 0.7rem;
  color: var(--text-dim);
  opacity: 0.6;
  text-align: center;
}

/* ---------- App shell ---------- */
#app-screen {
  display: flex;
  position: relative;
}

.sidebar-toggle {
  display: none;
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 50;
  background: var(--ink);
  color: var(--text-light);
  border: 1px solid var(--border);
  border-radius: 8px;
  width: 40px;
  height: 40px;
  align-items: center;
  justify-content: center;
}

.sidebar {
  width: 300px;
  flex-shrink: 0;
  background: var(--ink);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  height: 100dvh;
  overflow-y: auto;
  padding: 20px 18px;
  gap: 22px;
}

.brand-compact { margin-bottom: 2px; }

.search-row {
  position: relative;
  display: flex;
  align-items: center;
}

.search-icon {
  position: absolute;
  left: 11px;
  color: var(--text-dim);
  pointer-events: none;
}

.search-input {
  width: 100%;
  background: var(--ink-softer);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 9px 30px 9px 34px;
  color: var(--text-light);
  /* 16px minimum : en dessous, Safari iOS zoome automatiquement la page au
     focus du champ. */
  font-size: 16px;
  outline: none;
  transition: border-color 0.15s ease;
}
.search-input:focus { border-color: var(--accent); }
/* Remplacee par notre propre bouton .search-clear (coherent entre
   navigateurs, contrairement a ce bouton natif WebKit-only). */
.search-input::-webkit-search-cancel-button { display: none; }

.search-clear[hidden] { display: none; }
.search-clear {
  position: absolute;
  right: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
}
.search-clear:hover { background: var(--border); color: var(--text-light); }

.next-widget {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  width: 100%;
  background: var(--ink-softer);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px 12px;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
}
.next-widget:hover { border-color: var(--accent); }

.next-widget-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
  margin-top: 6px;
}

.next-widget-body {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.next-widget-label {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-dim);
}

.next-widget-title {
  font-weight: 600;
  color: var(--text-light);
  font-size: 0.9rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.next-widget-meta {
  font-size: 0.78rem;
  color: var(--text-dim);
}

.accordion-group {
  border-bottom: 1px solid var(--border);
  padding-bottom: 14px;
}
.accordion-group:last-of-type { border-bottom: none; padding-bottom: 0; }

.accordion-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-family: var(--font-display);
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text-light);
  cursor: pointer;
  list-style: none;
  padding: 4px 2px;
}
.accordion-summary::-webkit-details-marker { display: none; }
.accordion-summary::after {
  content: '';
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--text-dim);
  border-bottom: 2px solid var(--text-dim);
  transform: rotate(-45deg);
  transition: transform 0.15s ease;
  flex-shrink: 0;
}
.accordion-group[open] > .accordion-summary::after { transform: rotate(45deg); }

.accordion-body {
  display: flex;
  flex-direction: column;
  gap: 22px;
  padding-top: 16px;
}

.panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

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

.panel-title {
  font-family: var(--font-display);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--text-dim);
  margin: 0;
}

.link-btn {
  background: none;
  border: none;
  color: var(--accent-text);
  font-size: 0.78rem;
  cursor: pointer;
  padding: 0;
}

.date-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 6px;
  /* Separe visuellement du bloc "type de periode" au-dessus (boutons +
     barre + dates) : ce n'est pas un preset de plus, mais un reglage
     distinct (date de reference personnalisee). */
  margin-top: 4px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

.date-input {
  background: var(--ink-softer);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0 10px;
  color: var(--text-light);
  /* 16px minimum : en dessous, Safari iOS zoome automatiquement la page au
     focus du champ. */
  font-size: 16px;
  outline: none;
  transition: border-color 0.15s ease;
}
.date-input:focus { border-color: var(--accent); }

.date-row .range-btn { white-space: nowrap; }

.range-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}

.range-btn {
  background: var(--ink-soft);
  border: 1px solid var(--border);
  color: var(--text-dim);
  border-radius: 8px;
  padding: 9px 8px;
  font-size: 0.78rem;
  font-weight: 500;
  cursor: pointer;
  line-height: 1.25;
  transition: all 0.15s ease;
}

.range-btn[aria-pressed="true"] {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-text);
}

/* "Aujourd'hui" (5e preset) : seul sur la 3e ligne de .range-grid (grille a
   2 colonnes) - s'etire sur les deux colonnes plutot que de laisser un
   trou visuel a cote. */
.range-btn-wide {
  grid-column: 1 / -1;
}

.week-strip {
  position: relative;
  height: 8px;
  border-radius: 4px;
  background: var(--ink-soft);
  overflow: hidden;
  margin-top: 4px;
}

.week-strip-fill {
  position: absolute;
  top: 0;
  bottom: 0;
  background: var(--accent);
  border-radius: 4px;
}

.week-strip-today {
  position: absolute;
  top: -2px;
  width: 2px;
  height: 12px;
  background: var(--text-light);
  border-radius: 1px;
}

.range-label {
  margin: 0;
  font-size: 0.78rem;
  color: var(--text-dim);
}

.calendar-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 260px;
  overflow-y: auto;
}

.calendar-list-empty {
  color: var(--text-dim);
  font-size: 0.85rem;
  padding: 6px 0;
}

.unlocated-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 320px;
  overflow-y: auto;
}

.unlocated-row {
  padding: 8px 7px;
  border-radius: 8px;
  background: var(--ink-soft);
}

.unlocated-row-head {
  display: flex;
  align-items: flex-start;
  gap: 9px;
}

.unlocated-row-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
  margin-top: 5px;
}

.unlocated-row-title {
  margin: 0;
  font-weight: 600;
  color: var(--text-light);
  font-size: 0.88rem;
}

.unlocated-row-meta {
  margin: 2px 0 0;
  font-size: 0.78rem;
  color: var(--text-dim);
}

.unlocated-row-form {
  display: flex;
  gap: 6px;
  margin-top: 8px;
}

.unlocated-row-input {
  flex: 1;
  min-width: 0;
  background: var(--ink-softer);
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 7px 8px;
  color: var(--text-light);
  /* 16px minimum : en dessous, Safari iOS zoome automatiquement la page au
     focus du champ. */
  font-size: 16px;
  outline: none;
  transition: border-color 0.15s ease;
}
.unlocated-row-input:focus { border-color: var(--accent); }

.unlocated-row-submit {
  background: var(--accent-soft);
  color: var(--accent-text);
  border: none;
  border-radius: 7px;
  padding: 7px 10px;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}
.unlocated-row-submit:hover:not(:disabled) { background: var(--accent); color: #fff; }
.unlocated-row-submit:disabled { opacity: 0.6; cursor: default; }

.unlocated-row-error {
  margin: 6px 0 0;
  font-size: 0.76rem;
  color: var(--danger);
}
.unlocated-row-error[hidden] { display: none; }

.calendar-item label {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 6px;
  border-radius: 7px;
  cursor: pointer;
  font-size: 0.88rem;
}

.calendar-item label:hover { background: var(--ink-soft); }

.toggle-row[hidden] { display: none; }
.toggle-row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 6px;
  border-radius: 7px;
  cursor: pointer;
  font-size: 0.85rem;
  color: var(--text-dim);
}
.toggle-row:hover { background: var(--ink-soft); color: var(--text-light); }
.toggle-row input { accent-color: var(--accent); width: 15px; height: 15px; flex-shrink: 0; }

.calendar-checkbox {
  accent-color: var(--accent);
  width: 15px;
  height: 15px;
  flex-shrink: 0;
}

.color-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
  box-shadow: 0 0 0 2px var(--dot-ring);
}

.calendar-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar-footer {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

.event-count {
  margin: 0;
  font-size: 0.78rem;
  color: var(--text-dim);
}

.offline-badge {
  margin: 0 0 6px;
  font-size: 0.76rem;
  font-weight: 600;
  color: var(--warn);
}

/* ---------- Map / Liste ---------- */
.map-wrap {
  flex: 1;
  display: flex;
  flex-direction: column;
  position: relative;
  height: 100dvh;
}

.map {
  flex: 1;
  min-width: 0;
  min-height: 0;
  /* Fond visible brievement le temps que les tuiles Google chargent (ou sur
     les bords) : toujours clair (--paper, invariant entre les themes) pour
     matcher ces tuiles, elles-memes toujours claires (cf. commentaire pres
     de la definition de --paper plus haut). Contrairement a .list-view
     juste plus bas, qui elle suit normalement le theme. */
  background: var(--paper);
  /* color-scheme est une propriete heritee : sans cette ligne, le controle
     natif non stylise de l'InfoWindow Google (bouton de fermeture "x", une
     simple image sur fond de bouton par defaut) heritait du color-scheme
     de l'app (dark en theme sombre) et se rendait avec un fond gris fonce
     par defaut du navigateur - rendant son icone claire quasi invisible,
     sans affecter sa zone cliquable (d'ou un bug "la croix a disparu mais
     le clic ferme toujours"). Memes tuiles/InfoWindow toujours clairs
     (cf. plus haut) : color-scheme doit donc rester light ici, quel que
     soit le theme choisi par ailleurs. */
  color-scheme: light;
}

.map-wrap[data-view="list"] .map { display: none; }

@media (min-width: 821px) {
  .map-wrap[data-view="both"] { flex-direction: row; }
}

.view-toggle {
  position: absolute;
  top: 14px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 39;
  display: flex;
  /* Explicite plutot qu'implicite : sans ça, la largeur "auto" d'un
     element en position absolute avec left+transform se calcule par
     shrink-to-fit a partir de `left` *avant* transformation (donc sur la
     seule moitie de .map-wrap ici) - voir le commentaire de .view-btn,
     dont le white-space: nowrap contourne aussi ce probleme mais seul,
     de façon moins lisible. */
  width: max-content;
  background: var(--ink);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px;
  gap: 2px;
}

.view-btn {
  background: none;
  border: none;
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--text-dim);
  cursor: pointer;
  transition: all 0.15s ease;
  /* Sans ça, un libelle de deux mots ("Les deux", "İkisi de") revient a la
     ligne sur mobile : .view-toggle (position: absolute; left: 50%;
     transform: translateX(-50%)) calcule sa largeur "shrink-to-fit" a
     partir de `left` *avant* transformation, donc sur seulement la moitie
     de .map-wrap (~195px sur 390px) - insuffisant pour ces libelles, mais
     assez pour "Both"/l'anglais (un seul mot par bouton). Imposer nowrap
     releve la largeur minimale de l'algorithme a la largeur naturelle
     (non coupee) du libelle, qui l'emporte alors sur ce budget errone ;
     le centrage via translateX(-50%) reste correct car il se recalcule
     sur la largeur finale reelle de la pilule. */
  white-space: nowrap;
}
.view-btn[aria-pressed="true"] {
  background: var(--accent-soft);
  color: var(--accent-text);
}

.list-view {
  flex: 1;
  min-width: 0;
  min-height: 0;
  margin: 0;
  /* padding-top degage la bascule carte/liste/les deux et le selecteur de
     langue, flottants par-dessus, pour que le premier rendez-vous ne soit
     jamais masque dessous. */
  padding: 76px 8px 8px;
  list-style: none;
  overflow-y: auto;
  /* Contrairement a .map juste au-dessus : cette zone n'affiche rien de
     dessine par Google, rien ne l'empeche donc de suivre le theme comme le
     reste de l'app (--ink-soft, meme "palier" que les panneaux de la
     sidebar). En mode "Les deux", elle peut ainsi se retrouver sombre a
     cote d'une carte Google toujours claire : cote a cote assume, chacune
     des deux zones etant deja separee visuellement (pas de fond partage). */
  background: var(--ink-soft);
}

.list-empty {
  color: var(--text-dim);
  font-size: 0.9rem;
  text-align: center;
  padding: 40px 20px;
}

/* Sur mobile en mode "les deux", la liste est empilee sous la carte
   (flex-direction: column) : les controles flottants restent au-dessus de
   la carte, jamais de la liste, donc pas besoin de degagement en haut. */
@media (max-width: 820px) {
  .map-wrap[data-view="both"] .list-view { padding-top: 8px; }
  .map-wrap[data-view="both"] .list-row { scroll-margin-top: 8px; }
}

.list-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 8px;
  border-radius: 8px;
  cursor: pointer;
  border-bottom: 1px solid var(--border);
  /* Le scroll-vers-le-prochain-rdv aligne cette ligne sur le haut du
     conteneur : on laisse la place au selecteur d'affichage/au statut de
     la carte, flottants par-dessus, pour qu'elle ne soit pas masquee. */
  scroll-margin-top: 76px;
}
.list-row:hover { background: var(--ink-softer); }

.list-row-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
  margin-top: 5px;
}

.list-row-title {
  margin: 0;
  font-weight: 600;
  color: var(--text-light);
  font-size: 0.92rem;
}

.list-row-meta {
  margin: 2px 0 0;
  font-size: 0.8rem;
  color: var(--text-dim);
}

.list-row.is-next { background: var(--accent-soft); }

.map-status {
  position: absolute;
  top: 64px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--ink);
  color: var(--text-light);
  border: 1px solid var(--border);
  padding: 8px 16px;
  border-radius: 999px;
  font-size: 0.82rem;
  z-index: 40;
  box-shadow: 0 8px 24px rgba(0,0,0,0.25);
}

/* Bouton de geolocalisation pose directement sur les tuiles de la carte
   Google (toujours rendues dans leur style clair standard, cf. commentaire
   pres de @media (prefers-color-scheme: light) plus haut) : couleurs fixes
   volontairement non liees au theme app, pour rester lisible sur ce fond
   clair quel que soit le theme choisi par l'utilisateur. */
.locate-btn {
  position: absolute;
  bottom: 24px;
  right: 16px;
  z-index: 40;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: none;
  background: #ffffff;
  color: #33404d;
  box-shadow: 0 4px 14px rgba(0,0,0,0.25);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: color 0.15s ease, transform 0.1s ease;
}
.locate-btn:hover { color: #0a7cff; }
.locate-btn:active { transform: scale(0.94); }
.locate-btn.is-loading {
  color: #0a7cff;
  animation: locate-pulse 1s ease-in-out infinite;
}
@keyframes locate-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}

/* ---------- Info window content (injected into Google Maps InfoWindow) ----------
   Meme rationale que .locate-btn ci-dessus : cette bulle est dessinee par
   Google par-dessus la carte, toujours claire (cf. @media (prefers-color-scheme:
   light) plus haut) - ses couleurs restent donc volontairement fixes, non
   liees aux tokens de theme de l'app. */
.gm-pin-card {
  /* Largeur fixe (et non max-width) pour que la bulle ne change jamais de
     largeur entre l'etat "bouton distance" et l'etat "resultat distance" :
     seule la hauteur peut varier, evitant le sursaut/empietement au clic. */
  width: 240px;
}
.gm-pin-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.98rem;
  margin: 0 0 4px;
  color: #12161d;
  overflow-wrap: break-word;
}
.gm-pin-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 8px;
}
.gm-pin-cal {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.76rem;
  color: #55606e;
  min-width: 0;
}
.gm-pin-cal .cal-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gm-pin-cal .dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.gm-pin-datebadge {
  font-size: 0.76rem;
  font-weight: 600;
  color: #33404d;
  white-space: nowrap;
  flex-shrink: 0;
}
.gm-pin-addr {
  font-size: 0.82rem;
  color: #33404d;
  margin: 0 0 6px;
  overflow-wrap: break-word;
}
.gm-pin-local-badge[hidden] { display: none; }
.gm-pin-local-badge {
  display: inline-block;
  margin-left: 4px;
  padding: 1px 6px;
  border: none;
  border-radius: 5px;
  font-family: inherit;
  font-size: 0.68rem;
  font-weight: 700;
  background: #fdecd2;
  color: #a15c07;
  white-space: nowrap;
  vertical-align: middle;
  cursor: pointer;
}
.gm-pin-local-badge:hover:not(:disabled) { background: #fbe0b3; }
.gm-pin-local-badge:disabled { opacity: 0.6; cursor: default; }
.gm-pin-time {
  font-size: 0.78rem;
  color: #6b7684;
  margin: 0 0 10px;
}
.gm-pin-waze {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid #cfe8ff;
  background: #eaf5ff;
  color: #0a7cff;
  font-weight: 600;
  font-size: 0.78rem;
  padding: 7px 10px;
  border-radius: 7px;
  text-decoration: none;
  margin-bottom: 6px;
}
.gm-pin-waze:hover { background: #d8ecff; }
.gm-pin-waze::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #33ccff;
  flex-shrink: 0;
}
.gm-pin-btn {
  border: none;
  background: #eafaf7;
  color: #1b8474;
  font-weight: 600;
  font-size: 0.78rem;
  padding: 7px 10px;
  border-radius: 7px;
  cursor: pointer;
}
.gm-pin-btn:hover { background: #d7f3ee; }
.gm-pin-distance {
  margin-top: 8px;
  font-size: 0.8rem;
  color: #1b8474;
  font-weight: 600;
}

/* ---------- Responsive ---------- */
@media (max-width: 820px) {
  .sidebar-toggle { display: flex; }

  /* Le bouton burger est fixe en haut a gauche par-dessus le sidebar :
     on decale le logo pour qu'il ne se superpose pas au bouton. */
  .sidebar .brand-compact { margin-left: 46px; }

  .sidebar {
    position: fixed;
    inset: 0 25% 0 0;
    z-index: 45;
    transform: translateX(-105%);
    transition: transform 0.2s ease;
    box-shadow: 20px 0 40px rgba(0,0,0,0.35);
  }
  .sidebar.open { transform: translateX(0); }

  .map-wrap { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .sidebar { transition: none; }
  .btn { transition: none; }
}
