/* LIFE — base responsive (mobile-first), thème clair / sombre par variables CSS. */

/* Thème clair (défaut). Thème sombre uniquement sur choix explicite (html[data-theme="dark"], voir js/theme.js) : aucun mode automatique. */
:root {
  color-scheme: light;
  --bg: #f6f8fa;
  --surface: #ffffff;
  --input-bg: #ffffff;
  --text: #1f2328;
  --muted: #59636e;
  --border: #d1d9e0;
  --accent: #0b5cad;
  --accent-bg: #0b5cad;
  --on-accent: #ffffff;
  --hover: #eef2f6;
  --ok-bg: #e6f4ea;
  --ok-text: #14532d;
  --error-bg: #fdecea;
  --error-text: #7f1d1d;
  --danger: #b42318;
  --shadow: 0 8px 24px rgba(31, 35, 40, 0.18);
  --logo-backdrop: transparent;
  --page-background-image: url("/images/backgrounds/life-background-light.webp");
  --drag-bg: #eaf3ff;
  --drag-shadow: 0 10px 24px rgba(11, 92, 173, 0.28);
  --favorite: #b7791f;
  /* Repère personnel du Planning (LIFE-314/318) : rouge quand actif, jamais confondu avec le favori jaune de Shopping. */
  --planning-highlight: #c92a2a;
  /* LIFE-319 : bleu adouci propre aux actions d'en-tête du Planning (+ Événement / + Exception) — moins saturé que --accent-bg,
     pour rester élégant sans dominer la page. */
  --planning-action-bg: #3f6f99;
  --planning-action-bg-hover: #335c80;
  --planning-action-text: #ffffff;
  /* Coche : durée unique de l'animation et du passage visuel dans « achetés » (lue aussi par js/shopping.js, en ligne et hors ligne). */
  --shopping-check-delay: 1000ms;
  --sidebar-width: 15rem;
  --sidebar-collapsed-width: 4.25rem;
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0f141a;
  --surface: #171d25;
  --input-bg: #0f141a;
  --text: #e6edf3;
  --muted: #9aa4af;
  --border: #313a45;
  --accent: #6cb2ff;
  --accent-bg: #1f6feb;
  --on-accent: #ffffff;
  --hover: #212a35;
  --ok-bg: #11291c;
  --ok-text: #86e1a8;
  --error-bg: #331615;
  --error-text: #ffaba4;
  --danger: #ff7b72;
  --shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
  --logo-backdrop: #e9eef4;
  --page-background-image: url("/images/backgrounds/life-background-dark.webp");
  --drag-bg: #22303f;
  --drag-shadow: 0 10px 28px rgba(31, 111, 235, 0.45);
  --favorite: #f2c94c;
  --planning-highlight: #ff6b6b;
  --planning-action-bg: #4a7eac;
  --planning-action-bg-hover: #5c91bf;
  --planning-action-text: #ffffff;
}

* { box-sizing: border-box; }

/* L'attribut hidden l'emporte toujours sur un display défini (boutons, champs masqués par script). */
[hidden] { display: none !important; }

html { font-size: 16px; }

body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  color: var(--text);
  background: var(--bg);
  line-height: 1.5;
  position: relative;
  min-height: 100vh;
}

/* Fond décoratif global (CSS uniquement, jamais <img>) : une seule couche derrière tout le contenu, image choisie par
   --page-background-image selon data-theme (seule l'image du thème actif est téléchargée). Jamais répétée, toujours en cover.
   Mobile : la couche couvre tout le document et défile avec lui (pas de fond fixe).
   Desktop : couche fixe limitée à la zone de contenu, à droite de la barre latérale (qui garde son fond opaque) ; une couche
   position: fixed est composée par le navigateur, contrairement à background-attachment: fixed qui repeint à chaque défilement. */
body::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: var(--bg) var(--page-background-image) center top / cover no-repeat;
}
@media (min-width: 768px) {
  body::before { position: fixed; background-position: center center; }
  body.with-sidebar::before { left: var(--sidebar-width); }
  :root[data-sidebar="collapsed"] body.with-sidebar::before { left: var(--sidebar-collapsed-width); }
}

a { color: var(--accent); }

.container { max-width: 960px; margin: 0 auto; padding: 1.5rem 1rem 3rem; }

/* Logo officiel (images/life-logo.png, transparent) : seul branding visible, proportions conservées (hauteur fixée, largeur auto).
   En sombre, son tronc bleu nuit manque de contraste : un fond clair arrondi (--logo-backdrop) l'entoure, le fichier n'est jamais recolorisé. */
.brand { display: inline-flex; align-items: center; border-radius: 10px; text-decoration: none; }
.brand:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.brand-logo { display: block; width: auto; max-width: 100%; height: 40px; padding: 3px; border-radius: 10px; background: var(--logo-backdrop); object-fit: contain; }
.brand-logo-auth { height: 72px; padding: 6px; border-radius: 16px; }
.brand-logo-home { height: 96px; padding: 8px; border-radius: 20px; margin: 0 auto; }
@media (min-width: 768px) { .brand-logo-auth { height: 88px; } .brand-logo-home { height: 120px; } }

/* Pages anonymes (connexion, mot de passe oublié, MFA) : logo centré au-dessus du formulaire. */
.auth-brand { display: flex; justify-content: center; padding: 1.5rem 1rem 0; }

.icon { flex: 0 0 auto; width: 20px; height: 20px; }
.icon-button {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; min-height: 44px; margin: 0; padding: 0;
  border: 1px solid transparent; border-radius: 8px; background: none; color: var(--text); cursor: pointer;
}
.icon-button:hover { background: var(--hover); }

/* Navigation latérale. Mobile (< 768 px) : tiroir hors écran ouvert par la case à cocher #nav-toggle. */
.nav-toggle { position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0; pointer-events: none; }
.nav-toggle:focus-visible ~ .mobile-bar label.icon-button { outline: 2px solid var(--accent); outline-offset: 2px; }
.mobile-bar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.25rem 0.75rem; background: var(--surface); border-bottom: 1px solid var(--border);
}
/* Nom du module courant (Shopping List, Invest, Planning…) à la place du logo, juste après le menu ☰ : compact, sans hauteur ajoutée. */
.mobile-module-name { min-width: 0; overflow: hidden; font-size: 1.0625rem; font-weight: 700; line-height: 1.25; color: var(--text); white-space: nowrap; text-overflow: ellipsis; }
.drawer-backdrop { display: none; }
.sidebar {
  position: fixed; top: 0; bottom: 0; left: 0; z-index: 40;
  width: min(18rem, 85vw); display: flex; flex-direction: column; gap: 0.5rem;
  padding: 0.5rem; background: var(--surface); border-right: 1px solid var(--border); box-shadow: var(--shadow);
  overflow-y: auto; transform: translateX(-105%); transition: transform 0.2s ease; visibility: hidden;
}
.nav-toggle:checked ~ .sidebar { transform: none; visibility: visible; }
.nav-toggle:checked ~ .drawer-backdrop { display: block; position: fixed; inset: 0; z-index: 30; background: rgba(0, 0, 0, 0.45); }
.sidebar-head { display: flex; align-items: center; justify-content: space-between; gap: 0.25rem; flex-shrink: 0; min-height: 44px; padding-left: 0.5rem; }
.sidebar-collapse { display: none; }
.side-nav { display: flex; flex-direction: column; gap: 0.125rem; }
.side-bottom { margin-top: auto; padding-top: 0.5rem; border-top: 1px solid var(--border); }
.side-bottom form { margin: 0; }
.side-link {
  display: flex; align-items: center; justify-content: flex-start; gap: 0.75rem; width: 100%;
  min-height: 44px; margin: 0; padding: 0.5rem 0.75rem;
  border: 0; border-radius: 8px; background: none; color: var(--text);
  font: inherit; text-align: left; text-decoration: none; cursor: pointer; white-space: nowrap;
}
.side-link:hover { background: var(--hover); }
.side-link[aria-current="page"] { background: var(--hover); color: var(--accent); font-weight: 600; box-shadow: inset 3px 0 0 var(--accent); }
.side-label { overflow: hidden; text-overflow: ellipsis; }
/* Sous-liens Shopping (Mes listes / Archives) : tiroir mobile uniquement, rattachés visuellement à « Shopping list ».
   Leur boîte (et son trait bleu) est décalée de +24 px par rapport au parent, et leur texte est à +12 px du texte du parent.
   Actif : texte bleu, trait de 2 px et fond léger — plus discret que le parent (fond plein, trait de 3 px). */
.side-sublink { width: calc(100% - 1.5rem); min-height: 38px; margin-left: 1.5rem; padding: 0.375rem 0.75rem 0.375rem 2rem; font-size: 0.9375rem; color: var(--muted); }
.side-sublink[aria-current="true"] { background: color-mix(in srgb, var(--hover) 55%, transparent); color: var(--accent); font-weight: 600; box-shadow: inset 2px 0 0 var(--accent); }
@media (min-width: 768px) { .side-sublink { display: none; } }
/* Bouton de thème : icône et libellé du mode proposé (Mode sombre en clair, Mode clair en sombre). */
:root:not([data-theme="dark"]) .theme-to-light, :root[data-theme="dark"] .theme-to-dark { display: none; }

/* Desktop : barre latérale fixe, déployée ou réduite (icônes seules, libellés en aria-label / title). */
@media (min-width: 768px) {
  .mobile-bar, .drawer-backdrop, .drawer-close, .nav-toggle:checked ~ .drawer-backdrop { display: none; }
  body.with-sidebar { padding-left: var(--sidebar-width); }
  .sidebar, .nav-toggle:checked ~ .sidebar { width: var(--sidebar-width); transform: none; visibility: visible; box-shadow: none; transition: width 0.15s ease; }
  .sidebar-collapse { display: inline-flex; }
  :root[data-sidebar="collapsed"] body.with-sidebar { padding-left: var(--sidebar-collapsed-width); }
  :root[data-sidebar="collapsed"] .sidebar { width: var(--sidebar-collapsed-width); }
  :root[data-sidebar="collapsed"] .sidebar-head { flex-direction: column; padding-left: 0; }
  :root[data-sidebar="collapsed"] .side-label { display: none; }
  :root[data-sidebar="collapsed"] .brand-logo-sidebar { height: 32px; padding: 2px; border-radius: 8px; }
  :root[data-sidebar="collapsed"] .sidebar-collapse .icon { transform: rotate(180deg); }
  :root[data-sidebar="collapsed"] .side-link { justify-content: center; padding: 0.5rem; }
}

/* Accueil */
.home-brand { display: flex; justify-content: center; margin: 0.5rem 0 1.5rem; }
.module-grid { display: grid; grid-template-columns: 1fr; gap: 1rem; max-width: 640px; margin: 0 auto; }
@media (min-width: 640px) { .module-grid { grid-template-columns: repeat(auto-fit, minmax(14rem, 18rem)); justify-content: center; max-width: 960px; } }
.module-card {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.5rem;
  min-height: 160px; padding: 1.5rem;
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  text-decoration: none; color: var(--text);
}
.module-card:hover, .module-card:focus-visible { border-color: var(--accent); }
.module-title { font-size: 1.5rem; font-weight: 700; letter-spacing: 0.08em; }
.module-icon { font-size: 2rem; }

/* Cartes, formulaires */
.card { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 1.25rem; margin-bottom: 1rem; }
.narrow { max-width: 480px; margin-left: auto; margin-right: auto; }
.muted { color: var(--muted); }

form label { display: block; margin-top: 1rem; font-weight: 600; }
form label.checkbox { font-weight: 400; display: flex; align-items: center; gap: 0.5rem; }
input[type="email"], input[type="password"], input[type="text"], input[type="search"], input[type="number"], input:not([type]) {
  width: 100%; padding: 0.625rem 0.75rem; font-size: 1rem;
  border: 1px solid var(--border); border-radius: 8px; background: var(--input-bg); color: var(--text);
}
input[type="checkbox"] { width: 1.25rem; height: 1.25rem; }
.field-error { color: var(--error-text); font-size: 0.875rem; }

button, .button {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; margin-top: 1rem; padding: 0.5rem 1rem;
  font-size: 1rem; border-radius: 8px; border: 1px solid var(--border);
  background: var(--surface); color: var(--text); text-decoration: none; cursor: pointer;
}
button.primary, .button.primary { background: var(--accent-bg); border-color: var(--accent-bg); color: var(--on-accent); }
button.danger, .button.danger { border-color: var(--danger); color: var(--danger); }
button.link { margin: 0; padding: 0; min-height: auto; border: 0; background: none; color: var(--accent); font: inherit; cursor: pointer; }
form.inline { display: inline; }
.actions { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.5rem; }
.actions .button { margin-top: 0; }

.alert { padding: 0.75rem 1rem; border-radius: 8px; }
.alert:empty, .alert.validation-summary-valid { display: none; }
.alert-ok { background: var(--ok-bg); color: var(--ok-text); }
.alert-error { background: var(--error-bg); color: var(--error-text); }
.alert ul { margin: 0; padding-left: 1.25rem; }

.facts { display: grid; grid-template-columns: max-content 1fr; gap: 0.25rem 1rem; margin: 0; }
.facts dt { font-weight: 600; }
.facts dd { margin: 0; overflow-wrap: anywhere; }

/* MFA */
.steps li { margin-bottom: 1rem; }
.qr { display: block; margin: 0.75rem 0; width: 240px; max-width: 100%; height: auto; image-rendering: pixelated; }
.secret { display: inline-block; padding: 0.25rem 0.5rem; background: var(--bg); border-radius: 6px; overflow-wrap: anywhere; }
.codes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.5rem; padding: 0; list-style: none; }
.codes code { font-size: 1rem; }

/* Administration */
.user-header { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0.5rem; }
.user-flags { display: flex; flex-direction: column; gap: 0.125rem; }
.badge { font-size: 0.75rem; padding: 0.125rem 0.5rem; border-radius: 999px; background: var(--bg); border: 1px solid var(--border); }
.permissions { width: 100%; margin-top: 1rem; border-collapse: collapse; }
.permissions th, .permissions td { padding: 0.5rem; text-align: left; border-bottom: 1px solid var(--border); }
.permissions td { text-align: center; }

/* Invest / Administration : sous-navigation, listes en cartes, formulaires */
.page-header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.5rem 1rem; }
.page-header h1 { margin: 0.5rem 0; }
.page-header .button { margin-top: 0; }

.card-list { display: grid; grid-template-columns: 1fr; gap: 1rem; }
@media (min-width: 640px) { .card-list { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 960px) { .card-list { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.item-card { display: block; margin-bottom: 0; color: var(--text); text-decoration: none; }
a.item-card:hover, a.item-card:focus-visible { border-color: var(--accent); }
.item-header { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; margin-bottom: 0.5rem; }
.facts.compact { margin-top: 0.5rem; font-size: 0.9375rem; }

select {
  width: 100%; padding: 0.625rem 0.75rem; font-size: 1rem;
  border: 1px solid var(--border); border-radius: 8px; background: var(--input-bg); color: var(--text);
}
input.short { max-width: 8rem; text-transform: uppercase; }
fieldset { margin: 1rem 0 0; padding: 0.75rem 1rem; border: 1px solid var(--border); border-radius: 8px; }
legend { font-weight: 600; padding: 0 0.25rem; }
fieldset label.checkbox { margin-top: 0.5rem; }

.identifier-list { list-style: none; padding: 0; margin: 0; }
.identifier-list li { display: flex; justify-content: space-between; align-items: center; gap: 0.75rem; padding: 0.5rem 0; border-bottom: 1px solid var(--border); }
.identifier-list code { overflow-wrap: anywhere; }
button.small { min-height: 36px; margin-top: 0; padding: 0.25rem 0.75rem; font-size: 0.875rem; }

/* Transactions : filtres, tableau responsive (cartes sur mobile), pagination */
textarea {
  width: 100%; padding: 0.625rem 0.75rem; font: inherit;
  border: 1px solid var(--border); border-radius: 8px; background: var(--input-bg); color: var(--text);
}
input[type="datetime-local"], input[type="month"], input[type="date"], input[type="time"] {
  width: 100%; max-width: 16rem; padding: 0.5rem 0.75rem; font-size: 1rem;
  border: 1px solid var(--border); border-radius: 8px; background: var(--input-bg); color: var(--text);
}
.alert-info { background: var(--bg); border: 1px solid var(--border); }
.filters summary { cursor: pointer; font-weight: 600; min-height: 44px; display: flex; align-items: center; }
.filter-grid { display: grid; grid-template-columns: 1fr; gap: 0 1rem; }
@media (min-width: 640px) { .filter-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 960px) { .filter-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.filter-grid label { font-weight: 600; }
.filter-grid .actions { align-items: end; }
.filter-grid .actions .button, .filter-grid .actions button { margin-top: 1rem; }

.responsive-table { width: 100%; border-collapse: collapse; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; }
.responsive-table th, .responsive-table td { padding: 0.625rem 0.75rem; text-align: left; border-bottom: 1px solid var(--border); vertical-align: top; }
.responsive-table th { background: var(--bg); font-size: 0.875rem; }
.responsive-table td[data-label="Quantité"], .responsive-table td[data-label="Montant"] { white-space: nowrap; }
@media (max-width: 767px) {
  /* Mobile : chaque ligne devient une carte, libellé à gauche. */
  .responsive-table, .responsive-table tbody, .responsive-table tr, .responsive-table td { display: block; width: 100%; }
  .responsive-table { border: 0; background: none; }
  .responsive-table thead { display: none; }
  .responsive-table tr { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; margin-bottom: 0.75rem; padding: 0.5rem 0.75rem; }
  .responsive-table td { display: grid; grid-template-columns: 7rem 1fr; gap: 0.5rem; border: 0; padding: 0.25rem 0; }
  .responsive-table td::before { content: attr(data-label); font-weight: 600; color: var(--muted); }
}
.pagination { display: flex; justify-content: center; align-items: center; gap: 1rem; margin: 1rem 0; }
.pagination a { min-height: 44px; display: inline-flex; align-items: center; }

/* Portefeuille */
.issue-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.5rem; }
.transfer-route { font-size: 1.125rem; }

/* DCA : lignes du mois en cartes (mobile-first), actions au pouce */
.dca-totals { margin-bottom: 1rem; font-size: 1.0625rem; }
.dca-lines { display: grid; grid-template-columns: 1fr; gap: 0.75rem; }
@media (min-width: 640px) { .dca-lines { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.dca-line { padding: 0.75rem 1rem; border: 1px solid var(--border); border-radius: 12px; background: var(--surface); }
.dca-line p { margin: 0.125rem 0; }
.dca-line .actions .button, .dca-line .actions button { margin-top: 0.5rem; }
.dca-line.status-planned { border-left: 4px solid var(--accent); }
.dca-line.status-skipped { opacity: 0.8; }
.dca-amount { font-weight: 700; white-space: nowrap; }
.dca-status { font-weight: 600; }
.dca-allocation, .dca-history { list-style: none; padding: 0; margin: 0.5rem 0; display: grid; gap: 0.5rem; }
.dca-allocation li { display: flex; flex-wrap: wrap; gap: 0.25rem 0.75rem; padding: 0.5rem 0; border-bottom: 1px solid var(--border); }
.dca-history li { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 0.25rem 1rem; padding: 0.5rem 0.75rem; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; }
.dca-history a { display: flex; flex-wrap: wrap; gap: 0.25rem 1rem; min-height: 44px; align-items: center; }
.dca-history button.small { margin-top: 0; }
.dca-months { display: grid; grid-template-columns: 1fr; gap: 0 1rem; }
@media (min-width: 480px) { .dca-months { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.dca-form-line { padding: 0.5rem 0 1rem; border-bottom: 1px solid var(--border); }
.dca-form-line label { margin-top: 0.5rem; }
.dca-allocation-input input { max-width: 10rem; }
.dca-summary { font-weight: 700; }
button:disabled { opacity: 0.5; cursor: not-allowed; }

/* Stratégies : cibles et comparaison en cartes empilées (lisibles sur smartphone, pas de tableau large) */
.strategy-targets { list-style: none; padding: 0; margin: 0.25rem 0; display: grid; gap: 0.125rem; }
.strategy-targets li { display: flex; justify-content: space-between; gap: 1rem; }
.strategy-comparison { list-style: none; padding: 0; margin: 0.5rem 0; display: grid; grid-template-columns: 1fr; gap: 0.75rem; }
@media (min-width: 640px) { .strategy-comparison { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 960px) { .strategy-comparison { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.strategy-comparison li { padding: 0.75rem 1rem; border: 1px solid var(--border); border-radius: 12px; background: var(--surface); }
.strategy-form-line { display: grid; grid-template-columns: 1fr 7rem; gap: 0 0.75rem; align-items: end; padding: 0.25rem 0 0.75rem; border-bottom: 1px solid var(--border); }
.strategy-form-line label { margin-top: 0.5rem; }
.strategy-move { grid-column: 1 / -1; display: flex; gap: 0.5rem; margin-top: 0.5rem; }
.strategy-actions { align-items: center; margin-bottom: 1rem; }
.strategy-actions .button, .strategy-actions button { margin-top: 0; }
.price-freshness { display: block; font-size: 0.8125rem; color: var(--muted); }

/* Dashboard Invest : 3 KPI sur une ligne (desktop), empilés (mobile) ; barres de répartition décoratives + texte */
.kpi-grid { display: grid; grid-template-columns: 1fr; gap: 1rem; margin-bottom: 1rem; }
@media (min-width: 768px) { .kpi-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.kpi-grid .card { margin-bottom: 0; }
.kpi h2, .savings h2 { margin: 0; font-size: 1rem; color: var(--muted); font-weight: 600; }
.kpi-value { margin: 0.25rem 0; font-size: 1.75rem; font-weight: 700; overflow-wrap: anywhere; }
.kpi-value.kpi-empty { font-size: 1.125rem; }
.kpi-sub { margin: 0; font-weight: 600; }
.kpi-warning { margin: 0.25rem 0 0; font-size: 0.875rem; color: var(--error-text); }
.dashboard-status { margin-top: 0; font-size: 0.875rem; }
.dashboard-list { list-style: none; padding: 0; margin: 0.5rem 0; }
.dashboard-list li { display: flex; justify-content: space-between; gap: 1rem; padding: 0.375rem 0; border-bottom: 1px solid var(--border); }
.dashboard-list li > span:last-child { white-space: nowrap; text-align: right; }
.allocation { list-style: none; padding: 0; margin: 0.5rem 0 0; display: grid; gap: 0.625rem; }
.allocation-row { display: flex; justify-content: space-between; gap: 1rem; }
.allocation-row > span:last-child { white-space: nowrap; }
.allocation-bar { height: 0.5rem; margin-top: 0.25rem; background: var(--bg); border: 1px solid var(--border); border-radius: 999px; overflow: hidden; }
.allocation-bar span { display: block; height: 100%; background: var(--accent); }
.dca-month-actions { margin-top: 1rem; }

/* Actifs : filtres rapides, recherche, tri */
.chips { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 0.75rem; }
.chip { min-height: 36px; display: inline-flex; align-items: center; padding: 0 0.875rem; border-radius: 999px; border: 1px solid var(--border); background: var(--surface); color: var(--text); text-decoration: none; font-size: 0.9rem; }
.chip:hover { border-color: var(--accent); }
.chip[aria-current="true"] { background: var(--accent-bg); border-color: var(--accent-bg); color: var(--on-accent); font-weight: 600; }
.asset-search { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin-bottom: 0.5rem; }
.asset-search input[type="search"] { flex: 1 1 14rem; min-width: 0; }
.asset-search select { flex: 0 1 12rem; }
.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; }
.asset-search button { margin-top: 0; }
.item-card .actions { margin-top: 0.75rem; }
.item-card .actions form { margin: 0; }
.item-card .actions button { margin-top: 0; }

/* Évolution du patrimoine : SVG local, deux séries, pointillés sur les jours sans snapshot */
:root { --chart-invested: var(--accent); --chart-net: #b35c00; }
:root[data-theme="dark"] { --chart-net: #f0a35e; }
.wealth-chart { margin-top: 0.5rem; }
.wealth-legend { list-style: none; display: flex; flex-wrap: wrap; gap: 0.25rem 1.25rem; padding: 0; margin: 0 0 0.5rem; font-size: 0.9375rem; }
.wealth-legend li { display: inline-flex; align-items: center; gap: 0.375rem; }
.swatch { display: inline-block; width: 1.25rem; height: 0.25rem; border-radius: 2px; }
.swatch.invested { background: var(--chart-invested); }
.swatch.net { background: var(--chart-net); }
.wealth-plot { position: relative; }
.wealth-plot svg { display: block; width: 100%; height: clamp(190px, 45vw, 300px); background: var(--bg); border: 1px solid var(--border); border-radius: 8px; touch-action: pan-y; }
.wealth-plot svg:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.wealth-axis { stroke: var(--border); stroke-width: 1; vector-effect: non-scaling-stroke; }
.wealth-line { fill: none; vector-effect: non-scaling-stroke; stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.wealth-line.invested { stroke: var(--chart-invested); }
.wealth-line.net { stroke: var(--chart-net); }
.wealth-line.gap { stroke-dasharray: 4 5; stroke-width: 1.5; opacity: 0.8; }
.wealth-cursor { stroke: var(--muted); stroke-width: 1; vector-effect: non-scaling-stroke; stroke-dasharray: 2 3; }
.wealth-tooltip { position: absolute; top: 0.5rem; z-index: 5; display: flex; flex-direction: column; gap: 0.125rem; padding: 0.5rem 0.75rem; max-width: 16rem; font-size: 0.875rem; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; box-shadow: var(--shadow); pointer-events: none; }
.wealth-scale { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0 1rem; font-size: 0.8125rem; margin-top: 0.25rem; }
.wealth-summary { margin-top: 0.75rem; }
.wealth-note { font-size: 0.875rem; }
.wealth-table summary { cursor: pointer; min-height: 44px; display: flex; align-items: center; }
.wealth-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1rem; margin-top: 0.75rem; }
.wealth-actions p, .wealth-actions form { margin: 0; }
.wealth-actions .button, .wealth-actions button { margin-top: 0; }
.wealth-dots { position: absolute; inset: 1px; pointer-events: none; }
.wealth-dot { position: absolute; width: 7px; height: 7px; margin: -3.5px 0 0 -3.5px; border-radius: 50%; }
.wealth-dot.invested { background: var(--chart-invested); }
.wealth-dot.net { background: var(--chart-net); width: 6px; height: 6px; margin: -3px 0 0 -3px; }
.wealth-dot.active { width: 12px; height: 12px; margin: -6px 0 0 -6px; border: 2px solid var(--surface); box-shadow: 0 0 0 1px var(--muted); }

/* Shopping list : mobile-first, largeur confortable sur desktop, zones tactiles ≥ 44 px */
/* --shopping-row-inset : retrait horizontal des lignes d'articles, commun à la liste active et à la section des cochés (mêmes
   abscisses pour poignée, pictogramme, case, nom, quantité et ⋮ dans les deux blocs, à toute largeur). */
.shopping-page { --shopping-row-inset: 0.5rem; max-width: 640px; margin: 0 auto; padding-bottom: calc(2rem + env(safe-area-inset-bottom)); }
.shopping-page h1 { margin: 0.25rem 0; overflow-wrap: anywhere; }
.shopping-create, .shopping-add-row { display: flex; gap: 0.5rem; align-items: stretch; }
.shopping-create { margin: 0.75rem 0 1rem; }
.shopping-create input, .shopping-add-row input { flex: 1 1 auto; min-width: 0; min-height: 44px; }
.shopping-create button, .shopping-add-row button { margin-top: 0; flex: 0 0 auto; }
.shopping-add { position: relative; margin: 0.5rem 0 0.75rem; }
.shopping-add-button { width: 48px; font-size: 1.5rem; padding: 0; }
.shopping-quantity { margin-top: 0.25rem; font-size: 0.9375rem; }
.shopping-quantity summary { cursor: pointer; min-height: 36px; display: inline-flex; align-items: center; color: var(--muted); }
.shopping-quantity input { min-height: 44px; }
.shopping-suggestions { list-style: none; margin: 0.25rem 0 0; padding: 0.25rem; position: absolute; left: 0; right: 0; z-index: 10; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; box-shadow: var(--shadow); }
.shopping-suggestion { display: block; width: 100%; margin: 0; min-height: 44px; text-align: left; border: 0; border-radius: 6px; background: none; }
.shopping-suggestion:hover, .shopping-suggestion:focus-visible { background: var(--hover); }
.shopping-header { display: flex; justify-content: space-between; align-items: flex-start; gap: 0.5rem; }
.shopping-header-title { flex: 1 1 auto; min-width: 0; }
/* Retour (← Mes listes / Archives) : icône 20 px dans une zone de 40 × 40 px, centrée sur la première ligne du titre, légèrement tirée vers le bord. */
.shopping-back { flex: 0 0 auto; width: 40px; height: 40px; min-height: 40px; margin: 0.5rem 0 0 -0.5rem; border-radius: 50%; color: var(--text); }
.shopping-back:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.shopping-list-meta { margin: 0; font-size: 0.875rem; }
.shopping-group-title, .shopping-category-title { font-size: 0.9375rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; margin: 1rem 0 0.25rem; }
.shopping-lists { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.75rem; }
/* Carte d'une liste (« Mes listes ») : [⠿ favori] [☆ / ★] [nom + pastille « X à acheter » / ligne secondaire] [⋮ favori]. */
/* Carte d'une liste, même géométrie dans les trois groupes : [⠿][☆/★] nom · pastille [⋮]. Zone gauche resserrée pour laisser la
   largeur au nom : poignée 22 px (zone tactile 24 × 44), étoile 34 px (34 × 44), ⋮ 28 px (28 × 44), sans espace entre elles ;
   les zones tactiles débordent en hauteur par des pseudo-éléments, jamais sur l'action voisine. Plus de ligne propriétaire / partage. */
.shopping-list-card { display: flex; align-items: center; gap: 0; margin: 0; padding: 0.375rem 0.25rem 0.375rem 0.125rem; min-height: 56px; transition: transform 0.15s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.15s cubic-bezier(0.4, 0, 0.2, 1); }
.shopping-list-card:hover, .shopping-list-card:focus-within { border-color: var(--accent); }
.shopping-list-link { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 0.125rem; padding: 0.25rem 0.5rem 0.25rem 0.125rem; color: var(--text); text-decoration: none; border-radius: 8px; }
.shopping-list-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.shopping-list-line { display: flex; align-items: center; gap: 0.5rem; min-width: 0; }
.shopping-list-name { flex: 1 1 auto; min-width: 0; font-weight: 700; font-size: 1.0625rem; overflow-wrap: anywhere; }
/* Pastille compteur (cartes et en-tête) : nombre seul, quasi ronde (30 px mobile, 32 px desktop), centré et gras ;
   libellé complet « X articles à acheter » en aria-label (role="img"). Style neutre à 0. */
.shopping-count-badge { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; min-width: 30px; height: 30px; padding: 0 0.5rem; border-radius: 999px; border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent); background: color-mix(in srgb, var(--accent-bg) 13%, var(--surface)); color: var(--accent); font-size: 1rem; font-weight: 800; line-height: 1; white-space: nowrap; font-variant-numeric: tabular-nums; }
.shopping-count-badge.is-zero { border-color: var(--border); background: var(--bg); color: var(--muted); font-weight: 700; }
.shopping-header-count { margin-top: 0.75rem; }
@media (min-width: 768px) { .shopping-count-badge { min-width: 32px; height: 32px; font-size: 1.0625rem; } }
/* Étoile (favori personnel), poignée de réordonnancement (glisser dans le groupe) et ⋮ Monter / Descendre : sur toutes les cartes. */
.shopping-favorite-form { flex: 0 0 auto; margin: 0; }
.shopping-favorite-toggle { position: relative; display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 34px; height: 40px; min-height: 40px; margin: 0; padding: 0; border: 0; border-radius: 50%; background: none; color: var(--muted); font-size: 1.375rem; line-height: 1; cursor: pointer; }
.shopping-favorite-toggle::before { content: ""; position: absolute; inset: -2px 0; }
.shopping-favorite-toggle:hover { background: var(--hover); }
.shopping-favorite-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.shopping-favorite-toggle[aria-pressed="true"], .is-favorite > .shopping-favorite-toggle.is-static { color: var(--favorite); }
.shopping-favorite-toggle.is-static { cursor: default; }
.shopping-list-handle { position: relative; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 44px; min-height: 44px; margin: 0; padding: 0; border: 0; background: none; color: var(--muted); font-size: 1.125rem; cursor: grab; touch-action: none; }
.shopping-list-handle::before { content: ""; position: absolute; inset: 0 0 0 -2px; }
.shopping-list-handle:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.shopping-list-card-menu { flex: 0 0 auto; }
.shopping-list-card-menu-button { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 40px; border-radius: 8px; color: var(--muted); font-size: 1.25rem; font-weight: 700; }
.shopping-list-card-menu-button::before { content: ""; position: absolute; inset: -2px 0; }
.shopping-list-card-menu-button:hover, .shopping-list-card-menu[open] > .shopping-list-card-menu-button { background: var(--hover); color: var(--text); }
.shopping-list-card.is-dragging { position: relative; z-index: 3; transform: scale(1.02); background: var(--drag-bg); box-shadow: 0 0 0 2px var(--accent), var(--drag-shadow); }
.shopping-list-card.is-dragging .shopping-list-handle { color: var(--accent); cursor: grabbing; }
@media (prefers-reduced-motion: reduce) { .shopping-list-card, .shopping-list-card.is-dragging { transition: none; transform: none; } }
/* Hors ligne : étoile et Monter / Descendre inactifs (en ligne uniquement) ; le glisser-déposer reste actif (intention ReorderList). */
.shopping-page.is-offline .shopping-favorite-form, .shopping-page.is-offline .shopping-list-card-menu { opacity: 0.4; pointer-events: none; }
/* Mode d'affichage (Vrac / Catégories) : pictogramme informatif à gauche des boutons. */
.shopping-view-modes { align-items: center; }
.shopping-view-modes-icon { flex: 0 0 auto; color: var(--muted); }
/* Section des articles cochés : libellé selon l'état réel (ouverte « Masquer… (N) », fermée « Afficher… (N) »). */
.shopping-purchased:not([open]) .shopping-purchased-when-open, .shopping-purchased[open] .shopping-purchased-when-closed { display: none; }
/* Sur le fond décoratif, la liste d'articles et la section des cochés forment des cartes opaques (lisibilité des longues listes). */
.shopping-items { list-style: none; padding: 0 var(--shopping-row-inset); margin: 0; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; }
.shopping-item { display: flex; align-items: center; gap: 0.5rem; min-height: 48px; padding: 0; border-bottom: 1px solid var(--border); background: var(--surface); transition: opacity 0.3s ease, background-color 0.3s ease, transform 0.15s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.15s cubic-bezier(0.4, 0, 0.2, 1); }
.shopping-item:last-child { border-bottom: 0; }
.shopping-item form { margin: 0; }
.shopping-check { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 44px; min-height: 44px; margin: 0; padding: 0; border: 0; background: none; cursor: pointer; }
.shopping-check-mark { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; border: 2px solid var(--muted); border-radius: 50%; color: transparent; font-size: 0.9rem; font-weight: 700; transition: all 0.2s ease; }
.shopping-check:hover .shopping-check-mark { border-color: var(--accent); }
.shopping-check.static { cursor: default; }
.shopping-item.is-checked .shopping-check-mark, .shopping-item.is-checking .shopping-check-mark { background: var(--accent-bg); border-color: var(--accent-bg); color: var(--on-accent); }
/* Article coché qui attend la fin de la salve (LIFE-273 : plusieurs lignes à la fois, parfois plus d'1 s) : fond sur la ligne,
   atténuation sur ses enfants et non sur le li (comme les cochés, LIFE-271), sinon chaque ligne en attente formerait un
   contexte d'empilement qui passerait devant le menu ⋮ d'une ligne précédente. */
.shopping-item.is-checking { animation: shopping-checked var(--shopping-check-delay) ease forwards; }
.shopping-item.is-checking > :not(.shopping-item-menu), .shopping-item.is-checking .shopping-item-menu-button { animation: shopping-checked-fade var(--shopping-check-delay) ease forwards; }
.shopping-item.is-checking .shopping-check-mark { transform: scale(1.15); }
.shopping-item.is-checking .shopping-item-name, .shopping-item.is-checked .shopping-item-name { text-decoration: line-through; color: var(--muted); }
@keyframes shopping-checked { 0% { background-color: var(--hover); } }
@keyframes shopping-checked-fade { 70% { opacity: 1; } 100% { opacity: 0.45; } }
@media (prefers-reduced-motion: reduce) { .shopping-item.is-checking, .shopping-item.is-checking > *, .shopping-item.is-checking .shopping-item-menu-button { animation: none; } .shopping-item.is-checking > :not(.shopping-item-menu), .shopping-item.is-checking .shopping-item-menu-button { opacity: 0.6; } .shopping-check-mark { transition: none; } }
/* Une seule ligne : nom (toute la largeur, centré verticalement), marqueur ⏳ éventuel à droite ; la catégorie n'est plus écrite
   (pictogramme avant la case, texte masqué pour les lecteurs d'écran). */
.shopping-item-text { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 0.25rem; }
.shopping-item-text > .shopping-item-name { flex: 1 1 auto; min-width: 0; }
.shopping-item-text > .shopping-item-pending { flex: 0 0 auto; }
/* Nom cliquable (modification rapide dans la ligne) : même boîte que le texte seul, sur toute la largeur de la colonne, sans
   aspect bouton ni hauteur ajoutée ; léger soulignement au survol, contour de focus au clavier. */
.shopping-item-rename { display: block; color: inherit; text-decoration: none; cursor: pointer; border-radius: 4px; -webkit-tap-highlight-color: transparent; }
.shopping-item-rename:hover { text-decoration: underline; text-decoration-color: var(--border); text-underline-offset: 2px; }
.shopping-item.is-checked .shopping-item-rename:hover, .shopping-item.is-checking .shopping-item-rename:hover { text-decoration: line-through; }
.shopping-item-rename:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Champ de modification du nom : exactement la hauteur de la ligne du nom (1,5 em), même police, fond discret, accent au focus ;
   il déborde de 3 px de chaque côté (dans l'espacement de la ligne) pour que le texte reste aligné sur le nom. */
.shopping-item-text > .shopping-item-rename-input { display: block; width: calc(100% + 6px); min-width: 0; height: 1.5em; min-height: 0; margin: 0 -3px; padding: 0 2px; font: inherit; line-height: 1.375; color: var(--text); background: var(--input-bg); border: 1px solid var(--border); border-radius: 4px; box-shadow: none; }
.shopping-item-text > .shopping-item-rename-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.shopping-item-text > .shopping-item-rename-input[aria-invalid="true"] { border-color: var(--danger); box-shadow: 0 0 0 1px var(--danger); }
.shopping-item-name { overflow-wrap: anywhere; }
/* Articles à acheter : nom en semi-gras (actifs, vues Vrac et Catégories, en ligne et hors ligne) ; les cochés restent en graisse
   normale, barrés et atténués. Le champ de modification dans la ligne reprend la même graisse (pas de saut à l'ouverture). */
.shopping-items:not(.checked) .shopping-item-name, .shopping-items:not(.checked) .shopping-item-text > .shopping-item-rename-input { font-weight: 600; }
/* Mobile : approche resserrée d'1 % pour que le semi-gras tienne dans la largeur du texte normal (« Croquettes pour chat » sur
   une ligne à 360 px, lignes de 41 px) ; même valeur sur le champ de modification. */
@media (max-width: 767px) { .shopping-items:not(.checked) .shopping-item-name, .shopping-items:not(.checked) .shopping-item-text > .shopping-item-rename-input { letter-spacing: -0.01em; } }
/* Pictogramme de catégorie (vue « Vrac » et articles cochés) : SVG local en masque CSS (aucune requête, disponible hors ligne),
   forme propre à chaque catégorie et couleur stable, claire / sombre ; informatif (aria-hidden), jamais cliquable. */
.shopping-category-icon { flex: 0 0 auto; width: 20px; height: 20px; background-color: var(--cat, var(--muted)); -webkit-mask: var(--cat-shape) center / contain no-repeat; mask: var(--cat-shape) center / contain no-repeat; pointer-events: none; }
:root[data-theme="dark"] .shopping-category-icon { background-color: var(--cat-dark, var(--muted)); }
/* Titre de groupe (vue « Catégories ») : le même pictogramme (mêmes formes et couleurs ci-dessous), une seule fois par groupe,
   un peu plus grand (20 px mobile, 22 px desktop), centré sur le texte, 7 px d'écart ; la hauteur du titre ne change pas. */
.shopping-category-title { display: flex; align-items: center; gap: 0.4375rem; }
.shopping-category-title > .shopping-category-icon { width: 20px; height: 20px; margin: 0; }
@media (min-width: 768px) { .shopping-category-title > .shopping-category-icon { width: 22px; height: 22px; } }
@media (forced-colors: active) { .shopping-category-icon { forced-color-adjust: none; background-color: CanvasText; } }
.shopping-category-icon[data-category="FruitsVegetables"] { --cat: #2b8a3e; --cat-dark: #69db7c; --cat-shape: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 7.5c-1.6-1.3-5.2-1.6-6.6 1.4C4 12 5.6 17.2 8 19.5c1.3 1.2 2.6 1 4 .3 1.4.7 2.7.9 4-.3 2.4-2.3 4-7.5 2.6-10.6C17.2 5.9 13.6 6.2 12 7.5z'/%3E%3Cpath d='M12 7.5c0-2.2 1.2-3.9 3.5-4.5'/%3E%3C/svg%3E"); }
.shopping-category-icon[data-category="Fresh"] { --cat: #1971c2; --cat-dark: #74c0fc; --cat-shape: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 17.5 15.5 6.5l6 4.5v6.5z'/%3E%3Cpath d='M2.5 17.5h19'/%3E%3Cg fill='black' stroke='none'%3E%3Ccircle cx='15.5' cy='13.5' r='1.5'/%3E%3Ccircle cx='10.5' cy='15' r='1'/%3E%3C/g%3E%3C/svg%3E"); }
.shopping-category-icon[data-category="Grocery"] { --cat: #946f00; --cat-dark: #ffd43b; --cat-shape: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='7' y='2.5' width='10' height='3.5' rx='1'/%3E%3Cpath d='M8 6v1.5C6.6 8.4 6 9.5 6 11v8a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2v-8c0-1.5-.6-2.6-2-3.5V6'/%3E%3Cpath d='M6 13h12'/%3E%3C/svg%3E"); }
.shopping-category-icon[data-category="Drinks"] { --cat: #6741d9; --cat-dark: #b197fc; --cat-shape: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10 2h4v4.5c0 .6.4 1.1.9 1.4 1.3.8 2.1 2.1 2.1 3.6V20a2 2 0 0 1-2 2H9a2 2 0 0 1-2-2v-8.5c0-1.5.8-2.8 2.1-3.6.5-.3.9-.8.9-1.4z'/%3E%3Cpath d='M7 14.5h10'/%3E%3C/svg%3E"); }
.shopping-category-icon[data-category="Frozen"] { --cat: #0c8599; --cat-dark: #66d9e8; --cat-shape: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2v20M3.3 7l17.4 10M20.7 7 3.3 17'/%3E%3Cpath d='m9 3.5 3 2 3-2M9 20.5l3-2 3 2'/%3E%3C/svg%3E"); }
.shopping-category-icon[data-category="Hygiene"] { --cat: #c2255c; --cat-dark: #f783ac; --cat-shape: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 2.5s-6.5 7-6.5 11.5a6.5 6.5 0 0 0 13 0C18.5 9.5 12 2.5 12 2.5z'/%3E%3Cpath d='M9 14.5a3 3 0 0 0 3 3'/%3E%3C/svg%3E"); }
.shopping-category-icon[data-category="Household"] { --cat: #8a5a3b; --cat-dark: #d9a47a; --cat-shape: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 11.5 12 4l9 7.5'/%3E%3Cpath d='M5.5 9.5V20.5h13V9.5'/%3E%3Cpath d='M10 20.5v-5.5h4v5.5'/%3E%3C/svg%3E"); }
.shopping-category-icon[data-category="Baby"] { --cat: #9c36b5; --cat-dark: #e599f7; --cat-shape: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10 8.5V6a2 2 0 0 1 4 0v2.5'/%3E%3Cpath d='M4.5 10.5c2.1-1.3 4.6-2 7.5-2s5.4.7 7.5 2c-.6 1.8-2.4 2.8-4.2 2.8H8.7c-1.8 0-3.6-1-4.2-2.8z'/%3E%3Ccircle cx='12' cy='17.5' r='3.5'/%3E%3C/svg%3E"); }
.shopping-category-icon[data-category="Pets"] { --cat: #d9480f; --cat-dark: #ffa94d; --cat-shape: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Cellipse cx='12' cy='16.5' rx='4.8' ry='4'/%3E%3Ccircle cx='5.5' cy='10.5' r='2.2'/%3E%3Ccircle cx='9.3' cy='6' r='2.2'/%3E%3Ccircle cx='14.7' cy='6' r='2.2'/%3E%3Ccircle cx='18.5' cy='10.5' r='2.2'/%3E%3C/svg%3E"); }
.shopping-category-icon[data-category="DoItYourself"] { --cat: #364fc7; --cat-dark: #91a7ff; --cat-shape: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.5 7.5 14.5 3.5l6 6-4 4z'/%3E%3Cpath d='M13.5 10.5 3.5 20.5'/%3E%3C/svg%3E"); }
.shopping-category-icon[data-category="Other"] { --cat: #6c757d; --cat-dark: #adb5bd; --cat-shape: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2'%3E%3Crect x='2.5' y='5.5' width='19' height='13' rx='4'/%3E%3Cg fill='black' stroke='none'%3E%3Ccircle cx='7.5' cy='12' r='1.6'/%3E%3Ccircle cx='12' cy='12' r='1.6'/%3E%3Ccircle cx='16.5' cy='12' r='1.6'/%3E%3C/g%3E%3C/svg%3E"); }
.shopping-item-quantity { flex: 0 0 auto; max-width: 35%; padding: 0.125rem 0.5rem; border-radius: 999px; background: var(--hover); font-size: 0.875rem; overflow-wrap: anywhere; text-align: right; }
.shopping-drag { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 44px; min-height: 44px; margin: 0; padding: 0; border: 0; background: none; color: var(--muted); cursor: grab; touch-action: none; font-size: 1.25rem; }
/* Article saisi (glisser-déposer) : il « se soulève » en 150 ms — légère mise à l'échelle, fond teinté, contour bleu, ombre bleutée
   (visible aussi en sombre) ; texte, catégorie et quantité restent lisibles (opacité 1). Pendant le geste, quantité et ⋮ sont inertes.
   Le déplacement étant réordonné en direct, la ligne soulevée indique elle-même l'emplacement d'insertion. */
.shopping-item.is-dragging { position: relative; z-index: 3; opacity: 1; transform: scale(1.02); border-radius: 10px; border-bottom-color: transparent; background: var(--drag-bg); box-shadow: 0 0 0 2px var(--accent), var(--drag-shadow); }
.shopping-item.is-dragging .shopping-drag { color: var(--accent); cursor: grabbing; }
.shopping-item.is-dragging .quantity-stepper, .shopping-item.is-dragging .shopping-item-menu, .shopping-item.is-dragging .shopping-check { pointer-events: none; }
@media (min-width: 768px) { .shopping-item.is-dragging { transform: scale(1.03); } }
@media (prefers-reduced-motion: reduce) { .shopping-item, .shopping-item.is-dragging { transition: none; transform: none; } }
.menu { position: relative; }
.menu > summary { list-style: none; cursor: pointer; }
.menu > summary::-webkit-details-marker { display: none; }
.shopping-item-menu-button { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 44px; font-size: 1.25rem; color: var(--muted); border-radius: 8px; }
.shopping-item-menu-button:hover, .shopping-list-menu > summary:hover { background: var(--hover); }
/* Actions de la liste (⋮) : bouton rond transparent bien visible (symbole 26 px, zone 44 × 44 px), centré sur la première ligne du titre. */
.shopping-list-menu { flex: 0 0 auto; margin-top: 0.375rem; }
.shopping-list-menu-button { width: 44px; height: 44px; border-radius: 50%; color: var(--text); font-size: 1.625rem; font-weight: 700; line-height: 1; }
.shopping-list-menu-button:hover, .shopping-list-menu[open] > .shopping-list-menu-button { background: var(--hover); }
.shopping-list-menu-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.menu-panel { position: absolute; right: 0; top: 100%; z-index: 20; min-width: 12rem; display: flex; flex-direction: column; padding: 0.25rem; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; box-shadow: var(--shadow); }
.menu-panel a, .menu-panel button { display: flex; align-items: center; justify-content: flex-start; width: 100%; min-height: 44px; margin: 0; padding: 0 0.75rem; border: 0; border-radius: 6px; background: none; color: var(--text); text-align: left; text-decoration: none; font: inherit; cursor: pointer; }
.menu-panel a:hover, .menu-panel button:hover { background: var(--hover); }
.menu-panel p { margin: 0.5rem 0.75rem; font-size: 0.875rem; }
.menu-panel form { margin: 0; }
.menu-panel .menu-separator { height: 0; margin: 0.25rem 0.5rem; border-top: 1px solid var(--border); }
.danger-link { color: var(--danger) !important; }
.shopping-purchased { margin-top: 1rem; padding: 0 var(--shopping-row-inset); background: var(--surface); border: 1px solid var(--border); border-radius: 12px; }
.shopping-purchased > summary { list-style: none; display: flex; justify-content: space-between; align-items: center; min-height: 48px; padding: 0 calc(0.75rem - var(--shopping-row-inset)); cursor: pointer; font-weight: 600; color: var(--muted); }
.shopping-purchased .shopping-items { padding: 0; border: 0; border-top: 1px solid var(--border); border-radius: 0; }
.shopping-purchased > summary::-webkit-details-marker { display: none; }
.shopping-chevron { display: inline-block; font-size: 1.125rem; transition: transform 0.2s ease; }
.shopping-purchased[open] .shopping-chevron { transform: rotate(180deg); }
/* Cochés atténués élément par élément, jamais la ligne entière : une opacité < 1 sur la ligne (li) crée un contexte d'empilement
   qui enferme le menu ⋮ (panneau rendu sous les lignes suivantes, grisé, en partie non cliquable). Le panneau du menu reste hors
   de toute opacité, comme sur une ligne active ; seul le bouton ⋮ est atténué. */
.shopping-items.checked .shopping-item > :not(.shopping-item-menu), .shopping-items.checked .shopping-item-menu-button { opacity: 0.8; }
.shopping-empty { margin: 1rem 0; }
.shopping-notice { margin: 0.5rem 0; }

/* Hors ligne V1 (js/shopping-offline.js) : ligne d'état compacte (une ligne, ≈ 28 px), articles en attente discrets,
   actions indisponibles hors ligne désactivées (seuls l'ajout et la suppression restent possibles). */
.shopping-offline-status { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin: 0.25rem 0 0.375rem; padding: 0.25rem 0.625rem; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); color: var(--muted); font-size: 0.8125rem; line-height: 1.35; }
.shopping-offline-status.is-offline { border-color: var(--muted); }
.shopping-offline-status.is-error { border-color: var(--danger); color: var(--error-text); background: var(--error-bg); }
.shopping-offline-action { flex: 0 0 auto; min-height: 28px; margin: 0; padding: 0 0.625rem; border: 1px solid var(--border); border-radius: 999px; background: var(--surface); color: var(--accent); font-size: 0.8125rem; font-weight: 600; text-decoration: none; cursor: pointer; }
/* Même règle pour le marqueur « en attente » (hors ligne) : opacité sur le contenu, pas sur la ligne qui porte le menu. */
.shopping-item.is-pending > :not(.shopping-item-menu), .shopping-item.is-pending .shopping-item-menu-button { opacity: 0.85; }
.shopping-items.checked .shopping-item.is-pending > :not(.shopping-item-menu), .shopping-items.checked .shopping-item.is-pending .shopping-item-menu-button { opacity: 0.68; }
.shopping-item-pending { color: var(--accent); white-space: nowrap; }
/* Hors ligne : coche, décoche, glisser-déposer, ajout et suppression restent actifs ; quantité, filtres d'affichage et menu de la liste non. */
.shopping-page.is-offline .quantity-stepper, .shopping-page.is-offline .chips, .shopping-page.is-offline .shopping-list-menu { opacity: 0.4; pointer-events: none; }
.shopping-page.is-offline .shopping-item-menu .menu-panel > :not(.danger-link):not([data-item-edit]) { display: none; }
.shopping-editor form { display: grid; gap: 0.375rem; }
.shopping-editor label { font-weight: 600; }
.shopping-editor input, .shopping-editor select { width: 100%; }
.shopping-editor .shopping-editor-title { margin: 0 0 0.25rem; font-weight: 600; font-size: 1.0625rem; }
.shopping-editor .muted { font-size: 0.8125rem; }
.shopping-confirm { max-width: min(22rem, calc(100vw - 2rem)); padding: 1rem 1.25rem; border: 1px solid var(--border); border-radius: 12px; background: var(--surface); color: var(--text); box-shadow: var(--shadow); }
.shopping-confirm::backdrop { background: rgba(0, 0, 0, 0.45); }
.shopping-confirm p { margin: 0 0 0.5rem; }
.shopping-confirm-actions { display: flex; justify-content: flex-end; gap: 0.5rem; }
.shopping-confirm-actions button { margin-top: 0.5rem; }
.offline-shell .shopping-offline-status { margin-top: 0.5rem; }
.shopping-members { list-style: none; padding: 0; }
.shopping-members li { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 0.5rem; padding: 0.5rem 0; border-bottom: 1px solid var(--border); overflow-wrap: anywhere; }

/* Shopping mobile (< 768 px) : hauteur utile maximale avant les articles. Onglets Mes listes / Archives dans le tiroir (pas dans la page),
   titre remonté, ajout / filtres / lignes compacts. Rendu visuel réduit, zones tactiles conservées (≥ 44 px de haut via pseudo-éléments
   invisibles) ; le champ garde 16 px de texte (pas de zoom automatique iOS). */
@media (max-width: 767px) {
  .shopping-section-tabs { display: none; }
  .container:has(> .shopping-page) { padding-top: 0.5rem; }
  .shopping-page h1 { margin: 0; font-size: 1.625rem; line-height: 1.25; }
  .shopping-header .shopping-list-menu { margin-top: -0.3125rem; }
  .shopping-header { gap: 0.25rem; }
  .shopping-back { margin-top: -0.21875rem; }
  .shopping-header-count { margin-top: 0.28rem; }
  .shopping-add { margin: 0.375rem 0 0.375rem; }
  .shopping-add-row input { min-height: 34px; padding-top: 0.3125rem; padding-bottom: 0.3125rem; }
  .shopping-add-row .shopping-add-button { position: relative; width: 40px; min-height: 34px; font-size: 1.375rem; }
  .shopping-add-button::before { content: ""; position: absolute; inset: -6px -4px; }
  .shopping-page .chips { gap: 0.375rem; margin-bottom: 0.375rem; }
  .shopping-page .chip { position: relative; min-height: 28px; padding: 0 0.75rem; font-size: 0.8125rem; }
  .shopping-page .chip::before { content: ""; position: absolute; inset: -5px -2px; }
  /* Lignes denses (41 px avec la bordure) : case, poignée et ⋮ de 40 px ; le pseudo-élément étend leur zone tactile à toute la
     hauteur de la ligne (bordure comprise, sans zone morte entre deux lignes). */
  .shopping-item { min-height: 41px; padding: 0; }
  .shopping-item .shopping-check, .shopping-item .shopping-drag, .shopping-item .shopping-item-menu-button { position: relative; height: 40px; min-height: 40px; }
  .shopping-item .shopping-check::before, .shopping-item .shopping-drag::before { content: ""; position: absolute; inset: -2px; }
  .shopping-item .shopping-item-menu-button::before { content: ""; position: absolute; inset: -2px -3px; }
  .shopping-purchased { margin-top: 0.5rem; }
  .shopping-purchased > summary { min-height: 40px; }
}
/* Shopping list : quantité + / − sur la ligne (zones tactiles 40 px, mode sombre via les variables) */
.quantity-stepper { flex: 0 0 auto; display: inline-flex; align-items: center; border: 1px solid var(--border); border-radius: 999px; background: var(--surface); }
.quantity-stepper form { margin: 0; }
/* Quantité compacte (le nom garde la largeur) : boutons visuels de 24 × 30 px (groupe ≈ 68 px sur mobile), zone tactile élargie
   par un pseudo-élément invisible : 36 × 44 px pour − (débord côté nom, non interactif), 32 × 44 px pour +. */
.stepper-button { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 30px; min-height: 30px; margin: 0; padding: 0; border: 0; border-radius: 999px; background: none; color: var(--text); font-size: 1.0625rem; font-weight: 600; line-height: 1; cursor: pointer; }
.stepper-button::before { content: ""; position: absolute; inset: -7px -4px; }
.quantity-stepper form:first-child .stepper-button::before { left: -8px; }
.stepper-button:hover:not(:disabled) { background: var(--hover); }
.stepper-button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.stepper-button:disabled { color: var(--border); cursor: default; opacity: 1; }
.stepper-value { min-width: 1.125rem; padding: 0 1px; font-size: 0.9375rem; text-align: center; font-weight: 700; font-variant-numeric: tabular-nums; }
/* Mobile : nom prioritaire (espacement réduit). Desktop : contrôles un peu plus larges, jamais perdus dans la ligne. */
/* Mobile : largeur visuelle resserrée pour laisser au nom la place du pictogramme (18 px, collé à la case) ; largeur des zones
   tactiles conservée par les pseudo-éléments (poignée 24 px, case 32 px, ⋮ 28 px), hauteur = toute la ligne. */
@media (max-width: 767px) { .shopping-page { --shopping-row-inset: 0.125rem; } .shopping-item { gap: 0.1875rem; } .shopping-check { width: 28px; } .shopping-drag { width: 20px; } .shopping-item-menu-button { width: 22px; } .shopping-category-icon { width: 18px; height: 18px; margin-right: -2px; } }
@media (min-width: 768px) { .shopping-check { width: 44px; } .shopping-drag { width: 32px; } .shopping-item-menu-button { width: 36px; } .stepper-button { width: 28px; height: 34px; min-height: 34px; } .stepper-value { min-width: 1.5rem; } }

/* Navigation secondaire commune (Invest, Shopping list, Administration) : onglets « pilules » sur une seule ligne.
   Écran étroit : seule la barre défile horizontalement (jamais la page). Onglet courant : fond plein + gras + aria-current. */
.section-tabs { max-width: 100%; margin: 0 0 1rem; }
.section-tabs-list {
  position: relative; display: flex; gap: 0.25rem; width: max-content; max-width: 100%;
  margin: 0; padding: 0.25rem; list-style: none;
  overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x proximity; scrollbar-width: none; -webkit-overflow-scrolling: touch;
  background: var(--surface); border: 1px solid var(--border); border-radius: 999px;
}
.section-tabs-list::-webkit-scrollbar { display: none; }
.section-tabs-list li { flex: 0 0 auto; scroll-snap-align: start; }
.section-tab {
  display: inline-flex; align-items: center; min-height: 40px; padding: 0 1rem;
  border-radius: 999px; color: var(--muted); font-size: 0.9375rem; font-weight: 500; text-decoration: none; white-space: nowrap;
  transition: background-color 0.15s ease, color 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.section-tab:hover { background: var(--hover); color: var(--text); }
.section-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* Sans JavaScript : l'onglet courant porte lui-même le fond bleu. */
.section-tab[aria-current="page"] { background: var(--accent-bg); color: var(--on-accent); font-weight: 700; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18); }
.section-tab[aria-current="page"]:hover { background: var(--accent-bg); color: var(--on-accent); }
/* Avec JavaScript (js/layout.js, classe has-indicator) : une seule pastille bleue derrière les onglets, déplacée par transform / width
   (200 ms, cubic-bezier(0.4, 0, 0.2, 1)) ; les textes restent au-dessus. Pendant le glissement (is-settling), l'ancien onglet garde
   le texte clair et le nouveau le texte discret, puis les couleurs s'échangent au même rythme que la pastille. */
.section-tab-indicator { position: absolute; top: 0; left: 0; width: 0; height: 0; border-radius: 999px; background: var(--accent-bg); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18); pointer-events: none; opacity: 0; }
.section-tabs-list li.section-tab-indicator { scroll-snap-align: none; }
.section-tabs-list.has-indicator .section-tab-indicator { opacity: 1; }
.section-tabs-list.has-indicator li:not(.section-tab-indicator) { position: relative; z-index: 1; }
.section-tabs-list.has-indicator .section-tab[aria-current="page"], .section-tabs-list.has-indicator .section-tab[aria-current="page"]:hover { background: transparent; box-shadow: none; }
.section-tabs-list.is-animated .section-tab-indicator { transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1), width 0.2s cubic-bezier(0.4, 0, 0.2, 1); }
.section-tabs-list.is-settling .section-tab[aria-current="page"] { color: var(--muted); }
.section-tabs-list.is-settling .section-tab.is-previous { color: var(--on-accent); }
@media (prefers-reduced-motion: reduce) { .section-tab, .section-tabs-list.is-animated .section-tab-indicator { transition: none; } }
@media (min-width: 768px) { .section-tab { padding: 0 0.75rem; font-size: 0.875rem; } }

/* ----- Planning (socle LIFE-300) : enfants accessibles, pastille de couleur (valeur #RRGGBB validée), administration des accès. */
.planning-section-title { margin: 0.5rem 0 0.75rem; font-size: 1.0625rem; }
.planning-children { display: grid; grid-template-columns: 1fr; gap: 0.75rem; margin: 0 0 1rem; padding: 0; list-style: none; }
@media (min-width: 768px) { .planning-children { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); } }
.planning-child-card { display: flex; align-items: center; gap: 0.75rem; min-height: 56px; margin: 0; padding: 0.75rem 1rem; color: var(--text); text-decoration: none; }
.planning-child-card:hover, .planning-child-card:focus-visible { border-color: var(--accent); }
.planning-child-name { flex: 1 1 auto; min-width: 0; font-weight: 600; overflow-wrap: anywhere; }
.planning-child-swatch { flex: 0 0 auto; display: inline-block; width: 18px; height: 18px; border-radius: 50%; border: 2px solid var(--surface); box-shadow: 0 0 0 1px var(--border); }
.planning-child-title { display: flex; align-items: center; gap: 0.5rem; min-width: 0; overflow-wrap: anywhere; }
.planning-color-input { width: 64px; height: 40px; padding: 2px; }
.planning-access-list { list-style: none; padding: 0; }
.planning-access-list li { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; padding: 0.5rem 0; border-bottom: 1px solid var(--border); }
.planning-access-user { flex: 1 1 12rem; min-width: 0; overflow-wrap: anywhere; }
.planning-access-list form { margin: 0; }
/* Niveau (libellés longs) : le formulaire et la liste se rétrécissent jusqu'à la largeur de la carte (360 px compris). */
.planning-access-level { flex: 1 1 16rem; min-width: 0; max-width: 100%; display: flex; align-items: center; gap: 0.5rem; }
.planning-access-level select { flex: 1 1 auto; width: auto; min-width: 0; margin: 0; }
/* ----- Garde (LIFE-301) : listes de règles / exceptions / historique, statistiques, JSON d'historique sans débordement. */
.custody-list { list-style: none; margin: 0 0 1rem; padding: 0; }
.custody-list > li { padding: 0.75rem 0; border-bottom: 1px solid var(--border); overflow-wrap: anywhere; }
.custody-list > li.card { padding: 1rem; border-bottom: 1px solid var(--border); }
.custody-stats { margin-bottom: 1rem; }
.custody-deactivate { margin-top: 0.5rem; }
.custody-deactivate summary { cursor: pointer; color: var(--danger); }
/* LIFE-312 : règle désactivée, secondaire visuellement (la règle active reste la plus lisible de la liste). */
.custody-rule.is-inactive { opacity: 0.7; }
.custody-rule.is-inactive .item-header strong { font-weight: 400; }
.planning-history-filters { display: grid; grid-template-columns: 1fr; gap: 0.25rem 1rem; }
@media (min-width: 768px) { .planning-history-filters { grid-template-columns: repeat(4, minmax(0, 1fr)); align-items: end; } .planning-history-filters label { grid-row: 1; } .planning-history-filters button { grid-column: 1 / -1; justify-self: start; } }
.planning-json { margin: 0.5rem 0 0; padding: 0.5rem; max-width: 100%; overflow-x: auto; white-space: pre-wrap; overflow-wrap: anywhere; font-size: 0.8125rem; background: var(--bg); border: 1px solid var(--border); border-radius: 6px; }

/* ----- Calendrier des gardes (LIFE-302), vue Mois. Couleur de l'enfant (--child-color, #RRGGBB validé) seulement en accent :
   barre, point, bordure, fond très dilué ; le texte reste en couleur de texte du thème (lisible en clair comme en sombre).
   Exception : même couleur + bordure pointillée, hachures légères et symbole ◇ (jamais la couleur seule). */
.planning-calendar { --planning-cell-pad: 0.25rem; }
/* LIFE-312 : disposition en grille nommée — la position du titre, du groupe d'actions et de la navigation ne dépend jamais de la
   longueur du texte du titre (« 19 – 25 octobre 2026 » vs « 26 octobre – 1 novembre 2026 »), contrairement à un flex qui se
   réajuste selon le contenu. Mobile : trois rangées empilées, toujours dans le même ordre. */
.planning-calendar-header { display: grid; grid-template-columns: 1fr; grid-template-areas: "title" "nav" "new"; align-items: center; gap: 0.5rem; margin-bottom: 0.5rem; }
.planning-calendar-header h1 { grid-area: title; margin: 0; min-width: 0; overflow-wrap: anywhere; }
/* LIFE-319 : « + Événement » et « + Exception » forment un seul groupe (une seule zone de grille « new »), jamais deux éléments
   séparés pouvant finir sur des lignes ou des positions différentes. */
.planning-header-actions { grid-area: new; justify-self: start; display: flex; flex-wrap: nowrap; align-items: center; gap: 0.5rem; min-width: 0; }
.planning-month-nav { grid-area: nav; display: flex; gap: 0.375rem; }
.planning-month-nav .button { margin: 0; min-height: 40px; padding: 0 0.875rem; display: inline-flex; align-items: center; }
.planning-month-step { min-width: 44px; justify-content: center; font-size: 1.25rem; }
@media (min-width: 768px) {
    .planning-calendar-header { grid-template-columns: 1fr auto auto; grid-template-areas: "title new nav"; }
    .planning-header-actions { justify-self: end; }
}
/* LIFE-319 : même style pour les deux actions (bleu adouci, propre au Planning — jamais le bleu saturé de --accent-bg utilisé
   partout ailleurs), hauteur/rayon/typo identiques, jamais séparées par un retour à la ligne à 360 px (labels courts). */
.planning-header-actions .button { margin: 0; min-height: 40px; padding: 0 0.75rem; display: inline-flex; align-items: center; gap: 0.25rem; flex: 0 0 auto; white-space: nowrap; border-radius: 8px; font-weight: 600; background: var(--planning-action-bg); border-color: var(--planning-action-bg); color: var(--planning-action-text); }
.planning-header-actions .button:hover { background: var(--planning-action-bg-hover); border-color: var(--planning-action-bg-hover); }
.planning-header-actions .button:focus-visible { outline: 2px solid var(--planning-action-bg-hover); outline-offset: 2px; }
.planning-header-actions .button:disabled { background: var(--planning-action-bg); border-color: var(--planning-action-bg); opacity: 0.5; cursor: not-allowed; }
@media (max-width: 359px) {
    .planning-header-actions .button { padding: 0 0.5rem; font-size: 0.9375rem; }
}
/* LIFE-313 : barre des deux filtres (Enfants, Zone), en haut du planning, sur une seule ligne même à 360 px — chacun peut rétrécir
   (min-width: 0) mais jamais passer à la ligne suivante ; le panneau déplié de l'un n'affecte pas la position de l'autre. */
.planning-filter-bar { display: flex; flex-wrap: nowrap; align-items: flex-start; justify-content: space-between; gap: 0.5rem; margin-bottom: 0.75rem; }
.planning-filter-bar > .planning-filter { min-width: 0; flex: 0 1 auto; }
.planning-filter-bar > .planning-filter:last-child { margin-left: auto; }
/* Filtre compact (<details>/<summary>), replié par défaut. */
.planning-filter-summary { display: inline-flex; align-items: center; gap: 0.375rem; min-height: 36px; max-width: 100%; padding: 0 0.625rem; border: 1px solid var(--border); border-radius: 999px; background: var(--surface); font-size: 0.9rem; white-space: nowrap; cursor: pointer; list-style: none; user-select: none; }
.planning-filter-summary::-webkit-details-marker { display: none; }
.planning-filter-summary::after { content: "\25be"; margin-left: 0.125rem; color: var(--muted); }
.planning-filter[open] .planning-filter-summary::after { content: "\25b4"; }
.planning-filter-summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.planning-filter-dots { display: inline-flex; gap: 2px; flex: 0 0 auto; }
.planning-filter-dots span { width: 10px; height: 10px; border-radius: 50%; background: var(--child-color); transition: opacity 0.1s ease; }
/* LIFE-313 : plus de compteur « N/M » — la pastille elle-même s'atténue quand son enfant est décoché. */
.planning-filter-dots span.is-off { opacity: 0.25; }
.planning-filter-zone-dot { display: inline-flex; align-items: center; justify-content: center; width: 14px; height: 14px; border-radius: 4px; border: 1px solid var(--muted); font-size: 0.5625rem; font-weight: 700; line-height: 1; color: var(--muted); background: transparent; opacity: 0.5; }
.planning-filter-zone-dot.is-selected { color: var(--on-accent); background: var(--accent); border-color: var(--accent); opacity: 1; }
.planning-filter[open] .planning-filter-summary { border-radius: 999px 999px 0 0; border-bottom-color: transparent; }
/* LIFE-318 : les deux filtres (Enfants, Zone) ouvrent leur panneau en popover, par-dessus le planning, jamais en poussant son
   contenu — même logique visuelle, même z-index pour les deux. Enfants (à gauche) s'ancre à gauche, Zone (à droite) à droite, pour
   ne jamais déborder de l'écran ; js/planning-calendar.js ferme l'un quand l'autre s'ouvre, au clic ailleurs et à Échap (focus
   rendu au bouton), par un seul gestionnaire commun aux deux. */
.planning-filter { position: relative; }
.planning-filter-panel { position: absolute; top: 100%; left: 0; z-index: 20; width: max-content; max-width: calc(100vw - 2rem); display: flex; flex-wrap: wrap; align-items: center; gap: 0.375rem 0.5rem; margin-top: 0.375rem; padding: 0.625rem; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); box-shadow: 0 4px 12px rgb(0 0 0 / 0.15); }
.planning-filter-zones .planning-filter-panel, .planning-filter-bar > .planning-filter:last-child .planning-filter-panel { left: auto; right: 0; }
.planning-filter-chip { display: inline-flex; align-items: center; gap: 0.375rem; min-height: 36px; margin: 0; padding: 0 0.75rem 0 0.5rem; border: 1px solid var(--border); border-left: 4px solid var(--child-color); border-radius: 999px; background: var(--bg); font-size: 0.9rem; cursor: pointer; }
.planning-filter-chip input { width: auto; margin: 0; }
/* Prénom très long sans espace (80 caractères) : coupé dans la pastille, jamais de défilement horizontal de la page (LIFE-310). */
/* Prénom très long (LIFE-311) : coupé avec une ellipse dans la pastille (jamais de retour à la ligne dans un filtre compact) ;
   le nom complet reste dans l'attribut title de la pastille. */
.planning-filter-chip { max-width: 100%; }
.planning-filter-chip > span:last-child { min-width: 0; max-width: 14rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.planning-filter-chip:has(input:not(:checked)) { opacity: 0.6; }
.planning-filter-chip .planning-child-swatch, .planning-detail-head .planning-child-swatch { background-color: var(--child-color); }
.planning-legend-exception { display: inline-flex; align-items: center; gap: 0.375rem; font-size: 0.85rem; color: var(--muted); }
.planning-exception-sample { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 18px; border: 1.5px dashed var(--muted); border-radius: 4px; font-size: 0.75rem; }

.planning-month { width: 100%; table-layout: fixed; border-collapse: collapse; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; }
.planning-month th { padding: 0.375rem 0.25rem; font-size: 0.8125rem; font-weight: 600; color: var(--muted); text-align: center; }
.planning-month abbr { text-decoration: none; }
.planning-month th.planning-week-number, .planning-month thead th.planning-week-number { width: 2.75rem; font-size: 0.6875rem; font-weight: 500; }
.planning-month tbody th.planning-week-number { border-top: 1px solid var(--border); vertical-align: top; padding-top: 0.5rem; }
.planning-day { position: relative; height: 8rem; padding: var(--planning-cell-pad); border-top: 1px solid var(--border); border-left: 1px solid var(--border); vertical-align: top; overflow: hidden; }
.planning-day.is-outside { background: var(--bg); }
.planning-day.is-outside .planning-day-number { color: var(--muted); font-weight: 400; }
/* Jour hors plage synchronisée, coquille hors ligne uniquement (LIFE-311) : le mois reste entier, ce jour précis n'a aucune donnée. */
.planning-day.is-unavailable { background: repeating-linear-gradient(135deg, var(--bg) 0 6px, var(--surface) 6px 12px); }
.planning-day.is-unavailable .planning-day-number { display: inline-flex; align-items: center; justify-content: center; min-width: 1.625rem; height: 1.625rem; padding: 0 0.25rem; color: var(--muted); font-size: 0.875rem; font-weight: 400; }
.planning-day.is-selected { box-shadow: inset 0 0 0 2px var(--accent); }
.planning-day-link { display: block; color: var(--text); text-decoration: none; border-radius: 6px; text-align: center; }
/* Toute la cellule est la zone de sélection (tactile et souris) ; le lien reste le seul élément focusable du jour. */
.planning-day-link::after { content: ""; position: absolute; inset: 0; }
.planning-day-link:focus-visible { outline: none; }
.planning-day-link:focus-visible::after { outline: 2px solid var(--accent); outline-offset: -3px; border-radius: 4px; }
.planning-day-number { display: inline-flex; align-items: center; justify-content: center; min-width: 1.625rem; height: 1.625rem; padding: 0 0.25rem; border-radius: 999px; font-size: 0.875rem; font-weight: 600; }
.planning-day.is-today .planning-day-number { background: var(--accent-bg); color: var(--on-accent); }
/* LIFE-319.1 : numéro et étoile dans deux RANGÉES DE GRILLE distinctes (jamais un simple décalage en pixels) — l'étoile occupe
   toujours la rangée du haut (hauteur fixe, réservée même quand l'étoile est absente hors ligne — jour non marqué), le numéro la
   rangée du bas, centré sur toute la largeur de la cellule. Séparation géométrique : aucune intersection possible, même sur une
   colonne très étroite (320 px), avec ou sans étoile. */
.planning-day-head { position: relative; display: grid; grid-template-rows: 1.25rem auto; row-gap: 0; }
.planning-day-head .planning-day-link { grid-row: 2; justify-self: center; }
.planning-highlight-form { display: contents; }
/* Hors de la grille Mois (Semaine / Agenda / Chrono), l'étoile reste un simple élément de la ligne d'en-tête (comportement d'origine,
   jamais en absolu : elle serait alors positionnée par rapport à un ancêtre lointain, hors de sa ligne). */
.planning-highlight-star { position: relative; top: -0.0625rem; z-index: 1; display: inline-flex; align-items: center; justify-content: center; min-width: 1.25rem; min-height: 1.25rem; padding: 0; margin: 0; border: 0; background: none; font-size: 0.875rem; line-height: 1; color: var(--muted); cursor: pointer; border-radius: 4px; }
.planning-day-head .planning-highlight-star { grid-row: 1; justify-self: end; align-self: start; position: static; top: auto; }
.planning-highlight-star.is-on { color: var(--planning-highlight); }
.planning-highlight-star.is-static { cursor: default; }
.planning-highlight-star:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.planning-day-custody { position: relative; display: flex; flex-direction: column; gap: 3px; margin: 0.25rem 0 0; padding: 0; list-style: none; pointer-events: none; }
.planning-custody-line { display: flex; align-items: baseline; gap: 0.25rem; min-width: 0; height: 1.375rem; padding: 0 0.375rem; border-left: 4px solid var(--child-color); border-radius: 4px; background: color-mix(in srgb, var(--child-color) 14%, var(--surface)); font-size: 0.75rem; line-height: 1.375rem; white-space: nowrap; overflow: hidden; }
.planning-custody-line.is-empty { visibility: hidden; }
.planning-custody-child { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; font-weight: 600; }
.planning-custody-summary { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* Continuité d'une même période d'un jour à l'autre : barre prolongée jusqu'au bord de la cellule, sans coin arrondi. */
.planning-custody-line.continues-from { margin-left: calc(-1 * var(--planning-cell-pad)); border-top-left-radius: 0; border-bottom-left-radius: 0; }
.planning-custody-line.continues-to { margin-right: calc(-1 * var(--planning-cell-pad)); border-top-right-radius: 0; border-bottom-right-radius: 0; }
.planning-custody-line.continues-from:not(.has-switch) .planning-custody-child { font-weight: 500; }
/* Jour avec bascule (LIFE-311) : deux lignes au plus, quel que soit le prénom des parents — une cellule ne doit jamais grandir sans
   limite (le texte complet reste dans l'attribut title et dans le détail du jour sous la grille). */
.planning-custody-line.has-switch { display: block; height: auto; max-height: 2.6rem; padding-top: 1px; padding-bottom: 1px; line-height: 1.25; white-space: normal; overflow: hidden; }
.planning-custody-line.has-switch .planning-custody-summary { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; white-space: normal; overflow-wrap: anywhere; }
/* LIFE-312 : variante d'exception nettement plus visible qu'un simple hachurage — une couleur dérivée de celle de l'enfant (jamais
   codée en dur), plus sombre en thème clair et plus claire en thème sombre (contraste lisible dans les deux cas) ; le hachurage et le
   symbole ◇ restent l'indicateur non colorimétrique (accessibilité, daltonisme). */
:root { --child-color-exception: color-mix(in srgb, var(--child-color, #4C6EF5) 60%, black); }
:root[data-theme="dark"] { --child-color-exception: color-mix(in srgb, var(--child-color, #4C6EF5) 55%, white); }
.planning-custody-line.is-exception { border: 1.5px dashed var(--child-color-exception); border-left: 4px solid var(--child-color-exception); background: repeating-linear-gradient(135deg, color-mix(in srgb, var(--child-color-exception) 24%, var(--surface)) 0 4px, color-mix(in srgb, var(--child-color-exception) 10%, var(--surface)) 4px 8px); }
.planning-exception-mark { flex: 0 0 auto; font-size: 0.75rem; }
.planning-custody-line[hidden], .planning-detail-child[hidden] { display: none; }

.planning-day-details { margin-top: 1rem; }
.planning-day-detail h2 { margin-top: 0; font-size: 1.125rem; }
.planning-detail-list { margin: 0; padding: 0; list-style: none; }
.planning-detail-child { padding: 0.625rem 0 0.625rem 0.75rem; border-left: 4px solid var(--child-color); margin-bottom: 0.5rem; }
.planning-detail-head { display: flex; align-items: center; gap: 0.5rem; }
.planning-detail-head a { flex: 0 0 auto; margin-left: auto; font-size: 0.875rem; }
.planning-detail-head strong { min-width: 0; overflow-wrap: anywhere; }
.planning-detail-segments { margin: 0.375rem 0 0; padding: 0; list-style: none; }
.planning-detail-segments li { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.5rem; min-height: 32px; }
.planning-detail-segments li.is-exception { padding: 0 0.375rem; border: 1.5px dashed var(--child-color); border-radius: 6px; }
.planning-detail-hours { min-width: 6.5rem; font-variant-numeric: tabular-nums; color: var(--muted); }
.planning-exception-badge { border-style: dashed; }

/* Mobile : vraie mini-grille (numéro du jour + points de couleur), le détail du jour choisi s'affiche dessous. */
@media (max-width: 767px) {
  .planning-calendar { --planning-cell-pad: 0.125rem; }
  .planning-month th { padding: 0.25rem 0; font-size: 0.75rem; }
  .planning-month th.planning-week-number, .planning-month thead th.planning-week-number { width: 1.875rem; font-size: 0.625rem; }
  /* LIFE-319 : quelques pixels de plus (3.5rem -> 3.75rem) pour laisser l'étoile respirer sans toucher le numéro ni les pastilles. */
  .planning-day { height: 3.75rem; text-align: center; }
  .planning-day-number { min-width: 1.75rem; height: 1.75rem; font-size: 0.875rem; }
  /* LIFE-319.1 : rangée de l'étoile plus compacte sur mobile (place limitée dans une cellule de 3.75rem) — taille tactile réduite
     mais toujours utilisable, jamais de chevauchement possible puisque la séparation est géométrique (rangées), pas par pixels. */
  .planning-day-head { grid-template-rows: 1rem auto; }
  .planning-day-head .planning-highlight-star { min-width: 1rem; min-height: 1rem; font-size: 0.75rem; }
  .planning-day-custody { flex-direction: row; justify-content: center; gap: 3px; margin-top: 0.125rem; }
  .planning-custody-line { width: 8px; height: 8px; padding: 0; margin: 0 !important; border: 0; border-radius: 50%; background: var(--child-color); font-size: 0; }
  .planning-month .planning-day .planning-custody-line { height: 8px; min-height: 0; padding: 0; border-radius: 50%; }
  .planning-custody-line > * { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .planning-custody-line.is-empty, .planning-custody-line:nth-child(n + 4) { display: none; }
  /* Exception : point creux (forme différente, pas seulement la couleur). */
  .planning-month .planning-day .planning-custody-line.is-exception { border: 2px solid var(--child-color-exception); background: var(--surface); }
}

/* ----- Contexte du calendrier (LIFE-303) : vacances scolaires et jours fériés, toujours derrière les gardes. Vacances = teinte très
   légère de la cellule + pastille de zone (lettre) ; jour férié = étoile ★ + nom. Formes différentes, jamais le rouge d'erreur. */
/* LIFE-312 : filtre vacances déplacé sous le calendrier (plus d'encombrement au-dessus, avec le filtre enfants). */
.planning-zone-chip { display: inline-flex; align-items: center; gap: 0.25rem; min-height: 36px; margin: 0; padding: 0 0.625rem; border: 1px solid var(--border); border-radius: 999px; background: var(--surface); font-size: 0.875rem; cursor: pointer; }
.planning-zone-chip input { width: auto; margin: 0; }
.planning-zone-letter { display: inline-flex; align-items: center; justify-content: center; min-width: 1.25rem; height: 1.125rem; padding: 0 0.25rem; border: 1px solid var(--muted); border-radius: 4px; font-size: 0.6875rem; font-weight: 700; color: var(--text); background: var(--surface); }
.planning-legend-public { display: inline-flex; align-items: center; gap: 0.25rem; font-size: 0.85rem; color: var(--muted); }
.planning-public-mark { color: var(--accent); font-size: 0.8125rem; line-height: 1; }
.planning-holiday-missing { margin: 0.375rem 0 0; font-size: 0.85rem; }

.planning-day-context { position: absolute; top: 0.3125rem; right: 0.25rem; left: 2.25rem; display: flex; flex-wrap: nowrap; justify-content: flex-end; align-items: center; gap: 3px; pointer-events: none; overflow: hidden; }
.planning-public-holiday { display: inline-flex; align-items: center; gap: 2px; min-width: 0; font-size: 0.6875rem; color: var(--muted); white-space: nowrap; }
.planning-public-holiday-name { overflow: hidden; text-overflow: ellipsis; }
.planning-holiday-zone { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; min-width: 1.125rem; height: 1rem; padding: 0 3px; border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--border)); border-radius: 4px; font-size: 0.625rem; font-weight: 700; color: var(--muted); background: var(--surface); }
.planning-holiday-zone[hidden], .planning-detail-context[hidden] { display: none; }
/* Teinte de vacances (au moins une zone affichée) : très légère, la garde reste au premier plan. */
.planning-day:has(.planning-holiday-zone:not([hidden])) { background: color-mix(in srgb, var(--accent) 6%, var(--surface)); }
.planning-day.is-outside:has(.planning-holiday-zone:not([hidden])) { background: color-mix(in srgb, var(--accent) 5%, var(--bg)); }
.planning-detail-context { display: flex; align-items: center; gap: 0.5rem; margin: 0 0 0.375rem; font-size: 0.9375rem; color: var(--muted); }

@media (max-width: 767px) {
  /* Mini-grille : étoile au coin du jour, fins traits de zone sous le numéro — aucun texte long. */
  .planning-day-context { top: 3px; right: auto; left: 1px; flex-direction: column; align-items: center; justify-content: flex-start; gap: 2px; }
  .planning-day-number { min-width: 1.5rem; height: 1.5rem; }
  .planning-public-holiday-name { display: none; }
  .planning-public-mark { font-size: 0.5625rem; }
  .planning-holiday-zone { min-width: 0; width: 5px; height: 5px; padding: 0; border: 0; border-radius: 1px; background: color-mix(in srgb, var(--accent) 55%, var(--surface)); font-size: 0; }
  .planning-holiday-zone > * { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}

/* ----- Statistiques de garde (LIFE-304) : largeur raisonnable, couleur de l'enfant en accent du bloc seulement ; barres neutres
   (deux styles : plein / hachuré), décoratives, les chiffres restent en texte. */
.planning-stats-children { margin-bottom: 0.5rem; }
.planning-stats-child { gap: 0.375rem; max-width: 100%; border-left: 4px solid var(--child-color); overflow-wrap: anywhere; }
.planning-stats-card ~ p { overflow-wrap: anywhere; }
.planning-stats-child .planning-child-swatch, .planning-stats-card .planning-child-swatch { background-color: var(--child-color); }
.planning-stats-toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.5rem 1rem; margin-bottom: 0.75rem; }
.planning-stats-toolbar .chips { margin: 0; }
.planning-stats-card { max-width: 760px; border-top: 4px solid var(--child-color, var(--border)); }
.planning-stats-card h2 { margin-top: 0; }
.planning-stats-shares { margin: 0 0 1rem; padding: 0; list-style: none; }
.planning-stats-share { margin-bottom: 0.875rem; }
.planning-stats-share-line { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 0.75rem; }
.planning-stats-share-line strong { flex: 1 1 8rem; min-width: 0; overflow-wrap: anywhere; }
.planning-stats-days { font-variant-numeric: tabular-nums; font-weight: 600; }
.planning-stats-percent { min-width: 4.5rem; text-align: right; font-variant-numeric: tabular-nums; color: var(--muted); }
.planning-stats-bar { height: 10px; margin-top: 0.375rem; border-radius: 999px; background: var(--hover); overflow: hidden; }
.planning-stats-bar > span { display: block; height: 100%; border-radius: 999px; background: color-mix(in srgb, var(--text) 70%, var(--surface)); }
.planning-stats-share.is-alternate .planning-stats-bar > span { background: repeating-linear-gradient(135deg, color-mix(in srgb, var(--text) 55%, var(--surface)) 0 4px, color-mix(in srgb, var(--text) 30%, var(--surface)) 4px 8px); }
.planning-stats-totals { margin-bottom: 0.5rem; }
.planning-stats-empty { font-weight: 600; }
.planning-stats-note { font-size: 0.85rem; }
.planning-stats-table-scroll { max-width: 100%; overflow-x: auto; }
.planning-stats-table-scroll:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.planning-stats-months { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.planning-stats-months th, .planning-stats-months td { padding: 0.4rem 0.5rem; border-bottom: 1px solid var(--border); text-align: right; white-space: nowrap; }
.planning-stats-months th:first-child { text-align: left; }
.planning-stats-months thead th { font-size: 0.8125rem; color: var(--muted); }
.planning-stats-months tfoot th, .planning-stats-months tfoot td { font-weight: 700; border-bottom: 0; }
@media (max-width: 767px) { .planning-stats-months th, .planning-stats-months td { padding: 0.35rem 0.375rem; font-size: 0.875rem; } }

/* Événements familiaux (LIFE-305) : sous les gardes, plus discrets (ligne fine, fond de surface) ; un enfant = sa couleur en
   accent ; plusieurs enfants = accent neutre + petits points ; foyer = accent neutre double + ⌂. Deux au plus par cellule (desktop). */
.planning-day-events { display: flex; flex-direction: column; gap: 2px; margin: 3px 0 0; padding: 0; list-style: none; pointer-events: none; }
.planning-event-line { display: flex; align-items: center; gap: 0.25rem; min-width: 0; height: 1.125rem; padding: 0 0.3125rem; border: 1px solid var(--border); border-left: 3px solid var(--child-color, var(--muted)); border-radius: 4px; background: var(--surface); font-size: 0.6875rem; line-height: 1.125rem; white-space: nowrap; overflow: hidden; }
.planning-event-line:nth-child(n + 3), .planning-event-line[hidden] { display: none; }
.planning-event-line.is-multi { border-left-color: var(--muted); }
.planning-event-line.is-household { border-left: 3px double var(--muted); }
.planning-event-line.continues-from { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.planning-event-line.continues-to { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.planning-event-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.planning-event-icon { flex: 0 0 auto; color: var(--muted); }
.planning-event-dots { flex: 0 0 auto; display: inline-flex; gap: 2px; }
.planning-event-dots > span, .family-event-chip .planning-child-swatch, .family-event-child .planning-child-swatch { display: inline-block; background-color: var(--child-color); }
.planning-event-dots > span { width: 6px; height: 6px; border-radius: 50%; }
.planning-event-more { display: block; margin-top: 1px; font-size: 0.6875rem; color: var(--muted); pointer-events: none; }
.planning-event-mark { display: none; }

.planning-detail-subtitle { margin: 0.75rem 0 0.375rem; font-size: 1rem; }
.planning-detail-events { margin: 0 0 0.5rem; padding: 0; list-style: none; }
.planning-detail-event { padding: 0.5rem 0 0.5rem 0.75rem; margin-bottom: 0.375rem; border-left: 4px solid var(--child-color, var(--muted)); }
.planning-detail-event.is-household { border-left-style: double; }
.planning-detail-event[hidden] { display: none; }
.planning-detail-event-head { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.5rem; min-height: 32px; }
.planning-detail-event-title { font-weight: 600; overflow-wrap: anywhere; }
.planning-detail-event-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.5rem; font-size: 0.875rem; }
.planning-detail-location { color: var(--muted); overflow-wrap: anywhere; }
.planning-detail-add { margin: 0.25rem 0 0.75rem; }
/* LIFE-318 : actions du détail du jour en petits boutons discrets (bordure légère, fond neutre) — jamais un gros bouton bleu
   dominant comme + Événement / + Exception de l'en-tête. */
.planning-detail-action { min-height: 36px; margin-top: 0; padding: 0.375rem 0.75rem; border-radius: 999px; font-size: 0.875rem; background: var(--surface); }
.planning-detail-action:hover { background: var(--hover); }
/* LIFE-318 : « + Exception » près de « + Événement », visible seulement si au moins un enfant visible est éditable ; même
   mécanique de popup que les filtres (section 2) quand plusieurs enfants sont proposés au choix. */
.planning-exception-chooser .planning-filter-panel { display: flex; flex-direction: column; align-items: stretch; gap: 0.25rem; min-width: 10rem; }
.planning-exception-chooser .planning-filter-panel a { padding: 0.375rem 0.5rem; border-radius: 6px; color: var(--text); text-decoration: none; }
.planning-exception-chooser .planning-filter-panel a:hover { background: var(--hover); }
.planning-exception-chooser > summary.button { list-style: none; cursor: pointer; }
.planning-exception-chooser > summary.button::-webkit-details-marker { display: none; }
.family-event-chips { display: inline-flex; flex-wrap: wrap; gap: 0.375rem; }
.family-event-chip { display: inline-flex; align-items: center; gap: 0.3125rem; padding: 0.125rem 0.5rem; border: 1px solid var(--border); border-left: 3px solid var(--child-color); border-radius: 999px; font-size: 0.875rem; }
.family-event-chip .planning-child-swatch { width: 12px; height: 12px; border-width: 1px; }
.family-event-household { font-size: 0.8125rem; }

.family-event-card { border-top: 4px solid var(--child-color, var(--border)); }
.family-event-card.is-household { border-top-style: double; border-top-color: var(--muted); }
/* Titre libre jusqu'à 200 caractères (LIFE-311) : taille de titre de page normale, mais plafonnée pour qu'un titre très long
   reste dense (texte complet toujours affiché, seule la taille change) au lieu d'occuper tout l'écran. */
.family-event-title { margin: 0 0 0.25rem; font-size: 1.375rem; line-height: 1.3; overflow-wrap: anywhere; }
.family-event-notes-title { margin: 1rem 0 0.25rem; font-size: 1rem; }
.family-event-notes { margin: 0 0 1rem; white-space: pre-wrap; overflow-wrap: anywhere; }
.family-event-dates { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 0.75rem; }
.family-event-dates input { width: 100%; min-width: 0; }
.family-event-hint { margin: 0.25rem 0 0; font-size: 0.85rem; }
.family-event-child { gap: 0.375rem; }
.family-event-child .planning-child-swatch { width: 14px; height: 14px; }
.family-event-child.is-locked { display: flex; align-items: center; margin: 0.5rem 0 0; }
.family-event-form textarea { width: 100%; max-width: 100%; }
/* Sans JavaScript : champs inutiles masqués selon les choix (journée entière, foyer, sans répétition). */
.family-event-form:has(input[name="Form.IsAllDay"]:checked) .family-event-time { display: none; }
.family-event-form:has(input[name="Form.Scope"][value="household"]:checked) .family-event-children { display: none; }
.family-event-form:has(select[name="Form.Repeat"] option[value="None"]:checked) .family-event-repeat-end { display: none; }

@media (max-width: 767px) {
  .planning-day-events, .planning-event-more { display: none; }
  /* Indicateur compact : un trait (forme distincte des points de garde), le nombre en texte accessible. */
  .planning-event-mark { display: block; width: 14px; height: 3px; margin: 3px auto 0; border-radius: 2px; background: color-mix(in srgb, var(--text) 70%, var(--surface)); pointer-events: none; }
}
@media (max-width: 420px) { .family-event-dates { grid-template-columns: minmax(0, 1fr); } }

/* Vues Semaine, Agenda et Chrono (LIFE-306) : cartes LIFE, couleurs des enfants, exceptions hachurées (clair / sombre), aucune
   bibliothèque. Semaine : 7 colonnes sur grand écran, jours empilés sinon ; Agenda et Chrono : colonne centrale confortable. */
.planning-view-period { display: block; font-size: 0.95rem; font-weight: 500; color: var(--muted); }
.planning-today-badge { margin-left: 0.5rem; vertical-align: middle; background: var(--accent-bg); color: var(--on-accent); border-color: transparent; }
.planning-view-empty, .planning-view-limit { margin: 1rem 0; }

.planning-week-days { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0.75rem; margin: 0; padding: 0; list-style: none; }
@media (min-width: 1200px) {
  .planning-week-days { grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 0.5rem; }
  /* Journée chargée : la carte défile verticalement, la semaine garde une hauteur raisonnable. */
  .planning-week-day-body { max-height: 32rem; overflow-y: auto; }
}
.planning-week-day { margin: 0; padding: 0.75rem; min-width: 0; }
.planning-week-day.is-today { box-shadow: inset 0 0 0 2px var(--accent); }
.planning-week-day-heading { display: flex; align-items: baseline; gap: 0.25rem; margin: 0 0 0.5rem; min-width: 0; }
/* LIFE-319 : « Vendredi 16 octobre » ne doit jamais se couper au milieu (« 16 » / « octobre » sur deux lignes) — chaque morceau
   (jour, date) reste entier ; seul un retour à la ligne ENTRE les deux est permis, colonne 7 du desktop trop étroite oblige. Sur
   mobile (une seule colonne, pleine largeur), les deux tiennent toujours sur une même ligne. */
.planning-week-day-title { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.125rem 0.375rem; margin: 0; font-size: 1rem; min-width: 0; }
.planning-week-day-name, .planning-week-day-date { white-space: nowrap; }
.planning-week-day-date { font-weight: 500; color: var(--muted); }
.planning-week-day-heading .planning-highlight-star { flex: 0 0 auto; }
.planning-week-custody, .planning-week-events { display: flex; flex-direction: column; gap: 0.3125rem; margin: 0 0 0.5rem; padding: 0; list-style: none; }
.planning-week-custody-line { display: flex; align-items: flex-start; gap: 0.25rem; padding: 0.25rem 0.5rem; border-left: 4px solid var(--child-color); border-radius: 6px; background: color-mix(in srgb, var(--child-color) 14%, var(--surface)); font-size: 0.875rem; overflow-wrap: anywhere; }
.planning-week-custody-text, .planning-week-event a { display: flex; flex-wrap: wrap; gap: 0 0.375rem; min-width: 0; color: var(--text); text-decoration: none; }
.planning-week-custody-line.is-exception { border: 1.5px dashed var(--child-color-exception); border-left: 4px solid var(--child-color-exception); background: repeating-linear-gradient(135deg, color-mix(in srgb, var(--child-color-exception) 24%, var(--surface)) 0 4px, color-mix(in srgb, var(--child-color-exception) 10%, var(--surface)) 4px 8px); }
.planning-week-event { padding: 0.25rem 0.5rem; border: 1px solid var(--border); border-left: 3px solid var(--child-color, var(--muted)); border-radius: 6px; background: var(--surface); font-size: 0.875rem; overflow-wrap: anywhere; }
.planning-week-event.is-multi { border-left-color: var(--muted); }
.planning-week-event.is-household { border-left: 3px double var(--muted); }
.planning-week-event-time { font-variant-numeric: tabular-nums; color: var(--muted); }
.planning-week-event-title { font-weight: 600; }
.planning-week-event-meta { display: flex; flex-wrap: wrap; gap: 0.25rem; margin-top: 0.25rem; font-size: 0.8125rem; }
.planning-week-event a:hover { text-decoration: underline; }
.planning-week-event a:focus-visible, .planning-item-title:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.planning-week-custody-line[hidden], .planning-week-event[hidden], .planning-item[hidden] { display: none; }

.planning-list-view { max-width: 760px; }
.planning-agenda-day { padding: 0.75rem 1rem; }
.planning-agenda-day.is-today { box-shadow: inset 0 0 0 2px var(--accent); }
.planning-agenda-day-heading { display: flex; align-items: baseline; gap: 0.25rem; margin: 0 0 0.5rem; }
.planning-agenda-day h2 { margin: 0; font-size: 1.0625rem; }
.planning-items { margin: 0; padding: 0; list-style: none; }
.planning-item { display: grid; grid-template-columns: 4.25rem 1.25rem minmax(0, 1fr); gap: 0 0.5rem; align-items: baseline; padding: 0.4375rem 0; border-top: 1px solid var(--border); }
.planning-items > .planning-item:first-child { border-top: 0; }
.planning-item-time { font-variant-numeric: tabular-nums; font-weight: 600; font-size: 0.9375rem; }
.planning-item-icon { text-align: center; color: var(--child-color, var(--muted)); }
.planning-item-body { min-width: 0; overflow-wrap: anywhere; }
.planning-item-title { font-weight: 600; color: var(--text); }
a.planning-item-title { text-decoration: none; }
a.planning-item-title:hover { text-decoration: underline; }
.planning-item-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.5rem; margin-top: 0.125rem; font-size: 0.875rem; color: var(--muted); }
.planning-item.is-custody .planning-item-body, .planning-item.is-custody-state .planning-item-body { padding-left: 0.5rem; border-left: 4px solid var(--child-color); }
.planning-item.is-exception .planning-item-body { border: 1.5px dashed var(--child-color-exception); border-left: 4px solid var(--child-color-exception); border-radius: 6px; padding: 0.25rem 0.5rem; background: repeating-linear-gradient(135deg, color-mix(in srgb, var(--child-color-exception) 22%, var(--surface)) 0 4px, color-mix(in srgb, var(--child-color-exception) 9%, var(--surface)) 4px 8px); }
.planning-item.is-event.is-multi .planning-item-icon, .planning-item.is-household .planning-item-icon, .planning-item.is-public-holiday .planning-item-icon, .planning-item.is-school-holiday .planning-item-icon { color: var(--muted); }
.planning-item.is-public-holiday .planning-item-icon { color: var(--accent); }

/* Chrono : rail vertical et un point par jour ; la liste ordonnée reste compréhensible sans CSS. */
.planning-timeline { margin: 0; padding: 0; list-style: none; }
.planning-timeline-day { position: relative; margin: 0; padding: 0 0 1rem 1.5rem; border-left: 2px solid var(--border); }
.planning-timeline-day::before { content: ""; position: absolute; left: -7px; top: 0.3rem; width: 12px; height: 12px; border-radius: 50%; background: var(--surface); border: 2px solid var(--muted); }
.planning-timeline-day.is-today::before { background: var(--accent); border-color: var(--accent); }
.planning-timeline-heading { display: flex; align-items: baseline; gap: 0.25rem; margin: 0 0 0.375rem; }
.planning-timeline-label { margin: 0; font-size: 1.0625rem; }
.planning-timeline-items { padding: 0.25rem 0.75rem; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); }

@media (max-width: 420px) {
  .planning-item { grid-template-columns: 3.5rem 1rem minmax(0, 1fr); gap: 0 0.375rem; }
  .planning-item-time { font-size: 0.875rem; }
  .planning-timeline-day { padding-left: 1rem; }
  .planning-timeline-items { padding: 0.125rem 0.5rem; }
}
/* Semaine, colonnes étroites : contexte en ligne (lettre de zone puis texte), pastilles d'enfants compactes, jamais coupées dans un mot. */
.planning-week-day .planning-detail-context { display: block; margin: 0 0 0.25rem; font-size: 0.8125rem; line-height: 1.35; }
.planning-week-day .planning-detail-context .planning-zone-letter, .planning-week-day .planning-detail-context .planning-public-mark { margin-right: 0.25rem; }
.planning-week-event .family-event-chip { max-width: 100%; padding: 0 0.375rem; font-size: 0.75rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.planning-week-event .family-event-chip .planning-child-swatch { width: 9px; height: 9px; }

/* Pièces jointes et navigation (LIFE-307) : liste sobre, cibles tactiles ≥ 40 px, noms longs coupés proprement, aucun débordement. */
.family-event-maps { display: flex; flex-wrap: wrap; align-items: center; gap: 0.375rem 0.5rem; margin-top: 0.5rem; }
.family-event-maps-label { width: 100%; font-size: 0.85rem; color: var(--muted); }
.family-event-map { margin: 0; min-height: 40px; display: inline-flex; align-items: center; padding: 0 0.875rem; }
.family-event-attachments { margin: 1rem 0; }
.family-event-attachment-list { margin: 0 0 0.75rem; padding: 0; list-style: none; }
.family-event-attachment { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.75rem; padding: 0.5rem 0; border-top: 1px solid var(--border); }
.family-event-attachment:first-child { border-top: 0; }
.family-event-attachment-icon { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 2.5rem; height: 2rem; border: 1px solid var(--border); border-radius: 6px; font-size: 0.6875rem; font-weight: 700; color: var(--muted); }
.family-event-attachment-body { flex: 1 1 12rem; min-width: 0; display: flex; flex-direction: column; }
.family-event-attachment-name { font-weight: 600; overflow-wrap: anywhere; }
.family-event-attachment-meta { font-size: 0.8125rem; }
.family-event-attachment-delete { flex: 0 0 auto; }
.family-event-attachment-delete summary { cursor: pointer; min-height: 40px; display: inline-flex; align-items: center; color: var(--danger, #c92a2a); }
.family-event-attachment-delete form { margin: 0.25rem 0 0; }
.family-event-upload { display: grid; gap: 0.375rem; max-width: 100%; }
.family-event-upload input[type="file"] { max-width: 100%; min-width: 0; }
.family-event-upload button { justify-self: start; }
.family-event-attachment-delete { max-width: 100%; }
.family-event-attachment-delete:not([open]) form { display: none; }
.family-event-attachment-delete[open] { flex: 1 1 100%; }
.family-event-attachment-delete button { max-width: 100%; white-space: normal; }

/* Notifications Planning (LIFE-308) : délai atténué (mais utilisable et conservé) quand les rappels sont désactivés. */
.planning-notifications-form fieldset { margin-top: 0.75rem; }
.planning-notifications-delay { margin: 0.5rem 0 0 1.75rem; }
.planning-notifications-delay select { max-width: 100%; }
.planning-notifications-form:has([data-reminder-toggle]:not(:checked)) .planning-notifications-delay { opacity: 0.65; }
.planning-notifications-hint { font-size: 0.85rem; }
.planning-notification-log { margin: 0; padding-left: 1.1rem; overflow-wrap: anywhere; }
.planning-notification-log li { margin: 0.25rem 0; }
@media (max-width: 420px) { .planning-notifications-delay { margin-left: 0; } }

/* Planning hors ligne V1 (LIFE-309, lecture seule) : ligne d'état compacte (même gabarit que Shopping), messages de période
   indisponible, section Mon compte → Planning hors ligne. */
.planning-offline-status { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.25rem 0.5rem; margin: 0.25rem 0 0.5rem; padding: 0.25rem 0.625rem; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); color: var(--muted); font-size: 0.8125rem; line-height: 1.35; overflow-wrap: anywhere; }
.planning-offline-status[hidden] { display: none; }
.planning-offline-status.is-offline { border-color: var(--muted); }
.planning-offline-status.is-error { border-color: var(--danger); color: var(--error-text); background: var(--error-bg); }
.planning-offline-retry { flex: 0 0 auto; min-height: 28px; margin: 0; padding: 0 0.625rem; border: 1px solid var(--border); border-radius: 999px; background: var(--surface); color: var(--accent); font-size: 0.8125rem; font-weight: 600; cursor: pointer; }
.offline-shell .planning-offline-status { margin-top: 0.5rem; }
.planning-offline-unavailable { margin: 1rem 0 0.25rem; font-weight: 600; }
.planning-offline-coverage { margin: 0.25rem 0 0.5rem; font-size: 0.85rem; }
.planning-offline-settings-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.planning-offline-settings-actions button { margin: 0; }
.planning-offline-settings-hint { font-size: 0.85rem; }

/* Navigation minimale de la coquille Planning hors ligne (LIFE-311) : seules les autres pages réellement utilisables sans réseau. */
.offline-shell-nav { display: flex; gap: 1rem; padding: 0.5rem 1rem; background: var(--surface); border-bottom: 1px solid var(--border); font-size: 0.9375rem; }
.offline-shell-nav a { min-height: 32px; display: inline-flex; align-items: center; color: var(--accent); text-decoration: none; }
.offline-shell-nav a:hover, .offline-shell-nav a:focus-visible { text-decoration: underline; }
