/* KAFOUDJ — feuille de style unique.
   Sobre et dense : l'écran de gestion doit rester lisible avec une quarantaine
   de séjours à l'écran, comme le tableau de l'ancienne version. */

:root {
  --fond:        #f4f5f7;
  --surface:     #ffffff;
  --surface-2:   #fafbfc;
  --bordure:     #dfe3e8;
  --texte:       #1b2733;
  --texte-doux:  #64748b;
  --accent:      #2b6cb0;
  --accent-fonce:#21548a;
  --succes:      #2f7d4f;
  --alerte:      #b5793a;
  --erreur:      #c0392b;
  --rayon:       8px;
  --ombre:       0 1px 2px rgba(16, 24, 40, .06), 0 1px 3px rgba(16, 24, 40, .1);
}

/* Palette sombre déclarée sous les deux portées : la media query suit le
   réglage du système, le sélecteur [data-theme] laisse la place à un futur
   choix explicite dans l'application. Sans le second, une page marquée
   data-theme="dark" garderait des fonds clairs sous des couleurs sombres. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --fond:       #12161c;
    --surface:    #1a2029;
    --surface-2:  #202834;
    --bordure:    #2e3844;
    --texte:      #e5e9ef;
    --texte-doux: #94a3b8;
    --accent:     #63a4e8;
    --accent-fonce:#8cbdf0;
    --succes:     #5cb98a;
    --alerte:     #d9a05b;
    --erreur:     #e57368;
    --ombre:      0 1px 3px rgba(0, 0, 0, .4);
  }
}
:root[data-theme="dark"] {
  --fond:       #12161c;
  --surface:    #1a2029;
  --surface-2:  #202834;
  --bordure:    #2e3844;
  --texte:      #e5e9ef;
  --texte-doux: #94a3b8;
  --accent:     #63a4e8;
  --accent-fonce:#8cbdf0;
  --succes:     #5cb98a;
  --alerte:     #d9a05b;
  --erreur:     #e57368;
  --ombre:      0 1px 3px rgba(0, 0, 0, .4);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--fond);
  color: var(--texte);
  font: 14px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

a { color: var(--accent); }

/* ------------------------------------------------------------- barre haute */
.barre {
  display: flex; align-items: center; gap: 20px;
  padding: 0 20px; height: 54px;
  background: var(--surface);
  border-bottom: 1px solid var(--bordure);
  position: sticky; top: 0; z-index: 20;
  flex-wrap: wrap;
}
.marque {
  font-weight: 700; letter-spacing: .08em; font-size: 16px;
  color: var(--texte); text-decoration: none;
}
.barre nav { display: flex; gap: 4px; flex: 1; flex-wrap: wrap; }
.barre nav a {
  padding: 7px 12px; border-radius: 6px; text-decoration: none;
  color: var(--texte-doux); font-weight: 500; white-space: nowrap;
}
.barre nav a:hover { background: var(--surface-2); color: var(--texte); }
.barre nav a.actif { background: var(--accent); color: #fff; }
.barre-fin { display: flex; align-items: center; gap: 8px; }
.icone {
  text-decoration: none; color: var(--texte-doux); font-size: 17px;
  padding: 4px 7px; border-radius: 6px; line-height: 1;
}
.icone:hover { background: var(--surface-2); color: var(--texte); }

/* ------------------------------------------------------------------ cadre */
main { max-width: 1400px; margin: 0 auto; padding: 22px 16px 60px; }
main.large { max-width: 1750px; }
main.etroit { max-width: 460px; padding-top: 8vh; }

h1 { font-size: 21px; margin: 0 0 4px; }
h2 { font-size: 15px; margin: 26px 0 10px; color: var(--texte-doux);
     text-transform: uppercase; letter-spacing: .06em; font-weight: 600; }
.sous-titre { color: var(--texte-doux); margin: 0 0 18px; }

.entete-page {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 18px;
}

/* ------------------------------------------------------------------ blocs */
.carte {
  background: var(--surface); border: 1px solid var(--bordure);
  border-radius: var(--rayon); box-shadow: var(--ombre);
  padding: 16px; margin-bottom: 16px;
}
.carte > h3 { margin: 0 0 12px; font-size: 14px; }

.grille { display: grid; gap: 16px; }
.grille-2 { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.grille-3 { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }

/* ---------------------------------------------------------------- chiffres */
.tuiles { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.tuile {
  background: var(--surface); border: 1px solid var(--bordure);
  border-radius: var(--rayon); padding: 13px 15px; box-shadow: var(--ombre);
}
.tuile .etiquette {
  font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--texte-doux); font-weight: 600;
}
.tuile .valeur { font-size: 22px; font-weight: 650; margin-top: 4px;
                 font-variant-numeric: tabular-nums; }
.tuile .detail { font-size: 12px; color: var(--texte-doux); margin-top: 2px; }
.tuile.accent .valeur { color: var(--accent); }
.tuile.alerte .valeur { color: var(--alerte); }

/* ---------------------------------------------------------------- tableaux */
.tableau-cadre {
  background: var(--surface); border: 1px solid var(--bordure);
  border-radius: var(--rayon); box-shadow: var(--ombre); overflow-x: auto;
}
table { border-collapse: collapse; width: 100%; font-size: 13px; }
th, td { padding: 8px 10px; text-align: left; border-bottom: 1px solid var(--bordure); }
/* Pas de `position: sticky` ici : le conteneur .tableau-cadre est en
   overflow-x auto (13 colonnes à faire tenir sur un écran étroit), ce qui en
   fait un contexte de défilement. Le sticky se cale alors sur ce conteneur et
   non sur la fenêtre, et le décalage prévu pour passer sous la barre de
   navigation rabattait l'en-tête par-dessus la première ligne du tableau. */
th {
  background: var(--surface-2); font-size: 11px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .04em; color: var(--texte-doux);
  white-space: nowrap;
}
tbody tr:last-child td { border-bottom: none; }

/* En-têtes triables : la flèche est réservée en permanence (::after avec une
   largeur fixe) pour que la colonne ne saute pas de quelques pixels au tri. */
th.tri { cursor: pointer; user-select: none; }
th.tri:hover { color: var(--texte); }
th.tri::after {
  content: "↕"; display: inline-block; width: 1em; margin-left: 3px;
  opacity: .3; font-size: 11px;
}
th.tri[aria-sort="ascending"]::after  { content: "↑"; opacity: 1; color: var(--accent); }
th.tri[aria-sort="descending"]::after { content: "↓"; opacity: 1; color: var(--accent); }
th.tri:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
tbody tr:hover { background: var(--surface-2); }
tr.clic { cursor: pointer; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
tfoot td { font-weight: 650; background: var(--surface-2); border-top: 2px solid var(--bordure); }
tr.annulee td { opacity: .45; text-decoration: line-through; }
.vide { padding: 34px; text-align: center; color: var(--texte-doux); }

/* --------------------------------------------------------------- pastilles */
.pastille {
  display: inline-block; padding: 2px 8px; border-radius: 99px;
  font-size: 11px; font-weight: 600; white-space: nowrap;
  border: 1px solid transparent;
}
.pastille.solde   { background: #e4f3ea; color: #2f7d4f; }
.pastille.partiel { background: #fdf2e0; color: #9a6428; }
.pastille.retard  { background: #fbe6e3; color: #b23122; }
.pastille.attente { background: #eef1f5; color: #5a6b80; }
.pastille.option    { background: #eef1f5; color: #5a6b80; }
.pastille.confirmee { background: #e6eefa; color: #2b6cb0; }
.pastille.terminee  { background: #eef1f5; color: #5a6b80; }
.pastille.annulee   { background: #fbe6e3; color: #b23122; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .pastille.solde   { background: #1d3a2a; color: #7fd3a4; }
  :root:not([data-theme="light"]) .pastille.partiel { background: #3a2f1b; color: #e0b271; }
  :root:not([data-theme="light"]) .pastille.retard,
  :root:not([data-theme="light"]) .pastille.annulee { background: #3d211d; color: #f0908a; }
  :root:not([data-theme="light"]) .pastille.attente,
  :root:not([data-theme="light"]) .pastille.option,
  :root:not([data-theme="light"]) .pastille.terminee { background: #262f3b; color: #a3b1c2; }
  :root:not([data-theme="light"]) .pastille.confirmee { background: #1e3350; color: #8cbdf0; }
}
  :root[data-theme="dark"] .pastille.solde   { background: #1d3a2a; color: #7fd3a4; }
  :root[data-theme="dark"] .pastille.partiel { background: #3a2f1b; color: #e0b271; }
  :root[data-theme="dark"] .pastille.retard,
  :root[data-theme="dark"] .pastille.annulee { background: #3d211d; color: #f0908a; }
  :root[data-theme="dark"] .pastille.attente,
  :root[data-theme="dark"] .pastille.option,
  :root[data-theme="dark"] .pastille.terminee { background: #262f3b; color: #a3b1c2; }
  :root[data-theme="dark"] .pastille.confirmee { background: #1e3350; color: #8cbdf0; }

/* Couleurs d'origine — palette catégorielle validée (séparation vision normale
   et daltonienne vérifiée dans les deux thèmes). Les couleurs « de marque »
   employées auparavant (corail Airbnb, orange Leboncoin) étaient à ΔE 6,9 l'une
   de l'autre : indistinguables, même à vision normale. Chaque origine garde sa
   teinte quelles que soient celles présentes dans une saison. */
:root {
  --origine-airbnb:    #eb6834;
  --origine-leboncoin: #2a78d6;
  --origine-autre:     #1baf7a;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --origine-airbnb:    #d95926;
    --origine-leboncoin: #3987e5;
    --origine-autre:     #199e70;
  }
}
:root[data-theme="dark"] {
  --origine-airbnb:    #d95926;
  --origine-leboncoin: #3987e5;
  --origine-autre:     #199e70;
}

.plateforme {
  display: inline-block; width: 9px; height: 9px; border-radius: 3px;
  margin-right: 6px; vertical-align: baseline;
}
.plateforme.airbnb    { background: var(--origine-airbnb); }
.plateforme.leboncoin { background: var(--origine-leboncoin); }
.plateforme.autre     { background: var(--origine-autre); }

/* --------------------------------------------- répartition par origine --- */
/* Barre empilée à 100 % : la part de chaque origine dans les recettes de la
   saison. Un écart de 2px entre segments (bordure couleur surface) évite que
   deux parts voisines se lisent comme une seule. */
.repartition { display: flex; height: 22px; border-radius: 4px; overflow: hidden;
               background: var(--surface-2); min-width: 130px; }
.repartition .part {
  display: flex; align-items: center; justify-content: center;
  font-size: 10.5px; font-weight: 650; overflow: hidden;
  border-right: 2px solid var(--surface); white-space: nowrap;
}
.repartition .part:last-child { border-right: none; }
/* La couleur du pourcentage suit la clarté de son segment : en blanc partout,
   il devenait illisible sur le jaune et le vert, dont le contraste avec du
   blanc tombe sous le seuil des petits textes. */
.part.airbnb    { background: var(--origine-airbnb);    color: #2b1505; }
.part.leboncoin { background: var(--origine-leboncoin); color: #fff; }
.part.autre     { background: var(--origine-autre);     color: #04291b; }

.legende-origines { display: flex; gap: 16px; flex-wrap: wrap; margin: 0 0 12px;
                    font-size: 12px; color: var(--texte-doux); }
.legende-origines span { display: flex; align-items: center; gap: 6px; }
.legende-origines i { width: 11px; height: 11px; border-radius: 3px; display: inline-block; }

/* --------------------------------------------------------------- formulaire */
label { display: block; font-size: 12px; font-weight: 600; color: var(--texte-doux);
        margin-bottom: 4px; }
input, select, textarea {
  width: 100%; padding: 8px 10px; font: inherit; color: var(--texte);
  background: var(--surface); border: 1px solid var(--bordure);
  border-radius: 6px;
}
input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent);
}
input[type="checkbox"] { width: auto; }
textarea { resize: vertical; min-height: 70px; }
.champ { margin-bottom: 12px; }
.champs { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
.champs.serre { grid-template-columns: repeat(auto-fit, minmax(105px, 1fr)); }
.aide { font-size: 11px; color: var(--texte-doux); margin-top: 3px; }

.bascule { display: flex; gap: 0; border: 1px solid var(--bordure); border-radius: 6px;
           overflow: hidden; }
.bascule input { display: none; }
.bascule label {
  flex: 1; margin: 0; padding: 8px 10px; text-align: center; cursor: pointer;
  background: var(--surface); font-size: 13px; font-weight: 500; color: var(--texte-doux);
  border-right: 1px solid var(--bordure);
}
.bascule label:last-of-type { border-right: none; }
.bascule input:checked + label { background: var(--accent); color: #fff; }

/* ------------------------------------------------------------------ boutons */
.bouton {
  display: inline-block; padding: 8px 14px; border-radius: 6px;
  border: 1px solid var(--bordure); background: var(--surface); color: var(--texte);
  font: inherit; font-weight: 550; cursor: pointer; text-decoration: none;
  white-space: nowrap;
}
.bouton:hover { background: var(--surface-2); }
.bouton-accent { background: var(--accent); border-color: var(--accent); color: #fff; }
.bouton-accent:hover { background: var(--accent-fonce); }
.bouton-danger { color: var(--erreur); border-color: var(--erreur); background: transparent; }
.bouton-danger:hover { background: var(--erreur); color: #fff; }
.bouton.petit { padding: 5px 10px; font-size: 12px; }

/* « Tout encaissé » : il n'apparaît que sur un séjour dont le solde est positif,
   donc rarement — il doit se repérer d'un coup d'œil parmi les autres boutons.
   La pulsation est lente et de faible amplitude : elle attire le regard sans
   scintiller. Elle s'arrête au survol, et ne démarre pas du tout chez qui a
   demandé à son système de limiter les animations. */
.bouton-encaisser {
  background: #c0392b; border-color: #c0392b; color: #fff;
  font-weight: 650;
  /* Deux pulsations rapprochées puis un temps de repos : le rythme d'un
     battement de cœur. L'amplitude reste faible (3,5 % d'agrandissement) pour
     attirer l'œil sans faire sautiller la barre de boutons. */
  animation: battement 2.4s ease-in-out infinite;
}
/* Au survol le rouge s'éclaircit de 27 % — il reste un rouge, et c'est
   l'éclaircissement le plus marqué qui garde le libellé blanc lisible
   (4,53:1, juste au-dessus du seuil de 4,5). */
.bouton-encaisser:hover {
  background: #d54132; border-color: #d54132; color: #fff;
  animation: none;
}
@keyframes battement {
  0%       { transform: scale(1);     box-shadow: 0 0 0 0 rgba(192, 57, 43, .50); }
  12%      { transform: scale(1.035); box-shadow: 0 0 0 5px rgba(192, 57, 43, .22); }
  24%      { transform: scale(1);     box-shadow: 0 0 0 0 rgba(192, 57, 43, .40); }
  36%      { transform: scale(1.022); box-shadow: 0 0 0 8px rgba(192, 57, 43, 0); }
  48%, 100%{ transform: scale(1);     box-shadow: 0 0 0 0 rgba(192, 57, 43, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .bouton-encaisser { animation: none; box-shadow: 0 0 0 3px rgba(192, 57, 43, .35); }
}
.actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.actions.fin { justify-content: flex-end; }
/* Les champs sont en width:100% par défaut (formulaires en colonne) ; dans une
   barre d'actions ils doivent au contraire se dimensionner sur leur contenu,
   sinon un simple sélecteur d'année pousse les boutons voisins à la ligne. */
.actions select, .actions input, .actions button { width: auto; }

/* ----------------------------------------------------------------- messages */
.messages { margin-bottom: 16px; }
.message {
  margin: 0 0 8px; padding: 10px 14px; border-radius: 6px;
  border-left: 3px solid var(--texte-doux); background: var(--surface);
  box-shadow: var(--ombre);
}
.message-succes { border-left-color: var(--succes); }
.message-erreur { border-left-color: var(--erreur); }
.message-alerte { border-left-color: var(--alerte); }

/* --------------------------------------------------------------- calendrier */
.calendrier { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(255px, 1fr)); }
.mois {
  background: var(--surface); border: 1px solid var(--bordure);
  border-radius: var(--rayon); padding: 11px; box-shadow: var(--ombre);
}
.mois h3 { margin: 0 0 8px; font-size: 13px; text-transform: capitalize; }
.jours { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.jours .entete {
  font-size: 10px; color: var(--texte-doux); text-align: center; font-weight: 600;
  padding-bottom: 2px;
}
.jour {
  aspect-ratio: 1; display: flex; align-items: center; justify-content: center;
  font-size: 11.5px; border-radius: 4px; text-decoration: none; color: var(--texte);
  font-variant-numeric: tabular-nums;
}
.jour.hors { visibility: hidden; }
.jour.libre:hover { background: var(--surface-2); outline: 1px solid var(--bordure); }
.jour.occupe { color: #fff; font-weight: 600; }
.jour.occupe.airbnb    { background: var(--origine-airbnb); }
.jour.occupe.leboncoin { background: var(--origine-leboncoin); }
.jour.occupe.autre     { background: var(--origine-autre); }
.jour.aujourdhui { outline: 2px solid var(--accent); outline-offset: -2px; font-weight: 700; }
.legende { display: flex; gap: 14px; flex-wrap: wrap; font-size: 12px;
           color: var(--texte-doux); margin-bottom: 14px; }
.legende span { display: flex; align-items: center; gap: 5px; }

/* -------------------------------------------------------- lignes répétables */
.lignes { display: flex; flex-direction: column; gap: 8px; }
.ligne {
  display: grid; gap: 8px; align-items: start;
  grid-template-columns: 1fr 120px auto;
}
.ligne.paiement { grid-template-columns: 1fr 110px 130px 130px 110px auto; }
.ligne .supprimer {
  background: none; border: none; color: var(--texte-doux); cursor: pointer;
  font-size: 17px; padding: 6px 8px; line-height: 1; border-radius: 6px; width: auto;
}
.ligne .supprimer:hover { color: var(--erreur); background: var(--surface-2); }
@media (max-width: 720px) {
  .ligne, .ligne.paiement { grid-template-columns: 1fr 1fr; }
}

/* ---------------------------------------------------------------- récapitulatif */
.recap { position: sticky; top: 70px; }
.recap dl { margin: 0; display: grid; grid-template-columns: 1fr auto; gap: 7px 12px; }
.recap dt { color: var(--texte-doux); }
.recap dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; font-weight: 550; }
.recap .total { border-top: 1px solid var(--bordure); padding-top: 9px; margin-top: 3px; }
.recap .total dt, .recap .total dd { font-size: 16px; font-weight: 700; color: var(--texte); }

/* ------------------------------------------------------------------- divers */
.barre-outils { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 14px; }
.barre-outils form { display: flex; gap: 8px; align-items: center; }
.barre-outils input[type="search"] { width: 240px; }
.discret { color: var(--texte-doux); font-size: 12px; }
.centre { text-align: center; }
details.repli summary { cursor: pointer; font-weight: 600; color: var(--texte-doux);
                        padding: 6px 0; font-size: 13px; }

/* ------------------------------------------- règlements déjà encaissés --- */
/* Listés sous le récapitulatif, chacun annulable : un « Tout encaissé »
   cliqué par erreur se répare sans passer par l'échéancier, et sans risquer
   d'emporter un acompte voisin. */
.reglements { margin-top: 12px; border-top: 1px solid var(--bordure); padding-top: 10px; }
.etiquette-reglements {
  font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--texte-doux); font-weight: 600; margin-bottom: 6px;
}
.reglement {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-size: 12.5px; padding: 3px 0;
}
.reglement .supprimer { font-size: 15px; padding: 2px 6px; }
