:root {
  color-scheme: light dark;
  --bg: #f4f6f8;
  --fg: #1a222c;
  --card-bg: #ffffff;
  --accent: #2563eb;
  --accent-fg: #ffffff;
  --muted: #5b6774;
  --border: #d7dde3;
  --warn-bg: #fff7e6;
  --warn-border: #f0c36d;
}

@font-face {
  font-family: "Optician Sans";
  src:
    url("fonts/Optician-Sans.woff2") format("woff2"),
    url("assets/Optician-Sans.otf") format("opentype");
  font-display: block;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #12161b;
    --fg: #e8edf2;
    --card-bg: #1c232b;
    --accent: #3b82f6;
    --accent-fg: #ffffff;
    --muted: #98a4b0;
    --border: #313b46;
    --warn-bg: #2b2413;
    --warn-border: #8a6d2f;
  }
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-size: 18px;
  line-height: 1.65;
  /* évite un scroll horizontal parasite à cause des éléments plein-bord (100vw) */
  overflow-x: hidden;
}

.step { display: none; padding: 2rem 1.25rem 3.5rem; }
.step.active { display: block; }

#step-intro {
  position: relative;
  min-height: 100vh;
  overflow: hidden;
}
#step-intro .intro-bg {
  position: fixed;
  inset: 0;
  pointer-events: none;
}

#step-intro .intro-bg::before,
#step-intro .intro-bg::after {
  content: "";
  position: absolute;
  top: 50%;
  display: none;
  width: max(180px, calc((100vw - 860px) / 2));
  height: 100vh;
  background-image: url("assets/snellen-chart-site2.svg");
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  opacity: 0.5;
  transform: translateY(-50%);
}

#step-intro .intro-bg::before {
  left: 0;
}

#step-intro .intro-bg::after {
  right: 0;
}

@media (min-width: 1120px) {
  #step-intro .intro-bg::before,
  #step-intro .intro-bg::after {
    display: block;
  }
}

#step-intro .card {
  position: relative;
  background: color-mix(in srgb, var(--card-bg) 88%, transparent);
  border-color: color-mix(in srgb, var(--border) 70%, transparent);
  box-shadow: 0 18px 44px rgba(25, 34, 44, 0.12);
  backdrop-filter: blur(8px);
}

@media (prefers-color-scheme: dark) {
  #step-intro .card {
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.32);
  }
}

.card {
  max-width: 760px;
  margin: 0 auto 1.5rem;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 2rem 2.25rem;
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.07);
}

h1 { font-size: 2rem; margin-top: 0; line-height: 1.2; letter-spacing: -0.015em; }
h2 { font-size: 1.55rem; margin-top: 0; line-height: 1.25; letter-spacing: -0.012em; }

a { color: var(--accent); text-underline-offset: 2px; }
a:hover { text-decoration-thickness: 2px; }

input { accent-color: var(--accent); }

/* Fine barre de progression du parcours, en haut de page (remplie par show()) */
#flow-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  z-index: 20;
  pointer-events: none;
}
#flow-progress span {
  display: block;
  height: 100%;
  width: 0;
  background: var(--accent);
  border-radius: 0 2px 2px 0;
  transition: width 0.35s ease;
}
body.bs-dimmed #flow-progress { display: none; }

.lead { font-size: 1.18rem; }
.hint { color: var(--muted); font-size: 1rem; }

.steps-list li { margin-bottom: 0.55rem; }

.warning {
  background: var(--warn-bg);
  border: 1px solid var(--warn-border);
  border-radius: 8px;
  padding: 1rem 1.15rem;
  font-size: 1rem;
  margin: 1.15rem 0;
}

.btn {
  font: inherit;
  border: 1px solid var(--border);
  background: var(--card-bg);
  color: var(--fg);
  border-radius: 8px;
  padding: 0.8rem 1.35rem;
  cursor: pointer;
  transition: filter 0.1s, transform 0.12s ease, box-shadow 0.12s ease;
}
.btn:hover { filter: brightness(0.95); }
.btn:hover:not(:disabled) { transform: translateY(-1px); }
.btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.btn:disabled {
  cursor: not-allowed;
  opacity: 0.55;
}
.btn:disabled:hover { filter: none; transform: none; }
.btn.primary {
  background: var(--accent);
  color: var(--accent-fg);
  border-color: var(--accent);
  font-weight: 600;
  box-shadow: 0 2px 10px color-mix(in srgb, var(--accent) 30%, transparent);
}
/* Boutons principaux du parcours : pleine largeur, bien visibles — un seul
   geste évident par écran. */
#btn-start, #btn-calibrated, #btn-mode-next, #btn-manual-distance-next,
#btn-first-pass, #btn-second-pass, #btn-start-eye-test, #btn-restart {
  display: block;
  width: 100%;
  margin-top: 1.4rem;
  padding: 0.95rem 1.35rem;
  font-size: 1.08rem;
}

@media (prefers-reduced-motion: reduce) {
  .btn:hover:not(:disabled) { transform: none; }
  #flow-progress span { transition: none; }
}
.btn.small { padding: 0.5rem 0.9rem; font-size: 1rem; }
.btn.ghost { border-style: dashed; color: var(--muted); }
/* --- Calibration --- */
#card-zone {
  display: flex;
  /* Coin supérieur gauche ancré : on pose la carte une seule fois, puis on
     ajuste la taille sans avoir à la redéplacer à chaque changement. Même
     max-width/padding gauche que .card, pour que ce coin tombe exactement
     sous le bord gauche du texte des encadrés blancs au-dessus/en dessous. */
  justify-content: flex-start;
  align-items: flex-start;
  min-height: 40vh;
  max-width: 760px;
  margin: 0 auto;
  padding: 1rem 2.25rem;
  box-sizing: border-box;
}

#credit-card {
  /* ratio ISO ID-1 : 85.60 x 53.98 mm — hauteur fixée en JS */
  --mark-size: 38px;
  --mark-line: 2px;
  --mark-gap: 4px;
  background: linear-gradient(135deg, #3f5efb, #1e3a8a);
  border-radius: 4.5% / 7.2%; /* ~3.18 mm de rayon de coin */
  position: relative;
  color: rgba(255, 255, 255, 0.85);
  /* Sans ça, le flex item se laisse comprimer par le max-width de
     #card-zone (côté droit "écrasé") au lieu de déborder à droite : seul le
     coin supérieur gauche doit rester une limite, pas la largeur de carte. */
  flex-shrink: 0;
}
.corner-mark {
  position: absolute;
  width: var(--mark-size);
  height: var(--mark-size);
  /* couleur du thème : des repères noirs disparaissaient sur fond sombre */
  color: var(--fg);
  pointer-events: none;
  z-index: 2;
}
.corner-mark::before,
.corner-mark::after {
  content: "";
  position: absolute;
  background: currentColor;
}
.corner-mark::before {
  width: var(--mark-line);
  height: var(--mark-size);
  left: calc((var(--mark-size) - var(--mark-line)) / 2);
  top: 0;
}
.corner-mark::after {
  width: var(--mark-size);
  height: var(--mark-line);
  left: 0;
  top: calc((var(--mark-size) - var(--mark-line)) / 2);
}
.corner-mark.top-left {
  left: calc(var(--mark-size) / -2 - var(--mark-gap));
  top: calc(var(--mark-size) / -2 - var(--mark-gap));
}
.corner-mark.top-right {
  right: calc(var(--mark-size) / -2 - var(--mark-gap));
  top: calc(var(--mark-size) / -2 - var(--mark-gap));
}
.corner-mark.bottom-left {
  left: calc(var(--mark-size) / -2 - var(--mark-gap));
  bottom: calc(var(--mark-size) / -2 - var(--mark-gap));
}
.corner-mark.bottom-right {
  right: calc(var(--mark-size) / -2 - var(--mark-gap));
  bottom: calc(var(--mark-size) / -2 - var(--mark-gap));
}
.cc-chip {
  position: absolute;
  left: 8%; top: 30%;
  width: 14%; height: 20%;
  background: linear-gradient(135deg, #e8c76b, #b8963f);
  border-radius: 12%;
}
.cc-number {
  position: absolute;
  left: 8%; bottom: 18%;
  font-size: 0.9em;
  letter-spacing: 0.1em;
}

.controls { text-align: center; }
#card-slider { width: 100%; margin-bottom: 0.75rem; }
.fine-controls { display: flex; gap: 0.75rem; justify-content: center; margin-bottom: 1rem; }

/* --- Sélecteur de langue / language toggle --- */
#lang-toggle {
  position: fixed;
  top: 0.75rem;
  right: 0.75rem;
  display: flex;
  gap: 0.3rem;
  z-index: 10;
}
#lang-toggle .btn.selected {
  background: var(--accent);
  color: var(--accent-fg);
  border-color: var(--accent);
}

/* --- Distance --- */
.range-label {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 1rem;
  font-size: 1.05rem;
}
.mode-choices {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.75rem;
  margin: 1rem 0;
}
.mode-choice {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  min-height: 132px;
  text-align: left;
  padding-right: 2.2rem; /* réserve le coin de la coche de sélection */
}
.mode-choice span {
  color: var(--muted);
  font-size: 1rem;
}
.mode-choice.selected {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}
.mode-choice.selected::after {
  content: "✓";
  position: absolute;
  top: 0.55rem;
  right: 0.55rem;
  width: 1.35rem;
  height: 1.35rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-fg);
  font-size: 0.85rem;
  font-weight: 700;
  line-height: 1;
}
#mode-type-choices { grid-template-columns: repeat(3, minmax(0, 1fr)); }
#mode-eyes-choices { grid-template-columns: repeat(3, minmax(0, 1fr)); }

h3 { font-size: 1.2rem; margin-top: 1.4rem; margin-bottom: 0; }


hr { border: none; border-top: 1px solid var(--border); margin: 1.2rem 0; }

/* --- Tache aveugle / blind spot --- */
.bs-steps {
  margin: 0.6rem 0 1rem;
  padding-left: 1.3rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.bs-steps li { line-height: 1.5; }
.bs-controls { text-align: center; margin: 0.6rem 0 0; }
.bs-eye-side {
  position: fixed;
  top: 33vh;
  width: 112px;
  min-height: 112px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  padding: 0.75rem;
  background: var(--card-bg);
  border: 2px solid var(--border);
  border-radius: 12px;
  color: var(--fg);
  box-shadow: 0 8px 26px rgba(0, 0, 0, 0.14);
  transform: translateY(-50%);
  pointer-events: none;
  z-index: 5;
}
.bs-eye-side.left { left: 1rem; }
.bs-eye-side.right { right: 1rem; }
.bs-eye-side svg {
  width: 82px;
  height: 50px;
}
.bs-eye-side .eye-open,
.bs-eye-side .eye-closed {
  display: none;
}
.bs-eye-side.open .eye-open,
.bs-eye-side.closed .eye-closed {
  display: block;
}
.bs-eye-side span {
  font-size: 1rem;
  font-weight: 800;
  text-transform: uppercase;
}
.bs-eye-side.open {
  border-color: var(--accent);
}
.bs-eye-side.closed {
  opacity: 0.72;
}
.eye-open path {
  fill: none;
  stroke: currentColor;
  stroke-width: 7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.eye-open circle:first-of-type {
  fill: var(--accent);
}
.eye-open circle:last-of-type {
  fill: #000000;
}
.eye-closed path {
  fill: none;
  stroke: currentColor;
  stroke-width: 8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
#bs-camera-skip {
  text-align: center;
  background: color-mix(in srgb, var(--accent) 10%, var(--card-bg));
  border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--border));
  border-radius: 10px;
  padding: 1.1rem 1.25rem;
  margin: 1rem 0;
}
#bs-camera-skip-text { margin: 0 0 0.7rem; font-weight: 600; }
#blindspot-eye-box {
  background: #ffffff;
  color: #000000;
  border: 2px solid #000000;
  border-radius: 8px;
  padding: 1.05rem 1.2rem;
  margin: 1rem 0 1.1rem;
  font-size: 1.35rem;
  font-weight: 800;
  text-align: center;
}
#head-align-card {
  display: grid;
  grid-template-columns: 1fr;
  align-items: center;
  gap: 1.25rem;
  text-align: center;
  background: color-mix(in srgb, var(--accent) 12%, var(--card-bg));
  border: 3px solid color-mix(in srgb, var(--accent) 58%, var(--border));
  border-radius: 12px;
  padding: 1.2rem 1.3rem;
  margin: 0.25rem 0 1.25rem;
}
#head-align-card strong {
  display: block;
  font-size: 1.42rem;
  line-height: 1.2;
  margin-bottom: 0.45rem;
}
#head-align-card p {
  margin: 0;
  color: var(--fg);
  font-size: 1.16rem;
  font-weight: 650;
  line-height: 1.5;
}
#head-align-graphic {
  width: 100%;
  max-width: 300px;
  height: auto;
  justify-self: center;
}
#head-align-graphic .screen-frame {
  fill: #ffffff;
  stroke: var(--fg);
  stroke-width: 5;
}
#head-align-graphic .screen-midline,
#head-align-graphic .align-line,
#head-align-graphic .center-reference {
  stroke: var(--accent);
  stroke-width: 5;
  stroke-linecap: round;
  stroke-dasharray: 8 8;
}
#head-align-graphic .center-reference {
  opacity: 0.35;
}
#head-align-graphic .center-dot {
  fill: var(--accent);
  stroke: #ffffff;
  stroke-width: 4;
}
#head-align-graphic .head-shape {
  fill: var(--card-bg);
  stroke: var(--fg);
  stroke-width: 5;
}
#head-align-graphic .shoulders-shape,
#head-align-graphic .side-arrow,
#head-align-graphic .arrow-head {
  fill: none;
  stroke: var(--fg);
  stroke-width: 5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
#head-align-graphic .side-arrow,
#head-align-graphic .arrow-head {
  stroke: var(--accent);
}
/* Masqué sur l'écran clair de consigne : le compteur n'est utile que pendant
   l'essai plein écran assombri, où body.bs-dimmed le rend visible ci-dessous. */
#bs-progress-box {
  display: none;
  align-items: center;
  justify-content: center;
  gap: 0.8rem;
  background: var(--fg);
  color: var(--bg);
  border-radius: 8px;
  padding: 0.95rem 1.15rem;
  margin: 0 0 1.15rem;
  text-align: center;
}
#bs-progress-count {
  font-size: 2.1rem;
  line-height: 1;
}
#bs-progress-text {
  font-weight: 700;
}
/* min-height >= line-height (1.65em), sinon le passage vide->rempli déplace quand même les éléments en dessous */
#bs-status { text-align: center; min-height: 1.7em; }
/* Espace réservé fixe : le texte d'avertissement (essai manqué, écart pouce/tache
   aveugle) apparaît et disparaît dans cette zone sans jamais déplacer le point
   ou le bouton "Il a disparu" situés juste en dessous. */
#bs-result { text-align: center; min-height: 3.6em; }
/* Ces deux zones ne se remplissent que pendant l'essai plein écran assombri
   (carte masquée) ; vides sur l'écran clair de consigne, elles ne doivent pas
   réserver cet espace — relique de l'ancien flux où l'essai se faisait ici. */
#bs-status:empty,
#bs-result:empty { min-height: 0; }
.bs-warn { color: #c2620a; }

#bs-zone {
  position: relative;
  width: 100%;
  height: 180px;
  /* fond blanc constant : le point doit disparaître, pas se fondre */
  background: #ffffff;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  margin: 1rem 0;
  overflow: hidden;
}

/* Mode "essai en cours" : le fond blanc plein écran de la zone de mesure
   éblouit après quelques minutes fixé dans le noir/la pénombre. Pendant
   l'animation du point (body.bs-dimmed), tout l'écran passe au noir sauf
   la zone de mesure elle-même, qui devient gris moyen plutôt que blanc pur,
   avec le texte et la croix de fixation en gris clair — largement assez
   pour rester lisible sans agresser l'œil qui vient de s'adapter au noir. */
body.bs-dimmed {
  background: #000000;
}
body.bs-dimmed #lang-toggle,
body.bs-dimmed footer,
body.bs-dimmed #step-blindspot > .card {
  visibility: hidden;
}
body.bs-dimmed #bs-zone {
  /* Toute la largeur de l'écran, bord à bord : le point doit pouvoir
     parcourir la distance complète pour mesurer correctement même les
     grandes séparations (personnes éloignées de l'écran) — une largeur
     plus courte coupait la mesure trop tôt (« essai manqué ») alors que
     le point n'avait pas fini sa course. */
  position: fixed;
  top: 50%;
  left: 0;
  right: 0;
  transform: translateY(-50%);
  width: 100vw;
  height: 180px;
  margin: 0;
  background: rgb(20, 20, 20);
  border: none;
  z-index: 6;
}
body.bs-dimmed #bs-zone-instruction,
body.bs-dimmed #bs-cross {
  color: rgb(190, 190, 190);
}
body.bs-dimmed .bs-gone-controls {
  position: fixed;
  left: 50%;
  bottom: 8vh;
  transform: translateX(-50%);
  width: min(560px, 92vw);
  z-index: 6;
}
/* Compteur d'essais (X/5), remonté au-dessus de la zone assombrie : la carte
   qui le contenait normalement est masquée pendant l'essai, donc on force ce
   bloc à rester visible et on le fixe en haut de l'écran. */
body.bs-dimmed #bs-progress-box {
  display: flex;
  visibility: visible;
  position: fixed;
  top: 1.5rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 7;
}
#bs-zone.preview {
  height: 0;
  background: transparent;
  border: 0;
  margin: 0;
  overflow: visible;
}
#bs-zone.preview #bs-zone-instruction,
#bs-zone.preview #bs-dot {
  display: none;
}
#bs-zone.preview #bs-cross {
  position: fixed;
  top: 50vh;
  transform: translateY(-50%);
  background: #ffffff;
  border: 2px solid #000000;
  border-radius: 8px;
  color: #000000;
  min-width: 56px;
  min-height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 8px 18px rgba(0, 0, 0, 0.12);
  z-index: 8;
}
#bs-zone-instruction {
  position: absolute;
  left: 50%;
  top: 10px;
  transform: translateX(-50%);
  color: #000000;
  font-size: 1.05rem;
  font-weight: 700;
  text-align: center;
  white-space: nowrap;
  z-index: 1;
}
#bs-cross {
  position: absolute;
  left: 24px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 2.2rem;
  font-weight: 700;
  color: #000000;
  line-height: 1;
  user-select: none;
}
#bs-dot {
  position: absolute;
  top: 50%;
  left: 120px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: #d11a2a;
  transform: translate(-50%, -50%);
  transition: opacity 0.12s ease;
}
#bs-dot.bs-dot-captured { opacity: 0; }
/* Flash de confirmation : montre où la réponse (clic, Espace ou "oui") a été
   captée, pour qu'on voie clairement que ça a marché — surtout utile pour la
   voix, où rien d'autre ne confirme visuellement la capture. */
#bs-dot-confirm {
  position: absolute;
  top: 50%;
  left: 120px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: #16a34a;
  transform: translate(-50%, -50%);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease;
}
#bs-dot-confirm.visible { opacity: 1; }
.bs-gone-controls {
  display: flex;
  justify-content: center;
  margin: 0.9rem auto 1.25rem;
  padding: 0 1rem;
}
#btn-bs-gone {
  width: min(560px, 100%);
  min-height: 68px;
  font-size: 1.25rem;
  font-weight: 800;
  box-shadow: 0 8px 22px rgba(37, 99, 235, 0.24);
}

/* --- Encadrés repliables : suivi caméra, réponse vocale, mesure du pouce --- */
.collapsible {
  border: 1px dashed var(--border);
  border-radius: 10px;
  padding: 1.1rem 1.25rem;
  margin: 1.25rem 0;
}
.collapsible h3 { margin: 0; cursor: pointer; }
#mic-status { min-height: 1.3em; }
/* Ces paragraphes de statut sont vides tant que la caméra/le micro n'est pas
   activé : les masquer évite un encadré replié avec beaucoup de vide. */
#cam-status:empty,
#mic-status:empty,
#mic-expected-words:empty { display: none; margin: 0; }

.collapsible-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
}
.collapsible-actions {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.collapse-toggle {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--muted);
  font-size: 0.9rem;
  padding: 0.3rem 0.4rem;
  line-height: 1;
}
.collapse-toggle:hover { color: var(--fg); }
.collapsible-body { margin-top: 0.6rem; }
.collapsible-body p.small { font-size: 0.85rem; color: var(--muted); margin-top: 0.4rem; }
#mic-expected-words {
  min-height: 1.3em;
  font-weight: 600;
}
/* Zone d'essai : dès que le micro est actif, on peut prononcer un mot-clé
   pour vérifier qu'il est bien reconnu avant de démarrer le test. */
#mic-practice-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.6rem;
  min-height: 1.6em;
}
#mic-practice-label {
  color: var(--muted);
  font-size: 0.95rem;
}
#mic-practice-feedback {
  font-weight: 700;
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  background: var(--border);
  color: var(--fg);
  opacity: 0;
  transition: opacity 1.1s ease;
}
#mic-practice-feedback.visible {
  opacity: 1;
  transition: opacity 0.08s ease;
}
#mic-practice-feedback.recognized {
  background: #dcfce7;
  color: #166534;
}
#mic-practice-feedback.unrecognized {
  background: #fee2e2;
  color: #991b1b;
}
@media (prefers-color-scheme: dark) {
  #mic-practice-feedback.recognized { background: #14532d; color: #86efac; }
  #mic-practice-feedback.unrecognized { background: #4a1414; color: #ff9c9c; }
}

/* Pastille micro pendant le test (et pendant la tache aveugle, où « oui »/
   « yes » remplace le clic) : rangée séparée des badges caméra pour pouvoir
   s'afficher même sans caméra ; largeur fixe pour ne jamais faire bouger la
   mise en page quand le mot entendu change. */
#mic-badge-row,
#mic-badge-row-bs {
  display: flex;
  justify-content: center;
  margin: 0.4rem auto 0;
  width: min(760px, 100%);
}
#mic-badge,
#mic-badge-bs {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  font-size: 0.95rem;
  font-weight: 700;
  white-space: nowrap;
  width: 11rem;
  overflow: hidden;
  text-overflow: ellipsis;
  background: var(--border);
  color: var(--fg);
}
/* Pendant l'essai plein écran assombri, la pastille micro rejoint le
   compteur d'essais en haut au lieu de rester dans la carte masquée. */
body.bs-dimmed #mic-badge-row-bs {
  visibility: visible;
  position: fixed;
  top: 5.5rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 7;
}
#cam-video {
  width: 160px;
  height: 120px;
  border-radius: 8px;
  background: #000;
  object-fit: cover;
  transform: scaleX(-1);
  margin: 0.7rem 0;
}
#cam-status { min-height: 1.3em; }

#cam-badges {
  display: flex;
  justify-content: center;
  gap: 0.55rem;
  margin: 0.6rem auto 0;
  width: min(760px, 100%);
}
#cam-badge,
#cam-badge-angle,
#cam-badge-eye {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  font-size: 0.95rem;
  font-weight: 700;
  white-space: nowrap;
  /* Largeur fixe par badge : quel que soit le message (distance, angle, œil
     ouvert, tête tournée...), aucun des deux badges ne change jamais de
     taille et ne peut donc plus déplacer le label de l'œil ou le numéro
     d'optotype à côté d'eux. */
  overflow: hidden;
  text-overflow: ellipsis;
  /* Chiffres à largeur fixe : évite tout micro-tremblement du badge quand la
     valeur affichée change de chiffre à chaque frame ("0 buffer"). */
  font-variant-numeric: tabular-nums;
  /* Rétroaction chaud/froid continue : à la valeur cible, --cam-hue est vert
     (142) et le badge 100% opaque ; l'écart le fait glisser vers l'orange/rouge
     et devenir plus transparent (opacité fixée en JS, jamais sous 40%). */
  background: hsl(var(--cam-hue, 142) 65% 90%);
  color: hsl(var(--cam-hue, 142) 60% 26%);
  transition: background-color 0.15s ease, color 0.15s ease, opacity 0.15s ease;
}
#cam-badge { width: 9.2rem; }
#cam-badge-angle { width: 7rem; }
#cam-badge-eye { width: 11rem; }
@media (prefers-color-scheme: dark) {
  #cam-badge,
  #cam-badge-angle,
  #cam-badge-eye {
    background: hsl(var(--cam-hue, 142) 40% 20%);
    color: hsl(var(--cam-hue, 142) 65% 72%);
  }
}
#cam-badge.eye-warn,
#cam-badge-angle.eye-warn,
#cam-badge-eye.eye-warn { background: #fecaca; color: #991b1b; }
@media (prefers-color-scheme: dark) {
  #cam-badge.eye-warn,
  #cam-badge-angle.eye-warn,
  #cam-badge-eye.eye-warn { background: #4a1414; color: #ff9c9c; }
}

#cam-eye-hint-bs { min-height: 3.3em; color: #9c3b0a; font-weight: 700; }
/* Vide tant que la caméra n'est pas active pendant cette étape : ne pas
   réserver cet espace évite un grand vide entre les deux encadrés. */
#cam-eye-hint-bs:empty { display: none; min-height: 0; }
@media (prefers-color-scheme: dark) {
  #cam-eye-hint-bs { color: #ffb27a; }
}

#cam-reject-banner {
  max-width: 760px;
  width: 100%;
  margin: 0.75rem auto 0;
  padding: 0.85rem 1rem;
  background: var(--warn-bg);
  border: 1px solid var(--warn-border);
  border-radius: 10px;
  text-align: center;
  font-weight: 700;
}

/* --- Distance manuelle / manual distance entry --- */
#manual-distance-input-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0.6rem 0;
}
#manual-distance-input {
  font: inherit;
  font-size: 1.3rem;
  font-weight: 700;
  width: 7rem;
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--card-bg);
  color: var(--fg);
}
#manual-distance-input-row span { font-size: 1.1rem; color: var(--muted); }
#manual-distance-warning { min-height: 1.7em; color: #9c3b0a; font-weight: 600; }
@media (prefers-color-scheme: dark) {
  #manual-distance-warning { color: #ffb27a; }
}

/* --- Tableau Snellen complet / full chart --- */
#chart-header {
  display: flex;
  justify-content: center;
  max-width: 760px;
  width: 100%;
  margin: 1.5rem auto 0.5rem;
  color: var(--muted);
  font-size: 1.05rem;
  font-weight: 700;
}
#chart-instructions {
  text-align: center;
  max-width: 760px;
  margin: 0 auto 0.75rem;
}
#chart-precision-note {
  text-align: center;
  max-width: 760px;
  min-height: 1.7em;
  margin: 0 auto 0.75rem;
}
#chart-scroll {
  max-height: 60vh;
  overflow-y: auto;
  overflow-x: auto;
  background: #ffffff;
  border-radius: 12px;
  max-width: 900px;
  width: calc(100% - 2.5rem);
  margin: 0 auto 1rem;
  padding: 1.5rem 1rem;
  touch-action: pan-y;
}
.chart-row {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.4em 1rem;
}
.chart-row-letters {
  flex: 1 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4em;
  color: #000000;
  font-family: "Optician Sans", Arial, Helvetica, sans-serif;
  font-weight: 400;
  line-height: 1;
  white-space: nowrap;
}
.chart-row-letters span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}
.chart-row-label {
  flex: 0 0 auto;
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  white-space: nowrap;
}
.chart-row-index {
  min-width: 1.1rem;
  font-size: 0.75rem;
  color: #c2c8ce;
  text-align: right;
}
.chart-row-frac {
  font-size: 0.85rem;
  font-weight: 700;
  color: #6b7480;
}
#chart-line-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  justify-content: center;
  margin: 0.6rem 0;
}
.btn.chart-line { min-width: 4.5rem; }

/* --- Test --- */
#step-test { min-height: 90vh; display: none; flex-direction: column; }
#step-test.active { display: flex; }

#test-header {
  display: flex;
  justify-content: space-between;
  max-width: 760px;
  width: 100%;
  margin: 0 auto;
  color: var(--muted);
  font-size: 1.05rem;
  gap: 1rem;
}
#test-align-warning {
  max-width: 760px;
  width: 100%;
  margin: 0.75rem auto 0;
  padding: 0.85rem 1rem;
  background: color-mix(in srgb, var(--accent) 12%, var(--card-bg));
  border: 2px solid color-mix(in srgb, var(--accent) 50%, var(--border));
  border-radius: 10px;
  color: var(--fg);
  font-size: 1.08rem;
  font-weight: 800;
  text-align: center;
}

#test-precision-note {
  max-width: 760px;
  width: 100%;
  margin: 0.6rem auto 0;
  min-height: 1.7em;
  text-align: center;
}

#optotype-zone {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 45vh;
  /* fond blanc constant : un vrai tableau de Snellen est noir sur blanc */
  background: #ffffff;
  color: #000000;
  border-radius: 12px;
  max-width: 900px;
  width: 100%;
  margin: 1rem auto;
  touch-action: none;
}
#optotype { display: block; }
#crowding-frame {
  --optotype-size: 120px;
  --crowding-gap: 60px;
  --crowding-bar: 24px;
  --crowding-pad: 84px;
  position: relative;
  width: calc(var(--optotype-size) + var(--crowding-pad) + var(--crowding-pad));
  height: calc(var(--optotype-size) + var(--crowding-pad) + var(--crowding-pad));
  display: flex;
  align-items: center;
  justify-content: center;
}
.crowding-bar {
  position: absolute;
  display: block;
  background: #000000;
  pointer-events: none;
}
.crowding-bar.top,
.crowding-bar.bottom {
  width: var(--optotype-size);
  height: var(--crowding-bar);
  left: calc(var(--crowding-gap) + var(--crowding-bar));
}
.crowding-bar.top { top: 0; }
.crowding-bar.bottom { bottom: 0; }
.crowding-bar.left,
.crowding-bar.right {
  width: var(--crowding-bar);
  height: var(--optotype-size);
  top: calc(var(--crowding-gap) + var(--crowding-bar));
}
.crowding-bar.left { left: 0; }
.crowding-bar.right { right: 0; }
#letter-optotype {
  display: flex;
  align-items: center;
  justify-content: center;
  color: #000000;
  font-family: "Optician Sans", Arial, Helvetica, sans-serif;
  font-weight: 400;
  line-height: 1;
  text-align: center;
  user-select: none;
}

.answer-pad { text-align: center; max-width: 760px; margin: 0 auto; width: 100%; }
.arrow-grid {
  display: grid;
  grid-template-areas: ". up ." "left down right";
  gap: 0.5rem;
  justify-content: center;
  margin-bottom: 0.8rem;
}
.arrow[data-dir="up"]    { grid-area: up; }
.arrow[data-dir="left"]  { grid-area: left; }
.arrow[data-dir="down"]  { grid-area: down; }
.arrow[data-dir="right"] { grid-area: right; }
.btn.arrow { font-size: 1.65rem; width: 76px; height: 66px; padding: 0; }
#letter-grid {
  display: grid;
  grid-template-columns: repeat(5, 66px);
  gap: 0.65rem;
  justify-content: center;
  margin-bottom: 0.8rem;
}
.btn.letter-choice {
  width: 66px;
  height: 60px;
  padding: 0;
  font-weight: 700;
  font-size: 1.15rem;
}

/* --- Résultats --- */
#results-table { width: 100%; border-collapse: collapse; margin: 1rem 0; }
#results-table th, #results-table td {
  border: 1px solid var(--border);
  padding: 0.7rem 0.8rem;
  text-align: center;
}
#results-table th {
  background: color-mix(in srgb, var(--fg) 5%, var(--card-bg));
  font-size: 0.95rem;
}
#results-table td { font-variant-numeric: tabular-nums; }
#results-table tbody tr:nth-child(even) td {
  background: color-mix(in srgb, var(--fg) 3%, transparent);
}
#results-table th:first-child, #results-table td:first-child { text-align: left; }

footer { text-align: center; color: var(--muted); font-size: 0.9rem; padding: 1rem; }

@media (max-width: 560px) {
  html, body { font-size: 17px; }
  .step { padding: 1.25rem 0.75rem 2.5rem; }
  .card { padding: 1.35rem 1rem; }
  h1 { font-size: 1.65rem; }
  h2 { font-size: 1.35rem; }
  #head-align-card {
    grid-template-columns: 1fr;
    text-align: center;
    padding: 1rem;
  }
  #head-align-card strong { font-size: 1.25rem; }
  #head-align-card p { font-size: 1.05rem; }
  #head-align-graphic {
    justify-self: center;
    max-width: 220px;
  }
  .bs-eye-side {
    top: 33vh;
    width: 74px;
    min-height: 78px;
    padding: 0.45rem;
    border-radius: 10px;
    transform: translateY(-50%);
  }
  .bs-eye-side.left { left: 0.5rem; }
  .bs-eye-side.right { right: 0.5rem; }
  .bs-eye-side svg {
    width: 52px;
    height: 34px;
  }
  .bs-eye-side span { font-size: 0.72rem; }
  #btn-bs-gone {
    min-height: 62px;
    font-size: 1.1rem;
  }
  /* Les règles par ID (grilles à 3 colonnes) sont plus spécifiques que
     .mode-choices : il faut les viser explicitement pour empiler sur mobile. */
  .mode-choices,
  #mode-type-choices,
  #mode-eyes-choices { grid-template-columns: 1fr; }
  .mode-choice { min-height: 0; }
  #test-header { flex-direction: column; align-items: center; text-align: center; }
  #test-align-warning { font-size: 1rem; }
  #letter-grid { grid-template-columns: repeat(5, 54px); gap: 0.45rem; }
  .btn.letter-choice { width: 54px; height: 54px; }
  .btn.arrow { width: 68px; height: 60px; }
}
