/* Polices auto-hébergées (voir docs/DECISIONS.md : système fermé, pas de
   dépendance réseau au runtime — déjà pourquoi socket.io est servi en local). */
@font-face {
  font-family: 'Bebas Neue';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('assets/fonts/bebas-neue-v16-latin-regular.woff2') format('woff2');
}
@font-face {
  font-family: 'Open Sans';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('assets/fonts/open-sans-v44-latin.woff2') format('woff2');
}

/* DA Herde Holding : or pris sur le logo, sur fond sombre (conservé : lisibilité à
   distance dans un bureau éclairé, cohérent avec un tableau de suivi "TV board").
   Le rouge sombre reste réservé aux lignes en alerte. */
:root {
  --herde-gold: #e0b43a;
  --alert-bg: #4a1015;
  --bg: #161616;
  --border: #2e2a2a;
  --text-muted: #9b9b9b;
}

/* Écran kiosk : jamais de scroll (personne pour scroller), donc une hauteur figée et un
   pied de page toujours visible. La taille du texte suit la largeur de l'écran, mais
   moins vite qu'elle (formule "a·vw + b") : en 4K (3840 px, écran de 45 à 55" chez
   Rémy) le texte est 1,5× plus grand qu'en 1080p au lieu d'être plafonné à la même
   taille en pixels, qui le rendait deux fois plus petit à l'œil (NEATODO-10). */
html, body { height: 100%; overflow: hidden; }
body {
  font-family: 'Open Sans', sans-serif; background: var(--bg); color: #eee; margin: 0;
  display: flex; flex-direction: column;
}

/* overflow-x en secours : en dessous de la largeur minimale du tableau (cas hors kiosk,
   ex. fenêtre de navigateur très étroite), on défile plutôt que d'écraser les colonnes
   texte libre à 0px. Le kiosk réel ne descend jamais sous ce seuil. */
#board-wrap { flex: 1 1 auto; min-height: 0; overflow: auto hidden; padding: clamp(24px, 1.25vw, 48px) clamp(24px, 1.25vw, 48px) 0; }
table { width: 100%; min-width: 1000px; border-collapse: collapse; table-layout: fixed; font-size: clamp(20px, calc(0.85vw + 16px), 60px); }
th, td { padding: 0.6em; border-bottom: 1px solid var(--border); overflow: hidden; text-overflow: ellipsis; }
td { text-align: left; }
th {
  color: var(--herde-gold); font-size: clamp(17px, calc(0.6vw + 11px), 40px); text-align: center;
  font-family: 'Bebas Neue', 'Open Sans', sans-serif; font-weight: 400; letter-spacing: 0.06em;
}

/* Largeurs mesurées sur le contenu réel le plus long (voir commit) : Type/Statut/Posté
   par/Date sont des valeurs closes qui ne débordent jamais de leur colonne ("En cours",
   "PROBAT26", "ET2", "02/09" + le padding ci-dessus). Le reste (texte libre) se
   partage l'espace ainsi libéré ; Mission n'a pas de largeur fixe : elle reçoit tout ce
   qui reste, car c'est le texte le plus long à lire.
   Les tailles en "ch" suivent la taille de police (donc l'écran), pas les "%". */
.col-destinataire { width: 16%; }
.col-contact { width: 20%; }
.col-type { width: 11.5ch; } /* PROBAT26 / NEASTAGE en capitales : 10,8ch mesurés */
.col-statut { width: 9.5ch; }
/* Initiales d'un compte (jusqu'à "ET10") ou nom saisi par un invité : un prénom court
   tient en entier, un nom plus long est coupé avec "…". */
.col-poste-par { width: 9ch; }
/* white-space sur un <col> ne s'applique pas aux cellules : il faut le poser sur le td,
   sinon un nom long passe sur plusieurs lignes et agrandit toute la ligne. */
td.poste-par { white-space: nowrap; }
/* Jour/mois seulement (pas d'année) : le tableau ne montre que les missions en cours,
   jamais d'un exercice précédent, donc l'année n'apporte rien à l'écran. */
.col-date { width: 7ch; }
.col-type, .col-statut, .col-poste-par, .col-date { white-space: nowrap; }

tr.overdue { animation: blink 1.4s ease-in-out infinite; background: var(--alert-bg); }
@keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }

/* Flash vert puis disparition quand une mission vient d'être validée (voir app.js) :
   la ligne reste visible un court instant avant le rafraîchissement normal qui la
   retire du tableau, au lieu de disparaître d'un coup au prochain load(). */
tr.just-validated { animation: validated 900ms ease forwards; }
@keyframes validated {
  0% { background: #2e7d32; opacity: 1; }
  65% { background: #2e7d32; opacity: 1; }
  100% { background: #2e7d32; opacity: 0; }
}
/* Flash or quand une mission vient d'être créée (NEATODO-26) : visible de loin,
   distinct du vert « Validé ». La ligne reste ensuite dans son affichage normal.
   Durée alignée sur CREATED_ANIM_MS dans app.js. */
tr.just-created { animation: created 1000ms ease; }
@keyframes created {
  0%, 40% { background: var(--herde-gold); color: #161616; }
  100% { background: transparent; color: inherit; }
}
/* Couleurs de type : style inline depuis /api/types (NEATODO-3). */

/* Bascule entre les pages : fondu rapide, pas un effet qui mange le temps de lecture. */
#board-body { transition: opacity 220ms ease; }
#board-body.fade { opacity: 0; }

/* Pied de page : hauteur fixe, jamais recouvert par le tableau (voir #board-wrap ci-dessus) */
#status-bar {
  flex: 0 0 auto; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: clamp(16px, 1vw, 40px);
  padding: clamp(16px, 0.85vw, 32px) clamp(24px, 1.25vw, 48px); border-top: 1px solid var(--border);
}
/* Logo centré sur l'écran ; de chaque côté, la météo (entre l'heure et le logo) et
   l'éphéméride (entre le logo et le QR code) sont centrées dans l'espace qui reste
   (NEATODO-11) : flex: 1 leur donne cet espace, puis leur contenu y est centré. */
.footer-side { display: flex; align-items: center; gap: clamp(16px, 1vw, 40px); min-width: 0; }
#clock { display: flex; flex-direction: column; gap: 2px; color: var(--text-muted); flex: 0 0 auto; }
#meteo, #ephemeride { flex: 1 1 0; min-width: 0; font-size: clamp(13px, calc(0.42vw + 8px), 28px); color: var(--text-muted); }
#meteo { display: flex; align-items: center; justify-content: center; gap: 0.5em; }
#meteo[hidden], #ephemeride[hidden] { display: none; }
.meteo-icone {
  width: clamp(40px, calc(1.6vw + 24px), 110px); height: auto; aspect-ratio: 1; flex: 0 0 auto;
  fill: none; stroke: var(--herde-gold); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}
.meteo-texte { display: flex; flex-direction: column; gap: 2px; }
.meteo-temp { font-variant-numeric: tabular-nums; font-size: clamp(20px, calc(0.8vw + 15px), 50px); color: #eee; }
.meteo-detail { white-space: nowrap; }
#ephemeride { display: flex; flex-direction: column; align-items: center; gap: 4px; text-align: center; }
.eph-fete { font-size: clamp(20px, calc(0.8vw + 15px), 50px); color: #eee; white-space: nowrap; }
.eph-soleil { display: flex; align-items: center; gap: 0.35em; white-space: nowrap; font-variant-numeric: tabular-nums; }
.eph-icone {
  width: 1.5em; height: auto; aspect-ratio: 1; margin-left: 0.4em;
  fill: none; stroke: var(--herde-gold); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}
.eph-icone:first-child { margin-left: 0; }
#clock-date { font-size: clamp(13px, calc(0.42vw + 8px), 28px); text-transform: capitalize; }
#clock-time { font-variant-numeric: tabular-nums; font-size: clamp(20px, calc(0.8vw + 15px), 50px); color: #eee; }

#brand { display: flex; flex-direction: column; align-items: center; gap: 10px; }
/* Boîte de taille fixe (pas un aspect-ratio lié à un fichier) : la hauteur du pied est
   connue dès le premier rendu pour la pagination, et object-fit:contain évite d'écraser
   un logo custom (Herde ~3:2) ou le wordmark TodoWall (~800×220). */
#brand-logo {
  width: clamp(150px, calc(4vw + 80px), 320px);
  height: clamp(70px, calc(2.2vw + 40px), 140px);
  object-fit: contain;
  object-position: center;
}
#page-dots { display: flex; gap: 8px; }
#page-dots span { width: 10px; height: 10px; border-radius: 50%; background: var(--border); }
#page-dots span.active { background: var(--herde-gold); }

#invite-qr { flex: 0 0 auto; margin-left: auto; display: flex; align-items: center; justify-content: flex-end; gap: 16px; }
#invite-qr img { width: clamp(90px, calc(3vw + 58px), 200px); aspect-ratio: 1 / 1; height: auto; background: #fff; border-radius: 6px; }
#invite-qr p { margin: 0; color: var(--text-muted); font-size: clamp(16px, calc(0.55vw + 10px), 32px); }

/* Mode PC (/affichage/?pc, NEATODO-9) : même tableau, mais on défile au lieu de faire
   tourner des pages, et un bandeau en haut indique qui est connecté. */
body.mode-pc, html:has(body.mode-pc) { height: auto; overflow: auto; }
body.mode-pc { min-height: 100vh; }
body.mode-pc #board-wrap { overflow: visible; }
body.mode-pc #status-bar { position: sticky; bottom: 0; background: var(--bg); }
#pc-session {
  display: flex; align-items: center; justify-content: flex-end; gap: 16px; flex-wrap: wrap;
  padding: 10px clamp(24px, 1.25vw, 48px); border-bottom: 1px solid var(--border);
  color: var(--text-muted); font-size: 15px;
}
#pc-session[hidden] { display: none; }
#pc-session strong { color: #eee; }
#pc-session a, #pc-session button {
  color: var(--herde-gold); background: none; border: 1px solid var(--herde-gold); border-radius: 6px;
  padding: 6px 12px; font: inherit; cursor: pointer; text-decoration: none;
}
#pc-session .pc-error { color: #ff8a80; margin-right: auto; }
.statut-select {
  font: inherit; font-size: 0.85em; color: #eee; background: #222; border: 1px solid var(--herde-gold);
  border-radius: 6px; padding: 0.15em 0.2em; max-width: 100%; cursor: pointer;
}
body.mode-pc .col-statut { width: 11ch; }
