/* LaBase Watch — feuille unique. Brutalisme lisible : la structure est visible,
   rien n'est décoratif. Aucune ombre, aucun dégradé, aucun arrondi, une seule
   épaisseur de trait. Voir §2 de SPEC.md. */

/* ---------------------------------------------------------------- 1. FONTES */

/* Archivo variable : un fichier couvre le texte (400 / wdth 100) et les titres (800 / wdth 125). */
@font-face {
  font-family: "Archivo";
  src: url("/assets/archivo-latin-591a8b69.woff2") format("woff2");
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Le supplément latin n'est téléchargé que si un titre étranger en a besoin. */
@font-face {
  font-family: "Archivo";
  src: url("/assets/archivo-latin-ext-a0aa4f2d.woff2") format("woff2");
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* JetBrains Mono : tout ce qui est un nombre, sans exception. */
@font-face {
  font-family: "JetBrains Mono";
  src: url("/assets/jetbrains-mono-latin-77c7bd91.woff2") format("woff2");
  font-weight: 100 800;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "JetBrains Mono";
  src: url("/assets/jetbrains-mono-latin-ext-a2d5a95c.woff2") format("woff2");
  font-weight: 100 800;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---------------------------------------------------------------- 2. TOKENS */

:root {
  --paper: #0A0A0A;   /* fond, partout */
  --ink: #EDEDED;     /* texte, et tout trait qui borne un objet */
  --line: #333333;    /* trait partagé entre deux cellules, jamais porteur de sens */
  --grey: #808080;    /* métadonnées secondaires uniquement */
  --seen: #2F52F0;    /* bleu tampon : état "vu" */
  --queue: #FFD400;   /* jaune ticket : état "à voir" */
  --rule: 2px;        /* épaisseur unique de tous les traits de l'application */

  --sans: "Archivo", system-ui, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, monospace;

  --step: 0.75rem;    /* pas d'espacement ; tout écart en est un multiple */
  --measure: 65ch;    /* largeur de lecture maximale du texte courant */
}

/* ------------------------------------------------- 3. RÉINITIALISATION */

*, *::before, *::after { box-sizing: border-box; }

body, h1, h2, h3, p, figure, dl, dd, ul, ol {
  margin: 0;
  padding: 0;
}

ul, ol { list-style: none; }

img {
  display: block;
  max-width: 100%;
}

/* Aucun contrôle n'hérite d'un style de système : tout est redéclaré ici. */
input, button, select {
  font: inherit;
  color: inherit;
  background: none;
  border: none;
}

/* Un contrôle masqué à l'œil mais gardé au clavier. La position relative du
   label n'est pas cosmétique : sans elle, l'entrée absolue s'échappe vers le bloc
   conteneur initial. Mesuré à 375px, elle s'y étalait sur 500px et recouvrait la
   liste de tri, volant les touchers destinés au voisin — inoffensif à la souris,
   erratique au doigt. */
.mode,
.scale-box {
  position: relative;
}

.mode input,
.scale-box input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ------------------------------------------------------ 4. TYPOGRAPHIE */

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.5;
  -webkit-text-size-adjust: 100%;
}

/* Le rôle titre : Archivo étendu, gras, capitales, interlettrage serré. */
h1, h2, h3, .wordmark, .cell-title {
  font-family: var(--sans);
  font-weight: 800;
  font-stretch: 125%;
  text-transform: uppercase;
  letter-spacing: -0.02em;
  line-height: 1.05;
}

h1 { font-size: clamp(1.75rem, 6vw, 2.75rem); }
h2 { font-size: 1.25rem; }

p { max-width: var(--measure); }

/* La règle qui porte l'identité : tout nombre est en monospace. */
.data, time, .metadata, .count {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

.secondary { color: var(--grey); }

a {
  color: inherit;
  text-decoration-thickness: var(--rule);
  text-underline-offset: 0.2em;
}

/* --------------------------------------------------- 5. FOCUS CLAVIER */

/* Le contour de focus n'est jamais retiré. Le bleu tient 3,4:1 sur le fond, seuil
   des éléments non textuels. */
:focus-visible {
  outline: var(--rule) solid var(--seen);
  outline-offset: var(--rule);
}

/* Passer au contenu sans traverser la navigation, au clavier seul. */
.skip-link {
  position: absolute;
  left: -100vw;
}

.skip-link:focus-visible {
  position: static;
  display: inline-block;
  padding: var(--step);
}

/* ----------------------------------------------------- 6. MISE EN PAGE */

.page {
  max-width: 1200px;
  margin: 0 auto;
  padding: calc(var(--step) * 2) var(--step) calc(var(--step) * 4);
}

/* Le trait sous l'en-tête borne l'application entière : il est en --ink. */
.masthead {
  border-bottom: var(--rule) solid var(--ink);
}

.masthead-inner {
  max-width: 1200px;
  margin: 0 auto;
  padding: var(--step);
  display: flex;
  flex-wrap: wrap;
  gap: var(--step);
  align-items: baseline;
  justify-content: space-between;
}

.wordmark {
  font-size: 1.5rem;
  text-decoration: none;
}

.nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  font-family: var(--mono);
  font-size: 0.8125rem;
}

.nav a {
  text-decoration: none;
  padding: 0 calc(var(--step) * 1.25);
}

.nav a:first-child { padding-left: 0; }
.nav a:last-child { padding-right: 0; }

/* Le séparateur est le même filet que partout ailleurs, pas un caractère : les
   libellés restent en minuscules, comme le veut le ton du §2. */
.nav a + a { border-left: var(--rule) solid var(--line); }

/* L'onglet courant se signale par un trait, pas par une couleur d'accent. */
.nav a[aria-current="page"] {
  text-decoration: underline;
  text-decoration-thickness: var(--rule);
}

/* ------------------------------------------------------- 7. RECHERCHE */

.search { margin-bottom: calc(var(--step) * 2); }

/* Le mode et le tri sous le champ : on cherche un titre ou un réalisateur,
   jamais les deux à la fois. */
.search-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--step);
  margin-top: var(--step);
}

/* Deux boutons radio déguisés : le formulaire porte l'état, le navigateur gère
   le clavier, et rien ne peut diverger de ce qui est affiché. */
.modes {
  border: none;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: calc(var(--step) * 0.5);
  align-items: center;
}

.modes legend {
  font-family: var(--mono);
  font-size: 0.6875rem;
  text-transform: uppercase;
  color: var(--grey);
  margin-bottom: calc(var(--step) * 0.25);
}

.mode span {
  display: inline-block;
  border: var(--rule) solid var(--line);
  padding: calc(var(--step) * 0.5) var(--step);
  font-family: var(--mono);
  font-size: 0.8125rem;
  color: var(--grey);
  cursor: pointer;
}

.mode input:checked + span {
  border-color: var(--ink);
  color: var(--ink);
}

.mode input:focus-visible + span {
  outline: var(--rule) solid var(--seen);
  outline-offset: var(--rule);
}

.people {
  display: flex;
  flex-wrap: wrap;
  gap: var(--step);
  margin-bottom: calc(var(--step) * 1.5);
}

.person-choice {
  font-family: var(--mono);
  font-size: 0.8125rem;
  border: var(--rule) solid var(--line);
  padding: calc(var(--step) * 0.5) var(--step);
  text-decoration: none;
  color: var(--grey);
}

.person-choice[aria-current="page"] {
  border-color: var(--ink);
  color: var(--ink);
}

.count {
  display: block;
  margin-bottom: var(--step);
  font-family: var(--mono);
  font-size: 0.8125rem;
  color: var(--grey);
}

/* Le cadre est porté par le champ lui-même : le contour de focus s'y applique
   sans avoir à être déplacé sur un conteneur. */
.search input {
  width: 100%;
  border: var(--rule) solid var(--ink);
  padding: var(--step);
}

.search input::placeholder { color: var(--grey); }

/* La croix d'effacement de WebKit est une icône que cette interface n'a pas dessinée. */
.search input::-webkit-search-cancel-button { display: none; }

/* Deux planches quand la recherche reconnaît un réalisateur : ses films d'abord,
   les titres correspondants ensuite. */
.results-group + .results-group { margin-top: calc(var(--step) * 3); }

.results-title {
  font-size: 0.875rem;
  color: var(--grey);
  margin-bottom: var(--step);
}

/* ------------------------------------------- 8. PLANCHE-CONTACT (GRILLE) */

/* Chaque cellule ne dessine que son filet droit et son filet bas ; le conteneur
   ferme en haut et à gauche. Deux cellules voisines ne doublent donc jamais leur
   trait, et une dernière rangée incomplète ne laisse voir aucun fond de grille.
   minmax(0, 1fr) et non 1fr : le titre tronqué ne se replie pas, sa largeur
   minimale imposerait sinon des colonnes inégales et une grille qui déborde. */
.sheet {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  border-top: var(--rule) solid var(--line);
  border-left: var(--rule) solid var(--line);
}

/* min-width: 0 sur toute la chaîne : sans lui, la largeur minimale du titre non
   replié déborde de sa colonne au lieu d'être tronquée. */
.cell {
  min-width: 0;
  background: var(--paper);
  display: flex;
  flex-direction: column;
  border-right: var(--rule) solid var(--line);
  border-bottom: var(--rule) solid var(--line);
}

.cell-link {
  min-width: 0;
  display: flex;
  flex-direction: column;
  text-decoration: none;
}

.cell-poster {
  aspect-ratio: 2 / 3;
  width: 100%;
  object-fit: cover;
  background: var(--paper);
}

/* Affiche manquante : un cadre vide plutôt qu'une image cassée. */
.cell-poster--absent {
  display: grid;
  place-items: center;
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--grey);
  border-bottom: var(--rule) solid var(--line);
}

/* Un titre tronqué à une ligne garde les bandes de légende alignées d'une colonne à l'autre. */
.cell-caption {
  min-width: 0;
  padding: calc(var(--step) * 0.75);
  border-top: var(--rule) solid var(--line);
}

.cell-title {
  display: block;
  font-size: 0.8125rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Année en recherche, date de visionnage sur la page films : même emplacement. */
.cell-meta {
  display: block;
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--grey);
}

/* Les deux bascules se partagent la largeur de la cellule, séparées par le même
   filet que la grille. */
.cell-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--rule);
  background: var(--line);
  border-top: var(--rule) solid var(--line);
  margin-top: auto;
}

/* --------------------------------------------------------- 9. FICHE ŒUVRE */

/* Fiche cartonnée de catalogue : métadonnées à gauche, affiche posée à droite. */
.record {
  display: grid;
  grid-template-columns: 1fr 300px;
  gap: calc(var(--step) * 2);
  align-items: start;
}

.record-title {
  border-bottom: var(--rule) solid var(--ink);
  padding-bottom: var(--step);
  margin-bottom: var(--step);
}

.record-original {
  font-family: var(--mono);
  font-size: 0.8125rem;
  color: var(--grey);
  margin-top: calc(var(--step) * 0.5);
}

/* Le bloc de métadonnées est intégralement en monospace, libellés compris. */
.metadata {
  display: grid;
  grid-template-columns: 7rem 1fr;
  gap: calc(var(--step) * 0.5) var(--step);
  font-size: 0.875rem;
}

.metadata dt {
  color: var(--grey);
  text-transform: uppercase;
}

.metadata dd { margin: 0; }

/* L'affiche est posée sans habillage : son cadre borne l'objet, il est en --ink. */
.record-poster {
  width: 100%;
  border: var(--rule) solid var(--ink);
}

.record-synopsis {
  grid-column: 1 / -1;
  border-top: var(--rule) solid var(--line);
  padding-top: calc(var(--step) * 1.5);
}

/* -------------------------------------------- 9 bis. SUIVI PERSONNEL */

/* Une bascule éteinte n'est qu'un mot ; allumée, elle est un aplat plein. C'est
   le remplissage, pas l'étiquette, qui signale l'état de loin. */
.toggle {
  display: block;
  width: 100%;
  padding: calc(var(--step) * 0.5);
  background: var(--paper);
  font-family: var(--mono);
  font-size: 0.75rem;
  text-transform: uppercase;
  color: var(--grey);
  cursor: pointer;
}

.toggle:hover { color: var(--ink); }

.toggle--seen {
  background: var(--seen);
  color: var(--ink);
}

.toggle--queue {
  background: var(--queue);
  color: var(--paper);
}

.toggle:disabled {
  color: var(--line);
  cursor: default;
}

/* button_to produit un formulaire par bouton : il ne doit pas casser les lignes. */
.inline-form { display: inline; }

.record-personal {
  grid-column: 1 / -1;
  border-top: var(--rule) solid var(--line);
  padding-top: calc(var(--step) * 1.5);
}

.action-row {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: var(--step);
}

.action-row .inline-form,
.action-row form {
  display: flex;
  gap: var(--step);
}

.action-row .toggle {
  width: auto;
  padding: calc(var(--step) * 0.5) var(--step);
  border: var(--rule) solid var(--ink);
  color: var(--ink);
}

.date-field {
  border: var(--rule) solid var(--ink);
  padding: calc(var(--step) * 0.5) var(--step);
  font-family: var(--mono);
  font-size: 0.875rem;
}

/* Le sélecteur natif est dessiné en sombre : invisible sur ce fond sans inversion. */
.date-field::-webkit-calendar-picker-indicator {
  filter: invert(1);
  cursor: pointer;
}

.watch-log {
  margin-top: calc(var(--step) * 1.5);
  display: flex;
  flex-direction: column;
  gap: calc(var(--step) * 0.5);
  align-items: flex-start;
}

.watch-log li {
  display: flex;
  align-items: center;
  gap: var(--step);
}

/* Dix cases carrées bordées, jamais d'étoiles. Le bouton radio reste focusable :
   il est masqué visuellement, pas retiré de l'ordre de tabulation. */
.rating { margin-top: calc(var(--step) * 2); }

.scale {
  border: none;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--rule);
}

.scale legend {
  font-family: var(--mono);
  font-size: 0.75rem;
  text-transform: uppercase;
  color: var(--grey);
  margin-bottom: calc(var(--step) * 0.5);
}

.scale-box span {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border: var(--rule) solid var(--ink);
  font-family: var(--mono);
  font-size: 0.875rem;
  cursor: pointer;
}

.scale-box input:checked + span {
  background: var(--seen);
  color: var(--ink);
}

.scale-box input:focus-visible + span {
  outline: var(--rule) solid var(--seen);
  outline-offset: var(--rule);
}

/* Le commentaire est facultatif : replié tant qu'il est vide. */
.review {
  margin-top: calc(var(--step) * 1.5);
  font-family: var(--mono);
  font-size: 0.875rem;
}

.review summary {
  cursor: pointer;
  text-transform: uppercase;
  color: var(--grey);
}

.review textarea {
  display: block;
  width: 100%;
  max-width: var(--measure);
  margin: var(--step) 0;
  border: var(--rule) solid var(--ink);
  padding: var(--step);
  font-family: var(--mono);
  font-size: 0.875rem;
  background: var(--paper);
  color: var(--ink);
}

/* La file : un rang, un titre, des commandes. Pas de glisser-déposer. */
.queue {
  border: var(--rule) solid var(--line);
  counter-reset: rank;
}

.queue-row {
  display: flex;
  align-items: center;
  gap: var(--step);
  padding: var(--step);
  border-bottom: var(--rule) solid var(--line);
}

.queue-row:last-child { border-bottom: none; }

.queue-rank,
.queue-year {
  font-family: var(--mono);
  font-size: 0.875rem;
  color: var(--grey);
}

.queue-rank { min-width: 2ch; }

.queue-title {
  flex: 1;
  min-width: 0;
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Espacement franc entre les commandes : au doigt, deux boutons collés se
   confondent, et « retirer » n'est pas une action qu'on déclenche par erreur. */
.queue-controls {
  display: flex;
  gap: calc(var(--step) * 1.5);
}

.queue-controls .toggle {
  width: auto;
  min-width: 2.75rem;
  padding: calc(var(--step) * 0.5) var(--step);
  border: var(--rule) solid var(--line);
}

.queue-score {
  font-family: var(--mono);
  font-size: 0.875rem;
  padding: 0 calc(var(--step) * 0.5);
  background: var(--seen);
  color: var(--ink);
}

.queue-score:empty { display: none; }

/* --------------------------------------------------------- 9 ter. FILTRES */

.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--step);
}

.views {
  display: flex;
  gap: var(--step);
  font-family: var(--mono);
  font-size: 0.8125rem;
}

.views a { text-decoration: none; }

.views a[aria-current="page"] {
  text-decoration: underline;
  text-decoration-thickness: var(--rule);
}

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--step);
  align-items: flex-end;
  margin: calc(var(--step) * 2) 0;
  padding-bottom: calc(var(--step) * 2);
  border-bottom: var(--rule) solid var(--line);
}

.filter {
  display: flex;
  flex-direction: column;
  gap: calc(var(--step) * 0.25);
}

.filter-label {
  display: block;
  font-family: var(--mono);
  font-size: 0.6875rem;
  text-transform: uppercase;
  color: var(--grey);
  cursor: pointer;
}

/* Le chevron natif du select est dessiné par le système : on le remplace par
   rien et on garde le cadre, comme tout autre contrôle de cette interface. */
/* Largeur bornée : sans cela un nom de réalisateur étire sa liste sur le triple
   des autres et la barre part en dents de scie. */
.filter select {
  appearance: none;
  width: 9rem;
  border: var(--rule) solid var(--ink);
  padding: calc(var(--step) * 0.5) var(--step);
  font-family: var(--mono);
  font-size: 0.8125rem;
  background: var(--paper);
  color: var(--ink);
  cursor: pointer;
  text-overflow: ellipsis;
}

.filter select:disabled {
  border-color: var(--line);
  color: var(--line);
  cursor: default;
}

.filters-reset {
  font-family: var(--mono);
  font-size: 0.8125rem;
  padding-bottom: calc(var(--step) * 0.5);
}

/* Les faits à gauche, la note à droite. Année et durée se lisent d'un bloc. */
.cell-line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--step) * 0.5);
}

.cell-facts {
  display: flex;
  min-width: 0;
  gap: calc(var(--step) * 0.75);
}

/* Le tiret sépare l'année de la durée. Il est porté par le CSS parce qu'il ne
   dit rien : c'est de la ponctuation, elle n'existe que si la durée existe. */
.cell-runtime {
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--grey);
  white-space: nowrap;
}

.cell-runtime::before {
  content: "— ";
}

.queue-runtime {
  font-family: var(--mono);
  font-size: 0.875rem;
  color: var(--grey);
  white-space: nowrap;
}

.cell-score {
  font-family: var(--mono);
  font-size: 0.75rem;
  padding: 0 calc(var(--step) * 0.5);
  background: var(--seen);
  color: var(--ink);
}

/* ------------------------------------------- 9 quater. SÉRIES ET ÉPISODES */

.series {
  grid-column: 1 / -1;
  margin-top: calc(var(--step) * 2);
  border-top: var(--rule) solid var(--line);
  padding-top: calc(var(--step) * 2);
}

/* Un bloc plein dans un cadre, sans arrondi. La largeur est la seule valeur que
   le serveur calcule ; elle passe par une propriété custom, jamais par un style
   de largeur écrit à la main dans la vue. */
.progress {
  height: 1rem;
  border: var(--rule) solid var(--ink);
}

.progress-fill {
  width: var(--fill, 0%);
  height: 100%;
  background: var(--seen);
}

.series-state {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--step);
  max-width: none;
  margin-top: var(--step);
  font-family: var(--mono);
  font-size: 0.875rem;
}

.series-label {
  text-transform: uppercase;
  color: var(--grey);
}

.series-count {
  margin-left: auto;
  color: var(--grey);
}

.season {
  border-bottom: var(--rule) solid var(--line);
}

.season:first-of-type {
  border-top: var(--rule) solid var(--line);
  margin-top: calc(var(--step) * 2);
}

/* Le triangle natif est remplacé par un signe en monospace : du texte, pas une
   icône, et l'affordance reste lisible sur une ligne fermée. */
.season-summary::before {
  content: "+";
  font-family: var(--mono);
  color: var(--grey);
  margin-right: var(--step);
}

.season[open] > .season-summary::before { content: "\2013"; }

.season-summary {
  display: flex;
  align-items: baseline;
  gap: var(--step);
  padding: var(--step);
  font-family: var(--mono);
  font-size: 0.9375rem;
  text-transform: uppercase;
  cursor: pointer;
  list-style: none;
}

.season-summary::-webkit-details-marker { display: none; }

/* Le compteur est poussé à droite plutôt que d'espacer trois éléments : la puce
   ::before est elle-même un élément flex et déporterait le nom au centre. */
.season-count {
  margin-left: auto;
  color: var(--grey);
}

.season-body {
  padding: 0 var(--step) var(--step);
}

.season-action {
  width: auto;
  margin-bottom: var(--step);
  padding: calc(var(--step) * 0.5) var(--step);
  border: var(--rule) solid var(--line);
}

.episode {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--step);
  padding: calc(var(--step) * 0.5) 0;
  border-top: var(--rule) solid var(--line);
  font-size: 0.875rem;
}

.episode-code,
.episode-date,
.episode-runtime {
  font-family: var(--mono);
  font-size: 0.8125rem;
  color: var(--grey);
  white-space: nowrap;
}

/* L'épisode vu se marque par son code en aplat, pas par une coche. */
.is-seen .episode-code {
  background: var(--seen);
  color: var(--ink);
  padding: 0 calc(var(--step) * 0.5);
}

.episode-title {
  flex: 1;
  min-width: 8rem;
}

.is-future .episode-title { color: var(--grey); }

.episode-pending {
  font-family: var(--mono);
  font-size: 0.75rem;
  text-transform: uppercase;
  color: var(--line);
}

.episode-actions {
  display: flex;
  gap: calc(var(--step) * 0.75);
  margin-left: auto;
}

.episode-actions .toggle {
  width: auto;
  padding: calc(var(--step) * 0.25) calc(var(--step) * 0.75);
  border: var(--rule) solid var(--line);
}

.episode-next {
  display: inline-flex;
  gap: calc(var(--step) * 0.5);
}

/* Le bandeau d'accueil : ce qu'on reprend, avant même de chercher. */
.resume {
  border: var(--rule) solid var(--line);
  padding: var(--step);
  margin-bottom: calc(var(--step) * 2);
}

.resume-title {
  font-size: 0.875rem;
  color: var(--grey);
  margin-bottom: var(--step);
}

.resume-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--step);
  padding: calc(var(--step) * 0.5) 0;
}

.resume-work { font-weight: 600; }

.resume-episode {
  flex: 1;
  min-width: 8rem;
  color: var(--grey);
}

.resume-count {
  font-family: var(--mono);
  font-size: 0.8125rem;
  color: var(--grey);
}

/* --------------------------------------------- 9 quater bis. DISTRIBUTION */

.credits {
  grid-column: 1 / -1;
  margin-top: calc(var(--step) * 2);
  border-top: var(--rule) solid var(--line);
  padding-top: calc(var(--step) * 1.5);
}

.credits-title {
  font-size: 0.875rem;
  color: var(--grey);
  margin-bottom: var(--step);
}

.credits-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(22rem, 1fr));
  gap: calc(var(--step) * 0.25) calc(var(--step) * 2);
  font-family: var(--mono);
  font-size: 0.875rem;
}

.credit {
  display: flex;
  gap: var(--step);
  justify-content: space-between;
  min-width: 0;
}

.credit-name,
.credit-role {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Le personnage cède la place avant le nom : c'est le nom qu'on cherche. */
.credit-name { flex: 0 1 auto; }

.credit-role {
  flex: 1 4 auto;
  color: var(--grey);
  text-align: right;
}

/* ------------------------------------------ 9 quinquies. DISPONIBILITÉ */

.availability {
  grid-column: 1 / -1;
  margin-top: calc(var(--step) * 2);
  border-top: var(--rule) solid var(--line);
  padding-top: calc(var(--step) * 1.5);
}

.availability-title {
  font-size: 0.875rem;
  color: var(--grey);
  margin-bottom: var(--step);
}

.offer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--step);
  padding: calc(var(--step) * 0.5) 0;
}

/* Abonnement, location, achat se distinguent par un libellé, pas par une couleur :
   les deux accents ne disent que « vu » et « à voir ». */
.offer-label {
  min-width: 9rem;
  font-family: var(--mono);
  font-size: 0.75rem;
  text-transform: uppercase;
  color: var(--grey);
}

.provider-row {
  display: flex;
  flex-wrap: wrap;
  gap: calc(var(--step) * 0.5);
}

/* Hauteur fixe de 24px et trait de 2px, comme le §ÉTAPE 6 l'impose. */
.provider-logo {
  height: 24px;
  width: auto;
  border: var(--rule) solid var(--ink);
}

.provider-logo--absent {
  display: inline-flex;
  align-items: center;
  padding: 0 calc(var(--step) * 0.5);
  font-family: var(--mono);
  font-size: 0.6875rem;
  color: var(--grey);
}

/* Ce qu'on possède se lit sur la même ligne que les offres, en jaune parce que
   c'est de l'attente qui n'attend plus qu'un soir libre. */
.holdings {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--step);
  padding: calc(var(--step) * 0.5) 0;
  border-top: var(--rule) solid var(--line);
  margin-top: var(--step);
}

.holdings .toggle {
  width: auto;
  padding: calc(var(--step) * 0.5) var(--step);
  border: var(--rule) solid var(--line);
}

/* L'attribution JustWatch accompagne chaque affichage de ces données. */
.attribution {
  margin-top: calc(var(--step) * 1.5);
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--grey);
}

/* Le seul usage du jaune hors bascule : un titre de la file regardable sans
   payer un service de plus. */
.cell-flag {
  font-family: var(--mono);
  font-size: 0.6875rem;
  text-transform: uppercase;
  padding: 0 calc(var(--step) * 0.5);
  background: var(--queue);
  color: var(--paper);
  white-space: nowrap;
}

.provider-group { margin-top: calc(var(--step) * 3); }

.provider-group h2 {
  font-size: 0.875rem;
  color: var(--grey);
}

.provider-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--step);
  margin: calc(var(--step) * 2) 0;
}

.provider-choice label {
  display: flex;
  align-items: center;
  gap: calc(var(--step) * 0.75);
  border: var(--rule) solid var(--line);
  padding: calc(var(--step) * 0.75);
  cursor: pointer;
}

.provider-choice input:checked ~ .provider-name { color: var(--ink); }

.provider-choice label:has(input:checked) {
  border-color: var(--ink);
}

.provider-name {
  font-family: var(--mono);
  font-size: 0.8125rem;
  color: var(--grey);
}

/* ------------------------------------------ 9 sexies. STATISTIQUES */

/* Aucune librairie de graphiques : des blocs pleins et une grille, rien d'autre. */
.tallies {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  border-top: var(--rule) solid var(--line);
  border-left: var(--rule) solid var(--line);
  margin: calc(var(--step) * 2) 0;
}

.tally {
  display: flex;
  flex-direction: column;
  gap: calc(var(--step) * 0.25);
  padding: var(--step);
  border-right: var(--rule) solid var(--line);
  border-bottom: var(--rule) solid var(--line);
}

.tally-label {
  font-family: var(--mono);
  font-size: 0.6875rem;
  text-transform: uppercase;
  color: var(--grey);
}

.tally-value {
  font-family: var(--mono);
  font-size: clamp(1.5rem, 5vw, 2.25rem);
  font-variant-numeric: tabular-nums;
}

.tally-total {
  font-family: var(--mono);
  font-size: 0.875rem;
  color: var(--grey);
}

.tally-total::before { content: "total "; }

.calendar-block { margin: calc(var(--step) * 3) 0; }

/* Cases de 12px, une par jour de l'année, bissextile comprise. */
.calendar {
  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(7, 12px);
  gap: var(--rule);
  margin-top: var(--step);
  overflow-x: auto;
  padding-bottom: var(--step);
}

/* Aucune bordure : une case de 12px cerclée de 2px ne serait plus que du trait.
   Le jour vide est un aplat --line, les gouttières font la grille. */
.day {
  width: 12px;
  height: 12px;
  background: var(--line);
}

/* Trois paliers, jamais un dégradé. */
.day--1 { background: color-mix(in srgb, var(--seen) 35%, var(--line)); }
.day--2 { background: color-mix(in srgb, var(--seen) 65%, var(--line)); }
.day--3 { background: var(--seen); }

.breakdowns {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
  gap: calc(var(--step) * 3);
}

.breakdown h2 {
  font-size: 0.875rem;
  color: var(--grey);
  margin-bottom: var(--step);
}

.bar-row {
  display: flex;
  align-items: center;
  gap: var(--step);
  padding: calc(var(--step) * 0.25) 0;
  font-size: 0.875rem;
}

.bar-label {
  flex: 0 0 8rem;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bar {
  flex: 1;
  height: 0.75rem;
  border: var(--rule) solid var(--line);
}

.bar-fill {
  display: block;
  width: var(--fill, 0%);
  height: 100%;
  background: var(--seen);
}

.bar-count {
  font-family: var(--mono);
  font-size: 0.8125rem;
  color: var(--grey);
  min-width: 2.5ch;
  text-align: right;
}

/* ------------------------------------------------------- 10. ÉTATS */

/* Tampon d'archive : bloc plein, jamais un contour, jamais une icône. */
.stamp {
  display: inline-block;
  padding: calc(var(--step) * 0.5) var(--step);
  font-family: var(--mono);
  font-size: 0.875rem;
  text-transform: uppercase;
}

.stamp--seen {
  background: var(--seen);
  color: var(--ink);
}

/* Le jaune ne passe jamais en texte sur le fond : il n'y tient que 1,4:1. */
.stamp--queue {
  background: var(--queue);
  color: var(--paper);
}

/* Un état vide est une invitation, pas un constat. C'est un bloc, pas du texte
   courant : il ne se limite pas à la largeur de lecture. */
.empty {
  max-width: none;
  border: var(--rule) solid var(--line);
  padding: calc(var(--step) * 2);
  color: var(--grey);
}

/* ------------------------------------------------------ 11. CONTRÔLES */

.button {
  display: inline-block;
  border: var(--rule) solid var(--ink);
  padding: calc(var(--step) * 0.5) var(--step);
  font-family: var(--mono);
  font-size: 0.875rem;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
}

/* Changement d'état instantané, aucune transition : voir le plancher du §2. */
.button:hover {
  background: var(--ink);
  color: var(--paper);
}

/* -------------------------------------------------------- 12. CONNEXION */

.gate {
  max-width: 22rem;
  margin: calc(var(--step) * 6) auto;
  padding: 0 var(--step);
}

.gate input {
  width: 100%;
  border: var(--rule) solid var(--ink);
  padding: var(--step);
  margin: var(--step) 0;
}

.gate .button { width: 100%; }

.gate-aside {
  margin-top: calc(var(--step) * 2);
  font-family: var(--mono);
  font-size: 0.8125rem;
  color: var(--grey);
}

/* L'erreur dit ce qui ne va pas, sans s'excuser. Elle se marque par un trait et
   par le monospace, jamais par un accent : le bleu et le jaune ne disent que
   « vu » et « à voir ». */
.error {
  font-family: var(--mono);
  font-size: 0.875rem;
  border-left: var(--rule) solid var(--ink);
  padding-left: var(--step);
}

/* ---------------------------------------------------------- 13. À PROPOS */

.about h2 {
  margin-top: calc(var(--step) * 3);
  margin-bottom: var(--step);
}

/* Le logo TMDB est une obligation contractuelle, pas une image décorative. */
.attribution-logo {
  height: 24px;
  width: auto;
  margin: var(--step) 0;
}

/* --------------------------------------------------------- 14. ADAPTATIONS */

/* Trois colonnes en tablette, deux en mobile ; l'affiche garde son ratio 2:3. */
@media (max-width: 900px) {
  .sheet { grid-template-columns: repeat(3, 1fr); }

  .record {
    grid-template-columns: 1fr;
  }

  /* Sur une colonne, l'affiche passe en tête : elle identifie l'œuvre avant même
     qu'on lise le titre, et les métadonnées restent groupées avec lui. */
  .record-poster {
    order: -1;
    max-width: 260px;
  }
}

@media (max-width: 560px) {
  :root { --step: 0.625rem; }

  .sheet { grid-template-columns: repeat(2, 1fr); }

  .masthead-inner { align-items: flex-start; }

  .metadata { grid-template-columns: 5.5rem 1fr; }
}

/* Rien ne bouge dans cette interface ; la règle vaut pour ce qui viendrait s'y ajouter. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
