/* ==========================================================================
   WatchMyShow — surcouche Bootstrap 5.3
   --------------------------------------------------------------------------
   Bootstrap est charge en amont (CDN). Ce fichier ne contient que :
     1. le theme : la palette maison branchee sur les variables --bs-*
     2. les composants qui n'ont pas d'equivalent Bootstrap (calendrier,
        matrice de disponibilites, critiques, promotion, graphiques...)
   Tout ce que Bootstrap sait faire (boutons, tables, cartes, formulaires,
   alertes, badges, onglets, pagination, grille) passe par ses classes.
   ========================================================================== */

/* ── 1. Theme ─────────────────────────────────────────────────────────── */

:root,
[data-bs-theme="light"] {
  --wms-accent: #0f766e;
  --wms-accent-dark: #115e59;
  --wms-panel: #ffffff;
  --wms-surface-alt: #fbfcfa;
  --wms-placeholder: #eef1ed;

  --bs-primary: #0f766e;
  --bs-primary-rgb: 15, 118, 110;
  --bs-danger: #b42318;
  --bs-danger-rgb: 180, 35, 24;

  --bs-body-bg: #f7f7f4;
  --bs-body-color: #1f2328;
  --bs-body-color-rgb: 31, 35, 40;
  --bs-secondary-color: #687076;
  --bs-secondary-color-rgb: 104, 112, 118;
  --bs-tertiary-bg: #fbfcfa;
  --bs-emphasis-color: #1f2328;

  --bs-border-color: #d9ddd7;
  --bs-border-color-translucent: #d9ddd7;
  --bs-border-radius: 0.5rem;
  --bs-border-radius-sm: 0.375rem;
  --bs-border-radius-lg: 0.75rem;

  --bs-link-color: #115e59;
  --bs-link-color-rgb: 17, 94, 89;
  --bs-link-hover-color: #0f766e;
  --bs-link-hover-color-rgb: 15, 118, 110;

  --bs-body-font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --bs-body-line-height: 1.45;

  --bs-heading-color: #1f2328;
  --bs-focus-ring-color: rgba(15, 118, 110, 0.15);
  --bs-focus-ring-width: 3px;
}

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* Une classe `display: flex/grid` l'emporte sur l'attribut HTML `hidden` :
   sans ca, les blocs replies (nouveau lieu, renommage de campagne) restent
   visibles en permanence. */
[hidden] { display: none !important; }

h1, h2, h3, h4, h5, h6 {
  line-height: 1.15;
}

a { text-decoration: none; }
a:hover { text-decoration: underline; }

/* Boutons — le vert maison, decline sur les variantes Bootstrap. */
.btn {
  --bs-btn-font-weight: 650;
  --bs-btn-border-radius: 0.375rem;
  --bs-btn-padding-y: 0.5rem;
  --bs-btn-padding-x: 0.75rem;
  transition: box-shadow 0.15s ease, transform 0.15s ease;
}
.btn:active { transform: translateY(0); box-shadow: none; }

.btn-primary {
  --bs-btn-bg: #0f766e;
  --bs-btn-border-color: #0f766e;
  --bs-btn-hover-bg: #115e59;
  --bs-btn-hover-border-color: #115e59;
  --bs-btn-active-bg: #0d5f58;
  --bs-btn-active-border-color: #0d5f58;
  --bs-btn-disabled-bg: #0f766e;
  --bs-btn-disabled-border-color: #0f766e;
}
.btn-primary:hover {
  box-shadow: 0 6px 16px -4px rgba(15, 118, 110, 0.4);
  transform: translateY(-1px);
}

/* Equivalent de l'ancien `.button.secondary` : fond blanc, texte et bord verts. */
.btn-outline-primary {
  --bs-btn-color: #115e59;
  --bs-btn-bg: #ffffff;
  --bs-btn-border-color: #0f766e;
  --bs-btn-hover-color: #115e59;
  --bs-btn-hover-bg: #f5faf9;
  --bs-btn-hover-border-color: #0f766e;
  --bs-btn-active-color: #115e59;
  --bs-btn-active-bg: #eef6f4;
  --bs-btn-active-border-color: #0f766e;
}
.btn-outline-primary:hover {
  box-shadow: 0 4px 12px -4px rgba(31, 35, 40, 0.18);
  transform: translateY(-1px);
}

.btn-danger {
  --bs-btn-bg: #b42318;
  --bs-btn-border-color: #b42318;
  --bs-btn-hover-bg: #992015;
  --bs-btn-hover-border-color: #992015;
}
.btn-danger:hover {
  box-shadow: 0 6px 16px -4px rgba(180, 35, 24, 0.4);
  transform: translateY(-1px);
}

/* Bouton neutre discret : bord gris, texte vert (pagination, actions de ligne). */
.btn-outline-neutral {
  --bs-btn-color: #115e59;
  --bs-btn-bg: #ffffff;
  --bs-btn-border-color: #d9ddd7;
  --bs-btn-hover-color: #115e59;
  --bs-btn-hover-bg: #fbfcfa;
  --bs-btn-hover-border-color: #0f766e;
  --bs-btn-active-color: #115e59;
  --bs-btn-active-bg: #eef6f4;
  --bs-btn-active-border-color: #0f766e;
  --bs-btn-disabled-color: #687076;
  --bs-btn-disabled-border-color: #d9ddd7;
}

/* Bouton purement iconographique, carre. */
.btn-icon {
  align-items: center;
  display: inline-flex;
  justify-content: center;
  line-height: 1;
  min-width: 38px;
  padding-left: 0.5rem;
  padding-right: 0.5rem;
}
.btn-icon.btn-sm { min-width: 31px; }
.btn-icon > i { font-size: 1rem; }

/* Cartes — le fond blanc et le bord ligne du theme. */
.card {
  --bs-card-bg: var(--wms-panel);
  --bs-card-border-color: var(--bs-border-color);
  --bs-card-spacer-y: 1rem;
  --bs-card-spacer-x: 1rem;
  --bs-card-cap-bg: transparent;
  min-width: 0;
}

/* Carte "creation" en pointilles, glissee comme premiere tuile d'une grille
   (ex. workspace : "Nouvelle production") plutot qu'un bouton separe au-dessus. */
.add-card {
  border-style: dashed;
  color: var(--bs-secondary-color);
  transition: background-color 0.15s, border-color 0.15s, color 0.15s;
}
.add-card:hover, .add-card:focus-visible {
  background: var(--wms-surface-alt);
  border-color: var(--wms-accent);
  color: var(--wms-accent-dark);
}
.add-card-icon {
  align-items: center;
  border: 1.5px solid currentColor;
  border-radius: 50%;
  display: flex;
  font-size: 1.5rem;
  font-weight: 300;
  height: 2.5rem;
  justify-content: center;
  line-height: 1;
  width: 2.5rem;
}

/* Tables — entetes en petites capitales grises, comme aujourd'hui. */
.table {
  --bs-table-border-color: var(--bs-border-color);
  margin-bottom: 0;
}
.table > thead th {
  color: var(--bs-secondary-color);
  font-size: 0.84rem;
  font-weight: 700;
  text-transform: uppercase;
  white-space: nowrap;
}
.table > :not(caption) > * > * {
  padding: 0.625rem 0.5rem;
  vertical-align: top;
}
.table-middle > :not(caption) > * > * { vertical-align: middle; }

/* Formulaires. */
.form-label {
  font-weight: 650;
  margin-bottom: 0.25rem;
}
.form-control, .form-select {
  min-height: 38px;
}
.form-control:focus, .form-select:focus {
  border-color: var(--wms-accent);
  box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.15);
}
.form-check-input:checked {
  background-color: var(--wms-accent);
  border-color: var(--wms-accent);
}
.form-check-input:focus {
  border-color: var(--wms-accent);
  box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.15);
}
/* Django rend les erreurs de champ dans une <ul class="errorlist">. */
.errorlist {
  color: var(--bs-danger);
  font-size: 0.875rem;
  list-style: none;
  margin: 0 0 0.25rem;
  padding: 0;
}

/* Fil d'Ariane. */
.breadcrumb {
  --bs-breadcrumb-margin-bottom: 0;
  --bs-breadcrumb-divider-color: #9aa39c;
  --bs-breadcrumb-item-padding-x: 0.4rem;
  font-size: 0.9rem;
}
.breadcrumb a { font-weight: 650; }

/* Onglets — soulignement vert, defilement horizontal en mobile. */
.nav-tabs {
  --bs-nav-tabs-border-width: 2px;
  --bs-nav-tabs-border-color: var(--bs-border-color);
  --bs-nav-tabs-link-active-color: var(--wms-accent);
  --bs-nav-tabs-link-active-bg: transparent;
  --bs-nav-tabs-link-active-border-color: transparent transparent var(--wms-accent);
  --bs-nav-link-color: var(--bs-secondary-color);
  --bs-nav-link-hover-color: var(--bs-body-color);
  --bs-nav-link-font-weight: 600;
}
/* Pas de `overflow-x: auto` ici : il faisait de la barre un conteneur de
   defilement composite - 1,94 Mo de calque mesures sur iPhone, pour quatre
   onglets. Les libelles courts (cf. `SUMMARY_VIEWS`) tiennent sur une ligne,
   et le repli de Bootstrap sert de filet au-dela. */
/* Sur telephone, les 16 px de marge laterale par onglet de Bootstrap suffisaient
   a eux seuls a faire passer la barre sur deux lignes : 8 x 16 px pour quatre
   onglets, sur les ~330 px utiles d'un ecran de 360. */
@media (max-width: 575.98px) {
  .nav-tabs { --bs-nav-link-padding-x: 0.5rem; }
}
.nav-tabs .nav-link {
  border-bottom-width: 3px;
  border-radius: 0.375rem 0.375rem 0 0;
  margin-bottom: -2px;
}
.nav-tabs .nav-link:not(.active):hover {
  background: #f4f4f2;
  border-color: transparent;
}

/* Pilules de filtre (planning, catalogue, critiques). */
.filter-pill {
  background: var(--wms-panel);
  border: 1px solid var(--bs-border-color);
  border-radius: 999px;
  color: var(--bs-body-color);
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.85rem;
  font-weight: 600;
  padding: 0.3rem 0.75rem;
  text-decoration: none;
  transition: border-color 0.15s;
}
.filter-pill:hover { border-color: var(--wms-accent); color: var(--bs-body-color); text-decoration: none; }
.filter-pill.active { background: var(--wms-accent); border-color: var(--wms-accent); color: #fff; }
.filter-pill.active .text-body-secondary { color: rgba(255, 255, 255, 0.75) !important; }
.filter-pill-icon { font-size: 1rem; padding: 0.3rem 0.6rem; }

/* Badges de statut — declinaisons douces reprenant les couleurs actuelles. */
.badge-soft-success { background: #ecfdf5; color: #047857; }
.badge-soft-warning { background: #fff8eb; color: #9a3412; }
.badge-soft-danger  { background: #fef2f2; color: #b42318; }
.badge-soft-neutral { background: #eef1ed; color: var(--bs-secondary-color); }
.badge-soft-info    { background: #eef2ff; color: #3730a3; }
.badge-soft-accent  { background: #eef6f4; border: 1px solid #c9dfdc; color: var(--wms-accent-dark); }
/* Roles de workspace : owner ambre, admin bleu, le reste neutre. */
.badge-soft-amber   { background: #fef3c7; color: #92400e; }
.badge-soft-blue    { background: #dbeafe; color: #1e40af; }

/* ── 2. Coquille de page ──────────────────────────────────────────────── */

.site-header {
  background: #ffffff;
  border-bottom: 1px solid var(--bs-border-color);
}
.brand-logo {
  align-items: center;
  background: linear-gradient(155deg, var(--wms-accent) 0%, var(--wms-accent-dark) 100%);
  border-radius: 8px;
  box-shadow: 0 1px 2px rgba(15, 118, 110, 0.35);
  color: #ffffff;
  display: inline-flex;
  flex: 0 0 auto;
  font-weight: 850;
  height: 36px;
  justify-content: center;
  text-decoration: none;
  width: 36px;
}
.brand-logo:hover { color: #ffffff; text-decoration: none; }

.site-footer {
  border-top: 1px solid var(--bs-border-color);
  color: var(--bs-secondary-color);
  font-size: 0.85rem;
}
.site-footer a { color: var(--bs-secondary-color); }

/* Bouton d'alerte de la barre d'outils production, avec pastille de compte. */
.warning-button { border-color: var(--bs-danger) !important; color: var(--bs-danger) !important; position: relative; }
.warning-button-badge {
  background: var(--bs-danger);
  border-radius: 999px;
  box-shadow: 0 0 0 2px #ffffff;
  color: #ffffff;
  font-size: 0.65rem;
  font-weight: 700;
  height: 16px;
  line-height: 16px;
  min-width: 16px;
  padding: 0 3px;
  position: absolute;
  right: -6px;
  text-align: center;
  top: -6px;
}

/* ── 3. Etat vide ─────────────────────────────────────────────────────── */

.empty-state {
  align-items: center;
  display: grid;
  gap: 0.625rem;
  justify-items: center;
  padding: 3rem 1.5rem;
  text-align: center;
}
.empty-state-icon {
  align-items: center;
  background: #eef6f4;
  border-radius: 999px;
  color: var(--wms-accent-dark);
  display: flex;
  font-size: 1.4rem;
  height: 56px;
  justify-content: center;
  width: 56px;
}
.empty-state p { margin: 0; max-width: 380px; }

/* ── 4. Pages d'authentification ──────────────────────────────────────── */

@keyframes auth-rise {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}
.auth-page {
  background:
    radial-gradient(1100px 480px at 12% -10%, rgba(15, 118, 110, 0.12), transparent 60%),
    radial-gradient(900px 420px at 100% 0%, rgba(15, 118, 110, 0.08), transparent 55%),
    radial-gradient(circle, rgba(31, 35, 40, 0.07) 1px, transparent 1px) 0 0 / 24px 24px,
    var(--bs-body-bg);
}
.auth-shell {
  display: grid;
  gap: 1.75rem;
  justify-items: center;
  max-width: 400px;
  width: 100%;
}
.brand-lockup {
  align-items: center;
  animation: auth-rise 0.5s ease both;
  color: inherit;
  display: grid;
  gap: 0.75rem;
  justify-items: center;
  text-align: center;
  text-decoration: none;
}
.brand-lockup:hover { text-decoration: none; }
.brand-mark {
  align-items: center;
  background: linear-gradient(155deg, var(--wms-accent) 0%, var(--wms-accent-dark) 100%);
  border-radius: 15px;
  box-shadow: 0 8px 20px -4px rgba(15, 118, 110, 0.4), 0 0 0 5px rgba(15, 118, 110, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.25);
  color: #ffffff;
  display: inline-flex;
  font-size: 1.4rem;
  font-weight: 850;
  height: 56px;
  justify-content: center;
  width: 56px;
}
.brand-wordmark {
  font-size: 1.4rem;
  font-weight: 800;
  letter-spacing: -0.02em;
}
.auth-tagline {
  animation: auth-rise 0.5s ease 0.05s both;
  max-width: 320px;
}
.auth-card {
  animation: auth-rise 0.5s ease 0.1s both;
  border-radius: 18px;
  box-shadow: 0 1px 1px rgba(16, 24, 40, 0.03), 0 4px 10px -4px rgba(16, 24, 40, 0.08), 0 28px 56px -20px rgba(16, 24, 40, 0.22);
  overflow: hidden;
  position: relative;
  width: 100%;
}
.auth-card::before {
  background: linear-gradient(90deg, var(--wms-accent), var(--wms-accent-dark));
  content: "";
  height: 4px;
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
}
.auth-card .form-label {
  color: var(--bs-secondary-color);
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.auth-foot-note { animation: auth-rise 0.5s ease 0.15s both; }
.input-icon-group { position: relative; }
.input-icon-group i {
  color: var(--bs-secondary-color);
  font-size: 1rem;
  left: 13px;
  pointer-events: none;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}
.input-icon-group .form-control { padding-left: 38px; }
@media (prefers-reduced-motion: reduce) {
  .brand-lockup, .auth-tagline, .auth-card, .auth-foot-note { animation: none; }
}

/* ── 5. Planning — calendrier mensuel ─────────────────────────────────── */
/* En desktop : une grille de 7 colonnes par semaine.
   Sous md : la grille tomberait a ~40px de large par jour alors que les cartes
   de representation font plusieurs lignes de haut. On bascule donc en liste
   verticale, et les jours sans representation disparaissent. */

.planning-toolbar {
  border-bottom: 1px solid var(--bs-border-color);
  margin-bottom: 1.25rem;
  padding: 0.4rem 0 1rem;
}
.planning-toolbar .alert { flex: 1 1 auto; }
.month-nav-bar {
  align-items: center;
  display: flex;
  gap: 0.75rem;
}
.month-label {
  /* Largeur fixe (pas min-width) : "septembre 2026" est le mois francais le
     plus long, sinon la barre de navigation se decale a chaque changement de
     mois selon la longueur du nom. */
  font-size: 1.3rem;
  font-weight: 700;
  text-align: center;
  width: 11rem;
}
.month-label--current { color: var(--bs-body-color); }
.month-label--past { color: var(--bs-secondary-color); }
.month-label--future { color: #e0293b; }

.week-group { margin-bottom: 0.75rem; }
.week-row { display: flex; gap: 0.5rem; }
.week-number {
  align-items: center;
  background: var(--wms-surface-alt);
  border-radius: 6px;
  color: var(--bs-secondary-color);
  display: flex;
  flex: 0 0 2.4rem;
  font-size: 0.76rem;
  font-weight: 700;
  justify-content: center;
}
.week-days {
  display: grid;
  flex: 1;
  gap: 0.5rem;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  min-width: 0;
}
.day-slot {
  background: var(--wms-surface-alt);
  border: 1px solid transparent;
  border-radius: 6px;
  min-height: 60px;
  min-width: 0;
  overflow-wrap: break-word;
  padding: 0.4rem;
}
.day-slot.day-has-perf {
  background: var(--wms-panel);
  border-color: var(--bs-border-color);
}
.day-out-of-month { background: transparent; opacity: 0.35; pointer-events: none; }
.day-today {
  background: #eff6ff;
  border-color: #3b82f6 !important;
  border-width: 1.5px;
}
.day-today .day-date { color: #2563eb; font-weight: 700; }
.day-header {
  align-items: baseline;
  display: flex;
  gap: 0.3rem;
  margin-bottom: 0.3rem;
}
.day-name { color: var(--bs-secondary-color); font-size: 0.72rem; font-weight: 500; }
.day-date { font-size: 0.85rem; font-weight: 600; }

.performance-card {
  background: #f0f4ff;
  border-radius: 4px;
  font-size: 0.82rem;
  margin-top: 0.3rem;
  padding: 0.4rem 0.5rem;
}
.perf-card-top {
  align-items: center;
  display: flex;
  gap: 0.4rem;
  justify-content: space-between;
}
.perf-select { display: flex; }
/* Le jour est l'info la plus importante de la carte : gras et le plus lisible. */
.perf-day-label {
  color: var(--bs-body-color);
  font-size: 0.82rem;
  font-weight: 700;
  text-align: right;
  text-transform: capitalize;
  white-space: nowrap;
}
.perf-card-meta {
  align-items: baseline;
  display: flex;
  gap: 0.5rem;
  margin-top: 0.25rem;
}
.perf-number {
  color: var(--bs-secondary-color);
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
  font-weight: 500;
}
.perf-time { font-size: 0.82rem; font-weight: 600; margin-left: auto; }
.perf-cast { font-size: 0.78rem; list-style: none; margin: 0.3rem 0 0; padding: 0; }
.perf-cast li { margin-bottom: 0.15rem; }
.cast-role {
  color: var(--bs-secondary-color);
  font-size: 0.72rem;
  font-weight: 600;
  margin-right: 0.2em;
  text-transform: uppercase;
}

@media (max-width: 767.98px) {
  /* Liste verticale : plus de colonnes etroites, et on masque les jours vides. */
  .week-row { flex-direction: column; gap: 0.35rem; }
  .week-number {
    flex: 0 0 auto;
    font-size: 0.72rem;
    justify-content: flex-start;
    letter-spacing: 0.04em;
    padding: 0.2rem 0.5rem;
    text-transform: uppercase;
  }
  .week-days { display: flex; flex-direction: column; gap: 0.35rem; }
  .day-slot { min-height: 0; padding: 0.5rem 0.65rem; }
  /* Un jour sans representation n'apporte rien en liste : on le retire. */
  .day-slot:not(.day-has-perf) { display: none; }
  /* ...sauf aujourd'hui, qui sert de repere. */
  .day-slot.day-today { display: block; }
  .day-out-of-month { display: none !important; }
  .day-header {
    align-items: center;
    gap: 0.4rem;
    justify-content: flex-start;
    margin-bottom: 0;
  }
  .day-name { font-size: 0.8rem; font-weight: 600; text-transform: capitalize; }
  .day-date { font-size: 0.95rem; }
  /* Une semaine entierement vide ne doit pas laisser un numero orphelin. */
  .week-group:not(:has(.day-has-perf)):not(:has(.day-today)) { display: none; }
  .performance-card { font-size: 0.86rem; padding: 0.5rem 0.65rem; }
  .perf-cast { font-size: 0.82rem; }
}

/* ── 6. Statistiques comediens (onglet planning) ──────────────────────── */

.panel-title {
  color: var(--bs-secondary-color);
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  margin-bottom: 0.5rem;
  text-transform: uppercase;
}
.copy-feedback {
  color: #0f8a4a;
  font-size: 0.8rem;
  font-weight: 650;
  opacity: 0;
  transition: opacity 0.15s;
}
.copy-feedback.visible { opacity: 1; }
.copy-source-textarea {
  border: 0;
  height: 1px;
  left: -9999px;
  min-height: 0;
  overflow: hidden;
  padding: 0;
  position: absolute;
  top: -9999px;
  width: 1px;
}

/* ── 7. Photos et vignettes ───────────────────────────────────────────── */

/* Hauteur explicite + align-self : la vignette est un enfant flex, elle serait
   sinon etiree a la hauteur du bloc de texte voisin (align-items: stretch), qui
   varie d'une carte a l'autre selon les lignes affichees - d'ou des affiches de
   formats differents sur la meme grille. */
.poster-thumb {
  align-self: flex-start;
  aspect-ratio: 2 / 3;
  border-radius: 6px;
  flex: 0 0 64px;
  height: 96px;
  object-fit: cover;
  width: 64px;
}
.poster-thumb--lg { flex-basis: 96px; height: 144px; width: 96px; }
.poster-placeholder,
.photo-placeholder,
.profile-placeholder {
  align-items: center;
  background: var(--wms-placeholder);
  border: 1px solid var(--bs-border-color);
  color: var(--bs-secondary-color);
  display: flex;
  font-weight: 700;
  justify-content: center;
  text-transform: uppercase;
}
.photo-portrait,
.profile-placeholder {
  aspect-ratio: 4 / 5;
  border-radius: 6px;
  width: 100%;
}
.photo-portrait { display: block; object-fit: cover; }
.performer-row-photo {
  aspect-ratio: 4 / 5;
  border-radius: 6px;
  flex: 0 0 40px;
  height: 50px;
  object-fit: cover;
  width: 40px;
}
.team-card-photo-link { display: block; text-decoration: none; }

/* Choix des comediens habilites sur un role : une vignette cliquable par
   comedien plutot qu'une liste de cases. Meme repere visuel que l'onglet Equipe
   (photo + nom court), et une cible de clic large - la case seule est un
   mouchoir de poche. La case reste dans le DOM, non masquee : elle porte l'etat
   pour le clavier et les lecteurs d'ecran, `:has()` ne fait que l'habiller. */
.role-performer-option {
  align-items: center;
  border: 1px solid var(--bs-border-color);
  border-radius: 8px;
  cursor: pointer;
  display: grid;
  gap: 0.5rem;
  grid-template-columns: auto 40px 1fr;
  height: 100%;
  padding: 0.5rem;
  transition: background-color 0.12s ease, border-color 0.12s ease;
}
.role-performer-option:hover { background: var(--wms-surface-alt); }
.role-performer-option:has(.form-check-input:checked) {
  background: var(--wms-surface-alt);
  border-color: var(--bs-primary);
  box-shadow: inset 0 0 0 1px var(--bs-primary);
}
.role-performer-option:has(.form-check-input:focus-visible) {
  box-shadow: 0 0 0 var(--bs-focus-ring-width) var(--bs-focus-ring-color);
}
.role-performer-option .form-check-input { margin: 0; }
.role-performer-photo {
  aspect-ratio: 4 / 5;
  border-radius: 6px;
  display: block;
  overflow: hidden;
  width: 40px;
}
.role-performer-photo img {
  display: block;
  height: 100%;
  object-fit: cover;
  width: 100%;
}
.role-performer-initials {
  align-items: center;
  background: var(--wms-placeholder);
  color: var(--bs-secondary-color);
  display: flex;
  font-size: 0.72rem;
  font-weight: 700;
  height: 100%;
  justify-content: center;
  text-transform: uppercase;
}
.role-performer-name {
  font-size: 0.85rem;
  font-weight: 600;
  line-height: 1.25;
  overflow-wrap: anywhere;
}

/* Rappel lateral de l'ordre des roles : le numero se lit comme une pastille,
   pour retrouver d'un coup d'oeil les valeurs deja prises. */
.role-order-item {
  align-items: center;
  border-top: 1px solid var(--bs-border-color);
  display: flex;
  gap: 0.5rem;
  padding: 0.35rem 0;
}
.role-order-item:first-child { border-top: 0; }
.role-order-badge {
  background: var(--wms-surface-alt);
  border: 1px solid var(--bs-border-color);
  border-radius: 999px;
  flex: 0 0 auto;
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  min-width: 1.85rem;
  padding: 0.05rem 0.4rem;
  text-align: center;
}
.role-order-item--current .role-order-badge {
  background: var(--bs-primary);
  border-color: var(--bs-primary);
  color: #ffffff;
}
.role-order-name { overflow-wrap: anywhere; }
.team-card-photo-link img,
.team-card-photo-link .profile-placeholder { transition: opacity 0.15s; }
.team-card-photo-link:hover img,
.team-card-photo-link:hover .profile-placeholder { opacity: 0.8; }

/* ── 8. Zone de depot de fichiers ─────────────────────────────────────── */

.dropzone {
  align-items: center;
  background: var(--wms-surface-alt);
  border: 1px dashed #aeb8af;
  border-radius: 8px;
  cursor: pointer;
  display: grid;
  gap: 0.5rem;
  justify-items: center;
  margin: 0;
  min-height: 132px;
  padding: 1.125rem;
  position: relative;
  text-align: center;
}
.dropzone:hover { background: #f5f8f5; border-color: var(--wms-accent); }
.dropzone.drag-over {
  background: #eef6f4;
  border-color: var(--wms-accent);
  box-shadow: inset 0 0 0 1px var(--wms-accent);
}
.dropzone input[type="file"] {
  height: 1px;
  opacity: 0;
  overflow: hidden;
  padding: 0;
  position: absolute;
  width: 1px;
}
.dropzone-title { font-weight: 750; }
.dropzone-file-summary {
  background: #ffffff;
  border: 1px solid var(--bs-border-color);
  border-radius: 999px;
  color: var(--bs-secondary-color);
  display: inline-flex;
  font-size: 0.88rem;
  font-weight: 650;
  max-width: 100%;
  overflow: hidden;
  padding: 0.3rem 0.625rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dropzone-file-summary--error {
  background: #fef2f2;
  border-color: var(--bs-danger);
  color: var(--bs-danger);
}
.venue-form-photo-dropzone {
  aspect-ratio: 4 / 3;
  min-height: 0;
  padding: 0.375rem;
}
.venue-form-photo-dropzone .dropzone-title { display: none; }
.venue-form-photo-dropzone .dropzone-file-summary { font-size: 0.72rem; padding: 0.2rem 0.4rem; }
.venue-form-photo-dropzone i { color: #b9c2ba; font-size: 1.4rem; }
.venue-form-photo-preview { border-radius: 6px; height: 100%; object-fit: cover; width: 100%; }
.production-form-poster-dropzone {
  aspect-ratio: 2 / 3;
  min-height: 0;
  padding: 0.375rem;
}
.production-form-poster-dropzone .dropzone-title { display: none; }
.production-form-poster-dropzone .dropzone-file-summary { font-size: 0.72rem; padding: 0.2rem 0.4rem; }
.production-form-poster-dropzone i { color: #b9c2ba; font-size: 1.4rem; }
.production-form-poster-preview { border-radius: 6px; height: 100%; object-fit: cover; width: 100%; }
.format-box {
  background: linear-gradient(#0f766e 0 18%, transparent 18%), #f7f7f4;
  border: 1px solid var(--bs-border-color);
  border-radius: 5px;
  display: block;
  width: 34px;
}
.format-box.story { height: 60px; }
.format-box.square { height: 42px; width: 42px; }
.format-box.landscape { height: 30px; width: 54px; }

/* ── 9. Lieux ─────────────────────────────────────────────────────────── */

.venue-card:target { box-shadow: 0 0 0 2px var(--wms-accent); }
.venue-card-media {
  aspect-ratio: 16 / 9;
  background: linear-gradient(155deg, #eef1ed 0%, #e4e9e4 100%);
  position: relative;
}
.venue-card-media img { display: block; height: 100%; object-fit: cover; width: 100%; }
.venue-card-media-placeholder {
  align-items: center;
  color: #b9c2ba;
  display: flex;
  font-size: 2.1rem;
  height: 100%;
  justify-content: center;
  width: 100%;
}
.venue-map { border: 1px solid var(--bs-border-color); border-radius: 8px; overflow: hidden; }
.venue-map summary {
  align-items: center;
  color: var(--wms-accent-dark);
  cursor: pointer;
  display: flex;
  font-size: 0.82rem;
  font-weight: 650;
  gap: 0.375rem;
  list-style: none;
  padding: 0.5rem 0.625rem;
  user-select: none;
}
.venue-map summary::-webkit-details-marker { display: none; }
.venue-map[open] summary { border-bottom: 1px solid var(--bs-border-color); }
.venue-map iframe { border: 0; display: block; height: 160px; width: 100%; }

.merge-photo {
  border-radius: 6px;
  flex-shrink: 0;
  height: 52px;
  object-fit: cover;
  width: 78px;
}
.merge-photo-placeholder {
  align-items: center;
  background: var(--wms-placeholder);
  border-radius: 6px;
  color: #b9c2ba;
  display: flex;
  flex-shrink: 0;
  font-size: 1.3rem;
  height: 52px;
  justify-content: center;
  width: 78px;
}
.merge-candidate-row { transition: border-color 0.15s ease, box-shadow 0.15s ease; }
.merge-candidate-row:hover {
  border-color: var(--wms-accent);
  box-shadow: 0 4px 12px -6px rgba(15, 118, 110, 0.35);
}
.merge-status-label.kept i { color: #0f8a4a; }
.merge-status-label.deleted i { color: var(--bs-danger); }
.merge-pick-checkbox { accent-color: var(--wms-accent); flex-shrink: 0; height: 20px; width: 20px; }
.merge-pick-bar {
  bottom: 1rem;
  box-shadow: 0 8px 20px -8px rgba(16, 24, 40, 0.25);
  position: sticky;
}
#room-empty-form-template { display: none; }

/* ── 10. Graphiques (recettes, tendances) ─────────────────────────────── */

.tracking-graph {
  background: var(--wms-surface-alt);
  border: 1px solid var(--bs-border-color);
  border-radius: 8px;
  overflow-x: auto;
  padding: 0.625rem;
}
.tracking-graph svg { display: block; min-width: 620px; width: 100%; }
.axis-line { stroke: #8d9890; stroke-width: 1.5; }
.grid-line, .tick-line { stroke: #d9ddd7; stroke-width: 1; }
.axis-label { fill: var(--bs-secondary-color); font-size: 12px; font-weight: 650; }
.axis-label.x { text-anchor: middle; }
.axis-label.y.revenue { fill: #0f766e; text-anchor: start; }
.axis-label.y.entries { fill: #64748b; text-anchor: end; }
.tracking-line { fill: none; stroke-linecap: round; stroke-linejoin: round; stroke-width: 3; }
.tracking-line.revenue, .tracking-point.revenue { stroke: #0f766e; }
.tracking-line.entries, .tracking-point.entries { stroke: #64748b; }
.tracking-point { fill: #ffffff; stroke-width: 2; }

.monthly-chart {
  align-items: end;
  border-bottom: 1px solid var(--bs-border-color);
  display: grid;
  gap: 0.625rem;
  grid-template-columns: repeat(auto-fit, minmax(54px, 1fr));
  min-height: 240px;
  padding: 0.5rem 0 0.75rem;
}
.monthly-column { align-items: stretch; display: grid; gap: 0.5rem; min-width: 0; }
.monthly-bars {
  align-items: end;
  border-bottom: 1px solid var(--bs-border-color);
  display: flex;
  gap: 4px;
  height: 132px;
  justify-content: center;
  padding: 0 4px;
}
.monthly-bar { border-radius: 4px 4px 0 0; display: block; min-height: 3px; width: 14px; }
.monthly-bar.revenue, .legend-dot.revenue { background: #0f766e; }
.monthly-bar.entries, .legend-dot.entries { background: #64748b; }
.monthly-label, .monthly-values { display: grid; font-size: 0.78rem; line-height: 1.25; text-align: center; }
.monthly-values { color: var(--bs-secondary-color); }
.legend-dot { border-radius: 999px; display: inline-block; height: 9px; width: 9px; }

.trend-row {
  align-items: center;
  border-bottom: 1px solid var(--bs-border-color);
  display: grid;
  gap: 0.75rem;
  grid-template-columns: 72px minmax(0, 1fr) 92px;
  min-width: 0;
  padding-bottom: 0.625rem;
}
.trend-row:last-child { border-bottom: 0; padding-bottom: 0; }
.trend-date, .trend-ticket { display: grid; gap: 1px; }
.trend-ticket { text-align: right; }
.trend-bars { display: grid; gap: 0.375rem; min-width: 0; }
.trend-metric {
  align-items: center;
  display: grid;
  gap: 0.5rem;
  grid-template-columns: 70px minmax(80px, 1fr) 84px;
  min-width: 0;
}
.trend-metric span { color: var(--bs-secondary-color); font-size: 0.84rem; font-weight: 650; }
.trend-metric strong { font-size: 0.9rem; text-align: right; white-space: nowrap; }
.bar-track {
  background: var(--wms-placeholder);
  border-radius: 999px;
  height: 8px;
  overflow: hidden;
  width: 100%;
}
.bar-fill { display: block; height: 100%; min-width: 2px; }
.bar-fill.revenue { background: #0f766e; }
.bar-fill.entries { background: #64748b; }

@media (max-width: 767.98px) {
  .monthly-chart { gap: 0.5rem; grid-template-columns: repeat(6, minmax(42px, 1fr)); }
  .monthly-bars { height: 104px; }
  .monthly-bar { width: 11px; }
  .trend-row { align-items: start; grid-template-columns: 1fr; }
  .trend-ticket { text-align: left; }
  .trend-metric { grid-template-columns: 66px minmax(80px, 1fr) 78px; }
}

/* ── 11. Critiques ────────────────────────────────────────────────────── */

.critique-note {
  align-items: center;
  border-radius: 999px;
  color: #fff;
  display: inline-flex;
  font-size: 0.8rem;
  font-weight: 700;
  justify-content: center;
  line-height: 1;
  min-width: 2.8rem;
  padding: 3px 8px;
  white-space: nowrap;
}
.note-color-1  { background: #b42318; }
.note-color-2  { background: #d92d20; }
.note-color-3  { background: #f04438; }
.note-color-4  { background: #f97316; }
.note-color-5  { background: #f59e0b; }
.note-color-6  { background: #d6a000; }
.note-color-7  { background: #84a800; }
.note-color-8  { background: #4ca30d; }
.note-color-9  { background: #16a34a; }
.note-color-10 { background: #15803d; }
.note-color-empty { background: #6c757d; }
.note-color-1-bg  { background: #b42318; }
.note-color-2-bg  { background: #d92d20; }
.note-color-3-bg  { background: #f04438; }
.note-color-4-bg  { background: #f97316; }
.note-color-5-bg  { background: #f59e0b; }
.note-color-6-bg  { background: #d6a000; }
.note-color-7-bg  { background: #84a800; }
.note-color-8-bg  { background: #4ca30d; }
.note-color-9-bg  { background: #16a34a; }
.note-color-10-bg { background: #15803d; }
.note-color-1-text  { color: #b42318; }
.note-color-2-text  { color: #d92d20; }
.note-color-3-text  { color: #f04438; }
.note-color-4-text  { color: #f97316; }
.note-color-5-text  { color: #f59e0b; }
.note-color-6-text  { color: #d6a000; }
.note-color-7-text  { color: #84a800; }
.note-color-8-text  { color: #4ca30d; }
.note-color-9-text  { color: #16a34a; }
.note-color-10-text { color: #15803d; }

/* Recherche par mot-cle, repliee discretement dans la barre de filtres. */
.critiques-search-input {
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--bs-border-color);
  border-radius: 0;
  color: var(--bs-body-color);
  font-size: 0.76rem;
  height: 22px;
  line-height: 1;
  min-height: 0;
  padding: 2px 3px;
  transition: width 0.15s, border-color 0.15s;
  width: 100px;
}
.critiques-search-input::-webkit-search-cancel-button,
.critiques-search-input::-webkit-search-decoration { -webkit-appearance: none; appearance: none; }
.critiques-search-input::placeholder { color: var(--bs-secondary-color); }
.critiques-search-input:focus {
  border-bottom-color: var(--wms-accent);
  box-shadow: none;
  outline: none;
  width: 150px;
}

.critiques-sidebar { position: sticky; top: 12px; }
.note-bar-row {
  align-items: center;
  border-radius: 5px;
  display: flex;
  gap: 7px;
  padding: 2px 4px;
  text-decoration: none;
  transition: background 0.1s;
}
.note-bar-row:hover { background: var(--bs-body-bg); text-decoration: none; }
.note-bar-row.note-bar-active { background: var(--bs-body-bg); outline: 1px solid var(--bs-border-color); }
.note-bar-track {
  background: var(--bs-body-bg);
  border-radius: 3px;
  flex: 1;
  height: 8px;
  overflow: hidden;
}
.note-bar-fill { border-radius: 3px; height: 100%; min-width: 2px; transition: width 0.2s; }
.note-bar-count { color: var(--bs-secondary-color); font-size: 0.75rem; min-width: 22px; text-align: right; }

/* Grille semaine x note. Elle couvre tout l'historique de critiques et defile
   a l'interieur d'une carte de hauteur fixe : la page ne s'allonge pas quand
   la production tourne depuis deux ans. Le compte reste ecrit en clair dans
   chaque case — la teinte de fond ne fait qu'aider a reperer les zones denses,
   elle ne remplace jamais la lecture du chiffre ni de la note. */
/* La grille occupe toute la hauteur que la carte voisine lui donne, au lieu de
   s'arreter a une hauteur fixe en laissant du blanc sous le tableau : plus la
   carte "Critiques par comedien" est haute, plus on voit de semaines d'un coup. */
.weekly-grid-card .card-body { display: flex; flex-direction: column; }
.weekly-grid-scroll {
  flex: 1;
  max-height: 26rem;
  min-height: 14rem;
  overflow: auto;
  overscroll-behavior: contain;
}
.weekly-note-grid-table {
  border-collapse: separate;
  border-spacing: 0;
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  width: 100%;
}
/* Largeurs plancher seulement : le tableau remplit la carte et repartit le
   reste entre les colonnes. Fixer la colonne de semaine a 100% renvoyait les
   chiffres a l'autre bout de la carte, loin de leur libelle. */
.weekly-note-grid-table .weekly-grid-week { min-width: 7.5rem; }
.weekly-note-grid-table .weekly-grid-cell { width: 2.2rem; }
.weekly-note-grid-table .weekly-grid-num { width: 2.6rem; }
.weekly-note-grid-table .weekly-grid-avg { width: 3.6rem; }
.weekly-note-grid-table th,
.weekly-note-grid-table td {
  border-bottom: 1px solid var(--bs-border-color);
  padding: 0.15rem 0.3rem;
  vertical-align: middle;
}
/* En-tete et colonne de semaine collantes : aussi loin qu'on remonte, on doit
   toujours savoir quelle note on lit et de quelle semaine il s'agit. */
.weekly-note-grid-table thead th {
  background: var(--bs-card-bg, var(--bs-body-bg));
  /* Trait porte par une ombre plutot qu'une bordure : sur une cellule collante
     la bordure basse defile avec le tableau et laisse la ligne suivante
     affleurer l'en-tete. */
  box-shadow: 0 1px 0 var(--bs-border-color);
  position: sticky;
  top: 0;
  z-index: 2;
}
.weekly-note-grid-table .weekly-grid-week {
  background: var(--bs-card-bg, var(--bs-body-bg));
  left: 0;
  position: sticky;
  text-align: left;
  z-index: 1;
}
.weekly-note-grid-table thead .weekly-grid-week { z-index: 3; }
.weekly-grid-num { text-align: right; }
.weekly-note-grid-table thead .weekly-grid-num {
  color: var(--bs-secondary-color);
  font-weight: 600;
}
.weekly-grid-cell { text-align: center; }
.weekly-grid-note-badge {
  border-radius: 999px;
  color: #fff;
  display: inline-block;
  font-size: 0.68rem;
  font-weight: 700;
  line-height: 1.45;
  min-width: 1.45rem;
  text-align: center;
}
.weekly-grid-cell-link { font-weight: 700; text-decoration: none; }
.weekly-grid-cell-link:hover, .weekly-grid-cell-link.active { text-decoration: underline; }
/* La moyenne est un chiffre par ligne : en pastille pleine, soixante-dix
   semaines d'historique donnaient une colonne de gelules qui ecrasait le reste
   de la grille. En texte colore elle se lit aussi vite et pese dix fois moins. */
.weekly-grid-avg { font-weight: 700; }
/* La teinte reprend la couleur de la note de la colonne, dosee par le volume
   relatif a la case la plus fournie de la grille (`_cell_intensity`). */
/* Selecteurs prefixes par la table : `.table > :not(caption) > * > *` de
   Bootstrap repeint sinon chaque cellule en `--bs-table-bg` et la teinte ne
   sort jamais. */
.weekly-note-grid-table .weekly-grid-i1 { background: color-mix(in srgb, var(--note-tint) 13%, transparent); }
.weekly-note-grid-table .weekly-grid-i2 { background: color-mix(in srgb, var(--note-tint) 26%, transparent); }
.weekly-note-grid-table .weekly-grid-i3 { background: color-mix(in srgb, var(--note-tint) 40%, transparent); }
.weekly-note-grid-table .weekly-grid-i4 { background: color-mix(in srgb, var(--note-tint) 58%, transparent); }
/* Sur les teintes les plus soutenues, le chiffre passe en encre foncee neutre :
   le vert sur vert ou l'orange sur orange deviendrait illisible. */
.weekly-note-grid-table .weekly-grid-i3 .weekly-grid-cell-link,
.weekly-note-grid-table .weekly-grid-i4 .weekly-grid-cell-link { color: #1c2b21; }
.note-tint-1  { --note-tint: #b42318; }
.note-tint-2  { --note-tint: #d92d20; }
.note-tint-3  { --note-tint: #f04438; }
.note-tint-4  { --note-tint: #f97316; }
.note-tint-5  { --note-tint: #f59e0b; }
.note-tint-6  { --note-tint: #d6a000; }
.note-tint-7  { --note-tint: #84a800; }
.note-tint-8  { --note-tint: #4ca30d; }
.note-tint-9  { --note-tint: #16a34a; }
.note-tint-10 { --note-tint: #15803d; }
/* Une longue serie de semaines sans critique se replie en une ligne : remonter
   l'historique ne doit pas etre un deroule de lignes vides. */
.weekly-grid-gap td {
  color: var(--bs-secondary-color);
  font-size: 0.72rem;
  font-style: italic;
  padding: 0.1rem 0.3rem;
  text-align: center;
}
.weekly-reviews-current .weekly-grid-week,
.weekly-reviews-current .weekly-grid-num { font-weight: 600; }
.weekly-reviews-selected .weekly-grid-week { box-shadow: inset 3px 0 0 var(--bs-primary); }
.weekly-reviews-week-link { color: inherit; text-decoration: none; }
.weekly-reviews-week-link:hover { text-decoration: underline; }

.critique-platform-badge {
  border-radius: 4px;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  padding: 2px 7px;
  text-transform: uppercase;
}
.critique-platform-billetreduc { background: rgba(253, 126, 20, 0.12); color: #c2560a; }
.critique-platform-ticketac { background: rgba(25, 135, 84, 0.12); color: #146c43; }
.critique-texte {
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  cursor: pointer;
  display: -webkit-box;
  font-size: 0.875rem;
  line-height: 1.55;
  margin: 0 0 0.5rem;
  overflow: hidden;
}
.critique-texte.expanded { -webkit-line-clamp: unset; display: block; }

/* Critiques retirees de la plateforme : conservees et consultables, mais
   visuellement en retrait, parce qu'elles ne comptent plus dans les moyennes
   affichees juste au-dessus. */
.critiques-retirees > summary {
  color: var(--bs-secondary-color);
  cursor: pointer;
  font-size: 0.8rem;
}
.critique-retiree { opacity: 0.7; }
.critique-retiree .critique-texte { text-decoration: line-through; text-decoration-color: rgba(0, 0, 0, 0.25); }

/* ── 12. Catalogue ────────────────────────────────────────────────────── */

.catalogue-poster {
  background: var(--bs-border-color);
  border-radius: 4px;
  display: block;
  height: 56px;
  object-fit: cover;
  width: 40px;
}
.catalogue-poster-placeholder {
  background: var(--bs-border-color);
  border-radius: 4px;
  height: 56px;
  width: 40px;
}
.catalogue-rank-cell { font-size: 1.05rem; font-weight: 800; text-align: right; width: 2.4em; }
.catalogue-trend-up { color: #0f8a4a; font-weight: 700; }
.catalogue-trend-down { color: var(--bs-danger); font-weight: 700; }
.trend-chart-legend-dot { border-radius: 50%; display: inline-block; height: 10px; width: 10px; }

/* ── 13. Disponibilites et preparation de casting ─────────────────────── */

/* Statut de campagne, pose sur un `.badge` Bootstrap. */
.availability-status--draft { background: #eef2f6; color: #475569; }
.availability-status--open { background: #ecfdf5; color: #047857; }
.availability-status--closed { background: #f5f3ff; color: #5b21b6; }

/* Matrice comediens x dates : une campagne reelle fait 20 dates x 9 comediens,
   donc colonne d'entete figee + defilement horizontal contenu dans le panneau,
   jamais dans la page. */
.availability-matrix-scroll {
  border: 1px solid var(--bs-border-color);
  border-radius: 8px;
  max-height: 70vh;
  overflow: auto;
  width: 100%;
}
.availability-matrix { border-collapse: separate; border-spacing: 0; font-size: 0.88rem; width: 100%; }
.availability-matrix th,
.availability-matrix td {
  border-bottom: 1px solid var(--bs-border-color);
  padding: 6px 10px;
  text-align: left;
  white-space: nowrap;
}
.availability-matrix thead th { background: #f8fafc; position: sticky; top: 0; z-index: 2; }
.availability-matrix .availability-sticky-col {
  background: var(--wms-panel);
  font-weight: 650;
  left: 0;
  letter-spacing: 0;
  position: sticky;
  text-align: left;
  text-transform: none;
  z-index: 1;
}
.availability-matrix thead .availability-sticky-col { z-index: 3; }
.availability-matrix tbody tr:hover td,
.availability-matrix tbody tr:hover .availability-sticky-col { background: #f6faf9; }
.availability-matrix-date { text-align: center; }
.availability-matrix-date span { display: block; font-size: 0.8rem; line-height: 1.15; }
.availability-cell { text-align: center; }
.availability-dot {
  border-radius: 6px;
  display: inline-block;
  font-weight: 750;
  line-height: 1.4;
  min-width: 26px;
  text-align: center;
}
.availability-dot--available { background: #ecfdf5; color: #047857; }
.availability-dot--if_needed { background: #fff8eb; color: #9a3412; }
.availability-dot--unavailable { background: #fef2f2; color: #b42318; }
.availability-dot--missing { background: #f1f5f9; color: var(--bs-secondary-color); }

.availability-link-field {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.78rem;
  max-width: 100%;
  width: 100%;
}

/* Liste des destinataires : trois colonnes alignees (comedien / adresse /
   lien) des que la largeur le permet. En dessous, chaque cellule reprend toute
   la largeur et s'empile - une campagne se consulte aussi depuis un telephone,
   entre deux repetitions. */
.availability-recipients { display: grid; gap: 0.25rem; }
.availability-recipient-head { display: none; }
.availability-recipient-row {
  align-items: start;
  border-top: 1px solid var(--bs-border-color);
  display: grid;
  gap: 0.5rem 1rem;
  padding: 0.75rem 0;
}
.availability-recipient-cell {
  display: grid;
  gap: 0.4rem;
  min-width: 0;
}
.availability-recipient-actions { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.availability-recipient-identity .badge { margin-top: 0.15rem; }

@media (min-width: 992px) {
  .availability-recipient-head,
  .availability-recipient-row {
    grid-template-columns: minmax(9rem, 0.8fr) minmax(15rem, 1fr) minmax(18rem, 1.2fr);
  }
  /* Meme lecture au brouillon, ou la troisieme colonne ne porte qu'un etat :
     le lien personnel n'a pas encore de sens, rien n'est parti. */
  .availability-recipients--draft .availability-recipient-head,
  .availability-recipients--draft .availability-recipient-row {
    align-items: center;
    grid-template-columns: minmax(9rem, 0.9fr) minmax(15rem, 1fr) minmax(8rem, 0.5fr);
  }
  .availability-recipient-head {
    color: var(--bs-secondary-color);
    display: grid;
    font-size: 0.72rem;
    font-weight: 700;
    gap: 0.5rem 1rem;
    letter-spacing: 0.04em;
    padding-bottom: 0.35rem;
    text-transform: uppercase;
  }
}

/* Bloc repliable natif (`details`) : le chevron est dessine a la main, un
   `summary` en flex perd son marqueur par defaut sur Chrome. */
.availability-collapse-summary {
  align-items: baseline;
  cursor: pointer;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  list-style: none;
}
.availability-collapse-summary::-webkit-details-marker { display: none; }
.availability-collapse-summary::before {
  color: var(--bs-secondary-color);
  content: "\25B8";
  font-size: 0.9rem;
  line-height: 1;
}
.availability-collapse[open] > .availability-collapse-summary::before { content: "\25BE"; }
.availability-collapse-summary:hover { color: var(--wms-accent); }

/* Un mois de dates dans un selecteur : intertitre discret, pas une carte de
   plus - les mois s'enchainent a l'interieur d'un meme bloc. */
.availability-month + .availability-month { margin-top: 1.25rem; }

.availability-email-editor {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.85rem;
  line-height: 1.5;
}
.availability-variable-list {
  display: grid;
  font-size: 0.85rem;
  gap: 0.25rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.availability-variable-list code {
  background: var(--wms-placeholder);
  border-radius: 4px;
  padding: 0.05rem 0.3rem;
}
/* Bootstrap compile la couleur active des pills en dur : sans cela, l'onglet
   selectionne ressort en bleu Bootstrap au milieu d'une interface verte. */
.nav-pills .nav-link.active { background-color: var(--wms-accent); }

/* Apercu HTML : rendu dans une iframe pour que le CSS de l'email (fait pour un
   client mail) et celui de l'application ne se contaminent pas. */
.availability-email-frame {
  background: #ffffff;
  border: 1px solid var(--bs-border-color);
  border-radius: 8px;
  display: block;
  height: 30rem;
  max-width: 100%;
  width: 100%;
}
.availability-email-preview {
  background: #f8fafc;
  border: 1px solid var(--bs-border-color);
  border-radius: 8px;
  font-size: 0.82rem;
  margin: 0;
  overflow-x: auto;
  padding: 0.75rem;
  white-space: pre-wrap;
}
.availability-rename-input { flex: 1 1 260px; }
/* z-index : les boutons segmentes coches sont `position: relative`, ils
   passeraient au-dessus de la barre collante en la traversant au defilement. */
.availability-sticky-actions { background: var(--wms-panel); bottom: 0; padding: 0.625rem 0; position: sticky; z-index: 5; }
/* Meme barre, mais posee sur le fond de page (hors panneau) : page publique. */
.availability-sticky-actions--page {
  background: var(--bs-body-bg);
  box-shadow: 0 -8px 12px -8px rgba(31, 35, 40, 0.25);
}

/* ── Preparation du casting : une ligne par date, une colonne par role ──
   Preparer une distribution, c'est arbitrer en deux sens a la fois : la ligne
   (cette date est-elle pourvue ?) et la colonne (qui tient ce role, et a
   quelle frequence ?). Un tableau rend les deux lectures, une liste de cartes
   n'en rendait qu'une. Les roles ne reviennent donc jamais a la ligne : la
   grille defile horizontalement, colonne de date figee. */
.availability-prep-scroll {
  border: 1px solid var(--bs-border-color);
  border-radius: 8px;
  max-height: 78vh;
  overflow: auto;
  width: 100%;
}
.availability-prep-table {
  border-collapse: separate;
  border-spacing: 0;
  font-size: 0.86rem;
  /* Geometrie de la gouttiere de vacances, en variables : la largeur d'un
     couloir sert a la fois au fond degrade de la cellule et au decalage de la
     colonne de date collee, qui doivent rester d'accord. */
  --prep-lane-w: 13px;
  --prep-gutter-w: 39px;
  width: 100%;
}
.availability-prep-table th,
.availability-prep-table td {
  border-bottom: 1px solid var(--bs-border-color);
  padding: 5px 8px;
  text-align: left;
  vertical-align: middle;
}
.availability-prep-table thead th {
  background: #f8fafc;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  position: sticky;
  top: 0;
  z-index: 3;
}
.availability-prep-table .prep-role-col {
  max-width: 170px;
  min-width: 96px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Colonne de date figee : on lit une colonne de role en gardant la date sous
   les yeux, sinon le defilement horizontal fait perdre la ligne courante.
   `left` = largeur des trois couloirs de vacances (3 x 13 px). */
.availability-prep-table .prep-sticky-date {
  background: var(--wms-panel);
  left: var(--prep-gutter-w);
  position: sticky;
  z-index: 2;
}
.availability-prep-table thead .prep-sticky-date { z-index: 4; }
.availability-prep-table .prep-date { font-weight: 500; }
/* La mise en page va sur un enfant : un `display: flex` pose sur la cellule la
   sortirait de la mise en page tabulaire, et les colonnes de role perdraient
   leur largeur. */
.prep-date-inner {
  align-items: baseline;
  display: flex;
  flex-wrap: wrap;
  gap: 0 0.4rem;
  max-width: 250px;
  min-width: 186px;
}
.prep-date-day { font-weight: 700; text-transform: capitalize; white-space: nowrap; }
.prep-date-time { font-variant-numeric: tabular-nums; font-weight: 650; white-space: nowrap; }
.prep-date-place {
  color: var(--bs-secondary-color);
  flex: 1 1 100%;
  font-size: 0.76rem;
  /* `min-width: 0` sans quoi l'ellipse ne se declenche jamais : dans un
     conteneur flex, un enfant en `white-space: nowrap` a une largeur minimale
     automatique egale a son texte entier, et c'est lui - pas la date - qui
     fixait alors la largeur de la colonne. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.prep-date-flags { display: flex; flex: 1 1 100%; flex-wrap: wrap; gap: 0.3rem; }
.prep-date-flag {
  align-items: center;
  background: #fef2f2;
  border-radius: 999px;
  color: #b42318;
  display: inline-flex;
  font-size: 0.7rem;
  font-weight: 700;
  gap: 0.2rem;
  padding: 0.05rem 0.4rem;
}
.prep-date-flag[hidden] { display: none; }
.prep-date-flag--moved { background: #fff8eb; color: #9a3412; }
/* Nom de la periode de vacances, pose une fois a l'ouverture de la suite :
   repete a l'identique dans les trois filets, il ne se lisait plus. */
.prep-date-flag--holiday {
  background: color-mix(in srgb, var(--prep-zone-color) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--prep-zone-color) 40%, transparent);
  color: var(--prep-zone-color);
  font-weight: 700;
  text-transform: none;
}

/* Alternance de fond par mois : sur vingt dates, le changement de mois est le
   premier repere qu'on cherche. La bande d'intertitre le nomme, le fond le
   maintient visible pendant tout le defilement. */
.availability-prep-table .prep-month--1 > td,
.availability-prep-table .prep-month--1 > th { background: #eef3f0; }
.availability-prep-table .prep-month--0 > td,
.availability-prep-table .prep-month--0 > th { background: var(--wms-panel); }
.availability-prep-table .prep-month-band > td,
.availability-prep-table .prep-month-band > th {
  border-bottom: 1px solid var(--bs-border-color);
  color: var(--wms-accent-dark);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  padding-bottom: 3px;
  padding-top: 10px;
  text-transform: uppercase;
}
.availability-prep-table .prep-month-band .prep-sticky-date { left: var(--prep-gutter-w); }

/* Une date non pourvue ne doit pas se chercher : filet rouge et voile rose sur
   la colonne de date, plus le compteur "N a pourvoir". Deux canaux separes qui
   ne se marchent pas dessus : la position verticale dit le mois (fond alterne),
   le bord gauche dit la completude - teinter la ligne entiere effacait
   l'alternance mensuelle des que la moitie des dates etait a pourvoir.
   Les voiles passent par `box-shadow` et non par `background` pour ne pas
   entrer en concurrence de specificite avec l'alternance. */
.availability-prep-table .prep-row--incomplete > .prep-sticky-date {
  box-shadow: inset 4px 0 0 var(--bs-danger), inset 0 0 0 999px rgba(180, 35, 24, 0.05);
}
.availability-prep-table tbody tr:hover > td,
.availability-prep-table tbody tr:hover > th { background: #f2f8f7; }

/* Vacances scolaires : les dates sont des lignes, une periode est donc une
   suite de lignes voisines et se montre comme un filet vertical continu.
   Les trois zones ont chacune leur couloir et leur couleur - le public d'une
   salle vient des trois, et un comedien pose ses conges sur la zone de ses
   enfants, pas sur celle du theatre. */
/* Une seule cellule pour les trois couloirs, et non une par zone. Trois
   cellules collees par ligne faisaient trois calques de composition : sur une
   campagne de soixante-dix dates l'arbre de calques pesait ~70 Mo, au-dessus
   du budget memoire du GPU sur iPhone, et le defilement tombait a dix images
   par seconde alors que le thread principal restait a 13 % de charge. Les
   filets sont donc peints en fond, en trois degres plats superposes. */
.availability-prep-table .prep-gutters {
  background-color: var(--wms-panel);
  left: 0;
  /* `min-width` en plus de `width` : la cellule est vide, sans plancher la
     mise en page automatique du tableau la comprime jusqu'a effacer les filets. */
  min-width: var(--prep-gutter-w);
  padding: 0;
  position: sticky;
  width: var(--prep-gutter-w);
  z-index: 2;
}
/* `background-image` et non `background` : la couleur de fond reste libre pour
   l'alternance mensuelle, qui continue de passer dessous. */
.availability-prep-table tbody .prep-row > td.prep-gutters {
  background-image:
    linear-gradient(var(--prep-lane-a, transparent), var(--prep-lane-a, transparent)),
    linear-gradient(var(--prep-lane-b, transparent), var(--prep-lane-b, transparent)),
    linear-gradient(var(--prep-lane-c, transparent), var(--prep-lane-c, transparent));
  background-position: 0 0, var(--prep-lane-w) 0, calc(var(--prep-lane-w) * 2) 0;
  background-repeat: no-repeat;
  background-size: var(--prep-lane-w) 100%;
}
.prep-gutters--a { --prep-lane-a: #3b82c4; }
.prep-gutters--b { --prep-lane-b: #d98324; }
.prep-gutters--c { --prep-lane-c: #7c5cbf; }
/* Une periode est une suite de dates voisines et doit se lire comme un filet
   continu : la cellule perd son trait de separation des qu'une zone est en
   vacances. Les trois couloirs partagent desormais la cellule, donc le trait
   tombe pour les trois a la fois - il ne separait de toute facon que 39 px de
   fond, a gauche de la colonne de date. */
.availability-prep-table tbody .prep-row > td.prep-gutters--holiday {
  border-bottom-color: transparent;
}
.availability-prep-table thead th.prep-gutters { padding: 0; z-index: 4; }
.prep-legend-holiday {
  background: var(--prep-zone-color);
  border-radius: 3px;
  display: inline-block;
  height: 0.85rem;
  width: 5px;
}
/* Trois teintes franchement distinctes, prises hors de la famille vert/rouge
   qui code deja les reponses des comediens. La couleur voyage a part de la
   geometrie du couloir : la pastille de legende reprend la teinte sans rien
   heriter du positionnement colle. */
.prep-zone--a { --prep-zone-color: #3b82c4; }
.prep-zone--b { --prep-zone-color: #d98324; }
.prep-zone--c { --prep-zone-color: #7c5cbf; }

/* Une case = un role un soir. Les pastilles se lisent d'un coup d'oeil : la
   couleur donne la reponse du comedien, le relief donne la decision. */
.availability-prep-table .prep-cell { min-width: 108px; }
.prep-choices { display: flex; flex-wrap: wrap; gap: 3px; }
.prep-empty { color: var(--bs-secondary-color); }
.prep-cell-notes { display: flex; flex-wrap: wrap; gap: 0.2rem; }
.prep-cell-note {
  align-items: center;
  color: var(--bs-secondary-color);
  display: inline-flex;
  font-size: 0.66rem;
  font-weight: 700;
  gap: 0.15rem;
  line-height: 1.4;
}
.prep-cell-note--conflict { color: #9a3412; }
.availability-prep-table .prep-cell--divergent { box-shadow: inset 0 -2px 0 var(--bs-danger); }

/* Pastille comedien facon contact : photo si la fiche en porte une, initiales
   sinon. Le nom complet reste dans `title` et en texte lu par les lecteurs
   d'ecran - une colonne de noms complets ferait dix fois la largeur. */
.availability-avatar {
  align-items: center;
  background: var(--pick-soft);
  border: 1.5px solid var(--pick-line, transparent);
  border-radius: 999px;
  color: var(--pick-ink);
  cursor: pointer;
  display: inline-flex;
  font-size: 0.74rem;
  font-weight: 750;
  height: 31px;
  justify-content: center;
  letter-spacing: 0.01em;
  overflow: hidden;
  position: relative;
  transition: opacity 0.12s ease, transform 0.12s ease;
  user-select: none;
  width: 31px;
}
/* La photo se pose *par-dessus* les initiales, qui restent toujours dans le
   DOM : un fichier absent ou une URL morte laisse reapparaitre la pastille au
   lieu d'un carre d'image cassee. */
.availability-avatar-initials { line-height: 1; }
.availability-avatar-photo {
  border-radius: inherit;
  height: 100%;
  inset: 0;
  object-fit: cover;
  position: absolute;
  width: 100%;
}
/* Avec un portrait, le fond pastel disparait sous l'image : la reponse du
   comedien ne tient plus que sur le contour, qu'on epaissit et qu'on passe a
   la teinte saturee. Place avant les regles `:checked`, qui doivent garder la
   main sur la pastille choisie. */
.prep-choices .availability-avatar:has(.availability-avatar-photo) {
  border-color: var(--pick-strong);
  border-width: 2.5px;
}
.availability-pick--available { --pick-soft: #d9f2e6; --pick-line: #a7d9c3; --pick-ink: #08624a; --pick-strong: #047857; }
.availability-pick--if_needed { --pick-soft: #fdeccd; --pick-line: #f0c98a; --pick-ink: #8a4b09; --pick-strong: #b45309; }
.availability-pick--unavailable { --pick-soft: #fadcda; --pick-line: #eeb2ad; --pick-ink: #99271d; --pick-strong: #b42318; }
.availability-pick--missing { --pick-soft: #e9edf1; --pick-line: #d3dae1; --pick-ink: #56606a; --pick-strong: #475569; }

/* Distribution du soir ou l'auteur d'une critique a vu le spectacle. On
   reutilise la pastille de `availability` : meme composant, meme repli sur les
   initiales quand la fiche n'a pas de portrait. Ici elle est purement
   informative — pas de choix a faire, donc pas de curseur main ni d'effet de
   survol qui suggererait un clic. */
.review-cast { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.35rem; }
.review-cast-group { align-items: center; display: flex; flex-wrap: wrap; gap: 0.2rem; }
.review-cast-time {
  color: var(--bs-secondary-color);
  font-size: 0.7rem;
  font-weight: 600;
  margin-right: 0.15rem;
}
.review-cast-avatar {
  --pick-soft: #e9edf1;
  --pick-line: #d3dae1;
  --pick-ink: #56606a;
  font-size: 0.62rem;
  height: 24px;
  text-decoration: none;
  width: 24px;
}

/* Critiques par comedien. Une ligne = un comedien : pastille, identite, barre
   de volume, total, moyenne. La barre porte la couleur de la moyenne, si bien
   que la carte se lit en diagonale — qui a le plus de soirees critiquees, et
   dans quelle teinte — avant meme de lire les chiffres. */
.cast-stats-note {
  color: var(--bs-secondary-color);
  font-size: 0.74rem;
  line-height: 1.35;
  margin-bottom: 0.6rem;
}
.cast-stats { display: grid; gap: 1px; }
.cast-stat-row {
  align-items: center;
  border-radius: 7px;
  color: inherit;
  display: grid;
  gap: 0.55rem;
  grid-template-columns: 28px minmax(0, 1fr) minmax(2rem, 4.5rem) 2.4rem 3.4rem;
  padding: 0.3rem 0.4rem;
  text-decoration: none;
  transition: background 0.12s ease;
}
.cast-stat-row:hover { background: var(--bs-tertiary-bg); }
.cast-stat-row.is-selected { background: var(--bs-tertiary-bg); box-shadow: inset 3px 0 0 var(--bs-primary); }
.cast-stat-avatar {
  --pick-soft: #e9edf1;
  --pick-line: #d3dae1;
  --pick-ink: #56606a;
  font-size: 0.66rem;
  height: 28px;
  width: 28px;
}
.cast-stat-identity { display: grid; min-width: 0; }
.cast-stat-name {
  font-size: 0.84rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cast-stat-roles {
  color: var(--bs-secondary-color);
  font-size: 0.7rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cast-stat-bar {
  background: var(--bs-tertiary-bg);
  border-radius: 3px;
  display: block;
  height: 6px;
  overflow: hidden;
}
.cast-stat-bar-fill { border-radius: 3px; display: block; height: 100%; min-width: 2px; }
.cast-stat-count {
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.cast-stat-avg {
  font-size: 0.84rem;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  text-align: right;
}

/* Classement des distributions. Une ligne = une combinaison role/comedien
   effectivement jouee : rang, pastilles, noms, dates, critiques, moyenne. Les
   noms prennent la place restante pour que la carte remplisse sa largeur au
   lieu de laisser un bloc de chiffres flotter au milieu. */
/* Une production a vite vingt-cinq combinaisons : la liste defile a
   l'interieur de sa carte, comme la grille hebdomadaire, pour ne pas pousser
   la liste des critiques hors de l'ecran. */
.dist-stats {
  display: grid;
  gap: 1px;
  max-height: 26rem;
  overflow: auto;
  overscroll-behavior: contain;
}
.dist-row {
  align-items: center;
  border-radius: 7px;
  display: grid;
  gap: 0.65rem;
  grid-template-columns: 1.9rem auto minmax(0, 1fr) 4.6rem 5.8rem 4rem 4.5rem 4rem;
  padding: 0.3rem 0.45rem;
}
.dist-row:nth-child(odd) { background: var(--bs-tertiary-bg); }
/* Une moyenne assise sur moins de cinq critiques ne departage rien : elle
   reste lisible mais ne doit pas peser autant que les autres. */
.dist-row.is-thin { opacity: 0.55; }
.dist-rank {
  color: var(--bs-secondary-color);
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  text-align: right;
}
.dist-avatars { display: flex; gap: 0.15rem; }
.dist-avatar {
  --pick-soft: #e9edf1;
  --pick-line: #d3dae1;
  --pick-ink: #56606a;
  cursor: default;
  font-size: 0.6rem;
  height: 24px;
  width: 24px;
}
.dist-names {
  font-size: 0.82rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dist-metric {
  color: var(--bs-secondary-color);
  font-size: 0.78rem;
  text-align: right;
}
.dist-metric strong { color: var(--bs-body-color); font-variant-numeric: tabular-nums; }
.dist-avg {
  font-size: 0.86rem;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  text-align: right;
}
/* Sur telephone, les six colonnes ne tiennent pas : les pastilles et les noms
   passent sur une ligne, les trois chiffres sous eux. */
@media (max-width: 575.98px) {
  .dist-row {
    grid-template-columns: 1.9rem auto minmax(0, 1fr);
    row-gap: 0.15rem;
  }
  .dist-row .dev-cell { display: none; }
  .dist-metric:first-of-type { grid-column: 2 / 3; }
  .dist-metric { text-align: left; }
  .dist-avg { grid-column: 3 / 4; grid-row: 2; }
}

/* Rappel du filtre comedien actif, juste au-dessus de la liste : sans lui, une
   liste filtree ressemble a une production qui aurait perdu ses critiques. */
.critiques-active-filter {
  align-items: center;
  background: var(--bs-tertiary-bg);
  border-radius: 999px;
  display: inline-flex;
  font-size: 0.84rem;
  gap: 0.5rem;
  margin-bottom: 1rem;
  padding: 0.25rem 0.85rem 0.25rem 0.3rem;
}
.critiques-active-filter a { color: var(--bs-secondary-color); text-decoration: none; }
.critiques-active-filter a:hover { color: var(--bs-body-color); }
.availability-avatar--none {
  background: transparent;
  border-color: var(--bs-border-color);
  border-style: dashed;
  color: var(--bs-secondary-color);
  font-size: 0.8rem;
}

/* Selectionne : la pastelle devient pleine et prend un anneau de sa couleur
   forte. Les deux ensemble - pas seulement la teinte - pour rester lisible sur
   une capture noir et blanc comme pour un daltonien, et parce qu'un comedien
   avec photo masque le fond : sans anneau colore, il ne resterait rien. */
.btn-check:checked + .availability-avatar {
  background: var(--pick-strong);
  border-color: #ffffff;
  box-shadow: 0 0 0 2px var(--pick-strong), 0 1px 3px rgba(31, 35, 40, 0.3);
  color: #ffffff;
  transform: scale(1.04);
}
.btn-check:checked + .availability-avatar--none {
  background: var(--wms-surface-alt);
  border-color: var(--bs-border-color);
  border-style: solid;
  box-shadow: none;
  color: var(--bs-secondary-color);
  transform: none;
}
/* Case tranchee : les autres candidats s'effacent sans disparaitre, on doit
   pouvoir changer d'avis sans rouvrir quoi que ce soit. */
.prep-cell--picked .btn-check:not(:checked) + .availability-avatar { opacity: 0.42; }
.prep-cell--picked .btn-check:not(:checked) + .availability-avatar:hover { opacity: 1; }
.availability-avatar:hover { transform: scale(1.08); }
.btn-check:focus-visible + .availability-avatar {
  box-shadow: 0 0 0 var(--bs-focus-ring-width) var(--bs-focus-ring-color);
  z-index: 1;
}
.btn-check:disabled + .availability-avatar { cursor: default; opacity: 0.7; }
.prep-cell--picked .btn-check:disabled:not(:checked) + .availability-avatar { opacity: 0.35; }
.availability-avatar--legend { cursor: default; height: 24px; width: 24px; font-size: 0.64rem; }
.availability-avatar--legend-picked {
  background: var(--pick-strong);
  border-color: #ffffff;
  box-shadow: 0 0 0 2px var(--pick-strong);
  color: #ffffff;
}
.availability-avatar--recap { cursor: default; height: 24px; margin-right: 0.35rem; width: 24px; font-size: 0.64rem; }

/* ── Preparation du casting sur ecran etroit ───────────────────────────
   Deux paliers, sur les points de rupture Bootstrap.

   Sous `lg` (992 px) la grille tient dans la largeur : rien n'a donc a rester
   colle a gauche. C'est la le gros du gain - les trois couloirs de vacances et
   la colonne de date etaient colles sur chacune des soixante-dix lignes, soit
   ~300 elements promus en calques de composition, et les cellules qui les
   recouvraient l'etaient a leur tour : 1375 calques pour ~70 Mo mesures au Web
   Inspector sur iPhone. Le `thead` reste colle en haut (5 calques), c'est lui
   qui dit quelle colonne est quel role.

   Sous `md` (768 px) on resserre en plus, et `table-layout: fixed` rend
   l'ajustement garanti au lieu de dependre du contenu : en mise en page
   automatique la colonne de date se calait sur la plus longue chaine
   insecable de la campagne (un nom de salle) et la grille debordait encore. */
@media (max-width: 991.98px) {
  /* `tbody` explicite : le `thead` garde son `position: sticky`. */
  .availability-prep-table tbody .prep-gutters,
  .availability-prep-table tbody .prep-sticky-date { position: static; }
}

@media (max-width: 767.98px) {
  .availability-prep-table {
    --prep-lane-w: 7px;
    --prep-gutter-w: 21px;
    font-size: 0.78rem;
    table-layout: fixed;
  }
  /* 84 px pour la date et 28 px de pastille : le budget est calcule pour qu'une
     colonne de role garde 2 x 28 px + 3 px de gouttiere + 6 px de marges, soit
     65 px, sur un ecran de 360 px. En dessous les quatre choix s'empilent sur
     quatre rangees et la ligne double de hauteur. */
  .availability-prep-table .prep-date-col { width: 84px; }
  .availability-prep-table th,
  .availability-prep-table td { padding: 4px 3px; }
  .prep-choices .availability-avatar { height: 28px; width: 28px; }
  .prep-date-inner { max-width: none; min-width: 0; }
  /* Le nom de la salle sort de la grille : une campagne se joue presque toujours
     dans un seul lieu, et l'onglet « Par date » le porte de toute facon. C'est
     une ligne de moins par date, soit un tiers de la hauteur a faire defiler. */
  .prep-date-place { display: none; }
  /* Les etiquettes peuvent se replier plutot que d'elargir la colonne, et leur
     libelle passe aux lecteurs d'ecran seuls : dans 84 px « a pourvoir » tenait
     sur deux lignes. Le pictogramme, le compte, le bandeau du haut et le filet
     rouge suffisent a l'oeil. */
  .prep-date-flags,
  .prep-date-flag { min-width: 0; }
  .prep-flag-words {
    clip-path: inset(50%);
    height: 1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
    width: 1px;
  }
}

/* Recapitulatif live, groupe par role : la vraie question d'equilibrage est
   "qui tient ce role, et combien de soirs par mois", pas "qui joue". Il colle
   en haut de sa colonne des qu'il tient a cote de la grille. */
.availability-recap-table td { font-variant-numeric: tabular-nums; text-align: center; }
.availability-recap-table .availability-sticky-col > * { vertical-align: middle; }
.prep-recap-name { display: inline-block; max-width: 8.5rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.availability-recap-table .prep-recap-role th {
  background: var(--wms-surface-alt);
  color: var(--wms-accent-dark);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.availability-recap-total { font-weight: 750; }
.availability-recap-zero { color: var(--bs-secondary-color); }
.availability-recap-row--empty .availability-sticky-col { color: var(--bs-secondary-color); font-weight: 500; }
@media (min-width: 1400px) {
  .availability-recap { position: sticky; top: 1rem; }
}

/* Page publique du comedien : une ligne par date.
   Le comedien repond depuis son telephone, souvent sur vingt dates : une carte
   par date faisait une page a derouler interminablement. Ici une date tient
   sur une ligne, la saisie est un groupe segmente (un seul appui), et le
   commentaire - rare - se replie derriere une icone. */
.availability-public { max-width: 720px; }
.availability-legend { line-height: 1.5; }

.availability-month-head {
  background: var(--wms-panel);
  font-size: 0.78rem;
  font-weight: 750;
  letter-spacing: 0.06em;
  margin: 0;
  padding: 0.55rem 0 0.35rem;
  position: sticky;
  text-transform: uppercase;
  top: 0;
  z-index: 2;
}
.availability-month-head + .availability-date-list { margin-top: 0; }

.availability-date-list { list-style: none; margin: 0; padding: 0; }
.availability-date-row {
  align-items: center;
  border-top: 1px solid var(--bs-border-color);
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: 0.5rem 0;
}
.availability-date-row--removed { opacity: 0.65; }
.availability-date-label {
  align-items: baseline;
  display: flex;
  flex: 1 1 11rem;
  flex-wrap: wrap;
  gap: 0.4rem;
  min-width: 0;
}
.availability-date-day { font-weight: 650; }
.availability-date-time { font-variant-numeric: tabular-nums; }
.availability-date-place { color: var(--bs-secondary-color); font-size: 0.85rem; }
.availability-date-removed { flex: 1 1 100%; font-size: 0.85rem; }

/* Groupe segmente : les `input` sont visuellement masques par `.btn-check`
   de Bootstrap, seul le `label` est cliquable - donc pas de JS pour la saisie,
   et une cible tactile qui fait toute la hauteur du bouton. */
.availability-segmented { display: flex; flex: 0 0 auto; }
.availability-seg {
  --bs-btn-padding-y: 0.35rem;
  --bs-btn-padding-x: 0.65rem;
  --bs-btn-font-size: 0.85rem;
  border: 1px solid var(--bs-border-color);
  border-radius: 0;
  color: var(--bs-secondary-color);
  margin-left: -1px;
  white-space: nowrap;
}
.availability-seg:first-of-type {
  border-bottom-left-radius: var(--bs-border-radius-sm);
  border-top-left-radius: var(--bs-border-radius-sm);
  margin-left: 0;
}
.availability-seg:last-of-type {
  border-bottom-right-radius: var(--bs-border-radius-sm);
  border-top-right-radius: var(--bs-border-radius-sm);
}
.availability-seg--none { --bs-btn-padding-x: 0.5rem; flex: 0 0 auto; }
.availability-seg:hover { color: var(--bs-body-color); }
.btn-check:checked + .availability-seg { color: #fff; position: relative; z-index: 1; }
.btn-check:checked + .availability-seg--available { background: #047857; border-color: #047857; }
.btn-check:checked + .availability-seg--if_needed { background: #b45309; border-color: #b45309; }
.btn-check:checked + .availability-seg--unavailable { background: #b42318; border-color: #b42318; }
.btn-check:checked + .availability-seg--none {
  background: var(--wms-surface-alt);
  color: var(--bs-secondary-color);
}
.btn-check:focus-visible + .availability-seg {
  box-shadow: 0 0 0 var(--bs-focus-ring-width) var(--bs-focus-ring-color);
  z-index: 2;
}
.btn-check:disabled + .availability-seg { opacity: 0.75; pointer-events: none; }

.availability-date-note { flex: 0 0 auto; }
.availability-date-note > summary {
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius-sm);
  color: var(--bs-secondary-color);
  cursor: pointer;
  display: inline-flex;
  line-height: 1;
  list-style: none;
  padding: 0.45rem 0.55rem;
}
.availability-date-note > summary::-webkit-details-marker { display: none; }
.availability-date-note[open] { flex: 1 1 100%; }
.availability-date-note[open] > summary { background: var(--wms-surface-alt); color: var(--bs-body-color); }
.availability-date-note[open] > summary + * { margin-top: 0.4rem; }

.availability-bulk { padding-bottom: 0.5rem; }

@media (max-width: 575.98px) {
  /* Sur telephone la date prend sa ligne et le groupe segmente occupe toute
     la largeur : chaque choix garde une cible tactile confortable. */
  .availability-date-label { flex: 1 1 100%; }
  .availability-segmented { flex: 1 1 auto; }
  .availability-seg { flex: 1 1 auto; }
  .availability-seg--none { flex: 0 0 auto; }
}

@media (max-width: 719.98px) {
  .availability-matrix-scroll { max-height: 60vh; }
  .availability-matrix th, .availability-matrix td { padding: 5px 7px; }
}

/* ── 14. Scraping ─────────────────────────────────────────────────────── */

.scraping-log-table { font-size: 0.84rem; }
.scraping-log-table th { font-size: 0.76rem; }
.scrape-failures { color: #b42318; font-weight: 700; }
.status-ok { color: #047857; font-weight: 650; }
.status-running { color: #0369a1; font-weight: 650; }
.status-partial { color: #9a3412; font-weight: 650; }
.status-failed { color: #b42318; font-weight: 650; }
.source-badge--billetreduc { background: #c2410c; color: #fff; }
.source-badge--ticketac { background: #1d4ed8; color: #fff; }
.source-badge-square {
  align-items: center;
  border-radius: 8px;
  display: flex;
  flex-shrink: 0;
  font-size: 0.7rem;
  font-weight: 700;
  height: 32px;
  justify-content: center;
  letter-spacing: 0.02em;
  width: 32px;
}

/* ── 15. Promotion ────────────────────────────────────────────────────── */
/* Les noms de classe promo-* sont assertes par promotion/tests/test_views.py :
   ne pas les renommer. */

.promo-template-card { overflow: hidden; }
.promo-card-layout {
  align-items: stretch;
  display: grid;
  grid-template-columns: minmax(220px, 300px) minmax(0, 1fr);
  min-width: 0;
}
.promo-summary {
  align-items: center;
  background: #f4f6f3;
  border-right: 1px solid var(--bs-border-color);
  display: flex;
  justify-content: center;
  min-width: 0;
  padding: 1rem;
}
.promo-thumb {
  align-self: center;
  background: #1f2328;
  border-radius: 7px;
  color: #fff;
  display: block;
  justify-self: center;
  max-height: 420px;
  overflow: hidden;
  position: relative;
  width: 100%;
}
.promo-thumb--story { aspect-ratio: 9 / 16; max-width: 220px; }
.promo-thumb--square { aspect-ratio: 1 / 1; max-width: 240px; }
.promo-thumb--landscape { aspect-ratio: 16 / 9; max-width: 268px; }
.promo-thumb img { height: 100%; inset: 0; object-fit: cover; position: absolute; width: 100%; }
.promo-template-facts {
  display: grid;
  gap: 0.5rem 0.875rem;
  grid-template-columns: repeat(2, minmax(130px, 1fr));
  margin: 0;
}
.promo-template-facts div {
  align-content: start;
  background: var(--wms-surface-alt);
  border: 1px solid var(--bs-border-color);
  border-radius: 6px;
  display: grid;
  gap: 2px;
  min-width: 0;
  padding: 0.5625rem 0.625rem;
}
.promo-template-facts dt { color: var(--bs-secondary-color); font-size: 0.72rem; font-weight: 700; text-transform: uppercase; }
.promo-template-facts dd { font-size: 0.92rem; font-weight: 650; margin: 0; min-width: 0; overflow-wrap: anywhere; }
.promo-card-body { align-content: center; display: grid; gap: 1.125rem; min-width: 0; padding: 1rem 1.25rem; }
.promo-section-label {
  color: var(--bs-secondary-color);
  display: block;
  font-size: 0.74rem;
  font-weight: 750;
  letter-spacing: 0.04em;
  line-height: 1.2;
  text-transform: uppercase;
}
.promo-render-grid { display: grid; gap: 1.375rem; }
.promo-render-card {
  border-bottom: 1px solid var(--bs-border-color);
  display: grid;
  gap: 0.75rem;
  min-width: 0;
  padding: 0 0 1.375rem;
}
.promo-render-preview {
  align-items: flex-start;
  background: #f5f5f3;
  border: 1px solid var(--bs-border-color);
  border-radius: 6px;
  color: var(--bs-secondary-color);
  display: flex;
  font-size: 0.82rem;
  font-weight: 650;
  justify-content: flex-start;
  max-width: 100%;
  overflow: auto;
  padding: 0;
}
.promo-render-preview img { display: block; height: auto; max-width: 25%; width: 25%; }
.danger-icon { color: var(--bs-danger); }
.promo-error { color: var(--bs-danger); }

@media (max-width: 767.98px) {
  .promo-card-layout { grid-template-columns: 1fr; }
  .promo-summary { border-bottom: 1px solid var(--bs-border-color); border-right: 0; }
  .promo-template-facts { grid-template-columns: 1fr; }
}

/* ── 16. Divers ───────────────────────────────────────────────────────── */

.text-break-anywhere { overflow-wrap: anywhere; }
/* Bootstrap n'a pas d'utilitaire "annuler text-transform" : utile pour les
   liens glissés dans un titre en petites capitales (.panel-title). */
.text-tt-none { letter-spacing: 0; text-transform: none; }
.min-w-0 { min-width: 0; }
.list-divided { list-style: none; margin: 0; padding: 0; }
.list-divided > li { border-bottom: 1px solid var(--bs-border-color); padding-bottom: 0.75rem; }
.list-divided > li + li { padding-top: 0.75rem; }
.list-divided > li:last-child { border-bottom: 0; padding-bottom: 0; }
.member-avatar {
  align-items: center;
  background: var(--wms-accent);
  border-radius: 50%;
  color: #fff;
  display: flex;
  flex-shrink: 0;
  font-size: 0.8rem;
  font-weight: 700;
  height: 2.2rem;
  justify-content: center;
  width: 2.2rem;
}
.member-avatar--pending { background: var(--bs-secondary-color); font-size: 1rem; }
.member-actions { opacity: 0; transition: opacity 0.15s; white-space: nowrap; }
.member-row:hover .member-actions,
.member-row:focus-within .member-actions { opacity: 1; }

/* ── 17. Onglet Equipe — une ligne par role ────────────────────────────── */
/* Une ligne par role (photo, nom, distribution en pastilles, actions) pour
   qu'au moins 3 roles soient visibles sans scroller. Chaque `.role-row` est
   sa propre grille avec les memes largeurs de colonnes : comme toutes les
   lignes font la meme largeur totale, leurs colonnes s'alignent verticalement
   sans avoir besoin de partager une grille commune (evite `display:contents`,
   fragile : certains navigateurs y creent des cellules fantomes a partir des
   espaces/retours a la ligne du template entre les balises). */

.role-row-list {
  border-top: 1px solid var(--bs-border-color);
}
.role-row {
  align-items: center;
  border-bottom: 1px solid var(--bs-border-color);
  column-gap: 0.75rem;
  display: grid;
  grid-template-columns: 64px 12rem 1px 1fr auto;
  padding-block: 0.65rem;
  transition: background-color 0.12s ease;
}
.role-row:hover { background: var(--bs-border-color-translucent); }
.role-row-photo {
  aspect-ratio: 4 / 5;
  border-radius: 6px;
  overflow: hidden;
  width: 64px;
}
.role-row-photo img { display: block; height: 100%; object-fit: cover; width: 100%; }
.role-row-initials,
.role-cast-initials {
  align-items: center;
  background: var(--wms-placeholder);
  color: var(--bs-secondary-color);
  display: flex;
  font-size: 1.1rem;
  font-weight: 700;
  height: 100%;
  justify-content: center;
  text-transform: uppercase;
  width: 100%;
}
.role-row-name {
  align-items: center;
  display: flex;
  font-size: 0.9rem;
  font-weight: 600;
  gap: 0.4rem;
  overflow-wrap: anywhere;
}
.role-row-sep {
  align-self: stretch;
  background: var(--bs-border-color);
  width: 1px;
}
.role-row-cast {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  min-width: 0;
}
.role-cast-chip {
  align-items: center;
  background: var(--wms-surface-alt);
  border-radius: 8px;
  color: inherit;
  display: inline-flex;
  gap: 0.4rem;
  padding: 0.25rem 0.7rem 0.25rem 0.25rem;
  text-decoration: none;
  transition: background-color 0.12s ease;
}
.role-cast-chip:hover { background: var(--bs-border-color); }
.role-cast-photo {
  aspect-ratio: 4 / 5;
  border-radius: 5px;
  flex: 0 0 42px;
  overflow: hidden;
  width: 42px;
}
.role-cast-photo img { display: block; height: 100%; object-fit: cover; width: 100%; }
.role-cast-name { font-size: 0.84rem; font-weight: 600; }
.role-row-actions { display: flex; gap: 0.35rem; justify-self: end; }

@media (max-width: 767.98px) {
  /* Sous cette largeur la colonne "nom" fixe de 12rem ne laisse plus assez
     de place a la distribution : chaque ligne repasse en carte empilee. */
  .role-row {
    column-gap: 0.5rem;
    display: flex;
    flex-wrap: wrap;
    row-gap: 0.5rem;
  }
  .role-row-sep { display: none; }
  .role-row-cast { flex-basis: 100%; order: 3; }
  .role-row-actions { margin-left: auto; }
}


/* ── Page de statistiques critiques (experimentale) ────────────────────────
   Elle n'existe separement de l'onglet Critiques que parce qu'elle repose sur
   un sous-ensemble des critiques : la mise en page fait passer le cadrage
   avant les chiffres. */
.stats-experimental {
  background: var(--bs-tertiary-bg);
  border-radius: 999px;
  color: var(--bs-secondary-color);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 0.15rem 0.6rem;
  text-transform: uppercase;
  vertical-align: middle;
}
.coverage-bar {
  background: var(--bs-tertiary-bg);
  border-radius: 4px;
  height: 10px;
  margin-bottom: 0.6rem;
  overflow: hidden;
}
.coverage-bar-fill { background: #4ca30d; display: block; height: 100%; }
.coverage-lead { font-size: 0.92rem; margin-bottom: 0.6rem; }
.coverage-notes { font-size: 0.84rem; margin-bottom: 0; padding-left: 1.1rem; }
.coverage-notes li { margin-bottom: 0.2rem; }
.coverage-warning { color: #8a4b09; }

.stats-sort { display: flex; flex-wrap: wrap; gap: 0.6rem; font-size: 0.8rem; }
.stats-sort-link { color: var(--bs-secondary-color); font-weight: 500; text-decoration: none; }
.stats-sort-link:hover { text-decoration: underline; }
.stats-sort-link.active { color: var(--bs-body-color); font-weight: 700; }

.stats-table { font-size: 0.84rem; }
.stats-table thead th {
  color: var(--bs-secondary-color);
  font-size: 0.74rem;
  font-weight: 600;
  white-space: nowrap;
}
.stats-table td, .stats-table th { vertical-align: middle; }
.stats-table tbody td { font-variant-numeric: tabular-nums; }
/* Une ligne sous cinq critiques reste lisible mais ne doit pas peser autant
   que les autres. */
.stats-table tr.is-thin { opacity: 0.55; }
.stats-performer a {
  align-items: center;
  color: inherit;
  display: flex;
  gap: 0.5rem;
  text-decoration: none;
}
.stats-performer a:hover .cast-stat-name { text-decoration: underline; }
.stats-performer-identity { display: grid; min-width: 0; }

/* Barre d'ecart divergente : le trait central est la moyenne de reference, la
   barre part a droite au-dessus, a gauche en dessous. Un ecart qui ne sort pas
   de l'intervalle de confiance est dessine en gris — il ne dit rien. */
/* `display: block` seulement sur la version en `span` (le classement des
   distributions, qui est une grille) : sur un `td`, il sort la cellule du flux
   du tableau, qui la repeint alors en blanc sous la barre au lieu de la
   centrer dans sa ligne. */
.dev-cell { min-width: 4.5rem; }
span.dev-cell { display: block; }
.dev-track {
  background: linear-gradient(var(--bs-border-color), var(--bs-border-color)) center / 1px 100% no-repeat;
  display: grid;
  grid-template-columns: 1fr 1fr;
  height: 12px;
  width: 100%;
}
.dev-fill { align-self: center; border-radius: 2px; display: block; height: 7px; }
.dev-fill--up { background: #4ca30d; grid-column: 2; justify-self: start; }
.dev-fill--down { background: #f04438; grid-column: 1; justify-self: end; }
.dev-fill--noise { background: var(--bs-secondary-color); opacity: 0.45; }

.stats-verdict { font-size: 0.78rem; white-space: nowrap; }
.stats-verdict-up { color: #15803d; font-weight: 600; }
.stats-verdict-down { color: #b42318; font-weight: 600; }

.stats-role-block { margin-bottom: 1.1rem; }
.stats-role-block:last-child { margin-bottom: 0; }
.stats-role-head {
  align-items: baseline;
  border-top: 1px solid var(--bs-border-color);
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding-top: 0.5rem;
}
.stats-role-name { font-weight: 700; }

/* Comparaison des tendances entre plateformes. Le verdict passe avant le
   tableau : un coefficient de correlation seul ne dit rien a qui ne l'attend
   pas, et c'est la phrase qui porte l'information. */
.trend-headline {
  align-items: baseline;
  background: var(--bs-tertiary-bg);
  border-radius: 8px;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0.75rem;
  margin-bottom: 0.9rem;
  padding: 0.7rem 0.9rem;
}
.trend-r {
  color: var(--bs-secondary-color);
  font-size: 1.35rem;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  line-height: 1;
}
.trend-r--strong { color: #15803d; }
.trend-headline-detail { color: var(--bs-secondary-color); font-size: 0.78rem; }
.trend-verdict { flex-basis: 100%; font-size: 0.84rem; line-height: 1.45; }

/* Les deux plateformes se lisent en vis-a-vis : meme trio de colonnes, meme
   echelle de barres, si bien qu'un bloc concordant se reconnait a ses deux
   barres du meme cote avant meme de lire la colonne "Accord". */
.trend-table thead th { border-bottom-width: 1px; }
.trend-platform-head { font-size: 0.7rem; font-weight: 600; }
.trend-platform-head .critique-platform-badge { margin-right: 0.35rem; }
.trend-dev-cell { min-width: 3.5rem; padding-right: 1.1rem; }
.trend-agree { color: #15803d; font-weight: 700; }

/* Records. Trois tuiles, le chiffre d'abord : c'est la seule carte de la page
   qu'on lit pour le plaisir, elle doit se saisir sans lire une phrase. */
.fun-facts {
  display: grid;
  gap: 0.6rem;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
}
.fun-fact {
  background: var(--bs-tertiary-bg);
  border-radius: 8px;
  display: grid;
  gap: 0.15rem;
  padding: 0.8rem 0.9rem;
}
.fun-fact-value {
  font-size: 1.6rem;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  line-height: 1;
}
.fun-fact-label { font-size: 0.82rem; font-weight: 600; }
.fun-fact-detail { color: var(--bs-secondary-color); font-size: 0.74rem; }
