/* ─── Boutons : cinq etats explicites (DESIGN.md, section Etats) ───
   repos, survol (un pas de clarte), focus clavier (anneau global
   :focus-visible de variables.css), actif (retour sous 100 ms : echelle
   0.985 + fond assombri), desactive (couleurs dediees, jamais d'opacite).
   Seuls transform et les couleurs transitionnent : pas de lift, pas de
   halo. */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 16px;
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: var(--weight-emphasis);
  cursor: pointer;
  border: none;
  transition: background-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
  white-space: nowrap;
}

.btn:active {
  transform: scale(0.985);
}

.btn:disabled,
.btn[aria-disabled="true"] {
  background: var(--surface2);
  color: var(--muted2);
  border-color: transparent;
  cursor: not-allowed;
  transform: none;
}

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

.btn-primary .upte-icon {
  color: var(--on-primary);
  --icon-tint: color-mix(in srgb, var(--on-primary) 24%, transparent);
}

.btn-primary:hover {
  background: var(--green2);
}

.btn-primary:active {
  background: color-mix(in srgb, var(--green3) 88%, var(--bg));
}

.btn-ghost {
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
}

.btn-ghost:hover {
  background: var(--surface);
  color: var(--text);
}

.btn-ghost:active {
  background: var(--surface2);
  color: var(--text);
}

.btn-danger {
  background: var(--red-dim);
  color: var(--red);
  border: 1px solid color-mix(in srgb, var(--red) 20%, transparent);
}

.btn-danger:hover {
  background: color-mix(in srgb, var(--red) 20%, transparent);
}

.btn-danger:active {
  background: color-mix(in srgb, var(--red) 28%, transparent);
}

.btn-sm {
  padding: 5px 10px;
  font-size: 12px;
}

/* ─── Tags ─── */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  padding: 3px 8px;
  border-radius: var(--radius-xs);
}

.tag-green {
  background: var(--green-dim);
  color: var(--green-text);
}

.tag-orange {
  background: var(--orange-dim);
  color: var(--orange);
}

.tag-red {
  background: var(--red-dim);
  color: var(--red);
}

.tag-muted {
  background: var(--surface2);
  color: var(--muted);
}

/* ─── Animations ─── */
/* fadeIn : definition canonique unique (opacity only). Auparavant defini 3
   fois (utilities.css x2 + ar-ui.css), avec des translateY differents qui
   etaient silencieusement ecrases par l'ordre des imports. Ici on fige le
   comportement runtime existant (opacity-only, du a ar-ui qui chargeait en
   dernier) et on supprime les autres pour eviter qu'une edition future ne
   modifie inopineement un fichier dont la version etait morte. */
@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(12px) scale(0.96);
  }

  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

@keyframes toast-out {
  to {
    opacity: 0;
    transform: translateY(8px) scale(0.95);
  }
}

@media (max-width: 900px) {
  @keyframes toast-in {
    from {
      opacity: 0;
      transform: translateY(16px) scale(0.95);
    }

    to {
      opacity: 1;
      transform: translateY(0) scale(1);
    }
  }

  @keyframes toast-out {
    to {
      opacity: 0;
      transform: translateY(12px) scale(0.94);
    }
  }
}

.fade-in {
  animation: fadeIn var(--dur-slow) var(--ease-out);
}

.page {
  display: none;
  opacity: 0;
}

/* Sortie de page pilotee par UI.navigate (classe, pas de style inline) :
   l'ancienne page s'efface sur place pendant --dur-fast. */
.page.active.page--leaving {
  opacity: 0;
  transform: scale(0.98);
  transition: opacity var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
  animation: none;
}

.page.active {
  display: block;
  /* opacity explicite (pas de animation-fill-mode: forwards) : sinon forwards
     laisse un transform identite calcule permanent -> contexte d'empilement qui
     piege les menus position:fixed sous les modals. Sans forwards, apres
     l'animation le transform revient a `none` et l'opacite reste a 1 grace a
     cette regle de base. */
  opacity: 1;
  animation: pageEnter var(--dur-base) var(--ease-out);
}

@keyframes pageEnter {
  from {
    opacity: 0;
    transform: scale(0.97) translateY(6px);
  }

  to {
    opacity: 1;
    /* `none` (et non scale(1) translateY(0)) : sinon animation-fill-mode:
       forwards laisse un transform identite permanent sur la page active, ce
       qui cree un contexte d'empilement + un bloc conteneur. Resultat : les
       menus en position:fixed (combobox) etaient pieges sous les modals et la
       barre de nav. Visuellement identique, mais la page ne capture plus le
       fixed une fois l'animation finie. */
    transform: none;
  }
}

/* ─── Divider ─── */
.divider {
  height: 1px;
  background: var(--border);
  margin: 16px 0;
}

/* ─── Helpers ─── */
.section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}

.section-title {
  font-family: var(--font-display), sans-serif;
  font-weight: 700;
  font-size: 15px;
  color: var(--text);
}

.gap-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.mb-4 {
  margin-bottom: 16px;
}

.mb-6 {
  margin-bottom: 24px;
  margin-top: 24px;
}

.mt-6 {
  margin-top: 24px;
}

/* ─── Settings — liste des cours ─── */
.settings-course-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  background: var(--bg3);
  margin-bottom: 6px;
  transition: background var(--dur-base);
}

.settings-course-item:hover {
  background: var(--surface);
}

.sci-color {
  width: 4px;
  height: 36px;
  border-radius: var(--radius-xs);
  flex-shrink: 0;
}

.sci-info {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}

.sci-code {
  font-family: var(--font-display), sans-serif;
  font-weight: 700;
  font-size: 11px;
  flex-shrink: 0;
}

.sci-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sci-meta {
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
}

.sci-actions {
  display: flex;
  gap: 4px;
  flex-shrink: 0;
}

/* ─── Color picker ─── */
.color-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 6px;
}

.color-dot {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 2px solid transparent;
  cursor: pointer;
  transition: transform var(--dur-fast), border-color var(--dur-fast);
  padding: 0;
  flex-shrink: 0;
}

.color-dot:hover {
  transform: scale(1.15);
}

.color-dot.active {
  border-color: var(--text);
  transform: scale(1.15);
  box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--text);
}

/* ─── Schedule builder — modales cours (canonical) ─── */
.schedule-rows {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 8px;
}

.schedule-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  background: var(--bg3);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  transition: border-color var(--dur-base);
}

@media (min-width: 480px) {
  .schedule-row {
    padding: 14px 16px;
  }
}

.schedule-row:hover {
  border-color: var(--green3);
}

.schedule-add-btn {
  width: 100%;
  justify-content: center;
  margin-top: 4px;
  border-style: dashed;
}

.schedule-add-btn:hover {
  border-color: var(--green3);
  color: var(--green-text);
  background: var(--green-dim);
  border-style: dashed;
}

.schedule-empty-hint {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--muted2);
  padding: 10px 0 8px;
}

#add-schedules-error,
#edit-schedules-error {
  font-size: 11px;
  color: var(--red);
  margin-top: 4px;
  display: none;
}

#add-schedules-error.show,
#edit-schedules-error.show {
  display: block;
}

/* ─── Créneaux horaires dynamiques ─── */
.schedule-slots-container {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 6px;
}

.schedule-slot-row {
  animation: fadeIn var(--dur-base) var(--ease-out);
}

.slot-row-inner {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.slot-sep {
  font-size: 14px;
  color: var(--muted);
  padding-top: 10px;
  flex-shrink: 0;
}

.slot-del-btn {
  flex-shrink: 0;
  margin-top: 2px;
}

.schedule-slots-empty {
  font-size: 12px;
  color: var(--muted2);
  text-align: center;
  padding: 12px 0;
  font-style: italic;
}

.schedule-add-btn {
  width: 100%;
  justify-content: center;
  border-style: dashed;
  margin-top: 4px;
}

.schedule-add-btn:hover {
  border-color: var(--green3);
  color: var(--green-text);
  background: var(--green-dim);
}

.schedule-section-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: 8px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

/* ─── Course detail — créneaux ─── */
.cd-slot-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  background: var(--bg3);
  border-radius: var(--radius-sm);
  margin-bottom: 6px;
  font-size: 12.5px;
}

.cd-slot-day {
  font-family: var(--font-display), sans-serif;
  font-weight: 700;
  font-size: 12px;
  min-width: 70px;
}

.cd-slot-time {
  font-weight: 500;
  color: var(--text);
  flex: 1;
}

.cd-slot-salle {
  font-size: 11px;
  color: var(--muted);
}

/* ─── Settings — slots tags ─── */
.sci-slots {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 3px;
}

.sci-slot-tag {
  font-size: 10px;
  background: var(--green-dim);
  color: var(--green-text);
  padding: 2px 7px;
  border-radius: var(--radius-xs);
  font-weight: 500;
}

/* ─── Combobox custom (remplace datalist) ─── */
.combo-wrap {
  position: relative;
}

.combo-input {
  width: 100%;
  background: var(--bg3);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  min-height: 44px;
  padding: 10px 36px 10px 14px;
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--text-md);
  outline: none;
  transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
  cursor: text;
}

.combo-input:focus {
  border-color: var(--green3);
  box-shadow: 0 0 0 3px var(--green-dim);
}

.combo-chevron {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--muted);
  pointer-events: none;
  transition: transform var(--dur-base);
}

.combo-wrap.open .combo-chevron {
  transform: translateY(-50%) rotate(180deg);
}

.combo-dropdown {
  /* position: fixed -> le menu echappe a `overflow: hidden` des cartes
     parentes (sinon il etait coupe en bas, ex. Semestre sur ecran court).
     left / width / top|bottom / max-height sont poses par Combo._position(). */
  position: fixed;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  z-index: calc(var(--z-feuille) + 30);
  display: none;
  max-height: 280px;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.combo-wrap.open .combo-dropdown {
  display: block;
}

.combo-option {
  padding: 9px 14px;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
  transition: background var(--dur-fast);
}

.combo-option:hover,
.combo-option.highlighted {
  background: var(--green-dim);
  color: var(--green-text);
}

.combo-option.no-results {
  color: var(--muted);
  cursor: default;
  font-style: italic;
}

.combo-option.no-results:hover {
  background: transparent;
  color: var(--muted);
}

/* ─── Theme switcher toast ─── */
.theme-preview-dots {
  display: flex;
  gap: 5px;
  align-items: center;
}

.tpd {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: 1.5px solid var(--border);
  transition: background-color var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out), opacity var(--dur-base) var(--ease-out);
}

/* Pastilles de theme : chaque pastille montre la couleur du theme qu'elle
   represente, donc une valeur fixe par pastille (independante du theme actif). */
.tpd[data-theme="light"] {
  background: var(--swatch-light);
}

.tpd[data-theme="blue"] {
  background: var(--swatch-blue);
}

.tpd[data-theme="green"] {
  background: var(--swatch-green);
}

.tpd[data-theme="rose"] {
  background: var(--swatch-rose);
}

.tpd.active {
  transform: scale(1.4);
  border-color: var(--green);
}

/* ─── Bouton container topbar (plein ecran, cloche notif) ─── */
.btn-fullscreen {
  width: var(--tap-min);
  height: var(--tap-min);
  border-radius: var(--radius-sm);
  border: none;
  background: var(--surface2);
  color: var(--muted);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              transform var(--dur-base) var(--ease-out);
  flex-shrink: 0;
}

.btn-fullscreen:hover {
  background: var(--green-dim);
  color: var(--green-text);
}

.btn-fullscreen:active {
  background: var(--surface);
  transform: scale(0.96);
}

/* ─── Météo académique ─── */
.dash-weather-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 18px;
  border-radius: var(--radius);
  margin-bottom: 20px;
  background: var(--surface);
  animation: fadeIn var(--dur-slow) var(--ease-out);
}

.weather-active {
  border-color: var(--green3);
  background: var(--green-dim);
}

.weather-heavy {
  background: var(--red-dim);
}

.weather-medium {
  background: var(--orange-dim);
}

.weather-light {
  border-color: var(--green3);
  background: var(--green-dim);
}

.weather-done {
  border-color: var(--border);
  color: var(--muted);
}

.weather-free {
  border-color: var(--border);
}

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

.weather-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.weather-label {
  font-family: var(--font-display), sans-serif;
  font-weight: 700;
  font-size: 13px;
  color: var(--text);
}

.weather-sub {
  font-size: 12px;
  color: var(--muted);
}

/* ════════ (Innovation nav) Badges + prise en main + barre d'onglets ════════ */

/* A. Badge contextuel sur un item de nav (compteur d'attention, pousse a droite). */
.nav-badge {
  margin-left: auto;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--radius-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display), sans-serif;
  font-size: 10.5px;
  font-weight: 700;
  line-height: 1;
  color: var(--green-text);
  background: var(--green-dim);
  border: 1px solid var(--green3);
}

.nav-badge[hidden] { display: none; }

.nav-badge[data-tone="urgent"] {
  /* Le rouge du theme clair ne tient que 4,2:1 sur son lavis. */
  color: color-mix(in srgb, var(--red) 80%, var(--text));
  background: var(--red-dim);
  border-color: var(--red);
}

/* Sur l'item actif (fond sature), on garde le badge lisible. */
.nav-item.active .nav-badge {
  color: var(--on-primary);
  background: var(--green3);
}

/* B. Fil de prise en main dans la sidebar. */
.nav-onboarding {
  margin: 12px 10px 4px;
  padding: 12px;
  border-radius: var(--radius);
  background: var(--surface);
}

.nav-onboarding[hidden] { display: none; }

.nav-onb-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 8px;
}

.nav-onb-title {
  font-family: var(--font-display), sans-serif;
  font-weight: 700;
  font-size: 12px;
  color: var(--text);
}

.nav-onb-count {
  font-size: 11px;
  font-weight: 600;
  color: var(--green-text);
}

.nav-onb-bar {
  height: 4px;
  border-radius: var(--radius-pill);
  background: var(--surface2);
  overflow: hidden;
  margin-bottom: 10px;
}

.nav-onb-fill {
  height: 100%;
  border-radius: var(--radius-pill);
  background: var(--green);
  transition: width var(--dur-screen) var(--ease-out);
}

.nav-onb-cta {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--green-dim);
  color: var(--text);
  font: inherit;
  font-size: 12.5px;
  font-weight: 500;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out);
}

.nav-onb-cta:hover { background: var(--green-glow); }
.nav-onb-cta svg { margin-left: auto; color: var(--green); flex-shrink: 0; }

.nav-onb-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--green);
  flex-shrink: 0;
  box-shadow: 0 0 0 3px var(--green-dim);
}

/* C. Barre d'onglets mobile (acces rapide). Cachee sur desktop. */
.bottom-tabs { display: none; }

@media (max-width: 900px) {
  .bottom-tabs {
    display: grid;
    /* 5 onglets (Biblio) puis la case d'Apte. minmax(0, 1fr) : une colonne
       ne grossit jamais avec son texte (police systeme a 130 %, petit
       ecran) ; si un libelle ne tient plus, la barre passe en icones
       seules (barreAdaptative dans ui.js, design/bibliotheque/barre6). */
    grid-template-columns: repeat(5, minmax(0, 1fr)) calc(var(--fab-size-barre) + var(--space-4));
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: var(--z-barre);
    background: var(--bg2);
    border-top: 1px solid var(--border);
    padding-bottom: var(--safe-bottom);
    /* Paysage : les onglets sortent de l'encoche. */
    padding-left: var(--safe-left);
    padding-right: var(--safe-right);
  }

  /* Place pour la barre. L'orbe d'Apte vit dans la barre, le contenu n'a
     plus a lui reserver de hauteur. Specificite .app .content -> bat les
     paddings responsives en shorthand quel que soit l'ordre source. */
  .app .content {
    padding-bottom: calc(var(--bottom-tabs-space) + var(--safe-bottom));
  }

  .bottom-tabs .bt-item { min-width: 0; }

  .bottom-tabs .bt-item span { white-space: nowrap; }

  /* Temoin de taille de police (ui.js, barreAdaptative) : jamais vu. */
  .bt-temoin {
    position: absolute;
    visibility: hidden;
    white-space: nowrap;
    pointer-events: none;
    font-style: normal;
  }

  /* Un libelle ne tient plus (petit ecran, police grossie) : icones seules.
     Les libelles restent pour les lecteurs d'ecran ; la case garde sa
     hauteur pour que rien ne saute. */
  .bottom-tabs--icones .bt-item {
    position: relative;
    justify-content: center;
    min-height: calc(var(--tap-min) + var(--space-2));
  }

  .bottom-tabs--icones .bt-item span {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }

  .bottom-tabs--icones .bt-item svg { width: 24px; height: 24px; }

  /* Mode salon plein ecran : la barre s'efface. */
  .app--room-focus .bottom-tabs { display: none; }

  /* Clavier ouvert (couche.js) : la barre remonterait au-dessus du clavier
     et couvrirait le champ en cours de saisie. Elle revient a la fermeture. */
  .clavier-ouvert .bottom-tabs { display: none; }

  .clavier-ouvert .app .content {
    padding-bottom: calc(var(--space-4) + var(--safe-bottom));
  }
}

.bt-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 9px 4px 7px;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  cursor: pointer;
  color: var(--muted);
  font-family: inherit;
  font-size: 10.5px;
  font-weight: var(--weight-emphasis);
  transition: color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}

.bt-item:hover { color: var(--text); }
.bt-item:active { transform: scale(0.94); }

.bt-item svg { width: 22px; height: 22px; }
/* A11Y-01 : le label 10.5px sous l'icone doit tenir 4.5:1. */
.bt-item.active { color: var(--green-text); }
/* Actif : wash plein, le point de la marque s'allume (regles .nav-dot, bloc
   icones). */
.bt-item.active .upte-icon { --icon-tint: var(--icon-tint-active); }

@media (max-width: 480px) {
  .dash-weather-bar {
    padding: 10px 12px;
  }
}

/* (fadeIn / pomoBadgePop : definitions canoniques uniques. Voir le bloc
   "Animations" en haut du fichier pour fadeIn. pomoBadgePop est defini
   plus bas, ici on supprime les variantes intermediaires.) */

/* (.toast-pomo-card et .tpc-* : definition canonique unique plus bas, dans
   le bloc "Toast card Pomodoro". L'ancienne version etait redondante et
   silencieusement ecrasee, on la supprime pour eviter les regressions de
   maintenance. .tpc-bar.shrink reste defini en bas via la regle
   `transform: scaleX(0)` appliquee a `.tpc-bar` -> rajoute si besoin.) */

/* (.tpc-bar.shrink etait ici uniquement, on le replace pres de la def canon
   de .tpc-bar plus bas.) */

/* (pomoBadgePop : definition canonique unique plus bas, ligne ~1575.) */

/* ─── Indicateur Pomodoro topbar ─── */
.pti-ring {
  flex-shrink: 0;
  display: flex;
  align-items: center;
}

.pti-time {
  font-family: var(--font-display), sans-serif;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: var(--tracking-tight);
  line-height: 1;
}

.pti-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  flex-shrink: 0;
}

.pti-dot.running {
  background: var(--green);
  animation: ptiPulse 1.5s ease infinite;
}

.pti-dot.paused {
  background: var(--muted2);
}

@keyframes ptiPulse {

  0%,
  100% {
    box-shadow: 0 0 0 2px var(--green-dim);
  }

  50% {
    box-shadow: 0 0 0 5px var(--green-dim);
  }
}

/* ─── Badge et animations Pomodoro nav ─── */
@keyframes pomoBadgePop {
  0% {
    transform: scale(0.4);
    opacity: 0;
  }

  70% {
    transform: scale(1.3);
    opacity: 1;
  }

  100% {
    transform: scale(1);
    opacity: 1;
  }
}

/* ─── Toast card Pomodoro ─── */
.toast-pomo-card {
  padding: 0;
  overflow: hidden;
  min-width: 300px;
  flex-direction: column;
  gap: 0;
  position: relative;
}

.tpc-body {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px 10px;
}

.tpc-icon {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-sm);
  border: 1px solid;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.tpc-text {
  flex: 1;
  min-width: 0;
}

.tpc-title {
  font-family: var(--font-display), sans-serif;
  font-weight: 700;
  font-size: 13px;
  color: var(--text);
  line-height: 1;
  margin-bottom: 3px;
}

.tpc-msg {
  font-size: 12px;
  color: var(--muted);
  line-height: 1.4;
}

.tpc-footer {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px 12px;
  border-top: 1px solid var(--border);
}

.tpc-next-label {
  font-size: 11px;
  color: var(--muted2);
}

.tpc-next-badge {
  font-family: var(--font-display), sans-serif;
  font-size: 11px;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: var(--radius-xs);
}

.tpc-bar {
  position: absolute;
  bottom: 0;
  left: 0;
  height: 2px;
  width: 100%;
  transform-origin: left;
  transition: transform 4s linear;
}

/* Etat appliquee via requestAnimationFrame pour declencher la transition de
   shrink (compte a rebours visuel du toast Pomodoro). */
.tpc-bar.shrink {
  transform: scaleX(0);
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* ─── Native WebView performance overrides ─── */
.native-app * {
}

.native-app *,
.native-app *::before,
.native-app *::after {
  transition-duration: 0.1s !important;
  animation-duration: 0.15s !important;
}

.native-app .room-reaction-float,
.native-app .reaction-float,
.native-app .confetti-piece,
.native-app .celebration-pulse,
.native-app .streak-flame {
  animation-duration: 2s !important;
}

.native-app .modal-overlay,
.native-app .sidebar,
.native-app .notif-panel {
  background: var(--surface) !important;
}

/* ─── Guard perf appareils tactiles (PWA navigateur mobile) ───
   L'app native (.native-app) coupe deja le backdrop-filter, mais le site
   ouvert dans le navigateur du telephone (ou "Ajouter a l'ecran d'accueil")
   n'a pas .native-app : il garde tous les flous GPU, qui font freezer le
   rendu sur Android modeste (notre public). On reproduit donc la meme
   suppression sur tout appareil a pointeur grossier (telephones/tablettes),
   et on compense par des fonds plus opaques la ou le flou assurait la
   separation visuelle (sinon le contenu derriere reste trop visible). */
@media (pointer: coarse) {
  *,
  *::before,
  *::after {
  }

  .asst-overlay {
    background: var(--overlay-scrim-solid);
  }

  /* Suggestions de commandes : cibles tactiles confortables (~44px) au lieu
     des ~28px du desktop, pour eviter les ratés au doigt sur mobile. */
  .asst-action-chip {
    min-height: 40px;
    padding: 10px 16px;
    font-size: 13px;
  }
}

/* ─── Celebration confetti ─── */
.celebration-overlay {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: calc(var(--z-toast) + 5);
  overflow: hidden;
}

.confetti-piece {
  position: absolute;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-xs);
  top: -10px;
  animation: confettiFall 2.5s ease-in forwards;
}

@keyframes confettiFall {
  0% {
    transform: translateY(0) rotate(0deg);
    opacity: 1;
  }

  100% {
    transform: translateY(100vh) rotate(720deg);
    opacity: 0;
  }
}

/* ─── Success check pulse ─── */
.celebration-pulse {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(0);
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background: var(--green);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: calc(var(--z-toast) + 6);
  animation: successPop 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
  pointer-events: none;
  box-shadow: 0 0 40px var(--green-dim);
}

.celebration-pulse svg {
  width: 40px;
  height: 40px;
  stroke: var(--white);
  stroke-width: 3;
  fill: none;
}

@keyframes successPop {
  0% {
    transform: translate(-50%, -50%) scale(0);
    opacity: 0;
  }

  50% {
    transform: translate(-50%, -50%) scale(1.2);
    opacity: 1;
  }

  70% {
    transform: translate(-50%, -50%) scale(0.95);
  }

  85% {
    transform: translate(-50%, -50%) scale(1.05);
  }

  100% {
    transform: translate(-50%, -50%) scale(1);
    opacity: 1;
  }
}

/* ─── Streak flame glow ─── */
.streak-flame {
  display: inline-block;
  animation: flameGlow 1.5s ease-in-out infinite alternate;
}

@keyframes flameGlow {
  0% {
    filter: brightness(1) drop-shadow(0 0 2px var(--orange));
  }

  100% {
    filter: brightness(1.3) drop-shadow(0 0 8px var(--red));
  }
}

/* ─── Système d'icônes (duotone) ───
   Les icônes sont rendues par `getIcon()` (svg-icons.js). Elles arrivent avec
   la classe `.upte-icon` plus une taille (--sm/md/lg) et éventuellement un
   état (--active/--muted) ou un thème sémantique (--success/error/warning/info).
   Le wash duotone est piloté par `--icon-tint` (variables.css) et n'apparaît
   que sur les paths qui l'utilisent explicitement (path background des icônes
   "container"). Les icônes ligne pure (close, refresh, forward, etc.) restent
   en outline propre, sans wash. */
.upte-icon {
  flex-shrink: 0;
  vertical-align: middle;
  /* Jeu d'icones UpTe (DESIGN.md, section Icones) : un seul trait,
     --icon-stroke, extremites et angles ronds. Le CSS l'emporte sur
     l'attribut stroke-width des SVG, donc la regle vaut aussi pour les
     icones inline polishes, et il est herite par les clones <use>. */
  stroke-width: var(--icon-stroke);
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: color var(--dur-fast) var(--ease-out), fill var(--dur-fast) var(--ease-out), opacity var(--dur-fast) var(--ease-out);
}

/* Signature d'etat actif de la navigation (DESIGN.md, section Icones).
   Le point de la marque n'existe que dans le balisage des liens de
   navigation (sidebar, barre du bas, hamburger) : un glyphe seul ne peut pas
   l'afficher. Au repos il est invisible ; actif, il prend la couleur du lien
   et le trace se decoupe autour de lui via le masque du sprite (trou
   transparent, independant du fond). Sur le menu, le point ferme la
   troisieme barre : au repos c'est le wash du glyphe, actif il s'allume et
   le masque lui fait son halo. */
.nav-dot {
  fill: none;
  stroke: none;
}

.nav-item.active .nav-dot,
.bt-item.active .nav-dot,
.menu-toggle[aria-expanded="true"] .nav-dot {
  fill: currentColor;
}

.nav-item.active .upte-icon > use,
.bt-item.active .upte-icon > use {
  mask: url(#nav-dot-mask);
}

.menu-toggle[aria-expanded="true"] .upte-icon > use {
  mask: url(#nav-dot-mask-menu);
}

.upte-icon--sm {
  width: 16px;
  height: 16px;
}

.upte-icon--md {
  width: 24px;
  height: 24px;
}

.upte-icon--lg {
  width: 32px;
  height: 32px;
}

/* État actif : wash duotone plus marqué + couleur saturée. */
.upte-icon--active {
  --icon-tint: var(--icon-tint-active);
  color: var(--green-text);
}

/* État muted : opacité réduite, pas de wash. */
.upte-icon--muted {
  --icon-tint: transparent;
  opacity: .55;
}

/* Variantes sémantiques (toasts, statuts). Le stroke utilise currentColor,
   donc régler `color` propage sur l'icône. */
.upte-icon--success {
  color: var(--green-text);
}

.upte-icon--error {
  color: var(--red);
}

.upte-icon--warning {
  color: var(--orange);
}

.upte-icon--info {
  color: var(--green3);
}

/* `prefers-reduced-motion` : désactive les transitions douces. */
@media (prefers-reduced-motion: reduce) {
  .upte-icon {
    transition: none;
  }
}
/* Contenu reserve aux lecteurs d'ecran : visible pour eux, invisible a
   l'oeil. Ne pas utiliser display:none, qui le retirerait aussi de l'arbre
   d'accessibilite. Premier consommateur : la region d'annonces du salon
   (entree, sortie, main levee, reconnexion, fin de session). */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}


/* ─── Ecran tactile : cibles a 44 px (--tap-min) ───
   Uniquement au doigt : a la souris, rien ne change. */
@media (pointer: coarse) {
  .nav-onb-cta,
  .asst-action-chip {
    min-height: var(--tap-min);
  }
}
