:root {
  --bg: #0f1115;
  --panel: #1a1d24;
  --panel-border: #2a2e38;
  --text: #e6e8eb;
  --text-dim: #9aa0ab;
  --accent: #e0a52c;
  --ring-line: #3a3f4b;
  --ring-fill: #171a20;
  --ring-black: #0a0b0d;
  --ring-paper: #ddd0a6;
  --ring-line-paper: rgba(30, 24, 8, 0.35);
  --ring-label-on-black: #f2ede0;
  --ring-label-on-paper: #2a2113;
  --ring-mouche: rgba(255, 255, 255, 0.3);
  --impact: #39ff14;
  --ok: #3ecf8e;
  --off: #6b7280;
  --mpi-cross: #ff3b30;
  --score-panel-w: 300px;
  --score-panel-h-mobile: 40vh;
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  height: 100vh;
  overflow: hidden;
}

/* Affichage des scores (réglage Paramètres) : point entier, dixième, ou les
   deux — piloté par data-score-mode sur <body>, "both" par défaut. */
body[data-score-mode="integer"] .value-decimal,
body[data-score-mode="integer"] .impact-score-decimal {
  display: none;
}

body[data-score-mode="decimal"] .total-score .value,
body[data-score-mode="decimal"] .impact-score {
  display: none;
}

/* en mode "dixième seulement", le décimal devient la valeur principale :
   on lui reprend la taille/couleur/graisse de la valeur entière qu'il
   remplace, sinon il garde son style de simple annotation secondaire
   (petit, terne) et paraît "rétréci". */
body[data-score-mode="decimal"] .total-score .value-decimal {
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--accent);
}

body[data-score-mode="decimal"] #impact-list li .impact-score-decimal,
body[data-score-mode="decimal"] .series-chip .impact-score-decimal {
  color: var(--accent);
  font-weight: 700;
}

body[data-score-mode="decimal"] #impact-list li.miss .impact-score-decimal {
  color: var(--off);
}

select, button {
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--panel-border);
  border-radius: 8px;
  padding: 10px 14px;
  min-height: 44px;
  font-size: 1rem;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

button {
  cursor: pointer;
}

button:hover {
  border-color: var(--accent);
}

button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

button:disabled:hover {
  border-color: var(--panel-border);
}

.status {
  font-size: 0.8rem;
  padding: 4px 10px;
  border-radius: 999px;
}

.status-on {
  background: rgba(62, 207, 142, 0.15);
  color: var(--ok);
}

.status-off {
  background: rgba(107, 114, 128, 0.15);
  color: var(--off);
}

/* --- Scène plein écran : la cible est le fond de la page --------------- */

#target-stage {
  position: relative;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}

#target-svg {
  /* réduit à la zone réellement visible (hors dock de score) pour que le
     viewBox carré + preserveAspectRatio centrent la cible dans cet espace,
     et non dans la pleine largeur de l'écran cachée en partie par le dock */
  display: block;
  width: calc(100% - var(--score-panel-w));
  height: 100%;
  background: var(--ring-paper);
  touch-action: none;
  user-select: none;
  cursor: grab;
}

#target-svg.grabbing {
  cursor: grabbing;
}

.stage-controls {
  position: fixed;
  top: 16px;
  left: 16px;
  z-index: 5;
  display: flex;
  gap: 8px;
}

.stage-controls button {
  padding: 8px 12px;
  min-height: 36px;
  font-size: 0.85rem;
  background: rgba(26, 29, 36, 0.85);
  backdrop-filter: blur(4px);
  opacity: 0.9;
  white-space: nowrap;
}

.stage-controls button:hover {
  opacity: 1;
}

#autozoom-btn.active {
  border-color: var(--accent);
  color: var(--accent);
  opacity: 1;
}

/* Triangle en coin pour passer directement les essais et démarrer le match,
   sans ouvrir la modal Programme. Ancré au coin haut-droit de la zone
   réellement visible de la cible (juste à gauche du dock de score), sans
   texte : mix-blend-mode: difference inverse automatiquement sa couleur
   par rapport à ce qui se trouve dessous (noir sur zone claire, blanc sur
   zone noire), quel que soit le pan/zoom courant de la cible. */
.corner-triangle {
  position: fixed;
  top: 0;
  right: var(--score-panel-w);
  z-index: 6;
  width: 200px;
  height: 200px;
  padding: 0;
  min-height: 0;
  border: none;
  border-radius: 0;
  background: #fff;
  mix-blend-mode: difference;
  clip-path: polygon(100% 0, 100% 100%, 0 0);
  transition: transform 0.15s;
}

.corner-triangle:hover {
  border: none;
  transform: scale(1.06);
}

.corner-triangle.hidden {
  display: none;
}

@media (max-width: 480px) {
  .corner-triangle {
    right: 0;
  }
}

/* Panneau de score : dock plein hauteur sur le bord droit, au-dessus de la cible */
.score-panel {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 5;
  width: var(--score-panel-w);
  background: rgba(26, 29, 36, 0.92);
  backdrop-filter: blur(6px);
  border-left: 1px solid var(--panel-border);
  padding: 20px 16px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.phase-badge {
  text-align: center;
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 0.85rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  background: var(--ring-fill);
  color: var(--text-dim);
}

.phase-badge.hidden {
  display: none;
}

.phase-badge.phase-practice {
  color: var(--off);
}

.phase-badge.phase-match {
  color: var(--accent);
  outline: 1px solid var(--accent);
}

.phase-badge.phase-complete {
  color: var(--ok);
  outline: 1px solid var(--ok);
}

.total-score {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 16px;
  border-radius: 8px;
  background: var(--ring-fill);
}

/* Rangée du haut du bloc score : dernier tir à gauche, total à droite —
   deux moitiés égales (flex:1) pour que chaque valeur soit centrée dans
   son propre espace libre plutôt que collée au bord. */
.total-score-row {
  display: flex;
  flex-direction: row;
  align-items: center;
  width: 100%;
}

.total-score-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* Total (plus petit, secondaire) : la valeur du dernier tir est mise en
   évidence à gauche, voir .last-shot-value ci-dessous. */
.total-score .value {
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--accent);
}

.total-score .value-decimal {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-dim);
}

.mouche-count {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-dim);
}

/* Dernier tir (à gauche du total) : mis en évidence, plus grand que le
   total. */
.last-shot {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.last-shot-value {
  font-size: 3.2rem;
  font-weight: 700;
  color: var(--accent);
}

.last-shot-value-decimal {
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--text-dim);
}

body[data-score-mode="integer"] .last-shot-value-decimal {
  display: none;
}

body[data-score-mode="decimal"] .last-shot-value {
  display: none;
}

body[data-score-mode="decimal"] .last-shot-value-decimal {
  font-size: 3.2rem;
  color: var(--accent);
}

/* Totaux des séries de match, fenêtre glissante des 6 dernières séries
   complètes (couvre un 60BC entier) — une seule rangée de 6 colonnes :
   quand la 7e série arrive, S1 sort, tout décale vers la gauche, S7
   arrive à droite (voir computeSeriesTotals().slice(-SERIES_WINDOW), déjà
   dans cet ordre). Toujours 6 cases en DOM (voir renderSeriesTotals()) :
   la grille garde ainsi une largeur/hauteur fixe qu'il y ait 0 ou 6
   séries (pas de décalage du reste du panneau), et les séries pas encore
   jouées restent visibles en cadres vides ("–") plutôt que de laisser un
   trou dans le panneau. */
.series-totals {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 4px;
  width: 100%;
}

.series-chip-placeholder {
  opacity: 0.4;
  border-style: dashed;
}

.series-chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 4px 2px;
  border-radius: 6px;
  background: var(--panel);
  border: 1px solid var(--panel-border);
}

/* série en cours : total cumulatif mis à jour à chaque tir, avant la 10e
   balle — bordure accent + léger pouls pour la distinguer des séries closes */
.series-chip-live {
  border-color: var(--accent);
  animation: series-chip-live-pulse 1.6s ease-in-out infinite;
}

@keyframes series-chip-live-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(224, 165, 44, 0.35); }
  50% { box-shadow: 0 0 0 3px rgba(224, 165, 44, 0); }
}

.series-chip-label {
  font-size: 0.7rem;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.series-chip .impact-score {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--accent);
}

.series-chip .impact-score-decimal {
  font-size: 0.8rem;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

.series-chip-mouche {
  font-size: 0.7rem;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

h2 {
  font-size: 0.95rem;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin: 0;
}

#impact-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  /* ancre les tirs en bas : avec peu de tirs, l'espace vide reste en haut
     et chaque nouveau tir arrive tout en bas, contre le total-score. */
  justify-content: flex-end;
  gap: 1px;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

/* Largeurs de colonnes fixes (pas "auto") : chaque <li> est une grille
   indépendante, donc une colonne en "auto" se redimensionne selon le
   contenu de SA ligne (ex: l'emoji 🎯) et désaligne les colonnes entre
   les lignes. Des largeurs fixes garantissent le même alignement partout. */
#impact-list li {
  display: grid;
  /* minmax(0, 1fr), pas 1fr seul : sinon la colonne du libellé refuse de
     rétrécir sous la largeur de son texte et le reste de la ligne déborde
     sur une deuxième ligne dans le dock de score (300px de large) */
  grid-template-columns: minmax(0, 1fr) 1.2em 2em 4.2em;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  background: var(--ring-fill);
  border-radius: 6px;
  font-size: 0.9rem;
}

/* Colonnes explicites (pas de placement grid auto), sinon masquer un
   enfant (ex: .impact-score en mode "dixième seulement", display:none)
   fait glisser les suivants dans les colonnes précédentes plus étroites.
   L'ordre des <span> est toujours le même (libellé, direction/spacer,
   score, décimal) dans addImpactRow et addSeriesTotalRow. */
#impact-list li > span:nth-child(1) { grid-column: 1; }
#impact-list li > span:nth-child(2) { grid-column: 2; }
#impact-list li > span:nth-child(3) { grid-column: 3; }
#impact-list li > span:nth-child(4) { grid-column: 4; }

/* Quand une des deux valeurs (entier/décimal) est masquée par le réglage
   "Affichage des scores", sa colonne (2em ou 4.2em) reste réservée mais
   inutilisée par défaut : ça ne casse rien, mais la valeur restante garde
   une largeur pensée pour l'AUTRE valeur si on ne retire pas explicitement
   la colonne du template — d'où la troncature ("10…", "1…") en mode
   "dixième seulement" tant que le décimal restait sur une colonne de 2em
   pensée pour l'entier. On redéfinit donc le template par mode. */
body[data-score-mode="integer"] #impact-list li {
  grid-template-columns: minmax(0, 1fr) 1.2em 2em;
}

body[data-score-mode="decimal"] #impact-list li {
  grid-template-columns: minmax(0, 1fr) 1.2em 4.2em;
}
body[data-score-mode="decimal"] #impact-list li > span:nth-child(4) {
  grid-column: 3;
}

#impact-list li > span {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* ligne pointillée séparant les essais du match */
#impact-list li.phase-separator {
  display: block;
  height: 0;
  padding: 0;
  margin: 8px 4px;
  background: none;
  border-radius: 0;
  border-top: 2px dashed var(--accent);
}

/* total récapitulatif tous les 10 coups de match */
#impact-list li.series-total {
  background: var(--panel-border);
}

#impact-list li.series-total > span:first-child {
  font-weight: 700;
}

#impact-list li .impact-direction {
  font-weight: 700;
  text-align: center;
}

#impact-list li .impact-score {
  font-weight: 700;
  color: var(--accent);
  text-align: left;
}

#impact-list li .impact-score-decimal {
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  text-align: left;
}

#impact-list li.miss .impact-score {
  color: var(--off);
}

#impact-list li.mouche .impact-score {
  color: var(--accent);
}

/* essais : tout est atténué sauf le score, qui garde la même couleur
   qu'un coup de match pour rester bien visible */
#impact-list li.practice > span:not(.impact-score) {
  opacity: 0.55;
}

.program-status {
  font-size: 0.9rem;
  color: var(--text-dim);
  background: var(--ring-fill);
  border-radius: 8px;
  padding: 10px 12px;
  line-height: 1.5;
}

.program-status strong {
  color: var(--text);
}

@media (max-width: 480px) {
  /* trop étroit pour un dock plein hauteur : le score redescend en bandeau bas,
     donc c'est la hauteur du SVG (et non plus sa largeur) qu'il faut réduire
     pour garder la cible centrée dans l'espace visible au-dessus */
  .score-panel {
    top: auto;
    right: 0;
    left: 0;
    bottom: 0;
    width: 100%;
    height: var(--score-panel-h-mobile);
    border-left: none;
    border-top: 1px solid var(--panel-border);
  }

  #target-svg {
    width: 100%;
    height: calc(100% - var(--score-panel-h-mobile));
  }

  .stage-controls {
    flex-wrap: wrap;
    width: calc(100vw - 32px);
  }
}

/* --- Modal Paramètres ---------------------------------------------------- */

.modal {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: center;
}

.modal.hidden {
  display: none;
}

.modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
}

.modal-card {
  position: relative;
  z-index: 1;
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 12px;
  padding: 24px;
  width: 320px;
  max-width: 90vw;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.modal-card label {
  color: var(--text-dim);
  font-size: 0.9rem;
}

.modal-close {
  position: absolute;
  top: 12px;
  right: 12px;
  min-height: 32px;
  padding: 4px 10px;
  font-size: 0.9rem;
}

/* Modale Historique : plus large que les autres (liste + cible SVG +
   liste de tirs) et scrollable en hauteur — indispensable sur mobile où
   la fenêtre visible est souvent plus basse que le contenu. */
.history-modal-card {
  width: 480px;
  max-height: 85vh;
  overflow-y: auto;
}

.history-hint {
  font-size: 0.85rem;
  color: var(--text-dim);
  line-height: 1.5;
  margin: 0 0 4px;
}

.history-empty {
  padding: 12px 14px;
  border-radius: 8px;
  background: rgba(224, 165, 44, 0.12);
  color: var(--accent);
  font-size: 0.9rem;
}

.match-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.match-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 14px;
  border-radius: 8px;
  background: var(--ring-fill);
  border: 1px solid var(--panel-border);
  cursor: pointer;
}

.match-list li:hover {
  border-color: var(--accent);
}

.match-list .match-date {
  color: var(--text-dim);
  font-size: 0.85rem;
}

.match-list .match-title {
  font-weight: 700;
}

.match-list .match-score {
  color: var(--accent);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.history-back-btn {
  align-self: flex-start;
}

.match-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  padding: 12px 14px;
  border-radius: 8px;
  background: var(--ring-fill);
  font-size: 0.9rem;
}

.match-summary .summary-label {
  color: var(--text-dim);
  margin-right: 6px;
}

#history-target-svg {
  width: 100%;
  aspect-ratio: 1;
  max-height: 45vh;
  background: var(--bg);
  border-radius: 8px;
}

.history-shot-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
  max-height: 25vh;
  overflow-y: auto;
}

.history-shot-list li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 2em 4.2em 2.5em;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  background: var(--ring-fill);
  border-radius: 6px;
  font-size: 0.85rem;
}

.history-shot-list .impact-score {
  color: var(--accent);
  font-weight: 700;
}

.history-shot-list .impact-score-decimal {
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 480px) {
  .history-modal-card {
    width: 100%;
    max-width: 95vw;
    padding: 16px;
  }
}

.status-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 8px;
}


/* --- Animations d'impact -------------------------------------------------- */

/* seul le dernier impact reste coloré, les précédents sont gris */
.impact-dot {
  fill: var(--off);
}

.impact-dot.impact-latest {
  fill: var(--impact);
}

.impact-mouche {
  animation: mouche-blink 0.5s ease-in-out 5;
}

@keyframes mouche-blink {
  0%, 100% {
    filter: drop-shadow(0 0 2px var(--accent));
    opacity: 1;
  }
  50% {
    filter: drop-shadow(0 0 6px var(--accent));
    opacity: 0.35;
  }
}

.impact-label {
  pointer-events: none;
  user-select: none;
}

.shockwave {
  fill: none;
  stroke: var(--accent);
  transform-box: fill-box;
  transform-origin: center;
  animation: shockwave-pulse 0.9s cubic-bezier(0.2, 0.7, 0.3, 1) forwards;
  pointer-events: none;
}

@keyframes shockwave-pulse {
  0% {
    transform: scale(1);
    opacity: 0.95;
  }
  100% {
    transform: scale(3.5);
    opacity: 0;
  }
}
