:root {
  --bg: #f5f4f0;            /* fond crème très clair */
  --card: #ffffff;
  --ink: #252c3b;           /* bleu nuit DB Group */
  --muted: #6b7280;
  --navy: #252c3b;
  --cream: #efe8d9;
  --gold: #c2a264;
  --accent: #252c3b;
  /* Encre accentuée : la même couleur que --accent tant qu'elle sert de TEXTE.
     Les deux se séparent en mode sombre, où --accent reste un fond (bleu nuit
     sous du blanc) alors qu'un texte de cette teinte disparaîtrait dans la
     page. Toute couleur de texte accentuée doit passer par ici. */
  --accent-ink: #252c3b;
  --accent-soft: #ece7da;
  --pos: #157e49;          /* assombri : #178a50 tombait à 4,4:1 sur blanc */
  --neg: #c43d3d;
  /* Fond d'un écart calculé faute de référence N-1 : beige neutre, ni vert ni
     rouge — il ne juge pas le chiffre, il dit qu'il se lit sur un zéro. */
  --noref-bg: #ece7dc;
  /* Fond d'une cellule que le calendrier d'ouverture déclare fermée : gris
     neutre, volontairement distinct du beige ci-dessus — « fermé » et « pas de
     référence N-1 » sont deux histoires, deux teintes. */
  --ferme-bg: #e6e8ec;
  --border: #e4e1d8;
  --radius: 12px;
  --shadow: 0 1px 3px rgba(37, 44, 59, .10);
  --table-bg: #fff;
  --table-head-bg: #fafbfc;
}
* { box-sizing: border-box; }
body {
  margin: 0;
  font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
  background: var(--bg);
  color: var(--ink);
  font-size: 15px;
}
a { color: var(--accent-ink); text-decoration: none; }

/* --- thème Palm Beach (vert olive + doré) --- */
body.company-palmbeach {
  --navy: #4a5130;
  --ink: #3c4227;
  --accent: #4a5130;
  --accent-ink: #4a5130;
  --accent-soft: #ecead9;
  --gold: #c2a264;
  --cream: #f0ead6;
  --bg: #f6f5ee;
}
body.company-palmbeach .topnav { background: #4a5130; }
body.company-palmbeach.login-page { background: #4a5130; }

/* --- thème Nammos (turquoise adouci) --- */
body.company-nammos {
  --navy: #47867f;
  --ink: #2e5c57;
  --accent: #47867f;
  --accent-ink: #3e756f;   /* assombri : #47867f tombait à 3,6:1 sur --accent-soft */
  --accent-soft: #e6f1ef;
  --gold: #8fc6c0;
  --cream: #ffffff;
  --bg: #f6faf9;
}
body.company-nammos .topnav { background: #47867f; }
body.company-nammos.login-page { background: #47867f; }

/* === DARK MODE === */
html.dark {
  --bg: #1a1d24;
  --card: #23272f;
  --ink: #e0ddd5;
  --muted: #9a9fa8;
  --accent-soft: #2e3340;
  --accent-ink: #b9c4dc;
  --border: #3a3f4a;
  --shadow: 0 1px 4px rgba(0,0,0,.3);
  --table-bg: #23272f;
  --table-head-bg: #2a2e38;
  --pos: #5cd88a;
  --neg: #f07070;
  --noref-bg: #32363f;
  --ferme-bg: #2b2f37;
}

/* Le thème société pose ses variables sur <body>, le thème sombre sur <html>.
   Une déclaration portée par l'élément lui-même l'emporte toujours sur une
   valeur héritée : sans ces deux blocs, Palm Beach et Nammos gardaient en mode
   sombre leur fond crème et leur encre foncée (#3c4227) par-dessus des cartes
   sombres (#23272f) — du texte foncé sur fond foncé, page illisible. Toute
   variable redéfinie par une société doit donc l'être ici aussi. */
html.dark body.company-palmbeach {
  --bg: #1a1d24;
  --ink: #e0ddd5;
  --accent-soft: #2e3340;
  --accent-ink: #ccd2ab;              /* olive éclairci, lisible sur sombre */
}
html.dark body.company-nammos {
  --bg: #1a1d24;
  --ink: #e0ddd5;
  --accent-soft: #2e3340;
  --accent-ink: #9fd4ce;              /* turquoise éclairci */
}
html.dark .topnav { background: #15171d; }
html.dark body.login-page { background: #15171d; }
html.dark .btn.secondary { background: var(--card); color: var(--ink); border-color: var(--border); }
html.dark .daynav a { background: var(--card); border-color: var(--border); color: var(--ink); }
html.dark .filters select, html.dark .filters input[type=date] { background: var(--card); color: var(--ink); border-color: var(--border); }
html.dark .field input, html.dark .field select { background: var(--card); color: var(--ink); border-color: var(--border); }
html.dark input.cell { background: var(--card); color: var(--ink); border-color: var(--border); }
html.dark .tabs a, html.dark .tabs button { background: var(--card); color: var(--ink); border-color: var(--border); }
/* `html.dark .tabs a` est plus spécifique que `.tabs a.active` : sans cette
   ligne, l'onglet actif perdait sa couleur en mode sombre et rien ne
   distinguait plus l'onglet ouvert des autres. */
html.dark .tabs a.active, html.dark .tabs button.active {
  background: var(--accent); color: #fff; border-color: var(--accent-ink);
}
html.dark .login-wrap .card { background: var(--card); }
html.dark .card.group { background: #15171d; }

/* --- nav --- */
.topnav {
  display: flex; align-items: center; gap: 24px;
  background: var(--navy); color: var(--cream);
  padding: 10px 24px;
  position: sticky; top: 0; z-index: 10;
  flex-wrap: wrap;
}
.topnav .brand {
  font-weight: 600; font-size: 15px; letter-spacing: .22em;
  display: flex; align-items: center; gap: 12px; color: var(--cream);
}
.topnav .brand img { height: 34px; width: auto; max-width: 120px; object-fit: contain; display: block; }
.navlinks { display: flex; gap: 4px; flex: 1; flex-wrap: wrap; }
.navlinks a {
  color: #c8c3b6; padding: 7px 14px; border-radius: 8px; font-weight: 500;
}
.navlinks a.active, .navlinks a:hover { background: rgba(239,232,217,.14); color: var(--cream); }
/* Bandeau « beta » du menu Assistant IA. Couleurs figées et non variables :
   la barre de navigation garde le même fond sombre dans les deux thèmes, et
   --neg vire au rouge clair en mode sombre (blanc dessus deviendrait illisible).
   #c62828 / blanc = 5,6:1. */
.beta-tag {
  display: inline-block; margin-left: 6px; padding: 0 5px;
  background: #c62828; color: #fff; border-radius: 6px;
  font-size: 9px; font-weight: 700; font-style: italic;
  letter-spacing: .1em; text-transform: uppercase;
  vertical-align: middle; line-height: 15px;
}
.navright { display: flex; align-items: center; gap: 16px; font-size: 13px; }
.navright a { color: #c8c3b6; }
.lang-switch a.active { color: var(--cream); font-weight: 700; }
/* L'engrenage des préférences : un glyphe seul est plus petit à l'œil qu'un mot
   de même taille, d'où le point supplémentaire et le line-height qui le recale
   sur la ligne de base des libellés voisins. */
.navpref { font-size: 21px; line-height: 1; }
.logout { border: 1px solid rgba(255,255,255,.3); padding: 4px 10px; border-radius: 8px; }
/* --- sélecteur de société (groupe) --- */
.company-switcher { display: flex; gap: 6px; align-items: center; }
.company-pill {
  padding: 5px 14px; border-radius: 20px; font-size: 12px; font-weight: 700;
  letter-spacing: .08em; text-decoration: none; transition: all .15s;
  border: 2px solid transparent; opacity: .55;
}
.company-pill:hover { opacity: .85; }
.company-pill.active { opacity: 1; }
.company-pill-dbgroup { background: #252c3b; color: #efe8d9; border-color: #efe8d9; }
.company-pill-dbgroup.active { background: #efe8d9; color: #252c3b; }
.company-pill-palmbeach { background: #4a5130; color: #f0ead6; border-color: #c2a264; }
.company-pill-palmbeach.active { background: #c2a264; color: #3c4227; }
.company-pill-nammos { background: #47867f; color: #fff; border-color: #8fc6c0; }
.company-pill-nammos.active { background: #8fc6c0; color: #2e5c57; }

.nav-toggle { display: none; background: none; border: none; color: var(--cream); font-size: 22px; cursor: pointer; padding: 4px 8px; }

/* --- dark mode toggle --- */
.dark-toggle { background: none; border: none; font-size: 18px; cursor: pointer; padding: 2px 6px; border-radius: 6px; }
.dark-toggle:hover { background: rgba(255,255,255,.15); }

/* --- alerts --- */
.alert-badge { background: var(--neg); color: #fff; padding: 3px 10px; border-radius: 12px; font-size: 12px; font-weight: 700; cursor: pointer; }
.alert-panel { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px 16px; margin: 0 24px 0; box-shadow: var(--shadow); }
.alert-item { padding: 8px 0; border-bottom: 1px solid var(--border); font-size: 14px; }
.alert-item:last-child { border-bottom: none; }
.alert-no_data { color: var(--muted); }
.alert-under_budget { color: var(--neg); font-weight: 600; }
.alert-avg_ticket_drop { color: var(--neg); }
.alert-group_drop { color: var(--neg); }
.alert-missing_covers { color: var(--muted); }

/* --- assistant vocal --- */
/* Bouton flottant : la question se pose depuis n'importe quelle page, sans
   quitter le chiffre que l'on est en train de regarder. Il se place au-dessus
   de la barre d'onglets basse sur téléphone (cf. la règle mobile plus bas). */
.ia-mic {
  position: fixed; right: 20px; bottom: 20px; z-index: 45;
  width: 56px; height: 56px; border-radius: 50%;
  background: var(--accent); color: #fff; border: none;
  font-size: 24px; line-height: 1; cursor: pointer;
  box-shadow: 0 3px 12px rgba(37, 44, 59, .28);
}
.ia-mic:hover { filter: brightness(1.12); }
/* Pendant l'écoute : le bouton doit dire qu'il enregistre, sinon on parle à
   un micro éteint ou on continue de parler à un micro qui a déjà coupé. */
.ia-mic.ecoute { background: var(--neg); animation: ia-pulse 1.2s infinite; }
@keyframes ia-pulse {
  0%, 100% { box-shadow: 0 3px 12px rgba(196, 61, 61, .35); }
  50% { box-shadow: 0 3px 12px rgba(196, 61, 61, .9); }
}
.ia-panel {
  position: fixed; right: 20px; bottom: 88px; z-index: 45;
  width: min(380px, calc(100vw - 40px)); max-height: 70vh; overflow-y: auto;
  background: var(--card); color: var(--ink);
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 14px 16px; box-shadow: 0 6px 24px rgba(37, 44, 59, .22);
}
.ia-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ia-close {
  background: none; border: none; color: var(--muted);
  font-size: 18px; line-height: 1; cursor: pointer; padding: 4px 6px;
}
/* Fil de conversation : l'assistant se souvient des échanges de la session, il
   faut donc les voir. La question reste discrète et la réponse porte le texte
   — c'est elle qu'on relit. Le fil défile seul, sinon un long échange pousse
   le champ de saisie hors du panneau. Aucune couleur en dur : les bulles
   suivent les variables, donc le thème de la société et le mode sombre. */
.ia-thread { margin-top: 10px; max-height: 46vh; overflow-y: auto; }
.ia-thread:empty { display: none; }
.ia-msg { margin-top: 8px; border-radius: var(--radius); padding: 8px 10px; }
.ia-msg-q {
  font-size: 13px; color: var(--muted); font-style: italic;
  background: var(--bg); border: 1px solid var(--border);
}
/* Une réponse se lit, elle ne se déchiffre pas : interligne aéré et paragraphes
   séparés. La bulle porte des chiffres qu'on compare de l'œil d'une ligne à
   l'autre, ce qui demande plus d'air qu'un texte courant. */
.ia-msg-a { font-size: 15px; line-height: 1.55; background: var(--accent-soft); }
.ia-msg-err { background: none; color: var(--neg); }
/* Mise en forme de la réponse (cf. `rendre` dans ia.js) : le modèle répond en
   listes et en tableaux, et une réponse de gestion se lit en colonnes — c'est
   la forme du relevé journalier et du palmarès. Aucune couleur en dur ici non
   plus : tout passe par les variables, donc par le thème de la société et le
   mode sombre. */
.ia-msg-a .ia-p { margin: 0 0 9px; }
.ia-msg-a .ia-p:last-child { margin-bottom: 0; }
.ia-msg-a .ia-h {
  font-weight: 600; margin: 8px 0 4px; color: var(--accent-ink);
}
.ia-msg-a .ia-h:first-child { margin-top: 0; }
.ia-msg-a .ia-liste { margin: 6px 0 9px; padding-left: 18px; }
/* Chaque élément est une ligne de chiffres : elles se comparent l'une sous
   l'autre, d'où l'espace entre elles et le retrait qui les aligne. */
.ia-msg-a .ia-liste li { margin: 4px 0; }
.ia-msg-a .ia-liste li::marker { color: var(--muted); }
/* La sous-liste se serre contre son parent : c'est un détail de celui-ci, pas
   une liste de plus. */
.ia-msg-a .ia-sous-liste { margin: 3px 0 2px; padding-left: 16px; }
.ia-msg-a .ia-sous-liste li { margin: 1px 0; font-size: 14px; }
/* Un tableau large défile dans sa bulle et ne pousse jamais la page : même
   règle que les tableaux de l'application sur téléphone. */
.ia-tab-boite { overflow-x: auto; margin: 6px 0; }
.ia-tab { border-collapse: collapse; font-size: 13px; white-space: nowrap; }
.ia-tab th, .ia-tab td {
  border: 1px solid var(--border); padding: 3px 7px; text-align: left;
}
.ia-tab th { background: var(--table-head-bg); font-weight: 600; }
.ia-tab td { background: var(--table-bg); }
/* Les colonnes de chiffres se lisent alignées à droite : c'est ainsi qu'on
   compare deux montants d'un coup d'œil, et c'est la convention de toutes les
   tables de l'application. */
.ia-tab td + td, .ia-tab th + th { text-align: right; }
.ia-forget {
  display: block; margin-top: 10px; margin-left: auto;
  background: none; border: none; padding: 2px 0;
  color: var(--accent-ink); font-size: 12px; font-family: inherit; cursor: pointer;
}
.ia-answer { margin-top: 8px; font-size: 15px; line-height: 1.45; }
.ia-form { display: flex; gap: 6px; margin-top: 12px; }
.ia-form input { flex: 1; min-width: 0; }
.ia-panel .note:empty { display: none; }
.ia-more { font-size: 12px; margin-left: auto; margin-right: 8px; color: var(--accent-ink); }

/* --- page « Assistant IA » --- */
/* Les questions essentielles : des boutons portant leur texte en clair, assez
   grands pour être touchés du pouce. Une grille qui se replie en une colonne
   sur téléphone plutôt qu'une liste à puces — on les vise, on ne les lit pas. */
.ia-questions {
  display: grid; gap: 10px; margin-top: 12px;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.ia-q {
  text-align: left; padding: 12px 14px; min-height: 52px;
  background: var(--card); color: var(--ink);
  border: 1px solid var(--border); border-radius: var(--radius);
  font-size: 14px; font-family: inherit; line-height: 1.35; cursor: pointer;
}
.ia-q:hover { border-color: var(--accent-ink); background: var(--accent-soft); }
.ia-echange .ia-head { margin-bottom: 4px; }
.ia-mic-inline {
  background: var(--accent); color: #fff; border: none; border-radius: 50%;
  width: 44px; height: 44px; font-size: 19px; line-height: 1; cursor: pointer;
}
.ia-mic-inline.ecoute { background: var(--neg); animation: ia-pulse 1.2s infinite; }
.ia-answer-lg { font-size: 17px; line-height: 1.5; min-height: 3em; }
/* Sur la page dédiée, le fil a toute la largeur : il peut respirer davantage
   que dans le panneau flottant. */
.ia-thread-lg { max-height: none; }
.ia-thread-lg .ia-msg-a { font-size: 17px; line-height: 1.5; }
.ia-echange .ia-forget { margin-top: 0; }
/* Pendant l'attente, les questions ne doivent plus répondre au doigt : deux
   demandes lancées coup sur coup afficheraient la réponse de la première. */
.ia-occupe .ia-q { opacity: .5; pointer-events: none; }
.ia-page .note:empty { display: none; }
/* Choix du mode d'usage dans /preferences. Toute la ligne est cliquable — sur
   téléphone, viser un bouton radio de 13 px au doigt est un échec sur deux. */
.ia-mode-choix {
  display: flex; gap: 10px; align-items: flex-start; cursor: pointer;
  padding: 10px 12px; margin-top: 8px;
  border: 1px solid var(--border); border-radius: var(--radius);
}
.ia-mode-choix:hover { border-color: var(--accent-ink); background: var(--accent-soft); }
.ia-mode-choix input { margin-top: 3px; flex: none; }

.container { max-width: 1440px; margin: 24px auto; padding: 0 20px; }
.container.wide { max-width: 1700px; }
.flash {
  background: var(--accent-soft); border: 1px solid var(--accent-ink);
  color: var(--accent-ink); padding: 10px 16px; border-radius: var(--radius);
  margin-bottom: 16px;
}

/* --- page head / filters --- */
.pagehead { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; margin-bottom: 20px; }
.pagehead h1 { font-size: 22px; margin: 0; }
.filters { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.filters select, .filters input[type=date] {
  padding: 7px 10px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--card); color: var(--ink); font-size: 14px;
}
.btn {
  display: inline-block; background: var(--accent); color: #fff; border: none;
  padding: 8px 16px; border-radius: 8px; font-size: 14px; cursor: pointer; font-weight: 600;
}
.btn.secondary { background: var(--card); color: var(--accent-ink); border: 1px solid var(--accent-ink); }
.daynav { display: inline-flex; gap: 4px; }
.daynav a { padding: 7px 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--card); }

/* --- KPI cards --- */
.grid { display: grid; gap: 16px; }
.grid.cards { grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); }
.card {
  background: var(--card); border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 18px 20px; border: 1px solid var(--border);
}
.card h2 { margin: 0 0 4px; font-size: 16px; }
.card h3 { margin: 0 0 12px; font-size: 15px; }
.card .bignum { font-size: 28px; font-weight: 700; margin: 4px 0 2px; }
.card .subtle { color: var(--muted); font-size: 13px; }
/* Un écart affiché en petit garde sa couleur : `.card .subtle` est plus
   spécifique que `.pos`/`.neg`, qui restaient donc sans effet — le signe
   subsistait, la lecture au coup d'œil non. */
.card .subtle.pos { color: var(--pos); }
.card .subtle.neg { color: var(--neg); }
.kpi-row { display: flex; flex-wrap: wrap; gap: 8px 20px; margin-top: 12px; }
.kpi { min-width: 90px; }
.kpi .label { color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: .03em; }
.kpi .value { font-weight: 600; font-size: 15px; margin-top: 2px; }
.pos { color: var(--pos); }
.neg { color: var(--neg); }
/* Écart mesuré contre une année qui ne porte aucune ligne importée : la valeur
   reste lisible et gardée au tri, le fond dit qu'elle vaut tout le chiffre de
   la période et non un progrès sur une référence réelle. */
.noref { background: var(--noref-bg); }
/* Journée ou mois déclarés fermés dans le calendrier d'ouverture : le zéro a
   laissé place à un tiret, le fond dit pourquoi. Un établissement fermé n'est
   pas un établissement en échec, et la colonne les écrivait pareil. */
.ferme { background: var(--ferme-bg); }
.ferme.num { color: var(--muted); }
.nodata { color: var(--muted); font-style: italic; }
.card.group { background: var(--navy); color: #fff; border: none; }
.card.group .subtle, .card.group .kpi .label { color: rgba(255,255,255,.75); }
.card.group .kpi .value { color: #fff; }
.card.group .pos { color: #b8f5cd; font-weight: 700; }
.card.group .neg { color: #ffc4bc; font-weight: 700; }

/* --- tables --- */
table.data { width: 100%; border-collapse: collapse; background: var(--table-bg); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow); }
table.data th {
  text-align: left; font-size: 12px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); padding: 10px 14px; background: var(--table-head-bg); border-bottom: 1px solid var(--border);
}
table.data td { padding: 10px 14px; border-bottom: 1px solid var(--border); }
table.data tr:last-child td { border-bottom: none; }
table.data td.num, table.data th.num { text-align: right; font-variant-numeric: tabular-nums; }
.rankbadge {
  display: inline-flex; width: 24px; height: 24px; align-items: center; justify-content: center;
  border-radius: 50%; background: var(--accent-soft); color: var(--accent-ink); font-weight: 700; font-size: 12px;
}
.bar { background: var(--accent-soft); border-radius: 4px; height: 8px; }
.bar > span { display: block; height: 8px; border-radius: 4px; background: var(--accent); }

/* --- layout helpers --- */
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.section { margin-bottom: 24px; }
.section > h2 { font-size: 17px; margin: 0 0 12px; }
.note { color: var(--muted); font-size: 13px; margin-top: 8px; }

/* --- tabs --- */
.tabs { display: flex; gap: 4px; margin-bottom: 16px; flex-wrap: wrap; }
.tabs a, .tabs button { padding: 8px 16px; border-radius: 8px; background: var(--card); border: 1px solid var(--border); font-weight: 500; }
.tabs a.active, .tabs button.active { background: var(--accent); color: #fff; border-color: var(--accent-ink); }
/* Onglets internes à une carte : mêmes couleurs, moins d'encombrement. */
.tabs button { color: var(--ink); font: inherit; font-weight: 500; cursor: pointer; }
.tabs.compact { gap: 4px; margin-bottom: 10px; }
.tabs.compact button { padding: 5px 11px; font-size: 13px; border-radius: 7px; }
.tabs button.active .subtle { color: rgba(255, 255, 255, .75); }

/* --- login --- */
body.login-page { background: var(--navy); }
.login-wrap { max-width: 400px; margin: 8vh auto; }
.login-wrap .card { padding: 32px; }
.login-wrap h1 { text-align: center; margin: 0 0 24px; }
.login-logo { display: block; margin: 0 auto 20px; width: 170px; }
.field { margin-bottom: 14px; }
.field label { display: block; font-size: 13px; color: var(--muted); margin-bottom: 4px; }
.field input, .field select {
  width: 100%; padding: 10px 12px; border: 1px solid var(--border); border-radius: 8px; font-size: 15px;
}
.error { color: var(--neg); margin-bottom: 12px; font-size: 14px; }

/* --- admin --- */
.admin-section { margin-bottom: 32px; }
input.cell { width: 100px; padding: 5px 6px; border: 1px solid var(--border); border-radius: 6px; text-align: right; }
.status-ok { color: var(--pos); font-weight: 600; }
.status-error { color: var(--neg); font-weight: 600; }
.status-skipped { color: var(--muted); }
.inline-form { display: flex; gap: 8px; flex-wrap: wrap; align-items: end; }
.inline-form .field { margin-bottom: 0; }

/* --- menu « Colonnes » (au-dessus des grands tableaux) ---
   Un <details> plutôt qu'un menu en JS : il s'ouvre et se ferme sans une ligne
   de script, donc il fonctionne aussi tant que la page n'est pas interactive. */
.col-menu { position: relative; display: inline-block; }
.col-menu > summary {
  display: inline-block; background: var(--card); color: var(--accent-ink);
  border: 1px solid var(--accent-ink); padding: 8px 16px; border-radius: 8px;
  font-size: 14px; font-weight: 600; cursor: pointer; list-style: none;
}
.col-menu > summary::-webkit-details-marker { display: none; }
.col-menu > summary::after { content: ' ▾'; }
.col-menu[open] > summary::after { content: ' ▴'; }
.col-menu-panel {
  position: absolute; z-index: 30; right: 0; margin-top: 6px; padding: 14px 16px;
  min-width: 300px; background: var(--card); border: 1px solid var(--border);
  border-radius: 10px; box-shadow: var(--shadow); text-align: left;
}
/* Liste en une colonne : les flèches ↑ ↓ ne veulent rien dire dans une grille
   à deux colonnes, où « descendre » ferait sauter d'une colonne à l'autre. */
.col-menu-panel .cols {
  list-style: none; margin: 8px 0 12px; padding: 0;
  max-height: 60vh; overflow-y: auto;
}
.col-menu-panel .cols li {
  display: flex; align-items: center; gap: 8px;
  border-bottom: 1px solid var(--border);
}
.col-menu-panel .cols li:last-child { border-bottom: none; }
.col-menu-panel .col-move { margin-left: auto; display: flex; gap: 2px; }
.col-menu-panel .col-move .mv {
  background: var(--accent-soft); color: var(--accent-ink); border: 1px solid var(--border);
  border-radius: 6px; width: 26px; height: 24px; cursor: pointer; font-size: 12px;
  line-height: 1;
}
.col-menu-panel .col-move .mv:hover { background: var(--border); }
.col-menu-panel label {
  display: flex; align-items: baseline; gap: 7px; font-size: 13px;
  padding: 5px 0; cursor: pointer; font-weight: 400; flex: 1;
}
.col-menu-panel label.fixed { cursor: default; color: var(--muted); }
.col-menu-panel .note { margin: 0 0 4px; }
/* Sur téléphone le panneau déborderait de l'écran : il prend toute la largeur
   et se place dans le flux plutôt qu'en absolu. */
@media (max-width: 640px) {
  .col-menu, .col-menu-panel { position: static; min-width: 0; width: 100%; }
  .col-menu > summary { width: 100%; text-align: center; }
}

/* --- droits d'accès (volet sous chaque utilisateur) --- */
.rights-toggle { cursor: pointer; font-size: 12px; color: var(--muted); padding: 4px 0; list-style: none; }
.rights-toggle::-webkit-details-marker { display: none; }
.rights-toggle::before { content: '▸ '; display: inline-block; width: 14px; }
details[open] > .rights-toggle::before { content: '▾ '; }
.rights-toggle:hover { color: var(--ink); }

.rights-panel {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 20px; margin: 4px 0 12px; padding: 14px 16px;
  background: var(--bg); border: 1px solid var(--border); border-radius: 10px;
}
.rights-group > h4 {
  margin: 0 0 8px; font-size: 11px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted);
}
.rights-group .note { margin: -4px 0 8px; font-size: 12px; }

/* Une case par ligne (ou colonnes régulières) : la grille garantit
   l'alignement vertical des cases quelle que soit la longueur du libellé. */
.check-list { display: grid; gap: 7px 18px; }
.check-list.cols { grid-template-columns: repeat(auto-fill, minmax(165px, 1fr)); }
.check-list label,
.rights-group > label.check {
  display: flex; align-items: center; gap: 8px;
  font-size: 13px; line-height: 1.3; cursor: pointer;
}
.check-list input[type=checkbox],
.rights-group input[type=checkbox] { flex: none; margin: 0; width: 15px; height: 15px; }
.check-list label > span { min-width: 0; overflow-wrap: anywhere; }

.rights-group > label.check { margin-bottom: 10px; font-weight: 600; }
.rights-group input[type=password] { width: 100%; max-width: 220px; text-align: left; }
/* compte suspendu : la ligne et son volet de droits sont estompés ensemble */
.user-off > td { opacity: .5; }
.badge-ro {
  display: inline-block; margin-top: 4px; padding: 2px 9px; border-radius: 20px;
  font-size: 11px; font-weight: 700; background: var(--border); color: var(--muted);
}
/* --- analyse avancée --- */
/* Un article apparu ou arrêté : l'étiquette suit le libellé sur la même ligne,
   sinon chaque ligne du palmarès prend deux hauteurs pour rien. */
.badge-evo {
  display: inline-block; margin-left: 6px; padding: 1px 8px; border-radius: 20px;
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  vertical-align: middle;
}
.badge-evo.new { background: var(--accent-soft); color: var(--accent-ink); }
.badge-evo.gone { background: var(--border); color: var(--muted); }

/* Matrice établissements : jusqu'à vingt colonnes, donc serrées et jamais
   coupées au milieu d'un montant. La première colonne reste visible au
   défilement horizontal, sans quoi on perd la ligne qu'on est en train de lire. */
/* overflow visible + border-collapse separate : sans cela la colonne figée
   n'a pas de conteneur de défilement de référence et le sticky ne prend pas. */
table.data.matrix {
  width: auto; min-width: 100%; font-size: 13px;
  overflow: visible; border-collapse: separate; border-spacing: 0;
}
table.data.matrix th, table.data.matrix td { padding: 8px 10px; white-space: nowrap; }
table.data.matrix td.rowhead, table.data.matrix th.rowhead {
  position: sticky; left: 0; background: var(--table-bg); z-index: 1;
  box-shadow: 1px 0 0 var(--border);
}
table.data.matrix th.rowhead { background: var(--table-head-bg); }
/* Cellule dominante de la ligne : c'est l'information qu'on cherche en premier */
table.data.matrix td.best { font-weight: 700; color: var(--accent-ink); }
table.data.matrix td.empty { color: var(--border); }

/* Calendrier d'ouverture : sept colonnes de largeur égale, une case à cocher
   par jour. Jamais empilé en mobile (cf. base.html) — un mois qui devient une
   liste de trente lignes n'est plus un calendrier. */
table.data.calendar { table-layout: fixed; font-size: 13px; }
table.data.calendar th { padding: 8px 4px; text-align: center; }
table.data.calendar td { padding: 6px 2px; text-align: center; }
table.data.calendar label {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  cursor: pointer; padding: 4px 0; border-radius: 6px;
}
table.data.calendar label:hover { background: var(--table-head-bg); }
table.data.calendar input { width: 16px; height: 16px; }
/* Budget de la journée, sous sa case à cocher. Le sélecteur doit être plus
   précis que la règle ci-dessus, qui dimensionne les cases à cocher. */
table.data.calendar input.daybud {
  width: 100%; height: auto; margin-top: 2px; padding: 3px 4px;
  font-size: 12px; text-align: center;
}
table.data.calendar input.daybud::placeholder { opacity: .55; font-style: italic; }
/* Objectif de couverts, sous le montant : même case, une grandeur par ligne.
   Un peu plus discret que le CA — c'est le second objectif, pas le principal. */
table.data.calendar input.daybud.covers { margin-top: 3px; font-size: 11px; }

/* Grille des budgets : deux objectifs empilés par mois, et le ticket moyen
   visé rappelé dessous. Les cases restent alignées à droite comme le reste
   des montants. */
td.budcell { white-space: nowrap; }
td.budcell input.cell + input.cell { margin-top: 3px; }
td.budcell input.cell.covers { font-size: 12px; }
td.budcell .budticket {
  display: block; margin-top: 2px; font-size: 11px; color: var(--muted);
  text-align: right;
}

.scroll-x { overflow-x: auto; }

/* --- QR code d'installation mobile (documentation) --- */
.qr-install {
  display: flex; gap: 22px; align-items: center; flex-wrap: wrap;
  background: var(--table-head-bg); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 18px; margin: 14px 0;
}
.qr-install-code {
  /* Blanc en dur, y compris en mode sombre : un QR code se lit par contraste
     entre modules noirs et zone de silence claire. L'inverser le rend
     indéchiffrable pour une bonne partie des appareils photo. */
  flex: 0 0 auto; background: #fff; padding: 10px; border-radius: 10px;
  line-height: 0;                      /* pas d'espace fantôme sous le SVG */
}
.qr-install-code svg { display: block; width: 168px; height: 168px; }
.qr-install-text { flex: 1 1 240px; }
.qr-install-text p { margin: 0 0 10px; }
.qr-install-url code {
  background: var(--accent-soft); padding: 6px 12px; border-radius: 8px;
  display: inline-block; word-break: break-all; font-size: 13.5px;
}
/* Sur téléphone le QR code ne sert à rien : on y est déjà. */
@media (max-width: 640px) { .qr-install-code { display: none; } }

canvas { max-width: 100%; }

/* --- cartes restaurant (dashboard) --- */
.resto-card { display: flex; flex-direction: column; gap: 0; }
.resto-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 4px; }
.resto-header h2 { margin: 0; font-size: 16px; }
.resto-badge { font-size: 13px; font-weight: 700; padding: 3px 10px; border-radius: 20px; }
.resto-badge.pos { background: #e6f7ed; color: var(--pos); }
.resto-badge.neg { background: #fdecea; color: var(--neg); }
.resto-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
.resto-cell { text-align: center; padding: 6px 4px; }
.resto-cell .label { display: block; font-size: 11px; text-transform: uppercase; color: var(--muted); letter-spacing: .03em; }
.resto-cell .value { display: block; font-size: 15px; font-weight: 600; margin-top: 2px; }
/* Écart en valeur sous le chiffre : plus petit, il se lit en second sans
   disputer la place au pourcentage. La couleur porte le sens (.pos/.neg) ;
   sans écart calculable la cellule affiche « — » et reste grise. */
.resto-cell .sub { display: block; font-size: 12px; font-weight: 600; margin-top: 1px; color: var(--muted); }
.resto-cell .sub.pos { color: var(--pos); }
.resto-cell .sub.neg { color: var(--neg); }
/* Deux comparaisons seulement sur la première ligne : sans cette variante,
   la grille à trois colonnes laisserait un vide à droite. */
.resto-grid.two { grid-template-columns: repeat(2, 1fr); }
/* Périodes de comparaison : le sélecteur, puis les colonnes qu'il ouvre. */
.cmp-bar { display: flex; flex-direction: column; gap: 6px; }
.cmp-form { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.cmp-form .label { font-size: 12px; text-transform: uppercase; letter-spacing: .03em; color: var(--muted); }
.cmp-form input[type=date] { padding: 5px 8px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--card); color: var(--ink); }
/* Les périodes comparées se lisent en second : séparées par un filet, un cran
   plus petites que les chiffres de la période affichée. */
.kpi-row.cmp-row { border-top: 1px solid var(--border); margin-top: 8px; padding-top: 8px; }
.kpi-row.cmp-row .value { font-size: 14px; }
.kpi .sub { display: block; font-size: 11px; font-weight: 600; color: var(--muted); }
.kpi .sub.pos { color: var(--pos); }
.kpi .sub.neg { color: var(--neg); }
table.data td .sub { display: block; font-size: 11px; font-weight: 600; color: var(--muted); }
table.data td .sub.pos { color: var(--pos); }
table.data td .sub.neg { color: var(--neg); }

/* Sélecteur de référence N-1 : au-dessus des cartes, il vaut pour toutes. */
.n1-switch { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.n1-switch .label { font-size: 12px; text-transform: uppercase; letter-spacing: .03em; color: var(--muted); }
.n1-switch .tabs { margin-bottom: 0; }
/* Cartouches de la carte établissement : quatre encadrés, intitulé / valeur /
   écart. Le fond de page posé dans une carte blanche suffit à les détacher —
   aucune couleur écrite en dur, sinon le mode sombre garde un encadré clair
   sous du texte clair (cf. le bloc html.dark plus haut). */
.cartouches { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
.cartouche {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px 12px;
  min-width: 0;                      /* sinon un montant long élargit la grille */
}
.cartouche .label { display: block; font-size: 12px; color: var(--muted); }
.cartouche .value {
  display: block; font-size: 22px; font-weight: 700; margin: 2px 0 1px;
  white-space: nowrap;
}
.cartouche .gap { display: block; font-size: 12px; font-weight: 600; }
.cartouche .gap.pos { color: var(--pos); }
.cartouche .gap.neg { color: var(--neg); }
/* La référence est dite une fois pour la carte entière plutôt que répétée dans
   chacun des quatre encadrés. */
.cartouches-note { font-size: 11px; color: var(--muted); text-align: right; margin-top: 8px; }
html.dark .resto-badge.pos { background: #1a3a26; }
html.dark .resto-badge.neg { background: #3a1a1a; }

/* --- tableau synthèse (forcer 1 ligne par cellule) --- */
table.data.synthese-table td, table.data.synthese-table th { white-space: nowrap; padding: 10px 12px; }
table.data.synthese-table { width: auto; min-width: 100%; }
/* Ligne des totaux : teinte discrète qui suit le thème. */
table.data .total-row, table.data .total-row td { background: var(--accent-soft); font-weight: 700; }

/* --- tri des tableaux --- */
.sortable-header { cursor: pointer; user-select: none; white-space: nowrap; }
.sortable-header:hover { color: var(--accent-ink); }
.sortable-header .sort-arrow { font-size: 11px; color: var(--accent-ink); }
.sortable-header.sorted-asc, .sortable-header.sorted-desc { color: var(--accent-ink); }

/* --- boutons déplier / familles --- */
.expand-btn {
  display: block; width: 100%; margin-top: 8px; padding: 8px;
  background: var(--accent-soft); color: var(--accent-ink); border: 1px solid var(--border);
  border-radius: 8px; font-size: 13px; font-weight: 600; cursor: pointer; text-align: center;
}
.expand-btn:hover { background: var(--accent); color: #fff; }
.group-block { margin-bottom: 4px; }
.group-toggle {
  display: flex; justify-content: space-between; align-items: center; width: 100%;
  padding: 8px 12px; background: var(--accent-soft); border: none; border-radius: 8px;
  cursor: pointer; font-size: 14px; text-align: left; color: var(--ink);
}
.group-toggle:hover { background: var(--border); }
.group-toggle .arrow { font-size: 11px; color: var(--muted); }
.group-block .group-table { margin-top: 4px; margin-bottom: 8px; }

/* --- recherche produits --- */
.search-input {
  width: 100%; padding: 10px 14px; border: 1px solid var(--border); border-radius: 8px;
  font-size: 14px; margin-bottom: 12px; background: var(--card); color: var(--ink);
}
.search-input:focus { outline: 2px solid var(--accent); border-color: var(--accent-ink); }

/* === RESPONSIVE MOBILE === */
@media (max-width: 900px) {
  .two-col { grid-template-columns: 1fr; }
}
@media (max-width: 768px) {
  .nav-toggle { display: block; }
  .topnav { flex-wrap: wrap; padding: 8px 16px; gap: 8px; }
  .topnav .brand { font-size: 13px; letter-spacing: .12em; }
  .topnav .brand img { height: 26px; }
  .navlinks { display: none; flex-basis: 100%; flex-direction: column; gap: 2px; }
  .topnav.open .navlinks { display: flex; }
  .navlinks a { padding: 10px 14px; }
  .navright { gap: 10px; font-size: 12px; flex-wrap: wrap; }
  .lang-switch { display: none; }
  .container { padding: 0 12px; margin: 12px auto; }
  .pagehead { flex-direction: column; align-items: flex-start; }
  .pagehead h1 { font-size: 18px; }
  .filters { width: 100%; }
  .grid.cards { grid-template-columns: 1fr; }
  .card .bignum { font-size: 22px; }
  .cartouche .value { font-size: 19px; }
  .kpi-row { gap: 6px 14px; }
  .kpi { min-width: 70px; }
  .kpi .value { font-size: 14px; }
  table.data { font-size: 13px; }
  table.data th, table.data td { padding: 8px 10px; }
  .tabs a, .tabs button { padding: 6px 12px; font-size: 13px; }
  /* Les onglets internes à une carte (« moins vendus ») restent compacts à la
     souris ; au doigt, ils doivent atteindre la cible tactile des 44 px que
     tout le reste de la feuille respecte. */
  .tabs.compact button { min-height: 40px; padding: 8px 12px; }
}

/* ==================================================================== */
/*  Téléphone — iPhone 14 et suivants                                    */
/* ==================================================================== */

/* Zones sûres : avec viewport-fit=cover la page passe SOUS l'encoche et la
   barre d'accueil. Sans ces marges, le premier et le dernier élément sont
   inaccessibles au doigt. */
body {
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
  -webkit-text-size-adjust: 100%;             /* iOS grossit sinon le texte en paysage */
  /* Filet de sécurité : un nom d'article de caisse, un nom de fichier déposé
     ou un commentaire sans espace élargissait la page et faisait défiler tout
     le contenu horizontalement — le défaut que la mise en fiches doit éviter. */
  overflow-wrap: break-word;
}
.topnav { padding-top: calc(8px + env(safe-area-inset-top)); }

/* Safari zoome dès qu'un champ fait moins de 16 px, et ne dézoome jamais
   ensuite. C'est la première cause d'inconfort sur un formulaire iPhone. */
@media (max-width: 768px) {
  input, select, textarea, .btn, button { font-size: 16px; }
  input[type="date"], input[type="text"], input[type="number"],
  input[type="password"], select { min-height: 44px; }   /* cible tactile Apple */
  .btn, .nav-toggle, .dark-toggle { min-height: 44px; }
  .navlinks a { min-height: 44px; display: flex; align-items: center; }

  /* La barre du haut se réduit à l'essentiel. Avec la barre d'onglets en bas,
     garder en permanence le sélecteur de société, le nom du compte et la
     déconnexion coûtait 250 px sur les 850 de l'écran — soit un tiers de la
     page avant le premier chiffre. Tout cela rejoint le menu. */
  .company-switcher { display: none; flex-basis: 100%; order: 5; }
  .navright { display: none; flex-basis: 100%; order: 6; justify-content: flex-start; }
  .topnav.open .company-switcher, .topnav.open .navright { display: flex; }
  .topnav .alert-badge { margin-left: auto; }

  /* Les champs prennent la largeur, les boutons se partagent une ligne :
     un « Excel » seul sur toute la largeur n'apporte rien et repousse le
     contenu vers le bas. */
  .filters { display: flex; flex-wrap: wrap; align-items: stretch; gap: 8px; }
  .filters form { flex: 1 1 100%; }
  .filters select, .filters input { flex: 1 1 100%; width: 100%; }
  .filters .btn { flex: 1 1 calc(50% - 4px); text-align: center; }
  .filters label { flex: 1 1 100%; font-size: 12px; color: var(--muted); margin-bottom: -6px; }
  .daynav { flex: 0 0 auto; }
  .daynav a { min-width: 56px; min-height: 44px; display: inline-flex; align-items: center; justify-content: center; }
}

/* --- barre d'onglets basse --- */
.tabbar { display: none; }
@media (max-width: 768px) {
  .tabbar {
    display: grid; grid-template-columns: repeat(4, 1fr);
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
    background: var(--card); border-top: 1px solid var(--border);
    padding-bottom: env(safe-area-inset-bottom);
    box-shadow: 0 -1px 6px rgba(37, 44, 59, .08);
  }
  .tabbar a, .tabbar button {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 2px; padding: 8px 4px; min-height: 54px;
    font-size: 11px; font-weight: 600; color: var(--muted);
    background: none; border: none; cursor: pointer; text-decoration: none;
  }
  .tabbar .ico { font-size: 19px; line-height: 1; }
  .tabbar a.active, .tabbar button.active { color: var(--accent-ink); }
  /* de quoi faire défiler au-delà de la barre, sinon elle masque la dernière ligne */
  main.container { padding-bottom: calc(70px + env(safe-area-inset-bottom)); }
  .alert-panel { bottom: calc(70px + env(safe-area-inset-bottom)); }
  /* Le micro et son panneau remontent au-dessus de la barre d'onglets : posés
     dessous, ils masqueraient la navigation ou seraient masqués par elle. */
  .ia-mic { bottom: calc(76px + env(safe-area-inset-bottom)); right: 14px; }
  .ia-panel {
    right: 10px; left: 10px; width: auto;
    bottom: calc(142px + env(safe-area-inset-bottom));
    max-height: 55vh;
  }
}

/* --- tableaux en fiches --- */
/* En dessous de 640 px, un tableau de cinq colonnes de montants est illisible :
   chaque ligne devient une fiche, l'intitulé de colonne servant d'étiquette
   (posé par le script de base.html). */
@media (max-width: 640px) {
  table.data.stackable,
  table.data.stackable tbody,
  table.data.stackable tr,
  table.data.stackable td { display: block; width: auto; }
  table.data.stackable { box-shadow: none; background: none; }
  table.data.stackable thead { display: block; }
  table.data.stackable tr.stack-head { display: none; }       /* l'en-tête devient les étiquettes */
  table.data.stackable tr {
    background: var(--table-bg); border: 1px solid var(--border);
    border-radius: var(--radius); margin-bottom: 10px; padding: 6px 12px;
    box-shadow: var(--shadow);
  }
  table.data.stackable td {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: 14px; padding: 7px 0; border-bottom: 1px solid var(--border);
    text-align: right;
  }
  table.data.stackable tr td:last-child { border-bottom: none; }
  table.data.stackable td::before {
    content: attr(data-label); flex: 0 0 auto; text-align: left;
    font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
    color: var(--muted); font-weight: 600;
  }
  /* Une cellule sans étiquette (colonne de rang, barre de part) occupe la
     largeur entière plutôt que de laisser un blanc à gauche. */
  table.data.stackable td:not([data-label])::before,
  table.data.stackable td[data-label=""]::before,
  table.data.stackable td[data-label="#"]::before { content: none; }
  table.data.stackable td[data-label="#"] { justify-content: flex-start; }
  table.data.stackable .bar { flex: 1 1 auto; }

  .kpi-row { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
  .kpi { min-width: 0; }
  .tabs { display: grid; grid-template-columns: repeat(2, 1fr); gap: 6px; }
  .tabs a, .tabs button { text-align: center; }
  .pagehead h1 { font-size: 17px; }
  .card { padding: 14px; }
}

/* --- documentation --- */
.doc-layout { display: grid; grid-template-columns: 240px 1fr; gap: 24px; align-items: start; }
.doc-toc {
  position: sticky; top: 16px; background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 14px 16px; box-shadow: var(--shadow);
}
.doc-toc h3 { margin: 0 0 10px; font-size: 13px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.doc-toc ul { list-style: none; margin: 0; padding: 0; }
.doc-toc li { margin-bottom: 2px; }
.doc-toc a { display: block; padding: 6px 8px; border-radius: 8px; font-size: 13.5px; }
.doc-toc a:hover { background: var(--accent-soft); }
.doc-intro { margin: 0 0 16px; }
.doc-section { margin-bottom: 18px; scroll-margin-top: 16px; }
.doc-section h2 { font-size: 18px; margin: 0 0 14px; padding-bottom: 10px; border-bottom: 1px solid var(--border); }
.doc-section h3 { font-size: 14.5px; margin: 20px 0 8px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.doc-section p { margin: 0 0 10px; line-height: 1.6; }
.doc-section ul, .doc-section ol { margin: 0 0 12px; padding-left: 22px; line-height: 1.6; }
.doc-section li { margin-bottom: 5px; }
.doc-table { margin: 0 0 14px; font-size: 14px; }
.doc-note { border-left: 3px solid var(--border); border-radius: 0 8px 8px 0; padding: 10px 14px; margin: 0 0 12px; font-size: 14px; }
.doc-tip { border-left-color: var(--pos); background: var(--accent-soft); }
.doc-warn { border-left-color: var(--neg); background: rgba(196, 61, 61, .07); }
html.dark .doc-warn { background: rgba(240, 112, 112, .10); }
@media (max-width: 900px) {
  .doc-layout { grid-template-columns: 1fr; }
  .doc-toc { position: static; }
  .doc-toc ul { display: flex; flex-wrap: wrap; gap: 4px; }
  .doc-toc li { margin: 0; }
  .doc-toc a { border: 1px solid var(--border); font-size: 13px; }
}

/* --- Import : zone de glisser-déposer --- */
.dropzone {
  border: 2px dashed var(--border); border-radius: var(--radius);
  background: var(--table-head-bg); padding: 30px 18px; text-align: center;
  cursor: pointer; transition: border-color .15s, background .15s;
}
.dropzone:hover, .dropzone:focus-visible { border-color: var(--gold); outline: none; }
.dropzone.over { border-color: var(--gold); background: var(--accent-soft); }
.dropzone .dz-icon { font-size: 26px; line-height: 1; margin-bottom: 8px; color: var(--gold); }
.dropzone .dz-main { font-weight: 600; color: var(--ink); }
.dropzone .dz-hint { font-size: 13px; color: var(--muted); margin-top: 4px; }
.file-list { list-style: none; margin: 12px 0 0; padding: 0; }
.file-list li {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  border: 1px solid var(--border); border-radius: 8px; background: var(--card);
  padding: 7px 10px; margin-bottom: 6px; font-size: 14px;
}
.file-list .fl-size { color: var(--muted); font-size: 13px; white-space: nowrap; }
.file-list .fl-bad { color: var(--neg); }
.file-list .fl-del {
  border: 0; background: none; color: var(--muted); cursor: pointer;
  font-size: 16px; line-height: 1; padding: 0 2px;
}
.file-list .fl-del:hover { color: var(--neg); }

/* --- Commentaires d'une journée --- */
/* Un fil se lit dans l'ordre où il s'est écrit : pas de colonne, pas de tri,
   une pile de messages et un retrait pour les réponses. Le retrait est la
   seule marque de la hiérarchie — elle ne va qu'à un niveau, cf. notes.py. */
.notes { display: flex; flex-direction: column; gap: 12px; margin-top: 12px; }
.note-item {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--card); padding: 10px 12px;
}
.note-item .note-head {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  font-size: 13px; margin-bottom: 4px;
}
.note-item .note-head .subtle { color: var(--muted); }
/* L'auteur et l'heure d'abord, la suppression repoussée au bout de la ligne :
   c'est l'attribution qu'on vient lire, pas le bouton. */
.note-item .note-del { margin-left: auto; }
.note-body { white-space: pre-wrap; word-break: break-word; line-height: 1.45; }
.note-reply {
  margin: 10px 0 0 18px; border-left: 3px solid var(--accent-soft);
  background: var(--table-head-bg);
}
.note-reply-form { display: flex; gap: 8px; margin: 10px 0 0 18px; }
.note-reply-form input[name="body"] { flex: 1; min-width: 0; }
.note-new { margin-top: 14px; }
.note-new textarea {
  width: 100%; resize: vertical; font: inherit; padding: 8px 10px;
  border: 1px solid var(--border); border-radius: 8px; background: var(--card);
  color: var(--ink); margin-bottom: 8px;
}
/* --- rubriques du brief (service flow / VIP / infos générales) --- */
/* Une boîte par sujet, titre au-dessus : c'est le bloc NOTES du rapport F&B
   d'une page, transposé à l'écran. Le titre reste visible même quand la boîte
   est vide — un sujet oublié doit se voir. */
.rubriques { display: flex; flex-direction: column; gap: 12px; margin-top: 12px; }
.rubrique {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--card); padding: 10px 12px;
}
.rubrique label {
  display: block; font-size: 12px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 6px;
}
.rubrique textarea {
  width: 100%; resize: vertical; font: inherit; padding: 8px 10px;
  border: 1px solid var(--border); border-radius: 8px; background: var(--card);
  color: var(--ink);
}
.rubriques .btn { margin-top: 12px; align-self: flex-start; }

.linklike {
  border: 0; background: none; color: var(--muted); cursor: pointer;
  font-size: 15px; line-height: 1; padding: 0 2px;
}
.linklike:hover { color: var(--neg); }

/* Sur mobile la réponse en ligne devient une pile : un champ de saisie et un
   bouton côte à côte sous 400 px ne laissent la place ni à l'un ni à l'autre. */
@media (max-width: 640px) {
  .note-reply, .note-reply-form { margin-left: 10px; }
  .note-reply-form { flex-direction: column; align-items: stretch; }
}

/* --- Application « Assistant » (templates/assistant.html) -------------------
   L'assistant seul, plein écran, installé sur l'écran d'accueil d'un iPhone.
   Les couleurs viennent toutes des variables existantes : un fond écrit en dur
   ici, et le mode sombre rend la page illisible (cf. test_theme.py).

   Trois contraintes d'un téléphone tenu à la main, et rien d'autre :
   la conversation seule défile (la barre du haut et la saisie du bas restent
   où le pouce les attend), la hauteur se mesure en `dvh` (`vh` compte la barre
   d'adresse de Safari, qui se rétracte — le champ de saisie passait alors sous
   l'écran), et les encoches sont rendues à l'OS par `safe-area-inset-*`. */
.app-body { height: 100vh; height: 100dvh; overflow: hidden; }
.app-ecran { display: flex; flex-direction: column; height: 100%; }

.app-bar {
  display: flex; align-items: center; gap: 10px; flex: none;
  padding: 10px 14px; padding-top: calc(10px + env(safe-area-inset-top));
  background: var(--accent); color: #fff;
}
.app-logo { height: 26px; width: auto; }
.app-titre { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }
.app-titre strong { font-size: 16px; }
.app-sous { font-size: 12px; opacity: .75; }
/* « Nouvelle conversation » en toutes lettres et en petit : dans une barre
   de téléphone, l'intitulé complet prenait la moitié de la largeur, et une
   icône seule ne se survole pas — sur un écran tactile, son infobulle
   n'existe pas. */
.app-bar .ia-forget {
  margin-left: auto; flex: none; max-width: 40%; font-size: 11px;
  line-height: 1.15; padding: 5px 8px; color: #fff;
  border: 1px solid rgba(255, 255, 255, .55); background: none;
}

.app-corps {
  flex: 1; min-height: 0; overflow-y: auto; padding: 12px 14px;
  display: flex; flex-direction: column;
}

/* Écran d'accueil : le micro, en grand, au milieu. C'est la fonction de
   l'application — le montrer à cette taille dit quoi faire sans l'écrire, et
   le pouce le trouve sans que l'œil le cherche. `ia-vide` est posée par
   `majFil()` dans ia.js, seul endroit qui sache si la conversation est vide ;
   le gabarit la porte dès le premier rendu pour que le bouton ne surgisse pas
   après coup.

   Les deux boutons — celui-ci et celui de la barre du bas — sont le **même
   micro** : ia.js les câble tous les deux et leur donne le même état d'écoute.
   Le CSS n'en montre qu'un à la fois, jamais les deux. */
.app-hero { display: none; }
.app-ecran.ia-vide .app-hero {
  display: flex; flex: 1; flex-direction: column;
  align-items: center; justify-content: center; gap: 20px;
  text-align: center; padding-bottom: 24px;
}
.app-ecran.ia-vide .app-intro { max-width: 22em; }
/* Un seul micro visible à la fois : le grand tant que rien n'est demandé, le
   petit ensuite. Deux boutons pour la même chose, au même moment, se lisent
   comme deux fonctions. */
.app-ecran.ia-vide .app-mic-bas { display: none; }
/* Le fil occupe ici toute la place disponible : sa hauteur bornée sert au
   panneau flottant, qui se pose par-dessus une page. */
.app-thread { margin-top: 0; max-height: none; overflow-y: visible; }
.app-intro { color: var(--muted); font-size: 15px; line-height: 1.5; }

.app-pied {
  flex: none; background: var(--card); border-top: 1px solid var(--border);
  padding: 10px 14px; padding-bottom: calc(10px + env(safe-area-inset-bottom));
}
/* Une rangée qui défile, jamais un pavé qui s'enroule : sur un téléphone la
   hauteur appartient à la conversation. */
.app-questions {
  display: flex; gap: 8px; overflow-x: auto; padding-bottom: 8px;
  scrollbar-width: none;
}
.app-questions::-webkit-scrollbar { display: none; }
.app-questions .ia-q { flex: none; white-space: nowrap; }
.app-note { margin: 0 0 6px; }
.app-note:empty { display: none; }

.app-form { display: flex; align-items: center; gap: 8px; }
.app-form input { flex: 1; min-width: 0; }
.app-mic {
  flex: none; width: 44px; height: 44px; border-radius: 50%; border: none;
  background: var(--accent); color: #fff; font-size: 20px; cursor: pointer;
}
/* Le même micro, à la taille de l'écran d'accueil. Défini **après** `.app-mic`
   et non plus haut avec la mise en page du héros : à spécificité égale c'est la
   dernière règle du fichier qui l'emporte, et le grand bouton reprenait sinon
   ses 44 px sans que rien ne le signale. */
.app-mic-hero {
  width: 132px; height: 132px; font-size: 54px;
  box-shadow: 0 6px 20px rgba(37, 44, 59, .28);
}
/* Même signal d'écoute que les deux autres micros : une seule animation, sinon
   le même état se dirait de trois façons. */
.app-mic.ecoute { background: var(--neg); animation: ia-pulse 1.2s infinite; }
.app-envoi { flex: none; padding: 11px 16px; }
.app-retour {
  display: block; margin-top: 10px; text-align: center;
  font-size: 12px; color: var(--muted);
}
/* Le champ de saisie sous 16 px fait zoomer iOS sur le focus, et la page ne
   revient jamais tout à fait à sa taille. */
.app-form input { font-size: 16px; padding: 11px 12px; }
