:root {
  --bg: #f6f2ea;
  --surface: #ffffff;
  --surface-alt: #f0eae0;
  --text: #262019;
  --text-muted: #8a8074;
  --border: #e6dfd0;

  --primary: #b1552e;
  --primary-dark: #8f421f;
  --primary-soft: #f0e0d5;

  --success: #5c7c58;
  --success-dark: #45603f;
  --success-soft: #e6ece3;

  --danger: #ad4a3f;
  --danger-dark: #8a3a30;
  --danger-soft: #f1e2df;

  --pending: #ab8a3d;
  --pending-dark: #8a6d2e;
  --pending-soft: #f2ebd9;

  --chart-earned: var(--primary);
  --chart-spent: #2a7ab8;
  --chart-axis: var(--border);

  --font-display: Georgia, 'Iowan Old Style', 'Times New Roman', ui-serif, serif;
  --font-body: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;

  --radius-lg: 20px;
  --radius-md: 14px;
  --radius-sm: 10px;
  --shadow: 0 1px 2px rgba(38, 32, 25, 0.04), 0 8px 20px rgba(38, 32, 25, 0.05);
  --overlay: rgba(38, 32, 25, 0.5);
  --touch: 84px;
}

/* ==========================================================================
   Theme "Explorateur" — univers enfant (index.html, kid.html uniquement).
   Applique via <body data-theme="explorer">. L'espace parent garde le theme
   par defaut ci-dessus. Les composants reutilisent les memes noms de
   variables : la plupart des styles se re-habillent automatiquement.
   ========================================================================== */
[data-theme='explorer'] {
  --bg: #faf7ef;
  --surface: #ffffff;
  --surface-alt: #f2eee0;
  --text: #263b43;
  --text-muted: #718087;
  --border: #eae4d4;

  --primary: #269f9a;
  --primary-dark: #285c60;
  --primary-soft: #dcf0ee;

  --success: #54c6a4;
  --success-dark: #2e8c77;
  --success-soft: #e1f6ef;

  --danger: #e4664f;
  --danger-dark: #b94b39;
  --danger-soft: #fbe4df;

  --pending: #ffd166;
  --pending-dark: #9c7218;
  --pending-soft: #fff3d6;

  --chart-earned: var(--primary);
  --chart-spent: #5ba7e6;
  --chart-axis: var(--border);

  --font-display: 'Nunito', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-body: 'Nunito', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  --radius-lg: 26px;
  --radius-md: 20px;
  --radius-sm: 14px;
  --shadow: 0 2px 5px rgba(38, 59, 67, 0.05), 0 8px 20px rgba(38, 59, 67, 0.06);
  --overlay: rgba(20, 35, 40, 0.55);

  /* Categories de routine : couleur + fond doux, stables dans toute l'app. */
  --cat-matin: #ffd166;
  --cat-matin-dark: #9c7218;
  --cat-matin-soft: #fff3d6;
  --cat-ecole: #5ba7e6;
  --cat-ecole-dark: #2c6ca0;
  --cat-ecole-soft: #e3f1fc;
  --cat-maison: #7fbe45;
  --cat-maison-dark: #4c7a26;
  --cat-maison-soft: #ecf6e1;
  --cat-soir: #269f9a;
  --cat-soir-dark: #285c60;
  --cat-soir-soft: #dcf0ee;
  --cat-recompense: #ff965f;
  --cat-recompense-dark: #c9622f;
  --cat-recompense-soft: #ffe9dc;
}

/* ==========================================================================
   Theme nuit — meme univers "Explorateur", palette sombre. Applique en plus
   (pas a la place) via <body data-theme="explorer" data-mode="night">, active
   automatiquement selon la plage horaire choisie sur l'ecran d'accueil ET la
   page enfant (voir index.html/kid.html), reglable depuis l'espace parent.
   Reprend les memes roles de variables que ci-dessus (ex: *-dark reste "texte
   lisible sur *-soft", *-soft reste "fond teinte doux" - simplement inverses
   en clarte pour un fond sombre).
   ========================================================================== */
[data-theme='explorer'][data-mode='night'] {
  --bg: #0f171b;
  --surface: #182229;
  --surface-alt: #202b32;
  --text: #e8edef;
  --text-muted: #8fa2ab;
  --border: #2a363d;

  --primary: #4dd0c7;
  --primary-dark: #bdeeea;
  --primary-soft: #163332;

  --success: #6fd7ae;
  --success-dark: #bdf3da;
  --success-soft: #16332a;

  --danger: #f0876c;
  --danger-dark: #ffd9cd;
  --danger-soft: #3a2018;

  --pending: #ffd166;
  --pending-dark: #ffe9b3;
  --pending-soft: #3a2f10;

  --chart-earned: var(--primary);
  --chart-spent: #7ec2f2;
  --chart-axis: var(--border);

  --shadow: 0 2px 6px rgba(0, 0, 0, 0.35), 0 10px 26px rgba(0, 0, 0, 0.4);
  --overlay: rgba(5, 10, 12, 0.65);

  --cat-matin: #ffd166;
  --cat-matin-dark: #ffe9b3;
  --cat-matin-soft: #3a2f10;
  --cat-ecole: #7ec2f2;
  --cat-ecole-dark: #cfe8fb;
  --cat-ecole-soft: #16262f;
  --cat-maison: #9ad674;
  --cat-maison-dark: #dcf0c4;
  --cat-maison-soft: #212f16;
  --cat-soir: #4dd0c7;
  --cat-soir-dark: #bdeeea;
  --cat-soir-soft: #163332;
  --cat-recompense: #ffb185;
  --cat-recompense-dark: #ffe3d1;
  --cat-recompense-soft: #3a271c;
}

/* Meme theme nuit, pour l'espace parent cette fois (theme par defaut, pas "Explorateur" - voir
   :root en haut de fichier). Applique via <body data-mode="night"> (sans data-theme, l'espace
   parent n'en met jamais) ; specificite plus faible que la regle explorer ci-dessus, donc sans
   conflit meme si les deux selecteurs matchaient un jour la meme page. */
body[data-mode='night'] {
  --bg: #171310;
  --surface: #221d17;
  --surface-alt: #2a231b;
  --text: #ece6db;
  --text-muted: #a89a89;
  --border: #3a3226;

  --primary: #e0895c;
  --primary-dark: #f5c7ab;
  --primary-soft: #3a2418;

  --success: #7fbf76;
  --success-dark: #c9e8c2;
  --success-soft: #1e2f1c;

  --danger: #e4796a;
  --danger-dark: #f8cfc7;
  --danger-soft: #3a211b;

  --pending: #d1ac57;
  --pending-dark: #f5e2b0;
  --pending-soft: #362c14;

  --chart-earned: var(--primary);
  --chart-spent: #6ab0e8;
  --chart-axis: var(--border);

  --shadow: 0 2px 6px rgba(0, 0, 0, 0.35), 0 10px 26px rgba(0, 0, 0, 0.4);
  --overlay: rgba(5, 5, 5, 0.65);
}

/* Fondu entre les pages (index <-> kid.html) : le standard "cross-document view transitions"
   (@view-transition) donnait un rendu saccade - trop de facteurs hors de notre controle (support
   variable selon la version de Chrome, cumul avec les animations d'entree propres a chaque page
   comme .home-heading/.kid-tile qui rejouaient PAR-DESSUS le fondu du navigateur). Remplace par le
   meme mecanisme, simple et maitrise, que la popup liste de courses (opacite + transition CSS,
   classe ajoutee apres un double requestAnimationFrame) : un voile plein ecran qui se dissipe a
   l'arrivee et se referme juste avant de quitter la page. Memes duree/easing que cette popup.
   Voir #page-fade dans index.html et kid.html. */
.page-fade {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--bg);
  opacity: 1;
  pointer-events: none;
  transition: opacity 0.22s ease;
}

.page-fade.hidden {
  opacity: 0;
}

* {
  box-sizing: border-box;
}

/* Logo "Marmailloux" : un M barre de deux traits horizontaux, sur le principe du won (W) ou de l'euro (C).
   Rendu via masque CSS (currentColor) pour heriter la couleur du texte environnant sans dupliquer de SVG. */
.marmailloux-mark {
  display: inline-block;
  width: 1.15em;
  height: 1.15em;
  vertical-align: -0.2em;
  background-color: currentColor;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath d='M8 26 L8 6 L16 26 L24 6 L24 26' fill='none' stroke='%23000' stroke-width='3.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cline x1='0' y1='13' x2='32' y2='13' stroke='%23000' stroke-width='3' stroke-linecap='round'/%3E%3Cline x1='0' y1='19' x2='32' y2='19' stroke='%23000' stroke-width='3' stroke-linecap='round'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath d='M8 26 L8 6 L16 26 L24 6 L24 26' fill='none' stroke='%23000' stroke-width='3.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cline x1='0' y1='13' x2='32' y2='13' stroke='%23000' stroke-width='3' stroke-linecap='round'/%3E%3Cline x1='0' y1='19' x2='32' y2='19' stroke='%23000' stroke-width='3' stroke-linecap='round'/%3E%3C/svg%3E");
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  font-family: var(--font-body);
  background: var(--bg);
  color: var(--text);
  overflow-x: hidden;
  -webkit-user-select: none;
  user-select: none;
  /* Supprime le "flash" de surbrillance natif au tap (parfois lent/en retard sur Android) : le
     retour visuel passe entierement par les etats :active, plus rapides et coherents. */
  -webkit-tap-highlight-color: transparent;
  /* Coupe le delai de detection double-tap avant qu'un tap ne devienne un clic. Deja pose sur
     `button` ; ici en global il couvre aussi les elements tactiles qui ne sont pas des <button>
     (cartes de tache, cases de la semaine). Les zones d'edition texte (.sticky-note*) le
     re-passent a `auto` de leur cote. */
  touch-action: manipulation;
}

/* index.html uniquement (kid.html/parent.html gardent leur defilement normal) : la page elle-meme
   ne doit jamais defiler, seuls l'agenda et la liste de courses defilent en interne (voir
   .today-agenda / .shopping-list-scroll). Un garde-fou en plus de .home{overflow:hidden} - si le
   contenu d'une zone deborde legerement d'un pixel, il est coupe plutot que de faire apparaitre un
   ascenseur sur toute la page. */
body[data-page='home'] {
  overflow: hidden;
}

@keyframes riseIn {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

button {
  font-family: inherit;
  cursor: pointer;
  border: none;
  touch-action: manipulation;
  transition: filter 0.1s ease;
}

/* Retour visuel minimal garanti pour tout bouton, meme ceux sans :active dedie : sur tactile,
   sans le flash natif (retire plus haut), c'est le seul accuse de reception de l'appui. Les gros
   elements ajoutent en plus un leger scale (voir .btn, .pin-key, .kid-tab, .admin-nav button). */
button:active {
  transition-duration: 0s;
  filter: brightness(0.9);
}

button:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}

/* Pendant un appel API en cours (voir guarded() dans parent.html) : le bouton reste bloque contre
   le double-tap mais garde un aspect "en cours" plutot que l'opacite "desactive" (0.45) qui, le
   temps d'un aller-retour vers le VPS, donnait l'impression d'un bouton mort. */
button.btn-busy:disabled {
  opacity: 0.78;
  cursor: progress;
  animation: btnBusyPulse 1.4s ease-in-out infinite;
}

@keyframes btnBusyPulse {
  0%, 100% { opacity: 0.62; }
  50% { opacity: 0.85; }
}

input {
  font-family: inherit;
}

/* ---------- Layout generique ---------- */

.screen {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.top-back {
  position: fixed;
  top: 20px;
  left: 20px;
  z-index: 10;
  width: var(--touch);
  height: var(--touch);
  border-radius: 50%;
  background: var(--surface);
  border: 1px solid var(--border);
  font-size: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text);
  text-decoration: none;
}

.top-back:active {
  background: var(--surface-alt);
}

/* ---------- index.html ---------- */

/* Page divisee en 4 zones verticales de meme taille, quelle que soit la resolution : chacune prend
   flex:1 (25% de la hauteur dispo) et gere son propre debordement interne (scroll) plutot que de
   grandir au-dela de sa part - la division reste stable sur n'importe quel ecran. */
.home {
  flex: 1;
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  /* 100vh peut inclure une zone masquee par la barre du navigateur (elle ne represente pas
     toujours la hauteur reellement visible sur mobile/tablette), et 100dvh n'est pas supporte
     partout : --app-height (calcule en JS via window.innerHeight, voir setAppHeight) est la valeur
     la plus fiable quand elle est disponible, sinon on retombe sur 100vh. C'est cet ecart qui
     coupait le bas de la page (zone des post-it) sur certains navigateurs/tablettes. */
  height: var(--app-height, 100vh);
  overflow: hidden;
}

.home-zone {
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  /* Marge laterale fluide plutot que fixe : reste confortable sur grand ecran sans grignoter une
     part disproportionnee de la largeur sur un petit ecran etroit. */
  padding: 8px clamp(12px, 4vw, 40px);
  box-sizing: border-box;
  overflow: hidden;
}

.zone-clock {
  justify-content: center;
  align-items: center;
}

.zone-kids {
  justify-content: center;
  align-items: center;
}

.zone-panels {
  justify-content: center;
  /* Sans align-items:center, un enfant "stretch" (par defaut) qui atteint son max-width (voir
     .home-panels) reste colle au bord gauche de la zone au lieu d'etre centre - visible surtout
     sur un grand ecran d'ordinateur, ou la zone est bien plus large que les 960px de .home-panels. */
  align-items: center;
}

.zone-panels .home-panels {
  flex: 1;
  min-height: 0;
}

/* Zone reservee aux pense-betes : grille qui s'agence toute seule (flex-wrap), jamais de position
   ou redimensionnement au doigt a gerer - voir .sticky-note. Sa propre barre de defilement prend le
   relais si trop de notes tiennent pas d'un coup, plutot que de les couper ou les faire deborder. */
.zone-stickies {
  flex-direction: row;
  flex-wrap: wrap;
  align-content: flex-start;
  justify-content: center;
  gap: 14px;
  overflow-y: auto;
}

/* Zone du haut coupee en deux : l'heure a gauche (clock-half), la meteo a droite (weather-half),
   chacune la moitie de la largeur - flex-wrap:wrap les empile si l'ecran est trop etroit pour les
   deux cote a cote. */
/* Meme largeur maximale que .home-panels (agenda/liste de courses) : sans ca, cette rangee (horloge
   + meteo) s'etalait sur toute la largeur de sa zone alors que la rangee du dessous restait bornee a
   960px et centree - les deux rangees ne partageaient plus les memes marges au-dela de cette largeur
   (grand ecran d'ordinateur), rompant l'alignement vertical entre les deux. */
.home-heading {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(20px, 6vw, 72px);
  width: 100%;
  max-width: 960px;
  margin: 0 auto;
  flex-wrap: wrap;
  animation: fadeIn 0.5s ease both;
}

.clock-half,
.weather-half {
  flex: 1 1 260px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.screen-timers-bar {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  justify-content: center;
}

.screen-timer-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  background: var(--surface);
  box-shadow: var(--shadow);
  border: 2px solid var(--cat-soir);
}

.screen-timer-kid {
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--text);
}

.screen-timer-remaining {
  font-family: var(--font-display);
  font-variant-numeric: tabular-nums;
  font-size: 1.4rem;
  color: var(--text);
  min-width: 3ch;
}

.screen-timer-stop {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.08);
  color: var(--text);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.screen-timer-card.done {
  border-color: var(--danger);
  animation: screenTimerFlash 1s ease-in-out infinite;
}

.screen-timer-card.done .screen-timer-remaining {
  color: var(--danger-dark);
}

@keyframes screenTimerFlash {
  0%, 100% { background: var(--surface); }
  50% { background: var(--danger-soft); }
}

.home-clock {
  font-family: var(--font-display);
  /* Relatif a la hauteur ET a la largeur disponibles (min()) plutot qu'une taille fixe : s'adapte a
     la resolution reelle de l'ecran, borne pour rester lisible sur un tres petit ou tres grand
     affichage. La meteo vit desormais dans sa propre moitie (voir .weather-half), donc l'horloge
     peut prendre plus de place verticale (12vh) qu'avant - juste bornee en largeur (15vw, la moitie
     de zone qui lui est allouee) pour ne jamais deborder de son cote sur un ecran etroit. */
  font-size: clamp(2.8rem, min(12vh, 15vw), 11rem);
  line-height: 1;
  color: var(--text);
  font-weight: 500;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.home h1 {
  font-family: var(--font-display);
  font-size: 2.6rem;
  color: var(--text);
  font-weight: 500;
  margin: 0;
  letter-spacing: -0.01em;
}

.home-date {
  margin: 14px 0 0;
  font-size: 0.9rem;
  color: var(--text-muted);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.weather-strip {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 28px;
  margin-top: 14px;
}

.weather-entry {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--text-muted);
  font-size: 0.9rem;
}

.weather-entry .weather-label {
  font-weight: 600;
}

.weather-icon {
  color: var(--text-muted);
  flex-shrink: 0;
}

.weather-temps {
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

.weather-rain {
  color: var(--chart-spent);
  font-size: 0.85rem;
}

/* Meteo actuelle : gros, au premier coup d'oeil, cote a cote avec l'horloge (voir .weather-half). */
.weather-now {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.weather-now-main {
  display: flex;
  align-items: center;
  gap: clamp(8px, 2vw, 16px);
}

.weather-now-icon {
  width: clamp(30px, 6vh, 56px);
  height: clamp(30px, 6vh, 56px);
  color: var(--text-muted);
  flex-shrink: 0;
}

.weather-now-temp {
  font-family: var(--font-display);
  font-size: clamp(2rem, min(7vh, 9vw), 5rem);
  font-weight: 500;
  color: var(--text);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

/* Alerte pluie : jamais juste une couleur (voir principe general de l'appli) - toujours une icone
   ET un texte. Deux niveaux : plein/anime "maintenant", discret "bientot". */
.weather-rain-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 18px;
  border-radius: 999px;
  font-weight: 700;
  font-size: clamp(0.9rem, 2vh, 1.15rem);
}

.weather-rain-badge-icon {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
}

.weather-rain-badge.rain-now {
  background: var(--cat-ecole);
  color: #fff;
  animation: rainBadgePulse 1.8s ease-in-out infinite;
}

.weather-rain-badge.rain-soon {
  background: var(--cat-ecole-soft);
  color: var(--cat-ecole-dark);
}

@keyframes rainBadgePulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(91, 167, 230, 0.45); }
  50% { box-shadow: 0 0 0 9px rgba(91, 167, 230, 0); }
}

.home-panels {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  align-items: stretch;
  justify-content: center;
  width: 100%;
  max-width: 960px;
}

.today-agenda,
.shopping-panel {
  animation: fadeIn 0.6s ease both;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* Meme flex-basis/max-width pour les deux : la frontiere entre eux tombe alors exactement sur
   l'axe central de la page (agenda a gauche, courses a droite), pas seulement leur bloc englobant.
   Le scroll se fait dans .agenda-scroll (voir plus bas), pas ici : sinon l'en-tete et le bouton
   d'agrandissement defilaient avec la liste au lieu de rester fixes en haut du panneau.
   height:100% necessaire (mesure en Chrome headless) : .home-panels a flex-wrap:wrap, et sur une
   seule ligne wrap, align-items:stretch etire les items jusqu'a la taille du plus grand plutot que
   jusqu'a la hauteur reelle du conteneur - sans hauteur explicite ici, ce panneau (et .shopping-panel)
   grandissait pour englober tout son contenu (jamais de scroll interne declenche) et se faisait
   simplement rogner par l'overflow:hidden de .zone-panels plus haut, sans aucun signal visuel. */
.today-agenda {
  position: relative;
  flex: 1 1 400px;
  max-width: 460px;
  overflow: hidden;
  height: 100%;
}

/* Le panneau compact n'a jamais assez de hauteur pour garantir que tous les evenements du jour
   tiennent sans defiler (voir .agenda-scroll) - ce fondu en bas de cadre indique qu'il y en a
   d'autres en dessous plutot que de laisser croire que la liste s'arrete la. Visibilite pilotee en
   JS (updateAgendaScrollFade dans index.html) selon le scroll reel, pas juste au chargement.
   Le degrade seul se fondait dans var(--bg) (.today-agenda n'a pas de fond de carte propre, il est
   directement sur le fond de page) : quasi invisible. La pastille "+N" porte maintenant seule le
   signal, en couleur pleine plutot qu'un ton neutre proche du fond. */
.agenda-scroll-fade {
  position: absolute;
  left: 0;
  right: 10px;
  bottom: 0;
  height: 38px;
  background: linear-gradient(to bottom, transparent, var(--bg) 75%);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s ease;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 2px;
}

.agenda-scroll-fade.visible {
  opacity: 1;
}

/* Chiffre precisement combien d'evenements restent sous le fondu (voir updateAgendaScrollFade dans
   index.html), plutot que de laisser deviner si le degrade signifie "un peu plus" ou "beaucoup plus".
   Cliquable (voir index.html) : ouvre directement la popup d'agenda complet. */
.agenda-scroll-fade-count {
  pointer-events: auto;
  cursor: pointer;
  font-size: 0.74rem;
  font-weight: 700;
  color: white;
  background: var(--primary);
  border-radius: 999px;
  padding: 4px 12px;
  white-space: nowrap;
  box-shadow: var(--shadow);
}

.agenda-scroll-fade-count:empty {
  display: none;
}

.shopping-panel {
  flex: 1 1 400px;
  max-width: 460px;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.shopping-panel-header,
.agenda-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.shopping-panel-header .section-title,
.agenda-panel-header .section-title {
  margin: 0;
}

.agenda-scroll {
  flex: 1;
  min-height: 40px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding-right: 10px;
  margin-right: -10px;
}

.agenda-subheading {
  margin: 0 0 4px;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.expand-btn {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: none;
  background: var(--surface-alt);
  color: var(--text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
}

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

.shopping-list-scroll {
  flex: 1;
  min-height: 40px;
  overflow-y: auto;
  padding-right: 10px;
}

.shopping-add-form {
  display: flex;
  gap: 8px;
  margin-bottom: 10px;
}

.shopping-add-form input {
  flex: 1;
  min-height: 48px;
  padding: 0 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  font-size: 1rem;
  font-family: inherit;
  background: var(--surface-alt);
  color: var(--text);
}

.shopping-add-form .btn {
  min-height: 48px;
  min-width: 48px;
  padding: 0;
  font-size: 1.4rem;
  line-height: 1;
}

.shopping-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 5px 2px;
  border-bottom: 1px solid var(--border);
}

.shopping-item:last-child {
  border-bottom: none;
}

.shopping-check {
  flex-shrink: 0;
  width: 21px;
  height: 21px;
  border-radius: 50%;
  border: 2px solid var(--border);
  background: var(--surface);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
}

.shopping-check svg {
  width: 11px;
  height: 11px;
  stroke: white;
  opacity: 0;
}

.shopping-item.done .shopping-check {
  background: var(--success);
  border-color: var(--success);
}

.shopping-item.done .shopping-check svg {
  opacity: 1;
}

.shopping-label {
  flex: 1;
  min-width: 0;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text);
  text-align: left;
  background: none;
  border: none;
  font-family: inherit;
  cursor: pointer;
  padding: 0;
  overflow-wrap: break-word;
}

.shopping-item.done .shopping-label {
  text-decoration: line-through;
  color: var(--text-muted);
}

.shopping-delete {
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: none;
  background: none;
  color: var(--text-muted);
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.shopping-clear-btn {
  margin-top: 10px;
  border: none;
  background: none;
  color: var(--text-muted);
  font-size: 0.85rem;
  font-weight: 700;
  text-decoration: underline;
  cursor: pointer;
  padding: 4px 0;
}

.shopping-modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 30;
  background: var(--overlay);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  opacity: 0;
  transition: opacity 0.22s ease;
}

.shopping-modal-overlay.visible {
  opacity: 1;
}

.shopping-modal {
  background: var(--surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 26px 28px;
  width: 100%;
  max-width: 480px;
  max-height: 82vh;
  display: flex;
  flex-direction: column;
  transform: scale(0.94) translateY(10px);
  transition: transform 0.25s cubic-bezier(0.34, 1.15, 0.4, 1);
}

/* Plus large que la popup par defaut (liste de courses/agenda) : les formulaires tache/recompense,
   avec leurs sections en grille, ont besoin d'un peu plus de place pour rester lisibles sur 2-3
   colonnes plutot que de tout empiler sur une seule. */
.shopping-modal.modal-wide {
  max-width: 640px;
}

/* .shopping-modal-list decale sa boite de -14px/+14px (gouttiere de scrollbar) pour les listes
   simples (courses/agenda) : sur un formulaire a colonnes, ce decalage rend la marge droite plus
   etroite que la gauche (champs/textes qui semblent toucher le bord). On annule le decalage ici,
   ces formulaires depassant rarement assez pour avoir besoin de cette gouttiere. */
.shopping-modal.modal-wide .shopping-modal-list {
  margin: 6px 0 4px;
  padding-right: 0;
}

.shopping-modal-overlay.visible .shopping-modal {
  transform: scale(1) translateY(0);
}

.shopping-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}

.shopping-modal-header h2 {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.25rem;
  margin: 0;
}

.modal-close-btn {
  flex-shrink: 0;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: none;
  background: var(--surface-alt);
  color: var(--text-muted);
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.shopping-modal-list {
  flex: 1;
  overflow-y: auto;
  margin: 6px -14px 4px 0;
  padding-right: 14px;
}

/* Une seule ligne par evenement (heure + titre + lieu tronques ensemble avec une ellipse) plutot
   que le titre sur une ligne et la description sur une autre : plus compact, permet de voir plus
   d'evenements sans agrandir (voir aussi la popup .agenda-modal-overlay pour tout voir d'un coup). */
.agenda-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 6px 4px;
  border-bottom: 1px solid var(--border);
}

.agenda-row:last-child {
  border-bottom: none;
}

.agenda-row.is-past {
  opacity: 0.55;
}

.agenda-time {
  position: relative;
  flex-shrink: 0;
  min-width: 46px;
  padding-left: 13px;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--text);
  font-size: 0.78rem;
}

.agenda-time::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--danger);
}

.agenda-row.is-past .agenda-time {
  color: var(--text-muted);
}

.agenda-row.is-past .agenda-time::before {
  content: '✓';
  width: auto;
  height: auto;
  border-radius: 0;
  background: none;
  color: var(--chart-spent);
  font-size: 0.75rem;
  font-weight: 700;
}

.agenda-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
  font-size: 0.82rem;
}

.agenda-row.is-past .agenda-title {
  text-decoration: line-through;
  text-decoration-color: var(--border);
  text-decoration-thickness: 1px;
}

.kid-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-content: center;
  align-items: flex-start;
  gap: clamp(10px, 3vw, 40px);
  width: 100%;
  height: 100%;
  overflow: hidden;
}

/* Chaque tuile se voit attribuer une part EGALE de la largeur disponible (flex-basis 0 + grow 1),
   quel que soit le nombre d'enfants : la division se fait par construction (CSS pur), jamais de
   depassement de largeur a mesurer/corriger en JS. min-width:50px est un plancher pour ne pas les
   ecraser a l'infini avec beaucoup d'enfants (le retour a la ligne prend le relais au-dela) ;
   max-width:220px evite qu'ils deviennent enormes avec 1 ou 2 enfants seulement. */
.kid-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  background: none;
  padding: 8px;
  border-radius: var(--radius-lg);
  animation: riseIn 0.4s ease both;
  transition: transform 0.15s ease;
  flex: 1 1 0;
  min-width: 50px;
  max-width: 220px;
  touch-action: manipulation;
  /* Sans ca, un tap sur la photo d'un enfant est concurrence par les gestes natifs du navigateur
     (menu "enregistrer l'image", glisser-deposer) : celui-ci attend de voir si c'est un appui long
     avant de laisser passer le clic, ce qui donne l'impression qu'il faut appuyer plus longtemps
     que necessaire pour ouvrir la fiche de l'enfant. */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

.kid-tile:active {
  transition-duration: 0s;
  transform: scale(0.96);
}

@media (hover: hover) {
  .kid-tile:hover .kid-avatar {
    transform: translateY(-3px);
    box-shadow: var(--shadow), 0 0 0 1px var(--border);
  }
}

.kid-avatar {
  /* Remplit sa tuile (elle-meme dimensionnee par la division egale ci-dessus) jusqu'a 210px, et
     jamais plus que 16% de la hauteur d'ecran (min()) : les deux contraintes, largeur ET hauteur,
     sont donc respectees par construction, sans JS pour mesurer quoi que ce soit. 16vh (pas 25vh,
     la part exacte de la zone) laisse la place au prenom + espacements sous l'avatar dans la zone. */
  width: 100%;
  max-width: min(210px, 16vh);
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  background: var(--primary-soft);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 5vh, 3rem);
  font-weight: 500;
  color: var(--primary-dark);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.kid-avatar img,
.kid-avatar svg {
  width: 100%;
  height: 100%;
  object-fit: cover;
  -webkit-user-drag: none;
  pointer-events: none;
}

.kid-tile .kid-name {
  font-size: clamp(0.8rem, 2.2vh, 1.5rem);
  font-weight: 600;
  color: var(--text);
  /* max-width/text-overflow n'ont d'effet fiable qu'a partir d'un display block/inline-block :
     un <span> reste "inline" par defaut et ignorerait ces contraintes. */
  display: inline-block;
  /* 100% de la tuile (elle-meme deja bornee ci-dessus) : le prenom ne peut jamais elargir la tuile
     au-dela de ce que l'avatar occupe deja, un prenom trop long est tronque avec une ellipse. */
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Petit rappel de marque, seul coin encore libre (haut-droite a le bouton son, bas-gauche le
   post-it, bas-droite "Espace parent") : ne mange donc aucune place sur les 4 zones de contenu. */
.app-brand {
  position: fixed;
  top: 20px;
  left: 24px;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 8px;
  opacity: 0.75;
}

.app-brand-icon {
  width: 26px;
  height: 26px;
  flex-shrink: 0;
}

.app-brand-name {
  /* Police fixe (pas var(--font-display)) : le logo doit rendre a l'identique sur toutes les pages,
     y compris l'espace parent qui garde par ailleurs sa propre police (Georgia) pour tout le reste. */
  font-family: 'Nunito', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  font-weight: 700;
  font-size: 0.92rem;
  color: var(--text-muted);
  letter-spacing: 0.01em;
}

/* Repositionnement selon la page : en bas a gauche sur kid.html (le haut-gauche est deja pris par la
   barre du haut), en flux normal en tete de la barre laterale sur parent.html (voir plus bas) - meme
   logo partout, juste une position adaptee a une mise en page qui n'a pas toujours un coin libre. */
.app-brand.app-brand-bottom {
  top: auto;
  bottom: 20px;
  left: 24px;
}

.admin-nav .app-brand {
  position: static;
  padding: 0 20px 20px;
  opacity: 1;
}

/* Meme traitement "bouton coin" que .add-sticky-btn (couleur pleine, pilule) plutot qu'un lien texte
   discret : plus facile a reperer/toucher sur une tablette. */
.parent-link {
  position: fixed;
  bottom: 20px;
  right: 24px;
  z-index: 12;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 22px;
  border-radius: 999px;
  background: var(--primary);
  color: white;
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: 0.01em;
  text-decoration: none;
  box-shadow: var(--shadow);
  transition: transform 0.15s ease;
}

.parent-link:active {
  transform: scale(0.97);
}

.add-sticky-btn {
  position: fixed;
  bottom: 20px;
  left: 24px;
  z-index: 12;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 18px;
  border-radius: 999px;
  border: none;
  background: var(--primary);
  color: white;
  font-weight: 700;
  font-size: 0.9rem;
  font-family: var(--font-body);
  box-shadow: var(--shadow);
  cursor: pointer;
}

.add-sticky-btn svg {
  width: 16px;
  height: 16px;
}

.add-sticky-btn:disabled {
  background: var(--surface-alt);
  color: var(--text-muted);
  cursor: not-allowed;
  box-shadow: none;
}

.sound-unlock-btn {
  position: fixed;
  top: 20px;
  right: 24px;
  z-index: 12;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: none;
  background: var(--surface);
  color: var(--text-muted);
  box-shadow: var(--shadow);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0.6;
  transition: opacity 0.15s ease, color 0.15s ease;
}

.sound-unlock-btn svg {
  width: 20px;
  height: 20px;
}

.sound-unlock-btn.armed {
  color: var(--cat-soir);
  opacity: 1;
}

/* Element de flux normal dans la grille (.zone-stickies, flex-wrap) : ni position, ni taille geree
   au doigt. width en clamp() plutot que fixe pour que la grille tienne plus ou moins de colonnes
   selon la largeur d'ecran, par construction (pas de mesure JS). */
.sticky-note {
  width: clamp(140px, 24vw, 190px);
  min-height: 110px;
  flex-shrink: 0;
  padding: 10px 14px 14px;
  border-radius: 3px;
  box-shadow: 3px 5px 12px rgba(38, 30, 15, 0.22), 0 1px 2px rgba(38, 30, 15, 0.12);
  display: flex;
  flex-direction: column;
  transition: box-shadow 0.15s ease;
}

/* Pendant l'edition (textarea au focus) : sortie du flux de la grille et epinglee en haut de
   l'ecran, toujours au-dessus du clavier tactile quelle que soit sa hauteur (celui-ci ne recouvre
   que le bas de l'ecran). !important necessaire pour l'emporter sur la rotation cosmetique posee en
   inline (voir stickyNoteElement) - remise a plat le temps d'ecrire, pour une lecture confortable. */
.sticky-note.editing {
  position: fixed;
  top: 16px;
  left: 50%;
  transform: translateX(-50%) !important;
  width: min(92vw, 340px);
  height: min(50vh, 320px);
  z-index: 40;
  box-shadow: 6px 12px 26px rgba(38, 30, 15, 0.35), 0 2px 6px rgba(38, 30, 15, 0.18);
}

.sticky-note::after {
  content: '';
  position: absolute;
  bottom: 0;
  right: 0;
  width: 0;
  height: 0;
  pointer-events: none;
  border-style: solid;
  border-width: 0 0 18px 18px;
  border-color: transparent transparent rgba(38, 30, 15, 0.12) transparent;
}

.sticky-note-delete {
  position: absolute;
  top: 5px;
  right: 7px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: none;
  background: rgba(38, 30, 15, 0.1);
  color: #3a3226;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  touch-action: auto;
}

.sticky-note-text {
  flex: 1;
  width: 100%;
  border: none;
  background: none;
  outline: none;
  resize: none;
  font-family: 'Caveat', cursive;
  font-size: 1.35rem;
  line-height: 1.3;
  color: #3a3226;
  padding: 4px 0 0;
  touch-action: auto;
}

.sticky-note-text::placeholder {
  color: rgba(58, 50, 38, 0.45);
  font-family: 'Caveat', cursive;
}

.sticky-note.color-yellow {
  background: #fff4b8;
}

.sticky-note.color-pink {
  background: #ffd3e0;
}

.sticky-note.color-green {
  background: #d4f0c4;
}

.sticky-note.color-blue {
  background: #c9e7f5;
}

.sticky-note.color-orange {
  background: #ffdcb8;
}

/* ---------- kid.html ---------- */

.kid-topbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px 18px;
  padding: 18px 28px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  animation: fadeIn 0.4s ease both;
}

/* Fond + bordure + ombre plutot qu'une simple fleche sur fond transparent : se voit et se
   reconnait comme un bouton au premier coup d'oeil, pas seulement au survol/appui. */
.kid-topbar-back {
  flex-shrink: 0;
  width: 68px;
  height: 68px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  color: var(--text);
  font-size: 34px;
  text-decoration: none;
}

.kid-topbar-back:active {
  background: var(--surface-alt);
}

.kid-topbar-avatar {
  flex-shrink: 0;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--primary-soft);
  color: var(--primary-dark);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.7rem;
}

.kid-topbar-avatar img,
.kid-topbar-avatar svg {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
}

.kid-topbar-name {
  font-weight: 700;
  font-size: 1.85rem;
  color: var(--text);
  white-space: nowrap;
}

.kid-topbar-points {
  font-weight: 700;
  font-size: 1.65rem;
  color: var(--primary-dark);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.kid-topbar-points .unit {
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-left: 2px;
}

.kid-topbar-tabs {
  display: flex;
  gap: 8px;
  width: 100%;
  order: 1;
}

.kid-topbar-tabs .kid-tab {
  flex: 1;
  min-height: 52px;
  padding: 0 14px;
  font-size: 1.1rem;
  white-space: nowrap;
}

.streak-card {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 16px 22px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  background: var(--surface);
  transition: background-color 0.25s ease, border-color 0.25s ease;
}

.streak-icon {
  flex-shrink: 0;
  color: var(--text-muted);
  transition: color 0.25s ease;
}

.streak-icon path {
  fill: currentColor;
}

.streak-card[data-level='1'] {
  background: #f5e6da;
  border-color: #c98a5f;
}

.streak-card[data-level='2'] {
  background: #eed3bf;
  border-color: var(--primary);
}

.streak-card[data-level='3'] {
  background: #e4b998;
  border-color: var(--primary-dark);
}

.streak-card[data-level='4'] {
  background: #d99a6a;
  border-color: var(--primary-dark);
  border-width: 2px;
}

.streak-card[data-level='1'] .streak-icon {
  color: #c98a5f;
}

.streak-card[data-level='2'] .streak-icon {
  color: var(--primary);
}

.streak-card[data-level='3'] .streak-icon,
.streak-card[data-level='4'] .streak-icon {
  color: var(--primary-dark);
}

.streak-info {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.streak-count {
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--text);
}

.streak-card[data-level='1'] .streak-count,
.streak-card[data-level='2'] .streak-count {
  color: var(--primary-dark);
}

.streak-card[data-level='3'] .streak-count,
.streak-card[data-level='4'] .streak-count {
  color: #4a2712;
}

.streak-next {
  font-size: 0.9rem;
  color: var(--text-muted);
}

.streak-next strong {
  color: var(--text);
}

.streak-week {
  display: flex;
  gap: 6px;
  margin-left: auto;
}

.streak-dot {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 1.5px solid var(--border);
  background: var(--surface);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  line-height: 1;
}

.streak-dot.ok {
  background: var(--pending-soft);
  border-color: transparent;
}

.streak-dot.incident {
  background: var(--danger);
  border-color: var(--danger);
  color: white;
  font-size: 10px;
  font-weight: 700;
}

.streak-dot.future {
  opacity: 0.35;
}

.kid-tab {
  min-height: 64px;
  padding: 0 8px;
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--text-muted);
  background: none;
  border-bottom: 3px solid transparent;
  margin-bottom: -1px;
}

.kid-tab.active {
  color: var(--primary-dark);
  border-bottom-color: var(--primary);
}

.kid-tab:active {
  transition-duration: 0s;
  transform: scale(0.96);
}

.kid-tab-panel {
  display: none;
}

.kid-tab-panel.active {
  display: block;
}

.kid-body {
  flex: 1;
  padding: 28px 40px 60px;
  display: flex;
  flex-direction: column;
  gap: 40px;
  max-width: 1100px;
  margin: 0 auto;
  width: 100%;
}

/* Fond d'ecran discret, differe selon le theme d'icones choisi par l'enfant. */
body[data-icon-theme='duotone'] .kid-body {
  background-image: radial-gradient(circle, rgba(38, 159, 154, 0.09) 1.6px, transparent 1.6px);
  background-size: 28px 28px;
}

body[data-icon-theme='natural'] .kid-body {
  background-image: radial-gradient(circle, rgba(255, 150, 95, 0.12) 1.7px, transparent 1.7px),
    radial-gradient(circle, rgba(91, 167, 230, 0.12) 1.7px, transparent 1.7px),
    radial-gradient(circle, rgba(127, 190, 69, 0.12) 1.7px, transparent 1.7px);
  background-size: 42px 42px, 42px 42px, 42px 42px;
  background-position: 0 0, 14px 21px, 28px 7px;
}

.section-title {
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  margin: 0 0 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
  color: var(--text-muted);
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 16px;
}

#reward-list.card-grid {
  grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));
}

.reward-card {
  background: var(--surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 18px 22px;
  display: flex;
  align-items: center;
  gap: 16px;
  animation: riseIn 0.35s ease both;
  transition: transform 0.1s ease;
}

.reward-icon {
  flex-shrink: 0;
  width: 58px;
  height: 58px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.reward-icon svg {
  width: 36px;
  height: 36px;
}

.reward-info {
  flex: 1;
  min-width: 0;
}

.reward-info .reward-name {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 5px;
  letter-spacing: -0.01em;
}

.reward-cost {
  color: var(--text-muted);
  font-size: 0.85rem;
  font-weight: 700;
}

/* ---------- Progression du jour (onglet Taches) : chemin d'exploration discret ---------- */
.progress-header {
  background: var(--surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 18px 22px;
  margin-bottom: 18px;
}

.progress-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.progress-title-group {
  display: flex;
  align-items: center;
  gap: 8px;
}

.refresh-btn {
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: none;
  background: var(--surface-alt);
  color: var(--text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
}

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

.refresh-btn.spinning svg {
  animation: refreshSpin 0.6s linear;
}

@keyframes refreshSpin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.progress-label {
  font-weight: 800;
  font-size: 1.05rem;
}

.progress-count {
  font-size: 0.85rem;
  color: var(--text-muted);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.progress-path {
  position: relative;
  height: 22px;
}

.progress-track {
  position: absolute;
  top: 50%;
  left: 0;
  right: 22px;
  height: 3px;
  transform: translateY(-50%);
  background-image: repeating-linear-gradient(90deg, var(--border) 0 6px, transparent 6px 13px);
  border-radius: 2px;
}

.progress-fill {
  position: absolute;
  top: 50%;
  left: 0;
  height: 3px;
  transform: translateY(-50%);
  background: var(--primary);
  border-radius: 2px;
  transition: width 0.3s ease;
}

.progress-flag {
  position: absolute;
  top: 50%;
  width: 20px;
  height: 20px;
  transform: translate(-4px, -62%);
  transition: left 0.3s ease;
}

/* ---------- Carte tache : icone de categorie + checklist a coche ronde ---------- */
.chore-card {
  display: flex;
  align-items: center;
  gap: 14px;
  background: var(--surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 14px 18px;
  animation: riseIn 0.35s ease both;
  transition: opacity 0.2s ease, transform 0.12s ease;
  touch-action: manipulation;
}

.chore-card[data-chore-id],
.chore-card[data-claim-id],
.chore-card[data-yesterday-chore-id],
.chore-card[data-yesterday-claim-id] {
  cursor: pointer;
}

.chore-card[data-chore-id]:active,
.chore-card[data-claim-id]:active,
.chore-card[data-yesterday-chore-id]:active,
.chore-card[data-yesterday-claim-id]:active {
  transition-duration: 0s;
  transform: scale(0.97);
  filter: brightness(0.97);
}

.chore-card.submitting {
  opacity: 0.6;
  pointer-events: none;
}

.chore-card.done {
  opacity: 0.55;
}

.chore-card.done .chore-name {
  text-decoration: line-through;
  text-decoration-color: var(--text-muted);
  text-decoration-thickness: 1.5px;
}

.chore-icon {
  flex-shrink: 0;
  width: 58px;
  height: 58px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.chore-icon svg {
  width: 36px;
  height: 36px;
}

.chore-check {
  flex-shrink: 0;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 2.5px solid var(--border);
  background: var(--surface);
  display: flex;
  align-items: center;
  justify-content: center;
}

.chore-check svg {
  width: 18px;
  height: 18px;
  stroke: white;
}

.chore-card.done .chore-check {
  background: var(--success);
  border-color: var(--success);
  animation: checkPop 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes checkPop {
  0% {
    transform: scale(0.7);
  }
  60% {
    transform: scale(1.15);
  }
  100% {
    transform: scale(1);
  }
}

.chore-card.pending .chore-check {
  border-color: var(--pending);
  border-style: dashed;
}

.chore-card.pending .chore-check::after {
  content: '';
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--pending);
}

/* En retard : heure fixee deja passee et pas encore cochee. Couleur chaude (pas rouge pur) + symbole
   distinct (point d'exclamation) et texte "En retard", pour rester lisible en cas de daltonisme. */
.chore-card.late {
  box-shadow: var(--shadow), 0 0 0 2px var(--danger);
}

.chore-card.late .chore-meta {
  color: var(--danger-dark);
  font-weight: 800;
}

.chore-card.late .chore-check {
  border-color: var(--danger);
  border-style: solid;
  background: var(--danger-soft);
  color: var(--danger-dark);
}

.chore-card.late .chore-check svg {
  width: 14px;
  height: 14px;
  stroke: currentColor;
}

.chore-info {
  flex: 1;
  min-width: 0;
}

.chore-name {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 3px;
  letter-spacing: -0.01em;
}

.chore-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.82rem;
  color: var(--text-muted);
  font-weight: 600;
}

.chore-time {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 800;
  border-radius: 999px;
  padding: 1px 8px;
  font-variant-numeric: tabular-nums;
}

.chore-points {
  font-weight: 800;
  color: var(--text);
}

.btn {
  min-height: var(--touch);
  min-width: var(--touch);
  padding: 0 26px;
  border-radius: var(--radius-sm);
  font-size: 1.05rem;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  /* Retour au repos anime doucement ; l'appui lui est instantane (transition coupee sur :active
     ci-dessous) : ca donne le "clic" net qui manquait au tactile. */
  transition: transform 0.11s ease, filter 0.11s ease;
}

.btn:active {
  transition-duration: 0s;
  transform: scale(0.96);
  filter: brightness(0.93);
}

.btn-primary {
  background: var(--primary);
  color: white;
}

.btn-primary:active {
  background: var(--primary-dark);
}

.btn-success {
  background: var(--success);
  color: white;
}

.btn-danger {
  background: var(--danger);
  color: white;
}

.btn-outline {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
}

/* Discret plutot qu'un gros bouton plein qui rivalise avec "Enregistrer" dans la popup : pointille
   pour signaler "ajouter" sans peser autant qu'une action primaire, et align-self pour ne pas etre
   etire pleine largeur par le flex-column de .admin-panel.active. */
.add-item-btn {
  align-self: flex-start;
  background: transparent;
  color: var(--primary-dark);
  border: 1.5px dashed var(--primary);
  font-weight: 700;
  min-height: 44px;
}

.add-item-btn:active {
  background: var(--primary-soft);
}

.status-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 16px;
  border-radius: 999px;
  font-weight: 600;
  font-size: 0.85rem;
}

.status-pill::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

.status-pending {
  background: var(--pending-soft);
  color: var(--pending-dark);
}

.status-approved {
  background: var(--success-soft);
  color: var(--success-dark);
}

.reward-card.selected {
  background: var(--success-soft);
  box-shadow: 0 0 0 2.5px var(--success), var(--shadow);
}

.cart-bar {
  position: sticky;
  bottom: 16px;
  margin-top: 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 22px;
  background: var(--text);
  color: var(--bg);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow);
  font-weight: 600;
}

.cart-bar .btn-success {
  min-height: 56px;
}

/* Meme fondu+leger zoom que .shopping-modal-overlay (voir plus haut), plutot qu'une apparition
   instantanee : classe .visible ajoutee apres un double requestAnimationFrame (voir openTimerPinModal
   et compagnie), memes duree/easing pour rester coherent avec les autres popups de l'appli. */
.pin-modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 20;
  background: var(--overlay);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  opacity: 0;
  transition: opacity 0.22s ease;
}

.pin-modal-overlay.visible {
  opacity: 1;
}

.pin-modal {
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: 32px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  max-width: 360px;
  width: 100%;
  transform: scale(0.94) translateY(10px);
  transition: transform 0.25s cubic-bezier(0.34, 1.15, 0.4, 1);
}

.pin-modal-overlay.visible .pin-modal {
  transform: scale(1) translateY(0);
}

.pin-modal h2 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.4rem;
  margin: 0;
}

.avatar-modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 20;
  background: var(--overlay);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

.avatar-modal {
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: 32px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  max-width: 420px;
  width: 100%;
}

.avatar-modal h2 {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.3rem;
  margin: 0;
}

.pin-change-form-kid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  width: 100%;
}

.pin-change-form-kid input {
  flex: 1;
  min-width: 90px;
  min-height: 46px;
  padding: 0 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  font-size: 1rem;
  font-family: inherit;
  background: var(--surface);
  color: var(--text);
  text-align: center;
}

.avatar-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 14px;
}

.avatar-opt {
  width: 76px;
  height: 76px;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: var(--shadow);
  border: 3px solid transparent;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  padding: 0;
  overflow: visible;
}

.avatar-opt svg,
.avatar-opt img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
}

.avatar-opt.selected {
  border-color: var(--primary);
}

.avatar-opt.selected::after {
  content: '\2713';
  position: absolute;
  bottom: -3px;
  right: -3px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--primary);
  color: white;
  font-size: 12px;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--surface);
}

.theme-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 14px;
}

.theme-opt {
  width: 140px;
  border-radius: 18px;
  border: 3px solid transparent;
  background: var(--surface-alt);
  box-shadow: var(--shadow);
  padding: 14px 10px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  cursor: pointer;
}

.theme-opt.selected {
  border-color: var(--primary);
}

.theme-opt-preview {
  display: flex;
  gap: 6px;
}

.theme-opt-preview span {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.theme-opt-preview svg {
  width: 17px;
  height: 17px;
}

.theme-opt-label {
  font-size: 0.86rem;
  font-weight: 700;
  color: var(--text);
}

.kid-topbar-avatar {
  cursor: pointer;
}

.personalize-btn {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 10px 16px;
  border-radius: 999px;
  border: none;
  background: var(--primary-soft);
  color: var(--primary-dark);
  font-weight: 700;
  font-size: 0.95rem;
  font-family: inherit;
  cursor: pointer;
}

.personalize-btn svg {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

.time-balance-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 32px;
  text-align: center;
}

.time-balance-value {
  font-family: var(--font-display);
  font-size: 4rem;
  font-weight: 600;
  color: var(--primary-dark);
  line-height: 1;
}

.time-balance-unit {
  margin-top: 8px;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* ---------- parent.html ---------- */

.pin-screen {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 28px;
  padding: 30px;
}

.pin-screen h1 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.7rem;
  margin: 0;
}

.pin-dots {
  display: flex;
  gap: 20px;
}

.pin-dot {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid var(--border);
  background: transparent;
}

.pin-dot.filled {
  background: var(--primary);
  border-color: var(--primary);
}

.pin-error {
  color: var(--danger-dark);
  font-weight: 600;
  min-height: 1.5em;
}

.pin-pad {
  display: grid;
  grid-template-columns: repeat(3, 96px);
  gap: 18px;
}

.pin-key {
  width: 96px;
  height: 96px;
  border-radius: 50%;
  background: var(--surface);
  border: 1px solid var(--border);
  font-size: 1.9rem;
  font-weight: 600;
  color: var(--text);
  transition: transform 0.1s ease, background-color 0.1s ease;
}

.pin-key:active {
  transition-duration: 0s;
  background: var(--surface-alt);
  transform: scale(0.93);
}

.pin-key.wide {
  font-size: 1.05rem;
  color: var(--text-muted);
}

.admin-shell {
  display: flex;
  min-height: 100vh;
}

.admin-nav {
  width: 220px;
  background: var(--surface);
  border-right: 1px solid var(--border);
  padding: 24px 0 20px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex-shrink: 0;
}

.admin-nav button {
  display: flex;
  align-items: center;
  gap: 12px;
  background: none;
  text-align: left;
  padding: 18px 28px;
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--text-muted);
}

/* Exclut .logout-btn : ce n'est pas un item de nav (voir plus bas pour son propre style de bouton),
   la bordure gauche transparente ici le rendait quasi invisible (elle ecrasait la bordure normale
   heritee de .btn-outline sans jamais la remplacer par une couleur). */
.admin-nav button:not(.logout-btn) {
  border-left: 3px solid transparent;
}

.admin-nav button.active {
  color: var(--primary-dark);
  background: var(--primary-soft);
  border-left: 3px solid var(--primary);
}

.admin-nav button:active {
  transition-duration: 0s;
  transform: scale(0.98);
  filter: brightness(0.96);
}

.nav-icon {
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

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

.admin-main {
  flex: 1;
  padding: 40px 48px 80px;
  overflow-y: auto;
  max-height: 100vh;
  max-width: 1100px;
  margin: 0 auto;
  width: 100%;
}

.admin-panel {
  display: none;
}

.admin-panel.active {
  display: flex;
  flex-direction: column;
  gap: 28px;
  animation: fadeIn 0.25s ease both;
}

.admin-panel h2 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.6rem;
  margin: 0 0 24px;
}

.list-item {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 12px 16px;
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 8px;
  flex-wrap: wrap;
}

.list-item .item-main {
  flex: 1;
  min-width: 200px;
}

.list-item .item-title {
  font-weight: 600;
  font-size: 1rem;
}

.list-item .item-sub {
  color: var(--text-muted);
  font-size: 0.9rem;
  margin-top: 2px;
}

.list-item .item-actions {
  display: flex;
  gap: 8px;
}

/* Boutons d'action de liste plus compacts que .btn-sm (52px, pense pour d'autres usages tactiles) :
   ces rangees se repetent beaucoup, la densite compte plus ici que la cible tactile large. */
.list-item .item-actions .btn {
  min-height: 38px;
  min-width: auto;
  padding: 0 14px;
  font-size: 0.85rem;
}

.btn-sm {
  min-height: 52px;
  padding: 0 18px;
  font-size: 0.92rem;
  border-radius: var(--radius-sm);
}

.chores-columns {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 32px;
  align-items: start;
}

.chores-column .section-title {
  margin-top: 0;
}

.form-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 22px;
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  align-items: flex-end;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.field label {
  font-size: 0.88rem;
  color: var(--text-muted);
  font-weight: 600;
}

.field input,
.field select {
  min-height: 52px;
  padding: 0 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  font-size: 1rem;
  background: var(--surface);
  color: var(--text);
}

.field.checkbox {
  flex-direction: row;
  align-items: center;
  gap: 10px;
}

/* Regroupe deux champs courts cote a cote (ex: heure de debut / heure de fin) plutot que de les
   empiler en pleine largeur comme les champs texte habituels. */
.field-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

.field-row .field {
  flex: 1 1 140px;
}

.field.checkbox input {
  width: 24px;
  height: 24px;
  min-height: auto;
}

.kid-checkbox-group {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
  min-height: 52px;
  align-items: center;
}

.kid-checkbox-group label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.92rem;
  color: var(--text);
  font-weight: 400;
  cursor: pointer;
}

.kid-checkbox-group input {
  width: 18px;
  height: 18px;
  min-height: auto;
}

.icon-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  max-width: 520px;
}

.icon-picker-btn {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 2px solid var(--border);
  background: var(--surface);
  color: var(--text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
  padding: 0;
}

.icon-picker-btn svg {
  width: 20px;
  height: 20px;
}

.icon-picker-btn.auto {
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
}

.icon-picker-btn.selected {
  border-color: var(--primary);
  background: var(--primary-soft);
  color: var(--primary-dark);
}

/* Champ "Icone" dans le formulaire : juste l'icone choisie (voir openIconPickerModal), pas toute la
   bibliotheque - meme hauteur qu'un input normal pour s'aligner avec les autres champs. */
.icon-picker-trigger {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 52px;
  padding: 6px 14px 6px 6px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
}

.icon-picker-trigger-icon {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--primary-soft);
  color: var(--primary-dark);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.icon-picker-trigger-icon svg {
  width: 18px;
  height: 18px;
}

.icon-picker-trigger-label {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-muted);
}

.days-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.day-btn {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 2px solid var(--border);
  background: var(--surface);
  color: var(--text-muted);
  font-weight: 700;
  font-size: 0.82rem;
  cursor: pointer;
  padding: 0;
}

.day-btn.selected {
  border-color: var(--primary);
  background: var(--primary-soft);
  color: var(--primary-dark);
}

.form-card.stacked {
  flex-direction: column;
  align-items: stretch;
}

/* Selecteur d'enfant DIRECT uniquement : un .field a l'interieur d'un .form-section (voir plus bas)
   ne doit pas herer cette pleine largeur, sinon les champs groupes cote a cote a l'interieur d'une
   section se retrouveraient forces chacun sur leur propre ligne. */
.form-card.stacked > .field,
.form-card.stacked > .field input {
  width: 100%;
}

.form-card.stacked .form-section > .field {
  width: auto;
}

/* Regroupe des champs apparentes (ex: nom/points/icone) a l'interieur d'un .form-card.stacked, avec
   une etiquette de section - remplace le sac plat de champs qui rendait les formulaires tache/
   recompense difficiles a lire d'un coup d'oeil. */
/* Flex (pas grid) : avec une grille auto-fit, une ligne qui n'a pas assez de champs pour remplir
   toutes les colonnes calculees pour la section (colonnes reservees ailleurs par un champ pleine
   largeur comme les jours/cases enfants) laisse une case vide visible. Flex-wrap redistribue toujours
   exactement la largeur disponible entre les champs reellement presents sur la ligne. */
.form-section {
  display: flex;
  flex-wrap: wrap;
  gap: 14px 16px;
  align-items: flex-end;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}

.form-section:first-child {
  padding-top: 0;
  border-top: none;
}

.form-section > .field {
  flex: 1 1 160px;
}

.form-section-label {
  flex: 1 1 100%;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: -4px;
}

.form-section > .form-help {
  flex: 1 1 100%;
}

.form-section > .field:has(.kid-checkbox-group),
.form-section > .field:has(.days-picker) {
  flex: 1 1 100%;
}

/* Champ qui merite sa propre ligne (ex: Nom) plutot que de se retrouver seul sur une ligne a s'etirer
   bizarrement une fois les autres champs groupes par paires. */
.form-section > .field.field-wide {
  flex: 1 1 100%;
}

/* Info de reference (ex: maximum hebdomadaire de marmailloux) distincte visuellement du formulaire
   d'action qui suit, plutot que de se fondre dedans. */
.info-card {
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 18px 20px 4px;
}

.info-card .form-help {
  margin-bottom: 14px;
}

.info-card .stat-tiles {
  margin-bottom: 0;
}

/* Panneau Parametres : 3 formulaires independants cote a cote plutot qu'empiles en pleine largeur -
   utilise la largeur disponible pour eviter le defilement au lieu de l'empiler verticalement.
   .settings-card porte le cadre/fond de carte ; le .form-card qu'il contient perd le sien (sinon
   double cadre) et redevient un simple conteneur de champs. */
.settings-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 18px;
  align-items: start;
}

.settings-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 18px 20px 20px;
}

.settings-card .section-title {
  margin: 0 0 14px;
  padding-bottom: 10px;
}

.settings-card .form-card.stacked {
  background: none;
  border: none;
  box-shadow: none;
  padding: 0;
  margin: 0;
  gap: 12px;
}

.settings-card .form-help {
  margin: -4px 0 0;
}

/* Regroupe l'action et son message de statut sur une seule ligne, compacte, plutot qu'un gros bouton
   pleine largeur (herite de align-items:stretch sur .form-card.stacked) suivi d'une ligne de statut
   separee. */
.settings-actions {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 2px;
}

.settings-actions .form-help {
  margin: 0;
}

/* Case a cocher + les deux heures sur une meme ligne : le champ heure garde sa largeur naturelle
   (.field-row .field est deja flex:1 1 140px), la case prend le reste. */
.settings-inline .field.checkbox {
  flex: 1 1 200px;
}

/* Badge icone + puces de metadonnees pour une ligne de .list-item (taches/recompenses), remplace
   l'ancienne ligne .item-sub qui entassait tout en une seule chaine de texte separee par " - ". */
.item-icon {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--primary-soft);
  color: var(--primary-dark);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

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

.item-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 4px;
}

.item-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--surface-alt);
  border: 1px solid var(--border);
  font-size: 0.76rem;
  color: var(--text-muted);
  font-weight: 600;
}

.item-chip.chip-muted {
  opacity: 0.7;
  font-style: italic;
}

.form-help {
  color: var(--text-muted);
  font-size: 0.88rem;
  line-height: 1.5;
  margin: 0;
}

.empty-state {
  color: var(--text-muted);
  font-style: italic;
  padding: 20px 0;
}

/* Carte "une ligne par enfant" partagee par Comportement, Marmailloux et Temps (auparavant nommee
   .behavior-kid-card et reutilisee telle quelle pour ces deux derniers panneaux, qui n'ont rien a voir
   avec le comportement - renommee de facon neutre). */
.kid-panel-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 20px;
  margin-bottom: 18px;
}

.behavior-kid-name {
  font-weight: 700;
  font-size: 1.1rem;
  margin-bottom: 14px;
}

/* Marmailloux/Temps : ligne de saisie (montant, raison, minutes...) + boutons d'action. */
.kid-panel-controls {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.kid-panel-controls input {
  min-height: 48px;
  padding: 0 10px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  font-size: 1rem;
  background: var(--surface);
  color: var(--text);
}

.points-reason-input {
  flex: 1;
  min-width: 160px;
}

.points-delta-input,
.time-minutes-input {
  width: 100px;
}

.timer-minutes-input {
  width: 80px;
  min-height: 40px;
  font-size: 0.95rem;
}

.kid-panel-timer-block {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

.week-strip {
  display: flex;
  gap: 8px;
  margin-bottom: 14px;
}

.day-cell {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 10px 4px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  cursor: pointer;
  touch-action: manipulation;
  transition: transform 0.1s ease, filter 0.1s ease;
}

.day-cell:active {
  transition-duration: 0s;
  transform: scale(0.95);
  filter: brightness(0.95);
}

.day-cell .day-label {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}

.day-cell .day-num {
  font-size: 1rem;
  font-weight: 700;
  color: var(--text);
}

.day-cell .day-pts {
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--text-muted);
  min-height: 1em;
}

/* Bleu plutot que le vert d'origine : vert/rouge est la paire la moins distinguable pour un
   daltonien rouge-vert (deuteranopie/protanopie), la forme la plus frequente. Verifie avec le
   validateur de palette CVD (deltaE 15.7 vs 3.7 pour vert/rouge, cible >= 8). Complete par une
   icone (coche / croix) : jamais la couleur seule qui porte l'information. */
.day-cell.ok {
  background: #e4edf5;
  border-color: #3a6ea5;
}

.day-cell.ok .day-num,
.day-cell.ok .day-pts {
  color: #2a4f78;
}

.day-cell.incident {
  background: var(--danger-soft);
  border-color: var(--danger);
}

.day-cell.incident .day-num {
  color: var(--danger-dark);
}

.day-cell .day-status-icon svg {
  width: 14px;
  height: 14px;
  display: block;
}

.day-cell.ok .day-status-icon {
  color: #2a4f78;
}

.day-cell.incident .day-status-icon {
  color: var(--danger-dark);
}

.day-cell.future {
  cursor: not-allowed;
  opacity: 0.4;
}

.behavior-summary {
  color: var(--text-muted);
  font-size: 0.92rem;
}

.behavior-summary strong {
  color: var(--text);
}

.tier-editor {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: flex-end;
}

.tier-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 84px;
}

.tier-field label {
  font-size: 0.78rem;
  color: var(--text-muted);
  font-weight: 600;
}

.tier-field input {
  min-height: 48px;
  padding: 0 10px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  font-size: 1rem;
  text-align: center;
}

/* ---------- Historique ---------- */

.filter-row {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 24px;
  flex-wrap: wrap;
}

.filter-row select {
  min-height: 48px;
  padding: 0 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-size: 0.95rem;
  font-family: inherit;
}

.stat-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 14px;
  margin-bottom: 28px;
}

.stat-tile {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 16px 18px;
}

.stat-tile .stat-label {
  font-size: 0.82rem;
  color: var(--text-muted);
  font-weight: 600;
  margin-bottom: 6px;
}

.stat-tile .stat-value {
  font-family: var(--font-body);
  font-size: 1.7rem;
  font-weight: 700;
  color: var(--text);
}

.weekly-max-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
}

.weekly-max-row + .weekly-max-row {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px dashed var(--border);
}

.weekly-max-tag {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-muted);
}

.weekly-max-num {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--text);
}

.chart-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 20px 20px 8px;
  margin-bottom: 28px;
  position: relative;
}

.chart-legend {
  display: flex;
  gap: 20px;
  margin-bottom: 12px;
  font-size: 0.88rem;
  color: var(--text-muted);
}

.chart-legend .legend-item {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

.chart-legend .legend-key {
  display: inline-block;
  width: 14px;
  height: 3px;
  border-radius: 2px;
}

.chart-day-hit {
  fill: transparent;
  cursor: pointer;
}

.chart-day-hit:hover,
.chart-day-hit:focus {
  fill: rgba(11, 11, 11, 0.03);
}

.chart-tooltip {
  position: absolute;
  z-index: 5;
  pointer-events: none;
  background: var(--text);
  color: var(--bg);
  border-radius: 8px;
  padding: 8px 12px;
  font-size: 0.85rem;
  line-height: 1.5;
  white-space: nowrap;
  transform: translate(-50%, -100%);
  opacity: 0;
  transition: opacity 0.1s ease;
}

.chart-tooltip.visible {
  opacity: 1;
}

.chart-tooltip .tooltip-value {
  font-weight: 700;
}

.history-row {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 14px 20px;
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 10px;
}

.history-row .history-main {
  flex: 1;
  min-width: 200px;
}

.history-row .history-title {
  font-weight: 600;
  font-size: 1rem;
}

.history-row .history-sub {
  color: var(--text-muted);
  font-size: 0.86rem;
  margin-top: 2px;
}

.history-delta {
  font-weight: 700;
  font-size: 1.05rem;
  min-width: 56px;
  text-align: right;
}

.history-delta.positive {
  color: var(--chart-earned);
}

.history-delta.negative {
  color: var(--chart-spent);
}

/* Selecteur .admin-nav .logout-btn (pas juste .logout-btn) : l'emporte a coup sur sur .admin-nav
   button (padding/text-align/couleur) sans dependre de l'ordre des regles dans la feuille de style. */
.admin-nav .logout-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 20px;
  margin: 0 20px 16px;
  min-height: 48px;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--primary-dark);
  background: var(--primary-soft);
  border: 1px solid var(--primary);
  border-radius: var(--radius-sm);
}

/* ---------- Responsive : tablette portrait (iPad et similaires) ---------- */

/* Empiler les colonnes Routine/Bonus (ou le menu admin au-dessus du contenu) n'a de sens que si la
   largeur manque : sur un ecran large mais bas (voir plus bas), les empiler rendrait la page PLUS
   haute, contraire au but recherche. */
@media (max-width: 900px) {
  .chores-columns {
    grid-template-columns: 1fr;
    gap: 8px;
  }

  .admin-shell {
    flex-direction: column;
  }

  .admin-nav {
    width: 100%;
    flex-direction: row;
    overflow-x: auto;
    padding: 90px 10px 10px;
  }
}

/* Le seuil de largeur seul rate les petites tablettes larges-mais-basses en paysage (ex: Galaxy
   Tab A6 7", 1024x600 CSS px a DPR 1 : plus large que 900px mais aussi bas qu'un telephone couche).
   Le seuil de hauteur rattrape ce cas sans resserrer les tablettes 10"+ (qui restent hautes en paysage). */
@media (max-width: 900px), (max-height: 700px) {
  /* index.html : la mise en page en 4 zones (voir plus haut, .home-zone) s'adapte deja a la
     resolution via clamp()/vh sur l'horloge et les avatars, plus de reglages specifiques ici. */

  .home-panels {
    gap: 16px;
  }

  .home-panels .section-title {
    margin-bottom: 8px;
    padding-bottom: 6px;
  }

  .today-agenda,
  .shopping-panel {
    max-width: 100%;
    flex-basis: 0;
  }

  /* kid.html */
  .kid-topbar {
    padding: 12px 18px;
    gap: 10px 12px;
  }

  .kid-topbar-back,
  .kid-topbar-avatar {
    width: 56px;
    height: 56px;
  }

  .kid-topbar-back {
    font-size: 28px;
  }

  .kid-topbar-name {
    font-size: 1.5rem;
  }

  .kid-topbar-points {
    font-size: 1.3rem;
  }

  .kid-body {
    padding-left: 20px;
    padding-right: 20px;
  }

  .streak-card {
    flex-wrap: wrap;
    row-gap: 10px;
  }

  .streak-week {
    margin-left: 0;
    width: 100%;
  }

  .card-grid {
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  }

  #reward-list.card-grid {
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  }

  /* parent.html */
  .admin-main {
    max-height: none;
    padding: 24px 20px 60px;
  }

  .tier-field {
    width: 72px;
  }
}

/* index.html sur telephone (portrait) : la mise en page en ecran unique sans defilement (voir
   .home/body[data-page='home'] plus haut) part du principe que 4 zones empilees tiennent dans la
   hauteur disponible - vrai sur tablette, faux sur un telephone bien plus etroit (l'agenda/la liste
   de courses se retrouvent en 2 colonnes ecrasees, et sur certains navigateurs mobiles la page finit
   quand meme par defiler legerement, ce qui fait chevaucher les boutons "coin" fixes avec le contenu).
   Seuil de largeur uniquement (les tablettes meme 7" restent au-dessus) pour ne pas toucher au rendu
   tablette : on abandonne l'ecran unique pour une page qui defile normalement, plus lisible qu'un
   entassement force. */
@media (max-width: 480px) {
  body[data-page='home'] {
    overflow: visible;
    text-align: center;
    padding-bottom: 24px;
  }

  .home {
    height: auto;
    min-height: var(--app-height, 100vh);
    overflow: visible;
  }

  .home-zone {
    flex: 0 0 auto;
    overflow: visible;
  }

  .zone-stickies {
    overflow-y: visible;
  }

  .home-panels {
    flex-direction: column;
  }

  /* .today-agenda/.shopping-panel comptaient sur un enchainement de flex:1 remontant jusqu'a la
     hauteur fixe de .home (voir plus haut) pour se dimensionner - .home etant desormais en hauteur
     automatique, ce chainage n'a plus rien a remplir et les deux panneaux s'effondraient a 0 (ils
     "disparaissaient"). Hauteur explicite ici : independante de la hauteur du parent, garantit un
     panneau (et son scroll interne, voir .agenda-scroll/.shopping-list-scroll) meme dans une zone en
     auto-hauteur. */
  .today-agenda,
  .shopping-panel {
    width: 100%;
    max-width: 100%;
    flex: 0 0 auto;
    height: 42vh;
    min-height: 220px;
    max-height: 320px;
  }

  /* Remis dans le flux normal (en pied de page) plutot que fixes : sur une page qui defile
     desormais reellement, des boutons fixes finissent toujours par chevaucher le dernier post-it
     ou le dernier article de la liste au moment ou on les atteint en scrollant. */
  .app-brand,
  .parent-link,
  .sound-unlock-btn,
  .add-sticky-btn {
    position: static;
    display: inline-flex;
    margin: 6px;
    opacity: 1;
  }

  /* Agenda plus dense : la hauteur du panneau est plus contrainte qu'avant (voir .today-agenda
     ci-dessus), autant faire tenir plus de lignes dedans plutot que d'agrandir le fondu/scroll. */
  .home-panels .section-title {
    margin-bottom: 4px;
    padding-bottom: 4px;
  }

  .agenda-subheading {
    margin: 0 0 2px;
  }

  #agenda-tomorrow-section {
    margin-top: 6px !important;
  }

  .agenda-row {
    padding: 4px;
  }
}
