/* ==========================================================================
   L'interface de SETLINE, rejouée dans la page.

   Le pendant de `replica.css` sur le site voisin, et l'inverse d'une capture :
   l'application est redessinée en HTML et en CSS à partir de ses propres
   jetons — `CineHub/Theme.swift` pour la charte, `CineHub/Design/` pour les
   composants, les vues pour le reste. (`CineHub_Design_Tokens.md`, qui servait
   de relevé, décrit l'ancienne identité et porte un bandeau PÉRIMÉ : ne pas
   s'en servir.)

   Deux conséquences qui justifient de tout réécrire :

   - le poids. Une capture d'iPad en @2x pèse plusieurs centaines de kilos et
     reste floue sur un écran plus dense. Ce fichier pèse une trentaine de
     kilos et rend une interface nette à toutes les définitions ;
   - la vérité. Une capture vieillit à la première retouche de l'application.
     Ici, le jour où un jeton bouge dans Theme.swift, on le reporte et tout
     le site suit.

   Depuis le rhabillage du 9 août 2026, la charte est celle de Replica : vert
   #22c55e, noirs neutres, et la typographie du système — l'application
   n'embarque plus Bebas Neue ni IBM Plex Mono. Ces deux polices restent
   chargées par `site.css` pour la page autour, qui garde la voix de la maison.

   Une différence de fond avec Replica, et elle est dans le logiciel :
   l'application SETLINE **n'a pas de thème clair**. `CineHubApp` impose
   `preferredColorScheme(.dark)`, parce qu'elle se lit la nuit à côté d'un
   moniteur étalonné. La page, elle, suit le système ; l'appareil posé dessus
   reste sombre dans les deux cas. Il n'y a donc pas de `[data-theme]` ici, et
   c'est un choix documenté, pas un oubli.

   Tout est préfixé `sl-` et vit sous `.sl`.
   ========================================================================== */

.sl {
  /* --- Fonds. Des noirs neutres, très légèrement bleutés : c'est ce qui
         empêche l'image du plateau de prendre une teinte. ----------------- */
  --ab-void: #0b0b0d;
  --ab-bg: #101013; /* Brand.ink — le fond des écrans */
  --ab-surface: #16161a; /* Brand.panel */
  --ab-surface-2: #1c1c21; /* Brand.panel2 */
  --ab-raised: #26262b;
  --ab-card: #16161a;
  --ab-field: rgba(10, 10, 12, 0.42); /* Brand.glassSunken */
  --ab-fill: rgba(245, 245, 247, 0.09);
  --ab-fill-2: rgba(245, 245, 247, 0.06);

  /* --- Textes ----------------------------------------------------------- */
  --ab-bone: #f5f5f7; /* Brand.text */
  --ab-ink-faint: #c7c7cc; /* Brand.textSoft */
  --ab-ink-light: #98989d; /* Brand.muted */
  --ab-ink-mid: #6e6e73; /* Brand.dim */
  --ab-faint: #48484a;

  /* --- Accent unique ---------------------------------------------------- */
  --ab-accent: #22c55e;
  --ab-accent-dark: #15803d;
  --ab-accent-wash: rgba(34, 197, 94, 0.15);
  --ab-accent-line: rgba(34, 197, 94, 0.32);

  /* --- Sémantique. Le vert dit la bonne prise — et c'est aussi la couleur
         de marque, parce que c'est l'état que l'app existe pour produire.
         Le rouge ne dit que ce qui détruit. ------------------------------- */
  --ab-good: #22c55e;
  --ab-good-wash: rgba(34, 197, 94, 0.16);
  --ab-bad: #ff5f56;
  --ab-bad-wash: rgba(255, 95, 86, 0.15);

  --ab-hairline: rgba(245, 245, 247, 0.08);
  --ab-hairline-strong: rgba(245, 245, 247, 0.15);

  /* --- Verre. La matière des commandes hors du rapport : un voile
         translucide, un bord qui capte la lumière, un spéculaire qui
         s'éteint au tiers haut. ------------------------------------------ */
  --ab-glass: rgba(245, 245, 247, 0.08);
  --ab-glass-raised: rgba(245, 245, 247, 0.16);
  --ab-glass-edge: rgba(255, 255, 255, 0.14);
  --ab-glass-sheen: rgba(255, 255, 255, 0.16);

  /* --- Typographies. L'application n'embarque plus de police : elle prend
         celle du système, SF Pro pour le texte et SF Mono pour les données
         qui s'alignent en colonne. Sur un appareil Apple, la page affiche
         donc exactement les mêmes lettres que l'app ; ailleurs, la pile
         retombe sur la police d'interface du système, ce qui reste plus
         honnête que d'embarquer une imitation. -------------------------- */
  --ab-ui: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', Roboto,
    'Helvetica Neue', sans-serif;
  --ab-mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, monospace;
  --ab-display: var(--ab-ui);

  /* --- Rayons relevés dans les vues ------------------------------------- */
  --r-xs: 6px;
  --r-sm: 8px;
  --r-9: 8px;
  --r-md: 12px;
  --r-12: 12px;
  --r-lg: 16px;
  --r-xl: 20px;

  --ab-ease: cubic-bezier(0.32, 0.72, 0, 1);
  --ab-fast: 140ms var(--ab-ease);

  /* --- Le ressort ---------------------------------------------------------
     Un vrai ressort, echantillonne et non approxime : la meme formule que
     SwiftUI, x(t) = 1 - e^(-zeta.w0.t) [cos(wd.t) + (zeta.w0/wd) sin(wd.t)],
     posee en `linear()`.

     Ses valeurs ne sont pas celles de l'application. `Brand.smooth` y vaut
     response 0,34 et damping 0,86, ce qui ne depasse la cible que de 0,5 % :
     invisible. C'est un choix juste du logiciel, qui n'a pas a faire rebondir
     un formulaire qu'on remplit cent fois par jour. La page, elle, montre
     chaque geste une fois a quelqu'un qui ne le connait pas : elle s'autorise
     8 % de depassement, et seulement sur les **arrivees**. Ce qui defile ou se
     compare, timecode, curseur, jauge, garde `--ab-ease`, sans rebond.

     response 0,40 et damping 0,58, soit 680 ms et 10,5 % de depassement.

     Attention en reglant ces valeurs : le depassement s'applique a
     l'amplitude animee, pas a la taille finale. Un element qui part de 0,96
     ne remonte qu'a 1,004, c'est-a-dire rien. C'est le depart qui decide de
     ce qu'on voit : a 0,88, le pic atteint 1,013 et le rebond se lit. */
  --ab-spring: cubic-bezier(0.34, 1.7, 0.64, 1);
  --ab-pop: 560ms var(--ab-spring);
}

/* `linear()` encode la courbe reelle ; la bezier ci-dessus n'en est qu'une
   imitation, gardee pour les navigateurs qui ne la connaissent pas. */
@supports (animation-timing-function: linear(0, 1)) {
  .sl {
    --ab-spring: linear(
      0, 0.0831, 0.2729, 0.4973, 0.7079, 0.878, 0.9981, 1.0699, 1.102, 1.1055,
      1.0914, 1.0691, 1.0452, 1.024, 1.0078, 0.9969, 0.9909, 0.9887, 0.9891,
      0.991, 0.9936, 0.996, 0.9981, 0.9997, 1.0006
    );
  }
}

/* ---- L'appareil -----------------------------------------------------------
   Un iPad posé sur la page. Il est son propre conteneur de requêtes : il se
   replie sur sa largeur à lui, et non sur celle du navigateur — le même
   appareil sert en pleine largeur dans le héros et en demi-colonne plus bas.
   -------------------------------------------------------------------------- */

.sl {
  container-type: inline-size;
  container-name: sl;
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--ab-bg);
  color: var(--ab-bone);
  font-family: var(--ab-ui);
  font-size: 13px;
  line-height: 1.45;
  border-radius: 22px;
  /* Le châssis : un liseré clair, comme la tranche d'un iPad. */
  border: 1px solid #34343a;
  box-shadow:
    0 0 0 6px #131316,
    0 40px 90px -32px rgba(0, 0, 0, 0.85);
  overflow: hidden;
  isolation: isolate;
  -webkit-font-smoothing: antialiased;
}
.sl *,
.sl *::before,
.sl *::after {
  box-sizing: border-box;
}
.sl [hidden] {
  display: none !important;
}
/* La remise à zéro des boutons passe par `:where()`, qui ne compte pas dans
   la spécificité. Sans lui, `.sl button` (une classe + un type) l'emporterait
   sur `.sl-btn` (une classe) et tous les boutons de l'application
   ressortiraient nus — fond transparent, sans bord ni marge. */
.sl :where(button) {
  font: inherit;
  color: inherit;
  cursor: pointer;
  border: 0;
  background: none;
  padding: 0;
}
.sl .tabular {
  font-variant-numeric: tabular-nums;
}
.sl .sl-spacer {
  flex: 1;
}
.sl .ic {
  flex: none;
  display: block;
}

/* `BrandScreenHeader` : le grand titre figé. Il ne défile pas — c'est tout
   l'intérêt du composant dans l'application, il est donc `sticky` ici.
   L'application a sorti l'action de la barre de navigation pour la poser sur
   la ligne du titre : l'en-tête est donc une rangée, pas un simple bloc. */
.sl-headline {
  position: sticky;
  top: 0;
  z-index: 6;
  flex: none;
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--ab-bone);
  background: var(--ab-bg);
  padding: 8px 20px 12px;
  border-bottom: 1px solid var(--ab-hairline);
}
.sl-headline-text {
  display: grid;
  gap: 2px;
  min-width: 0;
  flex: 1;
}
.sl-headline-text b {
  font-size: 32px;
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.4px;
}
.sl-headline-text i {
  font-style: normal;
  font-size: 13px;
  color: var(--ab-ink-mid);
}
/* Le rond de verre du « + ». */
.sl-headaction {
  flex: none;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  color: var(--ab-accent);
  background: var(--ab-glass);
  border: 1px solid var(--ab-glass-edge);
}
.sl-body {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* La barre d'onglets. Le voile de `UITabBarAppearance` : un noir presque
   opaque posé sur le flou, et un filet en séparation. */
.sl-tabs {
  flex: none;
  display: flex;
  border-top: 1px solid var(--ab-hairline);
  background: rgba(11, 11, 13, 0.92);
  padding: 6px 0 8px;
}
.sl-tab {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  color: var(--ab-ink-mid);
}
.sl-tab b {
  font-size: 10px;
  font-weight: 500;
}
.sl-tab.on {
  color: var(--ab-accent);
}

/* ---- La vue partagée du rapport -------------------------------------------
   Sur un iPad de plein format : les prises à gauche, le formulaire à droite,
   largeur fixe 430 pt. C'est la disposition de `ReportView` en `sizeClass
   == .regular`.
   -------------------------------------------------------------------------- */

.sl-split-view {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 430px;
}
.sl-takes {
  min-width: 0;
  display: flex;
  flex-direction: column;
  border-right: 1px solid var(--ab-hairline);
}
.sl-takes-head {
  flex: none;
  padding: 12px 20px 8px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 1.54px; /* eyebrow : taille × 0,14 */
  text-transform: uppercase;
  color: var(--ab-ink-mid);
}
.sl-takes-list {
  flex: 1;
  min-height: 0;
  overflow: hidden auto;
  scrollbar-width: thin;
  padding-bottom: 8px;
}

/* Une ligne de prise. La barre verte de gauche est le seul signe de la bonne
   prise dans la liste ; elle fait 4 pt de large et 40 de haut, rayon 2. */
.sl-take {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 7px 16px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  /* Une ligne qui arrive : elle monte d'un cran et s'allume. Jamais de
     hauteur animée — la liste ne doit pas se réajuster sous elle. */
  animation: sl-land var(--ab-pop);
}
/* L'echelle fait le rebond. Une translation seule, meme au ressort, glisse et
   ne rebondit pas : c'est le retrecissement qui donne l'impression que la
   ligne se pose et se detend. */
@keyframes sl-land {
  from {
    opacity: 0;
    transform: translateY(-14px) scale(0.9);
  }
}
.sl-take-bar {
  width: 3px;
  height: 38px;
  border-radius: 2px;
  flex: none;
  background: transparent;
}
.sl-take.good .sl-take-bar {
  background: var(--ab-good);
}
.sl-take-main {
  flex: 1;
  min-width: 0;
}
.sl-take-head {
  display: flex;
  align-items: center;
  gap: 8px;
}
.sl-take-head b {
  font-size: 12.5px;
  font-weight: 500;
  white-space: nowrap;
}
.sl-good {
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.6px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--ab-good-wash);
  color: var(--ab-good);
  flex: none;
}
.sl-take-sub {
  margin-top: 3px;
  font-size: 9.5px;
  color: var(--ab-ink-mid);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sl-take-end {
  flex: none;
  text-align: right;
}
.sl-take-dur {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 10px;
  color: var(--ab-ink-mid);
  font-variant-numeric: tabular-nums;
}

/* ---- Le formulaire --------------------------------------------------------- */

/* Les cartes du formulaire. L'application a regroupé la saisie en sections
   titrées — Slate, Cameras rolling, Optics, White balance, Notes — sans
   déplacer un seul champ. Le titre est une petite capitale espacée, son
   symbole prend l'accent : c'est le motif `Card` de Replica. */
.sl-group {
  background: var(--ab-surface);
  border: 1px solid var(--ab-hairline);
  border-radius: var(--r-lg);
  /* Pas de `overflow: hidden` ici, et c'est délibéré : un élément de grille
     dont le débordement n'est pas `visible` devient un conteneur de
     défilement, ne contribue plus à la taille intrinsèque de sa rangée, et
     la carte s'écrase à un trait. Le bandeau de titre arrondit donc ses deux
     coins hauts lui-même. */
}
.sl-group-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  background: rgba(255, 255, 255, 0.012);
  border-bottom: 1px solid var(--ab-hairline);
  border-radius: calc(var(--r-lg) - 1px) calc(var(--r-lg) - 1px) 0 0;
  color: var(--ab-accent);
}
.sl-group-head h4 {
  margin: 0;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 1.54px;
  text-transform: uppercase;
  color: var(--ab-ink-light);
}
.sl-group-body {
  padding: 14px;
  display: grid;
  gap: 12px;
}

/* Les presets de balance des blancs : des pastilles, allumées à l'accent. */
.sl-presets {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.sl-preset {
  height: 34px;
  padding: 0 14px;
  border-radius: 999px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  color: var(--ab-ink-faint);
  background: var(--ab-fill);
  border: 1px solid var(--ab-hairline-strong);
}
.sl-preset {
  transition: background var(--ab-fast), color var(--ab-fast), border-color var(--ab-fast),
    transform var(--ab-pop);
}
.sl-preset.on {
  background: var(--ab-accent-wash);
  border-color: var(--ab-accent-line);
  color: var(--ab-accent);
  transform: scale(1.06);
}

.sl-form {
  min-width: 0;
  overflow: hidden auto;
  scrollbar-width: thin;
  padding: 16px;
  display: grid;
  gap: 14px; /* le rythme des sections de formulaire dans l'app */
  align-content: start;
}
.sl-form-solo {
  padding: 16px;
}

/* Le panneau de gros plan de la section « la prise ». Il ne contient qu'une
   commande : on lui donne de l'air plutôt que de le laisser flotter en haut
   d'un cadre vide, et on borne sa largeur pour que le bouton garde la
   proportion qu'il a dans l'application. */
.sl-solo-save {
  padding: 22px;
  gap: 16px;
  align-content: center;
  min-height: 100%;
}
.sl-inset {
  max-width: 460px;
}
/* Le chronomètre est figé sur une durée déjà capturée : c'est l'état dans
   lequel on appuie sur enregistrer. */
.sl-watch-static.held .sl-watch-time {
  color: var(--ab-bone);
}
.sl-row2,
.sl-row3 {
  display: grid;
  gap: 12px;
}
.sl-row2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.sl-row3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

/* Un champ : libellé en capitales espacées, puis la commande. Écart 6. */
.sl-field {
  display: grid;
  gap: 6px;
  min-width: 0;
}
.sl-field > label,
.sl-flabel {
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 1.33px; /* taille × 0,14, la règle de `.eyebrow()` */
  text-transform: uppercase;
  color: var(--ab-ink-mid);
}
.sl-grow {
  flex: 1;
  min-width: 0;
}
.sl-hint {
  font-size: 9px;
  color: var(--ab-ink-mid);
  margin: 0;
}

/* Une gouttière creusée : 44 pt de cible, rayon 12, un filet discret. */
.sl-input,
.sl-select {
  height: 44px;
  padding: 0 12px;
  border-radius: var(--r-md);
  border: 1px solid var(--ab-hairline);
  background: var(--ab-field);
  color: var(--ab-bone);
  font-family: inherit;
  font-size: 15px;
  width: 100%;
  min-width: 0;
  outline: none;
}
.sl-input::placeholder {
  color: var(--ab-ink-mid);
}
.sl-input:focus-visible,
.sl-select:focus-visible {
  outline: 2px solid var(--ab-accent);
  outline-offset: 1px;
}
.sl-select {
  cursor: pointer;
  appearance: none;
  padding-right: 28px;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--ab-ink-light) 50%),
    linear-gradient(135deg, var(--ab-ink-light) 50%, transparent 50%);
  background-position: calc(100% - 15px) 20px, calc(100% - 11px) 20px;
  background-size: 4px 4px, 4px 4px;
  background-repeat: no-repeat;
}
.sl-select option {
  background: var(--ab-surface-2);
  color: var(--ab-bone);
}

/* Le champ à pas : − valeur + sur un seul fond creusé, hauteur 44, rayon 12.
   Les signes sont sourds, pas à l'accent : dans le formulaire rhabillé, seul
   l'enregistrement porte la couleur. */
.sl-stepbox {
  display: flex;
  align-items: center;
  background: var(--ab-field);
  border: 1px solid var(--ab-hairline);
  border-radius: var(--r-md);
  overflow: hidden;
}
.sl-step {
  width: 38px;
  height: 44px;
  flex: none;
  color: var(--ab-ink-faint);
  font-size: 15px;
  line-height: 1;
  transition: background var(--ab-fast);
}
.sl-step:hover {
  background: rgba(255, 255, 255, 0.06);
}
.sl-step:active {
  background: var(--ab-accent-wash);
}
.sl-stepval {
  flex: 1;
  min-width: 0;
  height: 44px;
  border: 0;
  background: none;
  color: var(--ab-bone);
  font-family: var(--ab-mono);
  font-size: 19px;
  font-weight: 500;
  text-align: center;
  font-variant-numeric: tabular-nums;
  outline: none;
}

/* Les caméras qui tournent. */
.sl-cams {
  display: grid;
  gap: 10px;
}
.sl-campicker {
  display: flex;
  gap: 8px;
}
.sl-campick {
  flex: 1;
  min-height: 40px;
  border-radius: var(--r-9);
  background: var(--ab-fill-2);
  color: var(--ab-ink-light);
  font-size: 15px;
  font-weight: 500;
  border: 1px solid transparent;
  transition: background var(--ab-fast), color var(--ab-fast), border-color var(--ab-fast),
    transform var(--ab-pop);
}
/* La bascule se voit a la couleur ; le ressort lui donne le poids d'un geste.
   1,04, pas davantage : quatre boutons cote a cote, celui qui s'allume ne doit
   pas bousculer ses voisins. */
.sl-campick.on {
  background: var(--ab-accent-wash);
  border-color: var(--ab-accent);
  color: var(--ab-accent);
  transform: scale(1.04);
}
.sl-camlist {
  display: grid;
  gap: 10px;
}
.sl-cam {
  display: grid;
  gap: 8px;
  padding: 10px;
  border-radius: var(--r-md);
  background: var(--ab-fill);
  animation: sl-land 260ms var(--ab-ease);
}
.sl-cam-top {
  display: flex;
  align-items: flex-end;
  gap: 8px;
}
.sl-cam-id {
  width: 30px;
  height: 36px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: var(--r-sm);
  background: var(--ab-accent-wash);
  color: var(--ab-accent);
  font-size: 17px;
  font-weight: 700;
}
.sl-cam .sl-input {
  height: 44px;
}
.sl-icon-btn {
  width: 40px;
  height: 36px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: var(--r-sm);
  background: var(--ab-field);
  color: var(--ab-accent);
  transition: background var(--ab-fast);
}
.sl-icon-btn:hover {
  background: rgba(255, 255, 255, 0.14);
}
.sl-icon-btn:active {
  transform: scale(0.96);
}

/* ---- Le chronomètre --------------------------------------------------------
   Posé juste au-dessus de l'enregistrement, comme dans l'application : action,
   coupez, on note.
   -------------------------------------------------------------------------- */

.sl-watch {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px;
  border-radius: var(--r-12);
  background: var(--ab-fill);
}
.sl-watch-ic {
  color: var(--ab-ink-mid);
  display: block;
  transition: color var(--ab-fast);
}
.sl-watch.running .sl-watch-ic {
  color: var(--ab-good);
}
.sl-watch-time {
  font-size: 30px;
  font-weight: 500;
  letter-spacing: -0.5px;
  color: var(--ab-ink-mid);
  line-height: 1;
  transition: color var(--ab-fast);
}
.sl-watch.running .sl-watch-time,
.sl-watch.held .sl-watch-time,
.sl-watch-static .sl-watch-time {
  color: var(--ab-bone);
}

/* ---- Les boutons ----------------------------------------------------------
   `BrandButtonStyle` : capsule, 44 pt de cible, libellé en SF — plus de
   capitales ni d'interlettrage, l'application a cessé de crier.

   Une particularité qui vient du logiciel : **le rapport n'a pas de verre.**
   Un formulaire dense empile une vingtaine de commandes, et vingt lentilles
   font vibrer le fond. Les boutons du rapport sont donc des aplats mats ; le
   verre est réservé aux écrans aérés — dailies, lecteur.
   -------------------------------------------------------------------------- */

.sl-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: 44px;
  padding: 10px 18px;
  border-radius: 999px;
  font-family: inherit;
  font-size: 15px;
  font-weight: 500;
  color: var(--ab-bone);
  background: var(--ab-fill);
  border: 1px solid var(--ab-hairline-strong);
  white-space: nowrap;
  transition: transform 120ms ease-out, opacity 120ms ease-out, background 120ms ease-out;
}
/* `.scaleEffect(pressed ? 0.965 : 1)` */
.sl-btn:active {
  transform: scale(0.965);
  background: var(--ab-fill-2);
}
.sl-btn-primary {
  background: var(--ab-accent);
  color: #fff;
  font-weight: 600;
  border-color: transparent;
}
.sl-btn-primary:active {
  background: var(--ab-accent-dark);
}
.sl-btn-quiet {
  font-size: 14px;
  min-height: 44px;
  padding: 8px 16px;
}
.sl-btn-run {
  min-height: 44px;
  min-width: 96px;
  padding: 8px 18px;
  background: var(--ab-accent);
  color: #fff;
  font-weight: 600;
  border-color: transparent;
}
.sl-watch.running .sl-btn-run {
  background: transparent;
  color: var(--ab-bad);
  border-color: rgba(255, 95, 86, 0.4);
  box-shadow: inset 0 0 0 999px var(--ab-bad-wash);
}
.sl-save {
  display: grid;
  gap: 8px;
}
.sl-btn-save {
  width: 100%;
  flex-direction: column;
  gap: 1px;
  min-height: 54px;
  font-size: 17px;
  padding: 12px 22px;
}
.sl-btn-save i {
  font-size: 11px;
  font-style: normal;
  opacity: 0.85;
}
/* L'enregistrement se scinde : deux boutons, vert et rouge, qui décident du
   circulé au moment du save. */
.sl-split {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  animation: sl-split-in var(--ab-pop);
}
@keyframes sl-split-in {
  from {
    opacity: 0;
    transform: scale(0.88);
  }
}
/* La bonne prise prend l'aplat d'accent ; la mauvaise reste un voile rouge
   cerné — c'est le ton `.danger` de l'app, qui signale sans hurler. */
.sl-btn-good,
.sl-btn-bad {
  font-size: 17px;
  min-height: 54px;
  padding: 14px 12px;
}
.sl-btn-good {
  background: var(--ab-accent);
  color: #fff;
  font-weight: 600;
  border-color: transparent;
}
.sl-btn-bad {
  background: var(--ab-bad-wash);
  color: var(--ab-bad);
  border-color: rgba(255, 95, 86, 0.4);
}
.sl-cancel {
  font-size: 13px;
  color: var(--ab-ink-light);
  text-align: center;
  padding: 6px;
}

/* ---- La bande de stats du rapport ------------------------------------------ */

.sl-band {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  margin: 0 16px 16px;
  background: var(--ab-hairline);
  border: 1px solid var(--ab-hairline);
  border-radius: var(--r-md);
  overflow: hidden;
}
.sl-band-cell {
  background: var(--ab-surface);
  padding: 10px 12px;
}
.sl-band-cell dt {
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 1.98px;
  text-transform: uppercase;
  color: var(--ab-ink-mid);
}
.sl-band-cell dd {
  margin: 4px 0 0;
  font-size: 20px;
  font-weight: 500;
  line-height: 1;
  color: var(--ab-bone);
}
.sl-band-cell.hot dd {
  color: var(--ab-accent);
}
/* Le chiffre qui vient de bouger. Celui qui ne bouge pas — le temps tourné —
   ne s'allume jamais : c'est le sujet de la scène. */
.sl-band-cell dd.bump {
  animation: sl-bump 420ms var(--ab-ease);
}

/* Un champ que l'application vient de remplir toute seule. Le liseré s'allume
   une seconde : c'est le seul moyen de faire remarquer une valeur qui change
   sans que personne l'ait tapée. */
.sl-input.bumped {
  animation: sl-filled 1s var(--ab-ease);
}
@keyframes sl-filled {
  0%,
  60% {
    border-color: var(--ab-accent);
    background: var(--ab-accent-wash);
  }
}

/* Le bloc caméra qui arrive. Il se pose, il ne surgit pas. */
.sl-cam.landed {
  animation: sl-cam-in var(--ab-pop);
}
@keyframes sl-cam-in {
  from {
    opacity: 0;
    transform: translateY(-16px) scale(0.9);
  }
}
@keyframes sl-bump {
  40% {
    transform: translateY(-3px);
  }
}

/* ---- Dailies --------------------------------------------------------------- */

.sl-filters {
  flex: none;
  display: flex;
  gap: 10px;
  padding: 14px 16px 4px;
  overflow-x: auto;
  scrollbar-width: none;
}
.sl-filters::-webkit-scrollbar {
  display: none;
}
/* Les dailies gardent le verre : l'écran est aéré, les commandes peuvent se
   permettre d'être des lentilles. */
.sl-chip {
  flex: none;
  padding: 0 14px;
  height: 34px;
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  background: linear-gradient(180deg, var(--ab-glass-sheen), transparent 58%), var(--ab-glass);
  color: var(--ab-ink-faint);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  border: 1px solid var(--ab-glass-edge);
  transition: background var(--ab-fast), color var(--ab-fast), border-color var(--ab-fast),
    transform var(--ab-pop);
}
.sl-chip.on {
  transform: scale(1.05);
}
/* Le segment actif est une pastille de verre en relief, pas un aplat coloré :
   dans l'application, seul le filtre qui porte un état coloré prend sa
   couleur. « Toutes les prises » n'est pas un état, c'est l'absence de
   filtre. */
.sl-chip.on {
  background: linear-gradient(180deg, var(--ab-glass-sheen), transparent 58%),
    var(--ab-glass-raised);
  border-color: var(--ab-glass-edge);
  color: var(--ab-bone);
}
/* « Good takes » prend la couleur de ce qu'il montre. */
.sl-chip-good.on {
  background: var(--ab-good-wash);
  border-color: rgba(34, 197, 94, 0.55);
  color: var(--ab-good);
}
.sl-chip-select {
  appearance: none;
  padding-right: 26px;
  cursor: pointer;
  background-image:
    linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 14px) 16px, calc(100% - 10px) 16px;
  background-size: 4px 4px, 4px 4px;
  background-repeat: no-repeat;
}
.sl-chip-select option {
  background: var(--ab-surface-2);
  color: var(--ab-bone);
}

/* La grille : `adaptive(minimum: 230)`, gouttière 14 — DailiesView.swift. */
.sl-grid {
  flex: 1;
  min-height: 0;
  overflow: hidden auto;
  scrollbar-width: thin;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 14px;
  padding: 14px 16px 16px;
  align-content: start;
}
.sl-card {
  background: var(--ab-card);
  border: 1px solid var(--ab-hairline);
  border-radius: var(--r-lg);
  /* La vignette est rognée par `clip-path`, **pas** par `overflow: hidden`.
     Un élément de grille dont le débordement n'est pas `visible` devient un
     conteneur de défilement : il ne contribue plus à la hauteur de sa rangée,
     et la carte s'écrase à une quarantaine de pixels en avalant son image.
     `clip-path` rogne sans rien changer au calcul de taille. */
  clip-path: inset(0 round var(--r-lg));
  /* Le déplacement d'une carte quand la grille se réordonne : une
     translation, jamais une position animée. */
  transition: transform 460ms var(--ab-ease), opacity 200ms linear;
}
.sl-card-media {
  position: relative;
  aspect-ratio: 16 / 9;
  background: #000;
  display: grid;
  place-items: center;
  color: rgba(255, 255, 255, 0.22);
}
/* Le rush remplit la vignette. Le glyphe de lecture reste dessous : il
   réapparaît si l'image tarde ou ne charge pas. */
.sl-card-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.sl-card-good {
  position: absolute;
  top: 8px;
  left: 8px;
  padding: 3px 7px;
  border-radius: 999px;
  background: var(--ab-good);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.6px;
}
/* La durée est une donnée : mono, comme dans l'app. */
.sl-card-dur {
  position: absolute;
  right: 6px;
  bottom: 6px;
  padding: 2px 6px;
  border-radius: var(--r-xs);
  background: rgba(0, 0, 0, 0.65);
  color: #fff;
  font-family: var(--ab-mono);
  font-size: 11px;
  font-weight: 500;
}
.sl-card-text {
  padding: 10px;
  display: grid;
  gap: 3px;
}
.sl-card-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--ab-bone);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sl-card-sub {
  font-size: 12px;
  color: var(--ab-ink-mid);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Un rush qui n'a trouvé aucune prise : l'app le garde et le dit. */
.sl-card.unlinked .sl-card-sub {
  color: var(--ab-ink-mid);
  font-style: italic;
}

/* ---- Les échanges ----------------------------------------------------------
   La liste de l'onglet Fichiers. Une ligne par dépôt : le symbole que
   l'application choisit d'après l'extension, le nom, et surtout qui l'a
   déposé — c'est cette dernière colonne qui fait la différence avec un lien
   de transfert, où personne ne sait plus d'où vient quoi.
   -------------------------------------------------------------------------- */

.sl-files {
  flex: 1;
  min-height: 0;
  overflow: hidden auto;
  scrollbar-width: thin;
  padding: 14px 16px 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.sl-files-empty {
  flex: 1;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 8px;
  text-align: center;
  color: var(--ab-faint);
  padding: 24px;
}
.sl-files-empty b {
  font-size: 15px;
  font-weight: 600;
  color: var(--ab-ink-light);
}
.sl-files-empty i {
  font-style: normal;
  font-size: 12px;
  max-width: 26ch;
}
.sl-file {
  flex: none;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border-radius: var(--r-md);
  background: var(--ab-card);
  border: 1px solid var(--ab-hairline);
}
/* Le dépôt qui arrive se pose. Transformation et opacité seulement : la liste
   ne doit pas se réajuster sous les lignes déjà là. */
.sl-file.landed {
  animation: sl-file-in var(--ab-pop);
}
@keyframes sl-file-in {
  from {
    opacity: 0;
    transform: translateY(-16px) scale(0.9);
  }
}
.sl-file-ic {
  flex: none;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: var(--r-sm);
  background: var(--ab-accent-wash);
  color: var(--ab-accent);
}
.sl-file-main {
  flex: 1;
  min-width: 0;
  display: grid;
  gap: 2px;
}
.sl-file-main b {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ab-bone);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sl-file-main span {
  font-size: 11px;
  color: var(--ab-ink-mid);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sl-file-share {
  flex: none;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  color: var(--ab-ink-faint);
  background: var(--ab-glass);
  border: 1px solid var(--ab-glass-edge);
}

/* ---- Le lecteur ------------------------------------------------------------
   La zone image reste noire. Le site ne dispose d'aucun rush et n'en
   fabriquera pas : ce qu'il rejoue, c'est le transport et le timecode.
   -------------------------------------------------------------------------- */

.sl-player {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.sl-stage {
  aspect-ratio: 16 / 9;
  background: #000;
  position: relative;
  flex: none;
}
/* Le rush dans la fenêtre du lecteur. `contain` et non `cover` : un lecteur de
   post-production ne recadre jamais l'image qu'on lui confie. */
.sl-stage img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}
.sl-controls {
  padding: 14px 16px 16px;
  display: grid;
  gap: 13px;
}
.sl-tcbar {
  display: flex;
  align-items: center;
  gap: 14px;
}
.sl-tc {
  display: grid;
  gap: 3px;
  min-width: 0;
}
.sl-eyebrow {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 1.26px;
  text-transform: uppercase;
  color: var(--ab-ink-mid);
}
/* Le timecode est une donnée : SF Mono, comme dans l'app. */
.sl-tc b {
  font-family: var(--ab-mono);
  font-size: 27px;
  font-weight: 500;
  line-height: 1;
  color: var(--ab-bone);
  font-variant-numeric: tabular-nums;
}
.sl-tc-end {
  display: grid;
  gap: 3px;
  text-align: right;
}
.sl-fps {
  font-family: var(--ab-mono);
  font-size: 10px;
  font-weight: 600;
  color: var(--ab-accent);
}
.sl-tc-end span:last-child {
  font-family: var(--ab-mono);
  font-size: 11px;
  color: var(--ab-ink-mid);
}
.sl-round {
  width: 34px;
  height: 34px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--ab-hairline);
  color: var(--ab-bone);
  transition: background var(--ab-fast), transform var(--ab-fast);
}
.sl-round:hover {
  background: rgba(255, 255, 255, 0.06);
}
.sl-round:active {
  transform: scale(0.94);
}

.sl-timeline {
  display: grid;
  gap: 2px;
}
.sl-range {
  appearance: none;
  width: 100%;
  height: 20px;
  background: none;
  cursor: pointer;
  margin: 0;
}
.sl-range::-webkit-slider-runnable-track {
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(
    to right,
    var(--ab-accent) 0 var(--at, 0%),
    rgba(255, 255, 255, 0.18) var(--at, 0%) 100%
  );
}
.sl-range::-moz-range-track {
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(
    to right,
    var(--ab-accent) 0 var(--at, 0%),
    rgba(255, 255, 255, 0.18) var(--at, 0%) 100%
  );
}
.sl-range::-webkit-slider-thumb {
  appearance: none;
  width: 13px;
  height: 13px;
  margin-top: -5px;
  border-radius: 50%;
  background: var(--ab-bone);
}
.sl-range::-moz-range-thumb {
  width: 13px;
  height: 13px;
  border: 0;
  border-radius: 50%;
  background: var(--ab-bone);
}
.sl-range:focus-visible {
  outline: 2px solid var(--ab-accent);
  outline-offset: 4px;
  border-radius: 4px;
}
.sl-times {
  display: flex;
  justify-content: space-between;
  font-size: 9px;
  color: var(--ab-ink-mid);
}

.sl-transport {
  display: flex;
  align-items: center;
}
.sl-tbtn {
  flex: 1;
  min-height: 34px;
  display: grid;
  place-items: center;
  color: var(--ab-bone);
  transition: color var(--ab-fast), transform var(--ab-fast);
}
.sl-tbtn:active {
  transform: scale(0.9);
}
.sl-tbtn.sl-dim {
  color: var(--ab-ink-light);
}
.sl-skip {
  position: relative;
  display: grid;
  place-items: center;
}
.sl-skip i {
  position: absolute;
  font-size: 7px;
  font-style: normal;
  font-weight: 500;
  top: 51%;
  transform: translateY(-50%);
}
/* Le seul élément orange du transport : le point d'ancrage de l'œil. Cercle
   fin, pas de disque plein. */
/* Le bouton central est le seul élément coloré du transport, et il est plein :
   `AccentSurface(shape: Circle())`. L'ancien cercle au trait a disparu avec le
   rhabillage. */
.sl-play {
  flex: none;
  width: 46px;
  height: 46px;
  margin: 0 6px;
  border-radius: 50%;
  border: 0;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.26), transparent 50%),
    linear-gradient(180deg, var(--ab-accent), var(--ab-accent-dark));
  box-shadow: 0 6px 7px -4px rgba(34, 197, 94, 0.3);
  color: #fff;
}
.sl-toast {
  position: absolute;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  padding: 10px 16px;
  border-radius: 999px;
  background: rgba(22, 22, 26, 0.92);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--ab-hairline);
  font-size: 11px;
  font-weight: 500;
  color: var(--ab-bone);
  white-space: nowrap;
  animation: sl-toast-in 220ms var(--ab-ease);
  z-index: 8;
}
@keyframes sl-toast-in {
  from {
    opacity: 0;
    transform: translate(-50%, 8px);
  }
}

/* ---- Repli ------------------------------------------------------------------
   L'appareil se replie sur sa propre largeur. On ne rétrécit pas : on retire,
   dans l'ordre inverse de l'utilité. Ce qui reste — la prise en cours, le
   chronomètre, l'enregistrement — est ce que l'application a de plus important
   à faire.
   -------------------------------------------------------------------------- */

@container sl (max-width: 900px) {
  .sl-split-view {
    grid-template-columns: minmax(0, 1fr);
  }
  /* Le journal des prises passe au-dessus du formulaire, sur une hauteur
     bornée : on veut encore voir la ligne tomber. */
  .sl-takes {
    border-right: 0;
    border-bottom: 1px solid var(--ab-hairline);
    max-height: 208px;
  }
  .sl-headline-text b {
    font-size: 28px;
  }
}
@container sl (max-width: 620px) {
  .sl-headline {
    padding: 8px 14px 10px;
  }
  .sl-headline-text b {
    font-size: 24px;
  }
  .sl-headline-text i {
    font-size: 12px;
  }
  .sl-form,
  .sl-form-solo {
    padding: 12px;
    gap: 12px;
  }
  .sl-filters,
  .sl-grid {
    padding-inline: 12px;
  }
  .sl-band {
    margin-inline: 12px;
  }
  /* Le second rang du formulaire — optiques, WB, notes, navigation — est du
     contexte : à cette largeur il repousse le chronomètre hors de l'écran,
     et c'est lui le sujet. */
  .sl-optics {
    display: none;
  }
  .sl-takes {
    max-height: 168px;
  }
  .sl-tab b {
    display: none;
  }
  .sl-grid {
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  }
  .sl-tc b {
    font-size: 22px;
  }
  .sl-watch-time {
    font-size: 24px;
  }
}
@container sl (max-width: 420px) {
  .sl-row3 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .sl-take-end {
    display: none;
  }
}

/* ---- Mouvement réduit --------------------------------------------------------
   Les scènes se posent sur leur état final depuis le JavaScript ; ici on coupe
   ce qui tourne tout seul. Il reste une interface juste, simplement immobile.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .sl *,
  .sl *::before,
  .sl *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }
}
