/* Bémol · Planning OSR — habillage inspiré de l'identité visuelle de l'OSR :
   noir chaud et or des programmes de concert (osr.ch), typographie serif pour
   les titres, fond ivoire. Chaque Liste (production) a sa propre couleur,
   stable sur tous ses services (répétitions, générale, concert…) — cf. issue
   #109 : plus simple à repérer d'un coup d'œil qu'un code couleur par type de
   service. */

:root {
  /* Or/bronze foncé pour les surfaces claires (contraste AA sur blanc) */
  --accent: #75633f;
  --bg: #f5f2ea;
  --surface: #fff;
  --surface-alt: #f3f5f8;
  --surface-accent-soft: #ece5d2;
  --surface-accent-soft-2: #ddd0a8;
  --border: #ddd6c5;
  --border-soft: rgba(0, 0, 0, 0.06);
  --text: #26211a;
  --text-muted: #667;
  --text-faint: #889;
  --today-bg: #fdf6dd;
  --today-bg-strong: #f5e6a8;
  --hover-soft: #eef;
  --hover-brightness: 0.93;
  --shadow: rgba(0, 0, 0, 0.3);
  --backdrop: rgba(0, 0, 0, 0.35);
  --danger: #d33;
  --danger-soft: #fbe3e3;
  --success: #3a5;
  --success-text: #283;
  --success-soft: #e3f3e8;
  --diff-old: #a55;
  --purple: #7a5cc0;
  --purple-soft: #efeaf9;
  --purple-text: #6a4bb0;
  --memo-soft: #f6f2fc;
  --warn-bg: #fff3cd;
  --warn-text: #664d03;
  --warn-border: #ffe69c;
  --evt-loc: rgba(0, 0, 0, 0.55);
  --head-accent-text: #75633f;

  /* En-tête « programme de concert » : noir chaud, texte ivoire, or clair —
     invariant par thème (cf. bloc [data-theme="dark"] plus bas) */
  --header-bg: #1d1912;
  --header-fg: #f2ecdd;
  --gold: #c8a35c;
  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;

  /* Palette « code couleur par Liste » (#109) : une teinte par production,
     assignée par app.js (listeColorClass, hash stable du nom de la Liste) à
     l'une de ces LISTE_COLOR_COUNT cases, tournantes comme dans un agenda
     classique (au-delà de 12 Listes simultanées, la couleur se répète). */
  --liste-color-0: #f5a83a;
  --liste-color-1: #e2704a;
  --liste-color-2: #fbd45c;
  --liste-color-3: #d9b3e6;
  --liste-color-4: #b5e0bd;
  --liste-color-5: #cfe2f7;
  --liste-color-6: #f2c4c4;
  --liste-color-7: #c9d6a3;
  --liste-color-8: #f7c6dd;
  --liste-color-9: #a8d8d8;
  --liste-color-10: #d8c2a0;
  --liste-color-11: #b8c4e0;

  /* Couleur indépendante des Listes, pour l'accent « modifié » de la vue
     Modifs (cf. .change-item.modified) — anciennement --cat-concert. */
  --change-modified: #f5a83a;
  --change-modified-soft: #fdf0dc;

  /* Services « sans orchestre » (#116) : couleur neutre et volontairement
     distincte de la palette --liste-color-*, pour signaler d'un coup d'œil
     qu'un service ne concerne pas les musicien·nes de l'orchestre — quelle
     que soit sa Liste. */
  --no-orchestre-bg: #d8d4c8;
  --no-orchestre-text: #55503f;

  color-scheme: light;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family:
    -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
  font-size: 15px;
}

header {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--header-bg);
  color: var(--header-fg);
  border-bottom: 2px solid var(--gold);
  padding: 8px 12px 6px;
}

/* Bandeau d'avertissement quand les données ne sont plus actualisées
   (cf. checkDataFreshness() dans app.js) */
.stale-banner {
  background: var(--warn-bg);
  color: var(--warn-text);
  border-bottom: 1px solid var(--warn-border);
  padding: 8px 12px;
  text-align: center;
  font-size: 0.95em;
}

.header-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

h1 {
  margin: 0;
  font-family: var(--serif);
  font-size: 1.45em;
  font-weight: 600;
  color: var(--gold);
  white-space: nowrap;
  letter-spacing: 0.01em;
}

h1 .subtitle {
  font-weight: normal;
  font-style: italic;
  font-size: 0.62em;
  color: #a89a79;
  letter-spacing: 0.03em;
}

.header-controls {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

select,
button {
  font: inherit;
  padding: 5px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
}

#view-nav {
  display: flex;
  gap: 0;
}

#view-nav button {
  border-radius: 0;
  border-right-width: 0;
  position: relative;
}

#view-nav button:first-child {
  border-radius: 6px 0 0 6px;
}

#view-nav button:last-child {
  border-radius: 0 6px 6px 0;
  border-right-width: 1px;
}

/* Boutons de l'en-tête : déclinaison sombre (l'or est réservé à l'état actif) */
.header-controls button,
.header-controls select {
  background: rgba(255, 255, 255, 0.07);
  color: var(--header-fg);
  border-color: #4d4536;
}

#view-nav button.active {
  background: var(--gold);
  color: var(--header-bg);
  border-color: var(--gold);
  font-weight: 600;
}

.badge {
  background: var(--danger);
  color: #fff;
  border-radius: 9px;
  font-size: 0.7em;
  padding: 1px 5px;
  margin-left: 4px;
  vertical-align: top;
}

#view-nav button.active .badge {
  background: var(--header-bg);
  color: var(--gold);
}

main {
  padding: 10px 12px 40px;
  max-width: 1400px;
  margin: 0 auto;
}

/* --- Vue grille (Bible) --- */

.periode {
  margin-bottom: 26px;
}

/* Titre d'une période (« Période N — du … au … »), partagé entre la vue
   Grille (.periode > h2) et la vue Document (.doc-periode-planning > h2). */
.periode-title {
  background: var(--header-bg);
  color: var(--gold);
  font-family: var(--serif);
  font-size: 1em;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 6px 12px;
  border-radius: 6px 6px 0 0;
  margin: 0 0 2px;
}

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

table.week {
  border-collapse: collapse;
  width: 100%;
  min-width: 860px;
  margin-bottom: 2px;
  background: var(--surface);
  table-layout: fixed;
}

table.week th,
table.week td {
  border: 1px solid var(--border);
  vertical-align: top;
  padding: 2px;
}

table.week th {
  background: var(--surface-accent-soft);
  font-size: 0.78em;
  font-weight: 600;
  padding: 4px 2px;
}

table.week th.week-label {
  width: 52px;
  background: var(--surface-accent-soft-2);
}

table.week th.today,
table.week td.today {
  background-color: var(--today-bg);
}

table.week th.today {
  background: var(--today-bg-strong);
}

td .slot-label,
th.slot-col {
  width: 52px;
}

table.week td.slot-name {
  background: var(--surface-alt);
  font-size: 0.7em;
  color: var(--text-faint);
  text-align: center;
  vertical-align: middle;
}

/* Chip d'événement */
.evt {
  display: block;
  width: 100%;
  max-width: 100%;
  text-align: left;
  border: none;
  border-radius: 4px;
  padding: 3px 5px;
  margin: 1px 0;
  font-size: 0.74em;
  line-height: 1.3;
  cursor: pointer;
  background: var(--liste-color-0);
  /* Le texte reste toujours dans la case : on autorise le retour à la ligne
     (les <button> ne le font pas par défaut sur certains navigateurs) et la
     coupure des mots trop longs pour la largeur de colonne, très étroite sur
     téléphone (« Conseil de fondation », « enregistrement »…).
     `overflow-wrap: anywhere` (contrairement à `break-word`) réduit aussi la
     largeur minimale de la vignette : indispensable dans un tableau en
     `table-layout: fixed` où les colonnes sont très étroites, et `min-width: 0`
     empêche le <button> de refuser de rétrécir sous la largeur de son contenu
     (bug fréquent sur Safari iOS). */
  min-width: 0;
  white-space: normal;
  overflow-wrap: anywhere;
  word-break: break-word;
  hyphens: auto;
}

.evt b {
  font-weight: 700;
}

.evt .evt-loc {
  color: var(--evt-loc);
}

.evt.liste-color-0 {
  background: var(--liste-color-0);
}
.evt.liste-color-1 {
  background: var(--liste-color-1);
}
.evt.liste-color-2 {
  background: var(--liste-color-2);
}
.evt.liste-color-3 {
  background: var(--liste-color-3);
}
.evt.liste-color-4 {
  background: var(--liste-color-4);
}
.evt.liste-color-5 {
  background: var(--liste-color-5);
}
.evt.liste-color-6 {
  background: var(--liste-color-6);
}
.evt.liste-color-7 {
  background: var(--liste-color-7);
}
.evt.liste-color-8 {
  background: var(--liste-color-8);
}
.evt.liste-color-9 {
  background: var(--liste-color-9);
}
.evt.liste-color-10 {
  background: var(--liste-color-10);
}
.evt.liste-color-11 {
  background: var(--liste-color-11);
}

/* Service « sans orchestre » (#116) : couleur neutre volontairement à part de
   la palette --liste-color-*, prioritaire sur elle (déclarée après dans la
   cascade) pour rester reconnaissable quelle que soit la Liste. */
.evt.no-orchestra {
  background: var(--no-orchestre-bg);
  color: var(--no-orchestre-text);
}
.evt.no-orchestra .evt-loc {
  color: var(--no-orchestre-text);
  opacity: 0.75;
}

.evt.cancelled {
  text-decoration: line-through;
  opacity: 0.55;
}

.evt.recent::after {
  content: "●";
  color: var(--danger);
  margin-left: 4px;
  font-size: 0.9em;
}

@media (hover: hover) {
  .evt:hover {
    filter: brightness(var(--hover-brightness));
  }
}

/* Repères vacances scolaires & jours fériés (vue Grille) */
:root {
  --hol-ge: #c0392b; /* Genève */
  --hol-vd: #2f7d4f; /* Vaud */
  --hol-fr: #2f6fb0; /* France voisine */
  --hol-ge-soft: #ecc0bb;
  --hol-vd-soft: #c5e0cd;
  --hol-fr-soft: #bcd2ec;
  --vac-ge-text: #6e211a;
  --vac-vd-text: #1f5c34;
  --vac-fr-text: #1d3f63;
  --repos-bg: #dce9dc;
  --repos-bg-soft: #eef4ee;
  --repos-text: #2f6b3a;
  --repos-chip: #c3ddc3;
}

/* --- Mode sombre ---------------------------------------------------------
   Bascule pilotée par app.js (attribut data-theme posé sur <html>, d'après la
   préférence "auto" (système), "light" ou "dark" mémorisée dans les
   Réglages). Les teintes de la palette --liste-color-* sont assombries pour
   rester lisibles sur fond sombre, sans perdre leur code couleur d'origine
   (cf. issue #57 puis #109). */
:root[data-theme="dark"] {
  --accent: #4a86b8;
  --bg: #14181c;
  --surface: #1e2328;
  --surface-alt: #262c33;
  --surface-accent-soft: #24384a;
  --surface-accent-soft-2: #2c4a63;
  --border: #3a4149;
  --border-soft: rgba(255, 255, 255, 0.08);
  --text: #e8eaed;
  --text-muted: #a9b2bc;
  --text-faint: #8b95a1;
  --today-bg: #3a341c;
  --today-bg-strong: #4a4020;
  --hover-soft: #2a3038;
  --hover-brightness: 1.12;
  --shadow: rgba(0, 0, 0, 0.6);
  --backdrop: rgba(0, 0, 0, 0.6);
  --danger: #e35d5d;
  --danger-soft: #3a2020;
  --success: #4c9d6b;
  --success-text: #7fd9a0;
  --success-soft: #1f3a28;
  --diff-old: #d98f8f;
  --purple: #9d82df;
  --purple-soft: #352d55;
  --purple-text: #c1adf0;
  --memo-soft: #241f38;
  --warn-bg: #4a3f14;
  --warn-text: #f0d585;
  --warn-border: #6b5a1e;
  --evt-loc: rgba(255, 255, 255, 0.65);
  --head-accent-text: #bcdcef;

  --liste-color-0: #8a5a1a;
  --liste-color-1: #7a3a20;
  --liste-color-2: #7a6a1f;
  --liste-color-3: #5c3d6b;
  --liste-color-4: #2f5c3b;
  --liste-color-5: #2d4a66;
  --liste-color-6: #6b3535;
  --liste-color-7: #4a5a2a;
  --liste-color-8: #6b3a52;
  --liste-color-9: #2a5555;
  --liste-color-10: #5a4a30;
  --liste-color-11: #3a4560;

  --change-modified: #8a5a1a;
  --change-modified-soft: #3a2f14;

  --no-orchestre-bg: #3a3f47;
  --no-orchestre-text: #c2c8d1;

  --hol-ge-soft: #4a2521;
  --hol-vd-soft: #1f3a28;
  --hol-fr-soft: #1f3245;
  --vac-ge-text: #f0b4ab;
  --vac-vd-text: #a8dab8;
  --vac-fr-text: #a9c9ec;

  --repos-bg: #223020;
  --repos-bg-soft: #1c2a1a;
  --repos-text: #8fce9e;
  --repos-chip: #35502f;

  color-scheme: dark;
}

/* Case d'en-tête d'un jour férié : teinte de la (ou des) région(s) réellement
   concernée(s), pour ne pas laisser croire qu'un férié propre à une seule
   région (p. ex. FR) concerne aussi les autres. Les sélecteurs à deux/trois
   classes ont naturellement une spécificité plus grande que les sélecteurs à
   une classe : la combinaison l'emporte toujours sur une région seule, quel
   que soit l'ordre des classes posées par app.js. */
table.week th.ferie-ge {
  background: var(--hol-ge-soft);
}
table.week th.ferie-vd {
  background: var(--hol-vd-soft);
}
table.week th.ferie-fr {
  background: var(--hol-fr-soft);
}
table.week th.ferie-ge.ferie-vd {
  background: linear-gradient(90deg, var(--hol-ge-soft), var(--hol-vd-soft));
}
table.week th.ferie-ge.ferie-fr {
  background: linear-gradient(90deg, var(--hol-ge-soft), var(--hol-fr-soft));
}
table.week th.ferie-vd.ferie-fr {
  background: linear-gradient(90deg, var(--hol-vd-soft), var(--hol-fr-soft));
}
table.week th.ferie-ge.ferie-vd.ferie-fr {
  background: linear-gradient(
    90deg,
    var(--hol-ge-soft),
    var(--hol-vd-soft),
    var(--hol-fr-soft)
  );
}

.ferie-tags {
  display: flex;
  gap: 2px;
  justify-content: center;
  margin-top: 2px;
}

/* En `em` (pas `rem`), même raison que .vac-band / .vac-label plus bas :
   suivre la réduction de police de la vue Bible à l'impression. */
.ferie-tag {
  border: none;
  border-radius: 3px;
  padding: 0 3px;
  font-size: 0.62em;
  line-height: 1.5;
  font-weight: 700;
  color: #fff;
  cursor: pointer;
}

.ferie-tag.ferie-ge {
  background: var(--hol-ge);
}

.ferie-tag.ferie-vd {
  background: var(--hol-vd);
}

.ferie-tag.ferie-fr {
  background: var(--hol-fr);
}

tr.vac-row td {
  border: 1px solid var(--border);
  padding: 1px;
}

/* En `em` (pas `rem`) : ces bandeaux doivent suivre la réduction de police de
   la vue Bible à l'impression (body[data-view="document"], cf. plus bas) — en
   `rem` ils restaient calés sur la taille racine et ressortaient ~2x trop
   grands par rapport au reste du planning imprimé (retour #114). */
td.vac-label {
  font-size: 0.58em;
  font-weight: 700;
  text-align: center;
  vertical-align: middle;
}

/* Initiale de région colorée comme les pastilles de jour férié (.ferie-tag),
   pour identifier la région d'un coup d'œil sans ambiguïté possible. */
td.vac-label-ge {
  background: var(--hol-ge);
  color: #fff;
}
td.vac-label-vd {
  background: var(--hol-vd);
  color: #fff;
}
td.vac-label-fr {
  background: var(--hol-fr);
  color: #fff;
}

.vac-band {
  display: block;
  width: 100%;
  border: none;
  border-radius: 3px;
  padding: 1px 5px;
  font-size: 0.62em;
  line-height: 1.5;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
}

.vac-ge .vac-band {
  background: var(--hol-ge-soft);
  color: var(--vac-ge-text);
}

.vac-vd .vac-band {
  background: var(--hol-vd-soft);
  color: var(--vac-vd-text);
}

.vac-fr .vac-band {
  background: var(--hol-fr-soft);
  color: var(--vac-fr-text);
}

/* Rentrée scolaire : jour de reprise. On garde la teinte de région (comme les
   vacances et les jours fériés) pour distinguer Genève de la France voisine ;
   le gras signale qu'il s'agit d'un repère ponctuel, pas d'une période. */
.vac-band.rentree-band {
  font-weight: 700;
}

/* Week-ends « repos » (aucun service samedi ni dimanche) dans la Grille.
   Teinte verte très douce sur les colonnes samedi/dimanche ; « today » garde
   la priorité grâce au :not(.today). */
table.week th.repos:not(.today) {
  background: var(--repos-bg);
}

table.week td.repos:not(.today) {
  background: var(--repos-bg-soft);
}

/* En `em` (pas `rem`), même raison que .vac-band / .vac-label plus bas :
   suivre la réduction de police de la vue Bible à l'impression — sans ça,
   les pastilles « Repos » (comme les fériés ci-dessus) restaient calées sur
   la taille racine du document et ressortaient ~2x trop grandes par rapport
   au reste du planning imprimé, faisant déborder les périodes qui
   contiennent un week-end de repos (retour #114). */
.repos-tag {
  display: block;
  margin: 2px auto 0;
  width: fit-content;
  border: none;
  border-radius: 3px;
  padding: 0 6px;
  font-size: 0.62em;
  line-height: 1.5;
  font-weight: 700;
  color: var(--repos-text);
  background: var(--repos-chip);
  cursor: pointer;
}

.detail-box .holiday-list {
  margin: 8px 0 0;
  padding-left: 1.2em;
}

.detail-box .holiday-list li {
  margin: 3px 0;
}

@media (hover: hover) {
  .ferie-tag:hover,
  .vac-band:hover,
  .repos-tag:hover {
    filter: brightness(var(--hover-brightness));
  }
}

/* --- Vue document (saison complète imprimable) --- */

.doc-intro {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin: 0 0 16px;
}

.doc-intro p {
  margin: 0;
  color: var(--text-muted);
  font-size: 0.9em;
}

.doc-print-btn {
  flex: none;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 6px;
  padding: 8px 14px;
  font-size: 0.9em;
  font-weight: 600;
  white-space: nowrap;
}

@media (hover: hover) {
  .doc-print-btn:hover {
    filter: brightness(var(--hover-brightness));
  }
}

/* Bandeau sticky (sous-menu + recherche), commun aux vues Agenda
   personnalisé et Bible : reste visible en tête de page pendant le
   défilement du calendrier, juste sous l'en-tête (retour #132). `--header-h`
   est posée en JS par observeHeaderHeight() (cf. app.js) — hauteur réelle de
   l'en-tête, variable selon l'écran et les zones de sécurité iOS ; un
   décalage fixe aurait laissé un trou ou un chevauchement selon l'appareil.
   Fond opaque et z-index sous l'en-tête (10) : le contenu qui défile doit
   disparaître derrière, pas au travers. */
.view-toolbar {
  position: sticky;
  top: var(--header-h, 0px);
  z-index: 9;
  background: var(--bg);
  padding-top: 10px;
  border-bottom: 1px solid var(--border);
}

/* --- Vue Agenda personnalisé : sous-menu Aujourd'hui/Réglages/Abonnement,
   aussi réutilisé pour le sous-menu Aujourd'hui/Imprimer de la vue Bible
   (#132 sur #131) --- */

.agenda-actions-btns {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

/* Une période : planning (grille de services) — cf. renderPeriodePage dans
   app.js. renderPeriodePage construit aussi, à côté, les fiches de programme
   des Listes travaillées pendant la période (chef, solistes, œuvres…), mais
   celles-ci ne sont plus affichées à l'écran (cf. .doc-periode-listes
   plus bas) : toute l'info d'une Liste reste à un clic (dialogue Liste), la
   fiche complète n'apporte donc ici que de l'encombrement (retour #134). Ce
   layout flex ne sert donc plus qu'à l'impression, où planning et détail
   sont empilés sur deux pages dédiées (cf. @media print plus bas). */
.doc-periode-page {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 30px;
}

.doc-periode-planning {
  flex: 3 1 640px;
  min-width: 0;
}

/* Fiches de programme (chef, solistes, œuvres…) des Listes de la période :
   masquées à l'écran (retour #134 — « la version numérique [ne devrait
   afficher] que la partie agenda sans le détail des listes », déjà
   accessible en un clic sur un service), restaurées à l'impression
   (`display: block` sous @media print, cf. plus bas) pour la Bible PDF, qui
   reste le document de référence complet. `.detail-box` sur `.doc-liste-card`
   (au lieu d'un préfixe dédié) pour hériter tel quel du style de la fiche de
   production affichée dans le dialogue Liste. */
.doc-periode-listes {
  display: none;
}

/* Pas de fiche de programme pour cette période (mémo pas encore publié) :
   le planning occupe alors toute la largeur. */
.doc-periode-page.no-listes .doc-periode-planning {
  flex-basis: 100%;
}

.doc-liste-card {
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 10px 12px;
  background: var(--surface);
}

.doc-liste-title {
  margin: 0 0 4px;
  font-family: var(--serif);
  color: var(--accent);
  font-size: 1.05em;
}

/* --- Préparation de l'impression ----------------------------------------- */

.print-setup {
  width: 100%;
}

.print-setup-controls {
  max-width: 900px;
  margin: 0 auto 28px;
  padding: 20px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
}

.print-setup-controls > h2 {
  margin: 18px 0 6px;
  font-family: var(--serif);
  color: var(--accent);
  font-size: 1.5em;
}

.print-back-btn {
  min-height: 42px;
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}

.print-setup-intro,
.print-orientation-note,
.print-reference-note,
.print-preview-note,
.print-action p {
  color: var(--text-muted);
}

.print-setup-intro {
  margin: 0 0 18px;
}

.print-mode-fieldset,
.print-period-fieldset,
.print-size-fieldset {
  margin: 0;
  padding: 0;
  border: 0;
}

.print-mode-fieldset > legend,
.print-period-fieldset > legend,
.print-size-fieldset > legend {
  margin-bottom: 8px;
  font-weight: 700;
}

.print-mode-fieldset {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.print-mode-fieldset > legend {
  grid-column: 1 / -1;
}

.print-mode-option {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  min-height: 92px;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
}

.print-mode-option:has(input:checked) {
  border-color: var(--accent);
  background: var(--surface-accent-soft);
}

.print-mode-option input,
.print-period-option input,
.print-inline-option input {
  width: 19px;
  height: 19px;
  flex: none;
  margin: 1px 0 0;
}

.print-mode-option strong,
.print-mode-option small {
  display: block;
}

.print-mode-option small {
  margin-top: 5px;
  color: var(--text);
  line-height: 1.35;
}

.print-orientation-note {
  margin: 10px 0 0;
  font-size: 0.85em;
}

.print-period-controls {
  margin-top: 20px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
}

.print-reference-note {
  margin: 0 0 16px;
  font-size: 0.9em;
}

.print-selection-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

.print-selection-actions button {
  min-height: 40px;
}

.print-period-options {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 4px 12px;
  max-height: 330px;
  overflow-y: auto;
  padding: 6px;
  border: 1px solid var(--border);
  border-radius: 8px;
}

.print-period-option {
  display: flex;
  align-items: center;
  gap: 9px;
  min-height: 42px;
  padding: 7px 8px;
  border-radius: 6px;
  cursor: pointer;
}

.print-size-fieldset {
  margin-top: 18px;
}

.print-inline-options {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.print-inline-option {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 42px;
  padding: 7px 12px;
  border: 1px solid var(--border);
  border-radius: 7px;
  cursor: pointer;
}

.print-inline-option:has(input:checked) {
  border-color: var(--accent);
  background: var(--surface-accent-soft);
}

.print-period-summary {
  margin: 16px 0 0;
  font-weight: 700;
  color: var(--accent);
}

.print-period-warning {
  margin: 7px 0 0;
  color: var(--danger);
  font-weight: 600;
}

.print-action {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
}

.print-primary-btn {
  width: 100%;
  min-height: 48px;
  border: 0;
  background: var(--accent);
  color: #fff;
  font-weight: 700;
}

.print-primary-btn:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}

.print-action p {
  margin: 8px 0 0;
  font-size: 0.85em;
  text-align: center;
}

.print-preview {
  min-width: 0;
  padding-top: 22px;
  border-top: 1px solid var(--border);
}

.print-preview-title {
  margin: 0 0 4px;
  font-family: var(--serif);
  color: var(--accent);
}

.print-preview-note {
  margin: 0 0 12px;
  font-size: 0.85em;
}

.print-preview-scroll {
  max-width: 100%;
  min-width: 0;
  overflow-x: auto;
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface-alt);
  -webkit-overflow-scrolling: touch;
}

.print-preview-output {
  min-width: 0;
}

.print-empty-preview {
  margin: 0;
  padding: 50px 20px;
  color: var(--text-muted);
  text-align: center;
}

/* Feuille A4 paysage simulée à l'écran. Sa largeur minimale est volontaire :
   sur téléphone, seul ce cadre défile horizontalement, jamais l'app entière. */
.period-export-output {
  min-width: 1120px;
}

.period-export-page {
  --pe-list-0: #f5a83a;
  --pe-list-1: #e2704a;
  --pe-list-2: #fbd45c;
  --pe-list-3: #d9b3e6;
  --pe-list-4: #b5e0bd;
  --pe-list-5: #cfe2f7;
  --pe-list-6: #f2c4c4;
  --pe-list-7: #c9d6a3;
  --pe-list-8: #f7c6dd;
  --pe-list-9: #a8d8d8;
  --pe-list-10: #d8c2a0;
  --pe-list-11: #b8c4e0;
  width: 1120px;
  min-width: 1120px;
  margin: 0 auto 22px;
  padding: 22px;
  background: #fff;
  color: #26211a;
  box-shadow: 0 2px 12px var(--shadow);
  font-family: Arial, sans-serif;
}

.period-export-page:last-child {
  margin-bottom: 0;
}

.period-export-size-small {
  font-size: 10px;
}

.period-export-size-medium {
  font-size: 11px;
}

.period-export-size-large {
  font-size: 12px;
}

.period-export-header {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 20px;
  align-items: end;
  margin-bottom: 8px;
  padding-bottom: 7px;
  border-bottom: 2px solid #75633f;
}

.period-export-orchestra {
  margin: 0 0 2px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.85em;
  font-weight: 700;
  color: #75633f;
}

.period-export-header h2 {
  margin: 0;
  font-family: var(--serif);
  font-size: 1.55em;
  color: #26211a;
}

.period-export-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.3;
  text-align: right;
}

.period-export-week {
  width: 100%;
  margin: 0 0 5px;
  border-collapse: collapse;
  table-layout: fixed;
  background: #fff;
}

.period-export-week th,
.period-export-week td {
  border: 1px solid #b9b5aa;
}

.period-export-week thead th {
  padding: 3px 4px;
  background: #ece5d2;
  text-align: center;
  line-height: 1.15;
}

.period-export-week .period-export-slot-head,
.period-export-week .period-export-slot {
  width: 62px;
  background: #e1ddd3;
  color: #5d584e;
  text-align: center;
  font-weight: 700;
}

.period-export-week .period-export-slot {
  padding: 3px;
  font-size: 0.82em;
  vertical-align: middle;
}

.period-export-day,
.period-export-date,
.period-export-repos {
  display: block;
}

.period-export-day {
  text-transform: capitalize;
  font-weight: 700;
}

.period-export-date {
  font-size: 0.85em;
  color: #625e55;
}

.period-export-repos {
  width: fit-content;
  margin: 2px auto 0;
  padding: 0 4px;
  border-radius: 3px;
  background: #c3ddc3;
  color: #24542d;
  font-size: 0.72em;
}

.period-export-week .weekend {
  background: #f3f1eb;
}

.period-export-week .repos {
  background: #eef4ee;
}

.period-export-service-cell {
  padding: 2px;
  vertical-align: top;
}

.period-export-cell {
  min-height: 24px;
}

.period-export-event {
  margin: 0 0 2px;
  padding: 2px 3px;
  border-left: 3px solid rgba(0, 0, 0, 0.28);
  border-radius: 2px;
  line-height: 1.16;
  overflow-wrap: anywhere;
  break-inside: avoid;
}

.period-export-event:last-child {
  margin-bottom: 0;
}

/* L'aperçu HTML privilégie le contenu : les semaines et les créneaux
   grandissent avec le texte, sans chevauchement. La grille à hauteur fixe
   et créneaux égaux est réservée à l'impression (voir @media print). */
.period-export-simplified {
  display: grid;
  grid-template-rows: auto repeat(var(--period-weeks), auto) auto;
  gap: 5px;
}

.period-export-simplified .period-export-header,
.period-export-simplified .period-export-footer {
  min-height: 0;
  margin: 0;
}

.period-export-simplified .period-export-week {
  display: grid;
  min-height: 0;
  margin: 0;
  grid-template-columns: 62px repeat(7, minmax(0, 1fr));
  grid-template-rows: auto repeat(3, minmax(48px, auto)) auto;
  border-top: 1px solid #b9b5aa;
  border-left: 1px solid #b9b5aa;
}

.period-export-simplified .period-export-week thead,
.period-export-simplified .period-export-week tbody,
.period-export-simplified .period-export-week tfoot,
.period-export-simplified .period-export-week tr {
  display: contents;
}

.period-export-simplified .period-export-week th,
.period-export-simplified .period-export-week td {
  width: auto;
  min-width: 0;
  min-height: 0;
  border: 0;
  border-right: 1px solid #b9b5aa;
  border-bottom: 1px solid #b9b5aa;
}

.period-export-simplified .period-export-slot {
  display: grid;
  place-items: center;
}

.period-export-simplified .period-export-cell {
  min-height: 0;
}

.period-export-simplified .period-export-notes {
  grid-column: 1 / -1;
}

.period-export-simplified .period-export-repos {
  display: inline;
  margin-left: 3px;
}

.period-export-simplified .period-export-day,
.period-export-simplified .period-export-date {
  display: inline;
  margin-right: 3px;
}

.period-export-simplified .period-export-plain-event {
  background: transparent;
  border: 0;
  border-radius: 0;
  padding: 2px;
  font-weight: normal;
  line-height: 1.3;
}

.period-export-plain-event strong {
  font-weight: 700;
}

.period-export-plain-event em {
  font-style: italic;
}

.period-export-plain-time {
  color: #666;
}

.period-export-simplified .period-export-plain-event.cancelled {
  text-decoration: line-through;
}

.period-export-event-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px;
  font-size: 0.9em;
}

.period-export-event-head > :nth-child(2) {
  margin-left: auto;
  white-space: nowrap;
}

.period-export-activity {
  font-weight: 600;
}

.period-export-location {
  color: #26211a;
  font-size: 0.88em;
  font-weight: 400;
}

.period-export-cancelled {
  padding: 0 3px;
  border-radius: 2px;
  background: #fff;
  color: #a21f1f;
  font-size: 0.72em;
  font-weight: 800;
}

.period-export-event.cancelled .period-export-activity,
.period-export-event.cancelled .period-export-location {
  text-decoration: line-through;
}

.period-export-event.no-orchestra {
  background: #d8d4c8 !important;
  color: #55503f;
}

.period-export-event.liste-color-0 {
  background: var(--pe-list-0);
}
.period-export-event.liste-color-1 {
  background: var(--pe-list-1);
}
.period-export-event.liste-color-2 {
  background: var(--pe-list-2);
}
.period-export-event.liste-color-3 {
  background: var(--pe-list-3);
}
.period-export-event.liste-color-4 {
  background: var(--pe-list-4);
}
.period-export-event.liste-color-5 {
  background: var(--pe-list-5);
}
.period-export-event.liste-color-6 {
  background: var(--pe-list-6);
}
.period-export-event.liste-color-7 {
  background: var(--pe-list-7);
}
.period-export-event.liste-color-8 {
  background: var(--pe-list-8);
}
.period-export-event.liste-color-9 {
  background: var(--pe-list-9);
}
.period-export-event.liste-color-10 {
  background: var(--pe-list-10);
}
.period-export-event.liste-color-11 {
  background: var(--pe-list-11);
}

.period-export-notes {
  padding: 2px 4px;
  background: #faf8f2;
  color: #5f594f;
  font-size: 0.72em;
  line-height: 1.2;
}

.period-export-notes span:not(:last-child)::after {
  content: " · ";
  color: #9a9488;
}

.period-export-footer {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  margin-top: 7px;
  color: #69645b;
  font-size: 0.72em;
}

@media (hover: hover) {
  .print-mode-option:hover,
  .print-period-option:hover,
  .print-inline-option:hover {
    background: var(--surface-accent-soft);
  }
}

/* Popup « Aujourd'hui » (#131) : liste des services du jour. */
.today-events {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 10px;
}

/* --- Vue modifications --- */

.change-entry {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 12px;
  padding: 10px 14px;
}

.change-entry > h3 {
  margin: 0 0 8px;
  font-size: 0.9em;
  color: var(--accent);
}

.change-item {
  padding: 5px 8px;
  margin: 4px 0;
  border-left: 4px solid var(--border);
  font-size: 0.85em;
  background: var(--surface-alt);
}

.change-item.added {
  border-color: var(--success);
  background: var(--success-soft);
}
.change-item.removed {
  border-color: var(--danger);
  background: var(--danger-soft);
}
.change-item.modified {
  border-color: var(--change-modified);
  background: var(--change-modified-soft);
}
.change-item.memo {
  border-color: var(--purple);
  /* --memo-soft, pas --purple-soft : cette dernière est déjà prise par la
     pastille .change-tag ci-dessous, qui doit rester visible sur ce fond. */
  background: var(--memo-soft);
}

/* Légende des couleurs, sous l'en-tête de la vue Modifs (retour #180) : une
   case par type, même couleur que le fond des .change-item ci-dessus. Sticky
   comme .view-toolbar plus haut (retour #182 : rester visible en défilant
   dans la liste, pas seulement en haut de page). */
.modifs-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  margin: 0 0 12px;
  padding: 8px 0;
  position: sticky;
  top: var(--header-h, 0px);
  z-index: 9;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  font-size: 0.8em;
  color: var(--text-muted);
}
.modifs-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font: inherit;
  color: inherit;
  background: none;
  border: 1px solid transparent;
  border-radius: 14px;
  padding: 6px 10px;
  min-height: 36px;
  cursor: pointer;
}
.modifs-legend-item.active {
  border-color: var(--text-muted);
  background: var(--surface-alt);
  color: var(--text);
  font-weight: 600;
}
.modifs-legend-swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 3px;
}
.modifs-legend-swatch.added {
  background: var(--success);
}
.modifs-legend-swatch.removed {
  background: var(--danger);
}
.modifs-legend-swatch.modified {
  background: var(--change-modified);
}
.modifs-legend-swatch.memo {
  background: var(--purple);
}
.modifs-legend-swatch.concours-defini {
  background: var(--gold);
}

/* Concours dont le poste passait par « à définir » et vient d'être précisé
   (issue #178) : mise en avant volontairement plus marquée qu'une modif
   ordinaire, seul avertissement visible pour qui n'avait pas sélectionné ce
   concours faute de savoir de quel poste il s'agissait. */
.change-item.concours-defini {
  border-color: var(--gold);
  background: var(--warn-bg);
}
.change-item.concours-defini .field-diff {
  color: var(--warn-text);
}

/* Étiquette « Mémo de production » distinguant ces changements du planning */
.change-tag {
  display: inline-block;
  font-size: 0.75em;
  font-weight: 600;
  color: var(--purple-text);
  background: var(--purple-soft);
  border-radius: 8px;
  padding: 1px 7px;
  margin-right: 4px;
  vertical-align: middle;
}

.change-item .field-diff {
  color: var(--text-muted);
  margin-left: 12px;
}

.change-item .old {
  text-decoration: line-through;
  color: var(--diff-old);
}

.change-item .new {
  color: var(--success-text);
  font-weight: 600;
}

/* --- Recherche (intégrée aux vues Bible et Agenda personnalisé) --- */

.search-bar {
  margin-bottom: 12px;
}

.search-input {
  width: 100%;
  box-sizing: border-box;
  padding: 10px 14px;
  font-size: 1rem;
  border-radius: 8px;
}

.search-group {
  background: #fff;
  border: 1px solid #d8dce1;
  border-radius: 8px;
  margin-bottom: 12px;
  padding: 10px 14px;
}

.search-group > h3 {
  margin: 0 0 4px;
  font-size: 0.95em;
  color: var(--accent);
}

.search-chef {
  margin: 2px 0;
  font-weight: 600;
}

.search-solistes,
.search-works {
  margin: 2px 0;
  font-size: 0.85em;
  color: #556;
}

.search-dates {
  margin-top: 8px;
}

/* --- Dialogues --- */

dialog {
  border: none;
  border-radius: 10px;
  box-shadow: 0 8px 40px var(--shadow);
  padding: 18px 22px;
  max-width: min(480px, 92vw);
  width: 100%;
  background: var(--surface);
  color: var(--text);
}

dialog::backdrop {
  background: var(--backdrop);
}

dialog h2 {
  margin-top: 0;
  font-family: var(--serif);
  font-size: 1.2em;
  color: var(--accent);
}

/* En-tête d'un dialogue avec un bouton « Fermer » dupliqué en haut, en plus
   de celui du bas : évite de devoir tout faire défiler pour fermer quand on
   n'a modifié qu'un réglage en haut de la liste. */
.dialog-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.dialog-head h2 {
  margin-bottom: 0;
}

.dialog-head form {
  margin: 0;
}

.close-btn-top {
  flex: none;
  padding: 3px 9px;
  line-height: 1.4;
}

/* Variante flottante du même bouton, pour les dialogues dont le titre est
   généré dynamiquement (Détail, Liste) : mis en premier dans le contenu,
   il flotte à droite du titre au lieu d'être dans un en-tête flexbox fixe. */
.close-btn-top-form {
  float: right;
  margin: 0 0 6px 10px;
}

/* Étiquette de type de service (« Concert », « Générale »…) : simple badge
   neutre depuis #109 (la couleur, elle, identifie la Liste — cf. .liste-swatch). */
.detail-box .detail-cat {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 10px;
  font-size: 0.8em;
  margin-bottom: 8px;
  background: var(--surface-alt);
  border: 1px solid var(--border);
  color: var(--text-muted);
}

/* Point rouge sur le titre quand le mémo du programme a changé récemment */
.detail-box h2 .recent-dot {
  color: var(--danger);
  margin-left: 6px;
  font-size: 0.7em;
  vertical-align: middle;
}

.detail-box dl {
  margin: 8px 0;
  display: grid;
  grid-template-columns: 90px 1fr;
  gap: 4px 10px;
}

.detail-box dt {
  color: var(--text-faint);
  font-size: 0.85em;
}

.detail-box dd {
  margin: 0;
}

/* Seul le nom de la salle est souligné : l'adresse, en dessous, reste sobre
   (un soulignement porté par le lien lui-même déborderait sur elle). */
.detail-box .location-link {
  color: inherit;
  text-decoration: none;
}

.detail-box .location-name {
  text-decoration: underline dotted;
  text-underline-offset: 2px;
}

.detail-box .location-pin {
  font-size: 0.9em;
}

/* Adresse postale de la salle, sous son nom d'usage (venues.json). */
.detail-box .location-address {
  display: block;
  font-size: 0.85em;
  color: var(--text-muted);
  text-decoration: none;
}

@media (hover: hover) {
  .detail-box .location-link:hover {
    color: var(--accent);
  }
}

.detail-box .detail-section {
  margin: 14px 0 4px;
  font-size: 0.95em;
  color: var(--accent);
}

.detail-box .works,
.detail-box .solistes {
  margin: 0;
  padding-left: 1.2em;
}

.detail-box .works li,
.detail-box .solistes li {
  margin: 2px 0;
}

.detail-box .works li {
  margin: 6px 0;
}

.detail-box .work-dur {
  color: var(--text-faint);
  font-size: 0.85em;
  white-space: nowrap;
}

/* Détail d'instrumentation d'une œuvre (repris tel quel du mémo) */
.detail-box .work-detail {
  margin: 3px 0 2px;
  padding-left: 0.6em;
  border-left: 2px solid var(--border);
  color: var(--text-muted);
  font-size: 0.85em;
}

.detail-box .wd-row {
  display: flex;
  gap: 6px;
  margin: 1px 0;
}

.detail-box .wd-label {
  flex: 0 0 auto;
  min-width: 6.5em;
  color: var(--text-faint);
}

.detail-box .wd-val {
  white-space: pre-wrap;
}

.detail-box .chef,
.detail-box .info-generale,
.detail-box .effectif,
.detail-box .duree {
  margin: 0;
  white-space: pre-wrap;
}

/* Remarque du mémo propre à ce service précis (ex. « extraits »), sous les
   œuvres travaillées pendant ce service. */
.detail-box .service-note {
  margin: 4px 0 0;
  color: var(--text-muted);
  font-size: 0.85em;
  font-style: italic;
  white-space: pre-wrap;
}

/* Lien vers le portail de partitions Dièse (issue #79), affiché juste sous
   le titre de la fiche (#80) : la ligne qui le contient a donc le même
   traitement d'espacement qu'un <dl> voisin, et le lien lui-même reprend le
   style « pastille » de .liste-link pour rester cohérent. */
.score-portal-row {
  margin: 8px 0;
}

.score-portal-link {
  display: inline-flex;
  align-items: center;
  border: 1.5px solid var(--accent);
  border-radius: 999px;
  background: #e3edf5;
  padding: 5px 12px;
  font-weight: 700;
  font-size: 0.9em;
  color: var(--accent);
  text-decoration: none;
}

.score-portal-link:active {
  background: var(--accent);
  color: #fff;
}

@media (hover: hover) {
  .score-portal-link:hover {
    background: var(--accent);
    color: #fff;
  }
}

/* Nom de la Liste cliquable dans une fiche d'événement, ouvrant la vue par
   Liste (programme complet de la production). Style « pastille » (plutôt
   qu'un simple lien souligné) pour bien la distinguer du titre — qui est
   lui-même dans la couleur d'accent — et signaler que c'est tapable même
   sans survol (mobile). */
.liste-link {
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
  border: 1.5px solid var(--accent);
  border-radius: 999px;
  background: #e3edf5;
  padding: 3px 8px 3px 11px;
  margin: 0 2px 0 0;
  font: inherit;
  font-size: 0.85em;
  font-weight: 700;
  color: var(--accent);
  cursor: pointer;
}

.liste-link::after {
  content: "›";
  margin-left: 3px;
  font-weight: 900;
}

.liste-link:active {
  background: var(--accent);
  color: #fff;
}

@media (hover: hover) {
  .liste-link:hover {
    background: var(--accent);
    color: #fff;
  }
}

/* --- Dialogue « Liste » (programme complet d'une production) --- */

.liste-events {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.liste-events .evt {
  font-size: 0.85em;
  padding: 7px 9px;
  margin: 0;
  border-radius: 6px;
}

/* Historique des modifications d'un événement (issue #58), discret en bas de fiche */
#detail-content .detail-history {
  margin-top: 14px;
  padding-top: 8px;
  border-top: 1px solid #e2e5ea;
  color: #889;
  font-size: 0.8em;
}

#detail-content .detail-history p {
  margin: 2px 0;
}

.close-btn {
  margin-top: 10px;
}

/* --- Dialogue d'abonnement au calendrier --- */
#subscribe-content .subscribe-intro {
  margin: 0 0 14px;
  font-size: 0.9em;
}

/* Titres de section (« Mon planning » / « Calendrier complet ») quand
   l'abonnement personnalisé est disponible */
.subscribe-h {
  margin: 18px 0 8px;
  font-size: 1em;
  color: var(--accent);
}

.subscribe-h:first-child {
  margin-top: 0;
}

.subscribe-add {
  display: block;
  text-align: center;
  background: var(--accent);
  color: #fff;
  text-decoration: none;
  font-weight: 600;
  padding: 12px 14px;
  border-radius: 8px;
}

.subscribe-or {
  margin: 14px 0 6px;
  font-size: 0.85em;
  color: var(--text-muted);
}

.subscribe-url-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.subscribe-url {
  flex: 1 1 12em;
  min-width: 0;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface-alt);
  font-size: 0.85em;
  color: var(--text);
}

.subscribe-url-row .copy-btn {
  flex: 0 0 auto;
  background: var(--surface);
}

.subscribe-help {
  margin: 16px 0 6px;
  font-size: 0.85em;
}

.subscribe-help summary {
  cursor: pointer;
  color: var(--accent);
  font-weight: 600;
}

.subscribe-help ul {
  margin: 8px 0 0;
  padding-left: 1.2em;
}

.subscribe-help li {
  margin: 5px 0;
}

.subscribe-note {
  margin: 12px 0 0;
  font-size: 0.8em;
  color: var(--text-faint);
}

#prefs-content .prefs-section {
  padding: 5px 0;
}

#prefs-content .prefs-label {
  font-weight: 600;
  margin-bottom: 6px;
}

#prefs-content .prefs-cancelled {
  display: block;
  padding: 10px 0 5px;
}

#prefs-content .prefs-note {
  font-size: 0.8em;
  color: var(--text-faint);
  margin: 6px 0 0;
}

/* Pastille indiquant si les notifications sont activées sur cet appareil,
   à côté du libellé « Notifications : » (l'énoncé du bouton seul, « Activer »
   / « Désactiver », est trop discret pour voir l'état d'un coup d'œil). */
.notif-dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  margin-left: 7px;
  border-radius: 50%;
  background: var(--border);
  vertical-align: middle;
}

.notif-dot.is-on {
  background: var(--success);
}

/* Bouton « Désactiver les notifications » teinté quand elles sont actives,
   pour la même raison. */
#prefs-content .notif-btn-on {
  border-color: var(--success);
  color: var(--success-text);
}

.liste-filter-actions {
  display: flex;
  gap: 8px;
  margin-bottom: 8px;
}

.liste-filter-actions button {
  flex: 1;
  padding: 8px;
}

/* Bouton Tout cocher / Tout décocher mis en évidence (retour #129) quand il
   correspond à l'état courant (toutes les listes cochées, ou aucune). */
.liste-filter-actions button.active {
  background: var(--surface-accent-soft-2);
  border-color: var(--accent);
  color: var(--head-accent-text);
  font-weight: 600;
}

.liste-options {
  max-height: 45vh;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 4px 0;
}

.liste-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 12px;
  cursor: pointer;
}

.liste-option input {
  width: 18px;
  height: 18px;
  flex: none;
}

@media (hover: hover) {
  .liste-option:hover {
    background: var(--surface-accent-soft);
  }
}

#prefs-content .prefs-note-top {
  margin: 0 0 8px;
}

/* Pastille de couleur d'une Liste (production) : devant son nom dans le
   filtre par liste des Réglages, la fiche d'un service et le dialogue
   « Liste » — permet d'apprendre le code couleur de #109. */
.liste-swatch {
  display: inline-block;
  width: 14px;
  height: 14px;
  border-radius: 3px;
  flex: none;
  vertical-align: middle;
}
.liste-swatch.liste-color-0 {
  background: var(--liste-color-0);
}
.liste-swatch.liste-color-1 {
  background: var(--liste-color-1);
}
.liste-swatch.liste-color-2 {
  background: var(--liste-color-2);
}
.liste-swatch.liste-color-3 {
  background: var(--liste-color-3);
}
.liste-swatch.liste-color-4 {
  background: var(--liste-color-4);
}
.liste-swatch.liste-color-5 {
  background: var(--liste-color-5);
}
.liste-swatch.liste-color-6 {
  background: var(--liste-color-6);
}
.liste-swatch.liste-color-7 {
  background: var(--liste-color-7);
}
.liste-swatch.liste-color-8 {
  background: var(--liste-color-8);
}
.liste-swatch.liste-color-9 {
  background: var(--liste-color-9);
}
.liste-swatch.liste-color-10 {
  background: var(--liste-color-10);
}
.liste-swatch.liste-color-11 {
  background: var(--liste-color-11);
}

/* Genre de production dépliable (#128) : un bouton pleine largeur (grande
   cible tactile) révèle les listes du genre, avec un chevron d'état. */
.activite-tete {
  display: flex;
  align-items: center;
  width: 100%;
  border: none;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  padding: 9px 12px;
  cursor: pointer;
}
.activite-tete .activite-option {
  flex: 1;
  min-width: 0;
}
.activite-caret {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  margin-left: 8px;
  border-radius: 50%;
  background: var(--surface-accent-soft);
  color: var(--accent);
  font-size: 1.1em;
  font-weight: bold;
  line-height: 1;
}
.activite-sous-listes {
  padding: 2px 0 6px;
  margin-left: 30px;
  border-left: 2px solid var(--border);
}
.sous-liste-option {
  padding: 7px 12px;
}
@media (hover: hover) {
  .activite-tete:hover {
    background: var(--surface-accent-soft);
  }
  .activite-tete:hover .activite-caret {
    background: var(--surface-accent-soft-2);
  }
}

/* Sous-menu « Détail par service » (#144) : dans une Liste dont certains
   services de répétition sont spécifiques à un pupitre, indenté sous la case
   de la Liste, en plus discret que les sous-menus de genre (mêmes classes
   .activite-tete/.activite-caret, réduites) pour marquer un niveau plus fin. */
.liste-detail {
  margin: 0 0 4px 30px;
}
.liste-detail .activite-tete {
  padding: 6px 12px;
  font-size: 0.92em;
  color: var(--text-faint);
}
.liste-detail .activite-caret {
  width: 22px;
  height: 22px;
  font-size: 1em;
}
.activite-sous-listes-niveau2 {
  margin-left: 20px;
}
.sous-liste-note {
  margin: 2px 12px 4px;
}

footer {
  padding: 14px 12px 24px;
  text-align: center;
  color: var(--text-faint);
  font-size: 0.8em;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

footer a {
  color: var(--text-muted);
}

#loading {
  text-align: center;
  color: var(--text-faint);
  padding: 40px 0;
}

.empty-msg {
  text-align: center;
  color: var(--text-faint);
  padding: 30px 0;
}

@media (max-width: 700px) {
  body {
    font-size: 14px;
  }

  h1 .subtitle {
    display: none;
  }

  /* La barre de vues (Grille/Agenda personnalisé/…/Bible) ne tient plus sur
     une seule ligne en dessous d'un certain point : on la laisse défiler
     horizontalement plutôt que de la faire déborder ou passer à la ligne
     (ce qui casserait les coins arrondis du premier/dernier bouton).
     `min-width: 0` sur .header-controls est nécessaire : par défaut, un
     enfant flex ne rétrécit jamais sous la taille minimale de son propre
     contenu (ici, les boutons non compressibles de #view-nav), ce qui
     ferait déborder toute la ligne d'en-tête au lieu de faire défiler
     seulement la nav.
     La nav ne réclame plus 100% de la largeur (`flex: 1 1 auto` plutôt
     que `width: 100%`) : elle partage désormais sa ligne avec le bouton
     💬 avis (et Installer l'app, tant que l'app n'est pas encore
     installée) au lieu de les rejeter sur une ligne à part — c'était le
     cas sur petit écran comme l'iPhone mini (retour #188). Elle leur
     laisse la place en se rétrécissant et en défilant elle-même plus
     tôt au besoin. */
  .header-controls {
    min-width: 0;
  }

  #view-nav {
    flex: 1 1 auto;
    min-width: 0;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  #view-nav button {
    flex: 0 0 auto;
  }

  main {
    padding: 8px 6px 30px;
  }

  /* --- Vue grille sur téléphone --- */
  /* La semaine entière tient dans la largeur de l'écran : plus de
     défilement horizontal, on fait uniquement défiler verticalement
     comme la vue Agenda. Les cases sont compactées ; un appui sur un
     événement ouvre toujours le détail complet. */
  .week-scroll {
    overflow-x: visible;
  }

  table.week {
    min-width: 0;
  }

  table.week th,
  table.week td {
    padding: 1px;
  }

  table.week th {
    font-size: 0.62em;
    padding: 3px 1px;
  }

  table.week th.week-label {
    width: 16px;
  }

  /* Nom du créneau (Matin / Ap-midi / Soir) écrit à la verticale
     pour ne prendre qu'une colonne très étroite */
  table.week td.slot-name {
    font-size: 0.62em;
    writing-mode: vertical-rl;
    padding: 2px 0;
  }

  .evt {
    font-size: 0.6em;
    padding: 2px 3px;
    line-height: 1.2;
  }

  /* Emprise réduite de la barre de recherche (retour #188), mais la taille
     du texte reste à 16px (1rem) : en dessous, Safari iOS zoome tout
     l'écran dès qu'on touche le champ pour taper, ce qui serait bien
     plus gênant que les quelques pixels gagnés. On resserre donc plutôt
     le padding. */
  .search-input {
    padding: 7px 12px;
  }

  .print-setup-controls {
    padding: 14px;
  }

  .print-mode-fieldset,
  .print-period-options {
    grid-template-columns: 1fr;
  }

  .print-mode-option {
    min-height: 0;
  }

  .print-selection-actions button {
    flex: 1 1 160px;
  }

  .print-preview-scroll {
    padding: 8px;
  }
}

/* --- Impression : rendu proche de l'ancienne « Bible » PDF --- */

/* Page nommée, assignée uniquement aux feuilles de l'export par période.
   L'orientation de la Bible complète reste entièrement confiée à la boîte de
   dialogue du navigateur (cf. commentaire dans @media print ci-dessous). */
@page period-export {
  size: A4 landscape;
  margin: 5mm 6mm;
}

/* Titre affiché uniquement à l'impression (l'en-tête de navigation est masqué) */
.print-title {
  display: none;
}

@media print {
  /* Pas d'orientation forcée pour la Bible complète ici (retour #114) : la
     propriété CSS "size" n'est qu'une recommandation, que les navigateurs
     traitent chacun à leur façon quand l'utilisateur choisit une orientation
     différente dans la
     boîte de dialogue d'impression — sur Safari/iPadOS en particulier, cette
     contradiction entre l'orientation demandée par la CSS (paysage, fixée
     ici) et celle réellement choisie dans la boîte de dialogue (portrait, ou
     l'inverse en repassant) est l'explication la plus plausible aux pages
     manquantes en fin de document constatées en changeant d'orientation en
     cours d'aperçu : la pagination est calculée une fois pour une largeur de
     page, puis rendue sur une feuille d'une autre largeur. En laissant le
     choix entièrement à la boîte de dialogue (sans "size" ici), la
     pagination reste calculée pour l'orientation effectivement imprimée.
     La mise en page cible désormais le Portrait (planning agrandi sur sa
     propre page, détail des Listes sur la suivante, retour #114) ; le
     Paysage reste possible mais n'est plus recommandé dans l'app. */
  @page {
    margin: 1cm;
  }

  /* Conserver les couleurs (fonds des chips par Liste, en-têtes…) */
  * {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  body {
    background: #fff;
    font-size: 9.5px;
  }

  /* Vue Bible : police de base nettement resserrée par rapport à la vue
     Grille (inchangée ci-dessus) — sert de socle au détail des Listes
     (5px, cf. .doc-periode-listes plus bas) ; le planning, lui, remonte à
     9px puisqu'il a désormais sa propre page (retour #114, cf. plus bas).
     Le document est pensé pour l'export PDF, consultable en zoomant au
     besoin. Scopé à la vue Bible via l'attribut posé par setView() dans
     app.js : la vue Grille n'est jamais présente dans le DOM en même temps,
     donc aucun risque de fuite sur son propre rendu à l'impression. */
  body[data-view="document"],
  body[data-view="print"][data-print-mode="season"] {
    font-size: 6px;
  }

  /* On n'imprime que le contenu de la vue courante */
  header,
  footer,
  dialog {
    display: none !important;
  }

  main {
    padding: 0;
    max-width: none;
    margin: 0;
  }

  /* L'écran de préparation reste dans le DOM, mais seul son aperçu est
     imprimé. Les wrappers redeviennent de simples blocs sans bordure ni zone
     de défilement afin de laisser le moteur paginer le contenu normalement. */
  body[data-view="print"] .print-setup-controls,
  body[data-view="print"] .print-preview-title,
  body[data-view="print"] .print-preview-note {
    display: none !important;
  }

  body[data-view="print"] .print-setup,
  body[data-view="print"] .print-preview,
  body[data-view="print"] .print-preview-scroll,
  body[data-view="print"] .print-preview-output {
    width: auto;
    max-width: none;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: transparent;
    overflow: visible;
  }

  body[data-view="print"] .print-preview-scroll {
    outline: none;
  }

  .print-title {
    display: block;
    margin-bottom: 10px;
  }

  .print-title h1 {
    color: var(--accent);
    font-size: 1.4em;
    margin: 0;
  }

  .print-title p {
    margin: 2px 0 0;
    color: #445;
    font-size: 0.9em;
  }

  /* Chaque feuille paysage porte son propre en-tête : le titre global de la
     Bible ne doit pas créer une page séparée avant la première période. */
  body[data-view="print"][data-print-mode="periods"] .print-title,
  body[data-view="print"][data-print-mode="simplified"] .print-title {
    display: none;
  }

  /* Rappel, sur la vue Bible seulement (cf. printGenerationNotice() dans
     app.js), que le PDF n'est qu'un instantané figé au moment de l'export —
     contrairement à l'app en ligne, toujours à jour (retour #114). */
  .print-disclaimer {
    font-style: italic;
    color: #667;
  }

  /* Vue Grille : les périodes s'enchaînent sans saut de page forcé — sur un
     document de saison complète (13 périodes), imposer une page par période
     gâchait beaucoup de papier en bas de page et dispersait le document sur
     bien plus de pages que nécessaire (retour #114). On évite seulement de
     couper une période juste après son titre. */
  .periode {
    margin-bottom: 10px;
  }

  .periode-title {
    break-after: avoid-page;
  }

  /* Plus de défilement horizontal ni de semaine coupée en deux pages */
  .week-scroll {
    overflow: visible;
  }

  table.week {
    min-width: 0;
    break-inside: avoid;
  }

  /* Les chips ne sont plus cliquables sur papier */
  .evt {
    cursor: default;
  }

  /* Vue Document : l'aide en ligne ne sert à rien sur papier. Le bandeau
     sticky lui-même n'a plus de raison d'être à l'impression (retour #132) :
     display: contents laisse ses enfants (.doc-intro, .doc-search-bar, déjà
     masqués ci-dessous) piloter leur propre affichage, sans lui ajouter une
     boîte vide. */
  .view-toolbar {
    display: contents;
  }

  .doc-intro {
    display: none;
  }

  /* Recherche intégrée à la vue Bible (#131) : jamais imprimée, et le
     document complet reste imprimable même quand une recherche est active à
     l'écran (cf. renderDocument dans app.js, qui masque .doc-body via
     [hidden] pendant une recherche). */
  .doc-search-bar,
  .doc-search-results {
    display: none !important;
  }

  .doc-body[hidden] {
    display: block !important;
  }

  /* Une période par page (retour #114 : mise en page de l'ancienne Bible
     papier). Planning et détail des Listes EMPILÉS (plus côte à côte) :
     table CSS (display: table/table-cell), flex et flottants ont chacun été
     essayés (retours #114 précédents) et chacun a fini par tronquer le
     document en fin d'impression sous Safari/iPadOS (utilisé par les
     musiciens) tout en s'imprimant complet sous Chrome/Android — cf. le PDF
     "paysage" fourni par l'utilisatrice où les Périodes 12-13 disparaissent
     purement et simplement. C'est un bug connu du moteur d'impression de
     WebKit : le contenu d'une colonne (table-cell, flex-item ou flottant)
     dont la hauteur dépasse l'espace restant sur la page est purement
     TRONQUÉ au lieu de se poursuivre sur la page suivante, alors que
     Chromium gère ce cas correctement — d'où la différence Android/iOS.
     Le flux normal de blocs empilés (aucune colonne) est la seule mise en
     page dont la fragmentation à l'impression est fiable sur tous les
     moteurs, y compris WebKit : plus de pages au total (le détail des
     Listes vient sous la grille plutôt qu'à côté), mais aucun contenu ne
     peut plus disparaître silencieusement — priorité à l'exactitude du
     document sur sa compacité (cf. CLAUDE.md, § calendriers abonnés :
     rester conservateur plutôt que de miser sur un comportement non
     garanti). */
  .doc-periode-page {
    display: block;
    /* Un seul signal de rupture, sur la période qui commence (pas sur celle
       qui précède) : "break-before" sur CETTE période identifie sans
       ambiguïté "il faut une page neuve juste avant CET élément précis",
       alors qu'un "break-after" sur la période précédente dépend d'abord de
       savoir laquelle est "la dernière". */
    break-before: page;
    margin-bottom: 0;
  }

  .doc-periode-page:first-of-type {
    /* Seule exception sûre : "le tout premier élément du document" ne
       dépend d'aucun décompte, juste du fait que rien ne le précède. */
    break-before: avoid-page;
  }

  /* Pas d'équivalent ":last-of-type" ici : cette pseudo-classe désigne "le
     dernier élément de ce NOM DE BALISE" (ici <section>), pas "le dernier
     élément de cette CLASSE" — un piège classique. Elle servait à supprimer
     un "break-after" sur la Période 13 pour éviter une page blanche de fin
     de document ; mais si le décompte de pages se dérègle, rien ne garantit
     qu'elle cible encore la bonne section une fois le document fragmenté.
     Sans "break-after" du tout sur `.doc-periode-page`, cette ambiguïté
     disparaît : au pire, une page blanche superflue en fin de document
     (gênant mais inoffensif) — jamais une période qui disparaît. */

  /* Planning agrandi, seul sur sa page (retour #114) : tant qu’à empiler
     planning et détail des Listes (cf. commentaire ci-dessus), autant que
     le planning profite de toute la page plutôt que de rester à la taille
     resserrée pensée pour cohabiter avec les Listes juste en dessous —
     laisser des pages presque vides entre deux périodes n’a plus de sens
     une fois les deux parties séparées par un saut de page (retour #114).
     Resserré une nouvelle fois à 8px (retour #114, tour suivant) : à 9px,
     les périodes les plus chargées en semaines (3, 4, 7, 9) atteignaient
     jusqu'à 76 % de la hauteur d'une page mesuré sur Chromium en local avec
     les vraies données de production — marge trop juste pour rester sous
     100 % une fois rendu par le moteur d'impression de Safari/iPadOS
     (utilisé par les musiciens), qui a déjà montré à plusieurs reprises sur
     ce document un rendu plus haut que Chromium à réglage identique. Avec
     ce réglage, le pire cas mesuré redescend à 60 %. */
  .doc-periode-planning {
    display: block;
    font-size: 8px;
    margin-bottom: 0;
  }

  /* Détail des Listes sur la page suivante (retour #114) : un saut de page
     dédié, plutôt que de le laisser s’enchaîner, sur la même page, à la
     suite du planning — auparavant, un planning qui ne remplissait pas
     toute la page laissait le détail des Listes commencer dans l’espace
     restant, trop juste pour sa première fiche mais trop grand pour rester
     vide : d’où les pages presque blanches signalées. */
  /* Légèrement agrandi à 3.8px/1.1 (retour #114, tour suivant), au prix
     d'un peu de compacité : le resserrement précédent (3.6px) rendait le
     détail des Listes difficile à lire. Combiné au retour d'une ligne par
     catégorie ci-dessous (.work-detail), la période la plus chargée de la
     saison (Période 4 : concours de composition, programmes Petites
     Oreilles/Doudou Concert en plus des listes normales) remonte à ~84 %
     de la hauteur d'une page mesuré en local — un débordement sur une page
     supplémentaire pour cette période reste donc possible selon le moteur
     d'impression, comme déjà observé et accepté pour cette période
     précédemment dans ce fil : priorité donnée à la lisibilité plutôt qu'à
     un calcul pile-poil. */
  .doc-periode-listes {
    display: block;
    break-before: page;
    font-size: 3.8px;
    line-height: 1.1;
  }

  .doc-liste-card {
    break-inside: avoid;
    padding: 0.5px 2px;
    margin-bottom: 1px;
  }

  .doc-liste-title {
    margin: 0 0 1px;
    font-size: 1em;
  }

  /* Le détail complet par œuvre (instrumentation…) est restauré (retour
     #114) : resserrer ses espacements pour limiter le nombre de pages. */
  .doc-liste-card .detail-section {
    margin: 1px 0 0;
    font-size: 1em;
  }

  .doc-liste-card .works li,
  .doc-liste-card .solistes li {
    margin: 0;
  }

  /* Une ligne par catégorie (Remarques, Percussions, Claviers…), comme
     avant le tour précédent (retour #114) : le regroupement sur une même
     ligne (flex-wrap) gagnait de la place mais rendait le détail difficile
     à lire une fois combiné à une police déjà très petite. `.work-detail`
     retrouve son comportement par défaut (celui de `.detail-box`, cf. plus
     haut dans ce fichier) : bloc normal, chaque `.wd-row` sur sa propre
     ligne. Contrepartie assumée : plus de hauteur pour les Listes des
     périodes les plus chargées (cf. `.doc-periode-listes` ci-dessus). */
  .doc-liste-card .work-detail {
    margin: 0;
  }

  .doc-liste-card .wd-row {
    margin: 0;
    gap: 3px;
  }

  /* Étiquette (Remarques, Percussions, Détail…) en gras et plus sombre que
     la valeur, pour rester lisible sur le papier blanc de l'impression
     même quand l'app est en thème sombre (retour #114). */
  .doc-liste-card .wd-label {
    min-width: 3.8em;
    font-weight: 700;
    color: #26211a;
  }

  .doc-liste-card .chef,
  .doc-liste-card .effectif,
  .doc-liste-card .duree {
    margin: 0;
  }

  /* Cases de planning et chips d'événement : paddings fixes en px, ajustés
     à la police du planning (8px, cf. .doc-periode-planning ci-dessus) —
     pas à celle, plus petite, du reste de la vue Bible (retour #114). */
  .doc-periode-planning table.week th,
  .doc-periode-planning table.week td {
    padding: 1.5px;
  }

  .doc-periode-planning .evt {
    padding: 1.5px 2px;
    line-height: 1.1;
  }

  /* Export par période : page nommée A4 paysage, sans mise à l'échelle ni
     hauteur imposée. Une période exceptionnellement dense peut donc déborder
     sur une page suivante au lieu de perdre des services. */
  .period-export-output {
    min-width: 0;
  }

  .period-export-page {
    page: period-export;
    width: auto;
    min-width: 0;
    margin: 0;
    padding: 0;
    box-shadow: none;
  }

  .period-export-page + .period-export-page {
    break-before: page;
    page-break-before: always;
  }

  .period-export-size-small {
    font-size: 5.2pt;
  }

  .period-export-size-medium {
    font-size: 6.1pt;
  }

  .period-export-size-large {
    font-size: 7pt;
  }

  .period-export-header {
    break-after: avoid-page;
    margin-bottom: 1.4mm;
    padding-bottom: 1.2mm;
  }

  .period-export-week {
    break-inside: avoid-page;
    margin-bottom: 0.8mm;
  }

  .period-export-week thead th {
    padding: 0.5mm 0.7mm;
  }

  .period-export-week .period-export-slot-head,
  .period-export-week .period-export-slot {
    width: 14mm;
  }

  .period-export-service-cell {
    padding: 0.35mm;
  }

  .period-export-cell {
    min-height: 4.5mm;
  }

  .period-export-event {
    margin-bottom: 0.3mm;
    padding: 0.3mm 0.5mm;
    border-left-width: 0.7mm;
  }

  .period-export-simplified {
    height: 200mm;
    grid-template-rows: 13mm repeat(var(--period-weeks), minmax(0, 1fr)) 5mm;
    gap: 1mm;
    break-inside: avoid-page;
  }

  .period-export-simplified .period-export-week {
    grid-template-columns: 14mm repeat(7, minmax(0, 1fr));
    grid-template-rows: 6mm repeat(3, minmax(0, 1fr)) 4mm;
  }

  .period-export-simplified .period-export-plain-event {
    padding: 0;
    margin-bottom: 0.5mm;
    line-height: 1.2;
  }

  .period-export-notes {
    padding: 0.4mm 0.7mm;
  }

  .period-export-footer {
    break-inside: avoid-page;
    margin-top: 1.2mm;
  }

  .print-empty-preview {
    display: none;
  }
}

/* --- Installation de l'application (PWA) --- */

#install-btn {
  /* Appel à l'action : or plein sur l'en-tête sombre (comme l'onglet actif).
     Prime sur la déclinaison sombre générique des boutons d'en-tête. */
  background: var(--gold);
  color: var(--header-bg);
  border-color: var(--gold);
  font-weight: 600;
  white-space: nowrap;
}

#install-content .install-intro {
  margin: 0 0 14px;
  font-size: 0.9em;
}

.install-now {
  display: block;
  width: 100%;
  text-align: center;
  background: var(--accent);
  color: #fff;
  border: none;
  font-weight: 600;
  padding: 12px 14px;
  border-radius: 8px;
}

.install-or {
  margin: 14px 0 6px;
  font-size: 0.85em;
  color: var(--text-muted);
}

.install-steps {
  margin: 8px 0 0;
  padding-left: 1.3em;
  font-size: 0.9em;
}

.install-steps li {
  margin: 6px 0;
}

.install-note {
  margin: 14px 0 0;
  font-size: 0.8em;
  color: var(--text-faint);
}

.feedback-field {
  margin: 0 0 14px;
}

.feedback-message,
.feedback-name {
  display: block;
  box-sizing: border-box;
  width: 100%;
  margin-top: 6px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface-alt);
  color: var(--text);
  font: inherit;
}

.feedback-message {
  resize: vertical;
}

/* Piège à robots : hors champ visuel, mais toujours dans le DOM (donc
   toujours "rempli" par un robot naïf qui coche tout) — cf. app.js
   renderFeedback(). Pas de display:none, plus facilement repéré par un
   robot un peu moins naïf. */
.feedback-honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.feedback-status {
  min-height: 1.2em;
  margin: 4px 0 12px;
  font-size: 0.85em;
}

.feedback-status.feedback-error {
  color: var(--danger);
}

.feedback-status.feedback-ok {
  padding: 12px 0;
  font-size: 1em;
  text-align: center;
  color: var(--success-text);
}

.feedback-form .subscribe-add {
  width: 100%;
  border: none;
  font-size: 1em;
}

/* Écrans à encoche (iPhone) en mode application plein écran : on décale
   l'en-tête et le pied de page pour ne rien cacher sous la barre système. */
header {
  padding-top: calc(8px + env(safe-area-inset-top));
  padding-left: calc(12px + env(safe-area-inset-left));
  padding-right: calc(12px + env(safe-area-inset-right));
}

footer {
  padding-bottom: calc(24px + env(safe-area-inset-bottom));
}
