/* ══════════════════════════════════════════════════════════════
   CUBE SUDOKU — prototype, étapes 1 et 2 (17/10/2026)
   Chargé après sudoku-core.css (variables, mode sombre, .theme-btn).
   Toutes les classes propres au cube commencent par « cb- » pour ne
   jamais croiser les règles .cell / .grid-container du site.
   --s (taille d'une face, en px) est posée par cube-3d.js.
   24/10 (mise en ligne) : à la racine du site, ex-outils-dev/cube-3d/cube-3d.css.
══════════════════════════════════════════════════════════════ */

/* Police des pages de jeu (25/10, retour JC) : DM Mono, comme le body de sudoku-9x9.css
   (non chargée ici). Sans elle, le titre, le sous-titre, le message, la ligne d'aide et
   le texte des cartes tombaient dans la police par défaut du navigateur (Times). Les
   textes longs gardent la police système (aide « ? », réglages, texte sous le jeu). */
body { font-family: 'DM Mono', monospace; }
.cb-page { max-width: 640px; gap: 14px; position: relative; z-index: 1; }
/* Pages du site (24/10, étape 5) : <main id="main" tabindex="-1">, cible du lien
   « Aller au contenu ». Un clic dans le cube lui donne le focus, et la frappe d'un
   chiffre faisait paraître un cadre doré autour de toute la page. */
.cb-page:focus { outline: none; }
/* Pages du site : le jeu et les liens vers les autres cubes, sur toute la largeur
   (sans la classe .game-wrapper des pages de jeu, qui ouvrirait le menu vertical) */
.cb-game { width: 100%; }
.cb-page header { margin-bottom: 0; }
/* En-tête des pages 9×9 (copie de .site-title / .site-sub de sudoku-9x9.css,
   feuille non chargée ici). La marque porte le triple-clic du filtre secret. */
.cb-logo {
  font-family: 'Playfair Display', serif;
  font-size: clamp(2rem, 5.5vw, 3rem);
  font-weight: 900; letter-spacing: -1px;
  background: linear-gradient(135deg, var(--accent) 0%, #f0a500 100%);
  -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
  line-height: 1;
  user-select: none; -webkit-user-select: none;
}
.cb-h1 {
  margin: 8px 0 0;
  color: var(--text);
  font-size: clamp(1rem, 2.5vw, 1.25rem);
  font-weight: 600; letter-spacing: 1px;
}
.cb-sub { color: var(--muted); font-size: 0.9rem; margin: 6px 0 0; }
.cb-sub a { color: var(--accent-text); }   /* lien vers l'autre cube du prototype (18/10) */

/* ── Disposition ──
   Empilée (téléphone, écran étroit) : .cb-side s'efface (display: contents),
   ses éléments se rangent autour du cube par « order » : barre et statut
   au-dessus, message, pavé, boutons, pastilles, progression et aide dessous.
   Côte à côte (html.cb-wide, posée par cube-3d.js quand la face y gagne au
   moins 40 px) : cube à gauche, colonne de 330 px à droite. Il ne reste
   au-dessus du cube que l'en-tête : la face peut presque prendre toute la
   hauteur de la fenêtre (1688 × 832 : 412 → ~660 px). */
.cb-layout { display: flex; flex-direction: column; align-items: center; gap: 14px; }
.cb-side { display: contents; }
.cb-bar { order: 1; }
.cb-status { order: 2; }
.cb-stage-wrap { order: 3; }
.cb-msg { order: 4; }
.cb-numpad { order: 5; }
.cb-actions { order: 6; }
.cb-faces { order: 7; }
.cb-progress { order: 8; }
.cb-help { order: 9; }

/* Empilée, téléphone trop court pour une face de 300 px (html.cb-tight, posée par
   sudoku-cube-3d.js ; 24/10, étape 4 phase D) : 8 px entre les rangées au lieu de 14
   (30 px gagnés : les pastilles restent dans l'écran), mais toujours 14 au-dessus et
   au-dessous du cube, où les flèches de la face posée débordent de 11 px (au doigt :
   20 px, et 22 de place, 26/10, plus bas). */
html.cb-tight .cb-layout { gap: 8px; }
html.cb-tight .cb-stage-wrap { margin: 6px 0; }

html.cb-wide body { padding-bottom: 24px; }
html.cb-wide .cb-page { max-width: none; }
/* centré (24/10, étape 5) : face limitée par la hauteur de l'écran, le bloc cube +
   commandes restait collé à gauche, décalé sous le titre centré */
html.cb-wide .cb-layout { flex-direction: row; gap: 32px; justify-content: center; }
/* Pages du site (choix JC du 24/10) : calé à droite, contre la zone de la pub. La
   place libre passe à gauche, où s'ouvre le menu ☰ (replié, 240 px) : il ne vient
   plus sur la grille quand l'écran est assez large, et le cube se retrouve sous le
   titre, les commandes à sa droite. */
html.cb-wide .cb-game .cb-layout { justify-content: flex-end; }
html.cb-wide .cb-side {
  order: 9;
  display: flex; flex-direction: column; align-items: center; gap: 14px;
  width: 330px;
}
html.cb-wide .cb-numpad, html.cb-wide .cb-actions { width: 100%; }
/* pavé en 3 × 3, comme un clavier de téléphone */
html.cb-wide .cb-numpad { grid-template-columns: repeat(3, 1fr); }
html.cb-wide .cb-num { height: 54px; }

/* ── Barre d'outils ── */
.cb-bar { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; align-items: center; }
.cb-btn, .cb-select {
  font: 500 0.88rem 'DM Mono', monospace;
  min-height: 40px; padding: 0 14px;
  border: 1.5px solid var(--border); border-radius: 8px;
  background: var(--surface); color: var(--text);
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.cb-btn:hover, .cb-select:hover { border-color: var(--accent); }
.cb-btn.primary { background: var(--accent); border-color: var(--accent); color: #1a1a2e; }
.cb-btn.primary:hover { background: #b8952e; border-color: #b8952e; color: #fff; }
/* Bouton « ? » (Comment jouer) : carré, au bout de la barre */
.cb-btn.cb-q { min-width: 40px; padding: 0; font-weight: 700; font-size: 1rem; }

/* ⚙️ et 📊 (lot 2) : même bouton que le thème (.theme-btn du core, fixe,
   puis en absolu sous 600 px), une et deux places à sa gauche. La bande
   réservée en haut sous 480 px (64 px, sudoku-core.css) est étendue à
   520 px : entre 481 et ~505 px, le titre touchait le 3ᵉ bouton. */
#cb-prefs-btn { right: 64px; color: var(--text); }
#cb-stats-btn { right: 112px; }
@media (max-width: 520px) { html > body { padding-top: 64px; } }
/* Pages du site (24/10, étape 5) : 🌙, drapeau et ⛶ aux places des pages de jeu
   (16, 64 et 112 px, sudoku-core.css), ⚙️ et 📊 à leur gauche ; sous 600 px, ⛶
   est masqué (sudoku-core.css) et ils reprennent sa place. Le prototype, sans ⛶,
   garde les places du dessus. */
body:has(#fullscreen-btn) #cb-prefs-btn { right: 160px; }
body:has(#fullscreen-btn) #cb-stats-btn { right: 208px; }
@media (max-width: 600px) {
  body:has(#fullscreen-btn) #cb-prefs-btn { right: 112px; }
  body:has(#fullscreen-btn) #cb-stats-btn { right: 160px; }
}
/* Pages du site (24/10, retour JC) : ces 5 boutons et le ☰ sont attachés à la page
   à toutes les largeurs, plus à l'écran : ils défilent avec le titre, comme sous
   600 px partout sur le site (sudoku-core.css). Fixes, ils passaient sur la barre
   « Facile · Nouveau cube · ? » dès que la page défilait un peu. Le body est en
   position: relative (core) : même place qu'avant au chargement. */
body:has(.cb-game) .theme-btn, body:has(.cb-game) .lang-btn,
body:has(.cb-game) .fullscreen-btn, body:has(.cb-game) .nav-menu { position: absolute; }
/* Avec 4 boutons à droite (5 au-dessus de 600 px), la marque « Sudoku-Land »
   (≈ 6,2 × sa taille de police, 5,5vw) touchait 📊 jusqu'à ~790 px de large
   (mesuré le 24/10) : la bande de 64 px va jusqu'à 800 px sur ces pages. */
@media (max-width: 800px) { html > body:has(#fullscreen-btn) { padding-top: 64px; } }

/* ── Scène 3D ── */
.cb-stage {
  position: relative;
  width: var(--s, 320px); height: var(--s, 320px);
  perspective: calc(var(--s, 320px) * 4);
  touch-action: none;           /* glisser fait tourner le cube, pas défiler la page */
  user-select: none; -webkit-user-select: none;
  cursor: grab;
}
.cb-stage.dragging { cursor: grabbing; }

/* ── Flèches vers la face voisine ──
   Poignées à cheval sur le bord de la face posée à plat (moitié dehors) :
   fines (22 px de travers), elles ne mordent que 11 px sur la case du
   bord. Visibles seulement face à plat (.flat, posée par cube-3d.js).
   Au-dessus de la scène : .cb-stage crée son propre empilement (perspective). */
.cb-stage-wrap { position: relative; }
.cb-arrow {
  position: absolute; z-index: 2;
  display: none; align-items: center; justify-content: center;
  padding: 0;
  border: 1.5px solid var(--accent); border-radius: 999px;
  background: var(--surface); color: var(--accent-text);
  box-shadow: 0 2px 8px rgba(0,0,0,0.25);
  cursor: pointer; opacity: 0.9;
  transition: background 0.15s, color 0.15s, opacity 0.15s;
}
.cb-stage-wrap.flat .cb-arrow { display: flex; }
.cb-arrow:hover { background: var(--accent); color: #1a1a2e; opacity: 1; }
.cb-arrow svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.cb-arrow[data-dir="up"], .cb-arrow[data-dir="down"] { left: 50%; width: 46px; height: 22px; }
.cb-arrow[data-dir="left"], .cb-arrow[data-dir="right"] { top: 50%; width: 22px; height: 46px; }
.cb-arrow[data-dir="up"]    { top: 0;    transform: translate(-50%, -50%); }
.cb-arrow[data-dir="down"]  { bottom: 0; transform: translate(-50%, 50%); }
.cb-arrow[data-dir="left"]  { left: 0;   transform: translate(-50%, -50%); }
.cb-arrow[data-dir="right"] { right: 0;  transform: translate(50%, -50%); }
/* au doigt : zone élargie vers l'extérieur seulement (pas sur les cases) */
@media (pointer: coarse) {
  /* 26/10 (essai de JC sur son S22 Ultra : au doigt, la flèche prenait le toucher de
     la case du bord) : flèches posées sur le cadre de la face (2 px), dehors, au lieu
     d'à cheval (11 px sur la case). Place autour du cube : 8 px de plus au-dessus et
     au-dessous (+16 dans AROUND, sudoku-cube-3d.js) ; sur les côtés, les 7 px de marge
     de la face (largeur du contenu − 14) : 20 px de flèche + 3 px de zone = 16 + 7. */
  .cb-arrow[data-dir="up"]    { transform: translate(-50%, calc(-100% + 2px)); }
  .cb-arrow[data-dir="down"]  { transform: translate(-50%, calc(100% - 2px)); }
  .cb-arrow[data-dir="left"]  { transform: translate(calc(-100% + 2px), -50%); }
  .cb-arrow[data-dir="right"] { transform: translate(calc(100% - 2px), -50%); }
  .cb-arrow::after { content: ''; position: absolute; }
  .cb-arrow[data-dir="up"]::after    { inset: -8px 0 0 0; }
  .cb-arrow[data-dir="down"]::after  { inset: 0 0 -8px 0; }
  .cb-arrow[data-dir="left"]::after  { inset: 0 0 0 -3px; }
  .cb-arrow[data-dir="right"]::after { inset: 0 -3px 0 0; }
  html:not(.cb-wide) .cb-stage-wrap { margin: 8px 0; }
  html.cb-tight .cb-stage-wrap { margin: 14px 0; }
}
.cb-cube { position: absolute; inset: 0; transform-style: preserve-3d; }

.cb-face {
  position: absolute; inset: 0;
  box-sizing: border-box;
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  grid-template-rows: repeat(9, 1fr);
  gap: 1px;
  background: var(--border);
  border: 2px solid var(--accent);
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
}
/* Ombrage : plus la face s'éloigne de la lumière, plus le voile est sombre
   (--shade calculé à chaque image par cube-3d.js). */
.cb-face::after {
  content: ''; position: absolute; inset: -2px;
  background: #000; opacity: var(--shade, 0);
  pointer-events: none;
}
/* En sombre, les cases sont déjà foncées : voile allégé, sinon le cube devient noir. */
body.dark .cb-face::after { opacity: calc(var(--shade, 0) * 0.55); }
.cb-face[data-face="0"] { transform: translateZ(calc(var(--s) / 2)); }
.cb-face[data-face="1"] { transform: rotateY(90deg)  translateZ(calc(var(--s) / 2)); }
.cb-face[data-face="2"] { transform: rotateY(180deg) translateZ(calc(var(--s) / 2)); }
.cb-face[data-face="3"] { transform: rotateY(-90deg) translateZ(calc(var(--s) / 2)); }
.cb-face[data-face="4"] { transform: rotateX(90deg)  translateZ(calc(var(--s) / 2)); }
.cb-face[data-face="5"] { transform: rotateX(-90deg) translateZ(calc(var(--s) / 2)); }

.cb-cell {
  background: var(--cell-bg);
  display: flex; align-items: center; justify-content: center;
  font: 500 calc(var(--s, 320px) * 0.05)/1 'DM Mono', monospace;
  color: var(--given);
  -webkit-touch-callout: none;
}
.cb-cell[data-c="2"], .cb-cell[data-c="5"] { border-right: 2px solid var(--accent); }
.cb-cell[data-r="2"], .cb-cell[data-r="5"] { border-bottom: 2px solid var(--accent); }

/* ── États des cases (mêmes couleurs que le 9×9 du site) ── */
.cb-cell.user { color: var(--accent-text); }
.cb-cell.err  { color: var(--error); background: rgba(255,71,87,0.12); }
.cb-cell.hl   { background: var(--cell-highlight); }
.cb-cell.sel  { background: var(--cell-selected); box-shadow: inset 0 0 0 2px var(--accent); }
/* Face finie : teinte or posée en background-IMAGE, par-dessus la couleur de
   fond, pour que le surlignage reste visible dessous (même astuce que les
   diagonales du Sudoku X). */
.cb-face.done .cb-cell { background-image: linear-gradient(rgba(232,197,71,.26), rgba(232,197,71,.26)); }
body.dark .cb-face.done .cb-cell { background-image: linear-gradient(rgba(232,197,71,.18), rgba(232,197,71,.18)); }

/* 🥚 Filtre secret : mêmes teintes que sudoku-filtre.js (posées sur le fond
   var(--border) de la face, comme la grille 9×9 du site). Après .hl : elles
   passent devant le surlignage. */
.cb-cell.cb-same { background: rgba(232,197,71,.45); font-weight: 700; }
body.dark .cb-cell.cb-same { background: rgba(232,197,71,.30); }
.cb-cell.cb-spot { background: rgba(34,197,94,.16); }
body.dark .cb-cell.cb-spot { background: rgba(74,222,128,.14); }
.cb-notes span.cb-cand { color: #16a34a; font-weight: 700; }
/* Surligner les notes (réglage ON par défaut, D92) : pastille or ronde sur
   les notes du chiffre de la case choisie, comme .note-hl du site ; le vert
   du filtre secret passe devant. */
.cb-notes span.cb-nhl { background: radial-gradient(circle closest-side, #e8c547 94%, transparent 100%); color: #1a1a2e; font-weight: 700; }
.cb-notes span.cb-nhl.cb-cand { background: none; color: #16a34a; }

/* Grands caractères (réglage, OFF par défaut) : chiffres × 1,3, en gras,
   comme html.sl-big du site */
html.cb-big .cb-cell { font-size: calc(var(--s, 320px) * 0.065); font-weight: 600; }
html.cb-big .cb-notes span { font-size: max(9px, calc(var(--s, 320px) * 0.027)); font-weight: 600; }
html.cb-big .cb-num { font-size: clamp(1.4rem, 3.9vw, 1.85rem); font-weight: 600; }

.cb-notes {
  width: 100%; height: 100%;
  display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr);
}
.cb-notes span {
  display: flex; align-items: center; justify-content: center;
  font: 500 max(7px, calc(var(--s, 320px) * 0.021))/1 'DM Mono', monospace;
  color: var(--muted);
}

/* Vague dorée quand une ligne, une colonne, un bloc ou la face est complet */
@keyframes cbWave { 40% { background-color: rgba(232,197,71,.55); box-shadow: inset 0 0 0 2px #e8c547; } }
.cb-cell.wave { animation: cbWave 600ms ease-out; }
@media (prefers-reduced-motion: reduce) { .cb-cell.wave { animation: none; } }

/* ── Statut, message ── */
/* align-items: center (25/10, retour JC) : sans lui, les 3 morceaux prenaient la hauteur du
   bouton ⏸ et « Faces finies » / « Erreurs » restaient en haut, 4 px au-dessus du chrono */
.cb-status {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px 18px; justify-content: center;
  font: 0.85rem 'DM Mono', monospace; color: var(--muted);
}
.cb-status b { color: var(--text); font-weight: 500; }
/* Côte à côte (colonne de 330 px), les 3 infos ne tiennent pas sur une ligne et
   « Erreurs » partait seul, décalé (25/10, retour JC) : « Faces finies » et
   « Erreurs » ensemble, le chrono dessous, centré, juste au-dessus du message
   (« En pause… »). */
html.cb-wide .cb-timer { order: 1; flex-basis: 100%; justify-content: center; }
/* Pause du chrono (comme #pause-btn du 9×9 : ⏸, puis ▶ en or pendant la pause) */
.cb-timer { display: inline-flex; align-items: center; gap: 6px; }
.cb-pause {
  position: relative;
  min-width: 30px; height: 24px; padding: 0 6px;
  border: 1px solid var(--border); border-radius: 4px;
  background: var(--surface); color: var(--muted);
  font: 0.8rem/1 'DM Mono', monospace;
  cursor: pointer; transition: color 0.2s, border-color 0.2s;
}
.cb-pause:hover, .cb-pause.active { color: var(--accent-text); border-color: var(--accent-text); }
.cb-pause:disabled { opacity: 0.4; cursor: default; }
/* au doigt : zone de 44 px sans grossir la ligne */
@media (pointer: coarse) { .cb-pause::after { content: ''; position: absolute; inset: -10px -7px; } }
.cb-msg { min-height: 1.35em; margin: 0; text-align: center; font-size: 0.9rem; color: var(--muted); }
.cb-msg.error { color: var(--error); }
.cb-msg.ok { color: var(--accent-text); }

/* ── Pavé de chiffres et boutons d'action (largeur d'une face) ── */
.cb-numpad, .cb-actions { width: var(--s, 320px); display: grid; gap: 6px; transition: opacity 0.2s; }
.cb-numpad { grid-template-columns: repeat(9, 1fr); }
.cb-actions { grid-template-columns: repeat(5, 1fr); }
/* 6 boutons quand « Auto » est affiché : libellés sans espacement, pour
   tenir dans 52 px (téléphone) */
.cb-actions.six { grid-template-columns: repeat(6, 1fr); }
.cb-actions.six .cb-lbl { letter-spacing: 0; }
.cb-act[hidden] { display: none; }
.cb-numpad.off, .cb-actions.off { opacity: 0.35; pointer-events: none; }
.cb-num {
  position: relative; height: 46px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 4px;
  color: var(--text); font: 500 clamp(1.1rem, 3vw, 1.4rem) 'DM Mono', monospace;
  cursor: pointer; transition: background 0.1s, border-color 0.1s;
}
.cb-num:hover { background: var(--cell-hover); border-color: var(--muted); }
.cb-num:active { transform: scale(0.92); }
.cb-num.used { color: var(--muted); background: var(--cell-hover); opacity: 0.4; pointer-events: none; }
.cb-badge, .cb-count {
  position: absolute; bottom: 3px; right: 5px;
  font: 500 0.62rem/1 'DM Mono', monospace; color: var(--muted); opacity: 0.5;
  pointer-events: none;
}
/* chiffres restants un peu plus grands quand la place le permet (25/10, retour JC) :
   10 px sur téléphone comme avant, jusqu'à 12 px sur grand écran */
.cb-badge { font-size: clamp(0.62rem, 2.6vw, 0.75rem); }
.cb-act {
  position: relative; height: 52px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 6px;
  color: var(--muted); cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}
.cb-act:hover { color: var(--text); border-color: var(--muted); }
.cb-act:disabled { opacity: 0.45; cursor: default; }
.cb-ico { font-size: 1.05rem; line-height: 1; }
.cb-lbl { font: 500 0.66rem/1 'DM Mono', monospace; letter-spacing: 1px; text-transform: uppercase; }
.cb-count { top: 4px; bottom: auto; right: 6px; opacity: 0.8; color: var(--accent-text); }
/* Notes allumées : même gris-bleu que le bouton Notes du 9×9 */
#cb-notes-btn.active { background: #7a8a9a; border-color: #5a6a7a; color: #fff; }
/* Anneau allumé : or, comme le bouton « ⊙ Anneau ON » du 9×9 */
#cb-ring-btn.active { color: var(--accent-text); border-color: var(--accent); }
#cb-ring-btn .cb-ico { font-size: 1.25rem; }

/* ── Anneau de saisie ──
   Les boutons portent .ring-btn : leur style vient de sudoku-core.css (or uni,
   notes en gris italique, ✕ rouge). .cb-ring reprend les 2 retouches de
   sudoku-9x9.css (police DM Mono, ombre plus marquée). Taille et place :
   posées par cube-jeu.js. */
.cb-ring { font-family: 'DM Mono', monospace; font-weight: 700; box-shadow: 0 2px 10px rgba(0,0,0,0.5); }
.cb-ring:hover { box-shadow: 0 4px 18px rgba(201,162,39,0.5); }
/* Bouclier : disque transparent sous l'anneau (les boutons, à 501, restent au-dessus) */
#cb-ring-shield { position: fixed; z-index: 500; border-radius: 50%; background: transparent; }

/* Message du filtre secret (copie de .fd-toast) */
.cb-toast {
  position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 9999;
  background: #1a1a2e; color: #fff; padding: 10px 16px; border-radius: 8px; font-size: 14px;
  box-shadow: 0 4px 14px rgba(0,0,0,.25); pointer-events: none; transition: opacity .4s;
}
.cb-toast.hide { opacity: 0; }

/* ── Pastilles des faces ── */
.cb-faces { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.cb-faces button {
  width: 40px; height: 40px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font: 500 0.95rem 'DM Mono', monospace;
  border: 1.5px solid var(--border); background: var(--surface); color: var(--text);
  cursor: pointer;
}
.cb-faces .cb-overview { border-radius: 8px; color: var(--muted); }
.cb-faces .cb-overview:hover { border-color: var(--accent); }
/* Progression de chaque face (17/10 au soir) : anneau de 3 px qui se
   remplit en or, cases justes / 81, chiffres donnés compris (comme la barre
   « 0 / 81 » du 9×9). Deux fonds : un disque (--disc) posé sur un camembert
   (conic-gradient) ; --p (0 à 1) est posé par cube-jeu.js.
   Face en jeu : un liseré or autour (l'ancien disque or plein cachait sa
   progression). Face finie : anneau plein, disque doré. */
.cb-faces button:not(.cb-overview) {
  --p: 0; --disc: var(--surface);
  border: none;
  background:
    radial-gradient(closest-side, var(--disc) calc(100% - 3.5px), transparent calc(100% - 3px)),
    conic-gradient(var(--accent) calc(var(--p) * 360deg), var(--border) 0);
}
.cb-faces button:not(.cb-overview):not(.done):hover { --disc: var(--cell-hover); }
.cb-faces button.done { --disc: color-mix(in srgb, var(--accent) 30%, var(--surface)); color: var(--accent-text); }
.cb-faces button.active {
  color: var(--accent-text); font-weight: 700;
  box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent);
}

/* Progression du cube entier (25/10, demande JC), sous les pastilles : la barre « 30 / 81 »
   du 9×9 (4 px, verte une fois pleine), aux couleurs des anneaux des pastilles juste au-dessus.
   Compteur posé par sudoku-cube-jeu.js (cases justes / 386 ou 486), sur 9 caractères pour que
   la barre ne raccourcisse pas quand les chiffres grandissent. */
.cb-progress { display: flex; align-items: center; gap: 10px; width: var(--s, 320px); max-width: 100%; }
html.cb-wide .cb-progress { width: 100%; }
.cb-progress-track { flex: 1; height: 4px; border-radius: 4px; background: var(--border); overflow: hidden; }
.cb-progress-fill {
  width: 0; height: 100%; border-radius: 4px; background: var(--accent);
  transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.cb-progress-fill.complete { background: #22c55e; }
.cb-progress-text {
  min-width: 9ch; text-align: right; white-space: nowrap;
  font: 500 0.75rem 'DM Mono', monospace; font-variant-numeric: tabular-nums; color: var(--text);
}

.cb-help { color: var(--muted); font-size: 0.9rem; text-align: center; margin: 0; }


/* ── Cartes (confirmation, victoire) : style des cartes « Reprendre » du 9×9 ── */
.cb-shield {
  position: fixed; inset: 0; z-index: 400;
  display: flex; align-items: center; justify-content: center; padding: 16px;
  background: rgba(15,14,23,0.35);
}
.cb-shield[hidden] { display: none; }
.cb-shield.cb-win { background: transparent; align-items: flex-end; padding-bottom: 28px; pointer-events: none; }
/* 24/10 (retour JC) : la carte « Bravo » reste ouverte en bas ; une carte ouverte ensuite (📊, ⚙️, ?)
   passe par-dessus au lieu d'être cachée (même z-index : la dernière dans la page gagnait) */
#cb-win { z-index: 399; }
.cb-card {
  width: min(90vw, 380px); padding: 20px 22px; text-align: center;
  background: var(--surface); border: 1px solid var(--accent); border-radius: 8px;
  box-shadow: 0 12px 32px rgba(0,0,0,0.35);
  pointer-events: auto;
  animation: cbCardIn 0.3s ease;
}
@keyframes cbCardIn { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
/* écran bas : la carte défile au lieu de déborder */
.cb-card { max-height: calc(100vh - 32px); max-height: calc(100dvh - 32px); overflow-y: auto; overscroll-behavior: contain; }
/* la confirmation peut s'ouvrir par-dessus une autre carte (remise à zéro des stats) */
#cb-dialog { z-index: 410; }
.cb-card-title { margin: 0 0 6px; font: 700 1.35rem 'Playfair Display', serif; color: var(--text); }
.cb-card-text { margin: 0 0 16px; font-size: 0.92rem; line-height: 1.45; color: var(--muted); }
.cb-card-btns { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.cb-win-emoji { font-size: 2.2rem; line-height: 1; margin-bottom: 6px; }
/* 25/10 (D120) : bouton « Partager le résultat », sur sa ligne au-dessus des deux autres ;
   « ✓ Copié ! » en vert comme .win-share-btn.copied du 9×9 (vert plus foncé en clair : 4,5:1) */
.cb-win-share { margin: 0 0 8px; }
.cb-btn.copied { color: #15803d; border-color: #22c55e; }
body.dark .cb-btn.copied { color: #4ade80; }

/* ── Comment jouer (lot 1) : la modale d'aide des pages 9×9 (.help-modal /
   .help-list de sudoku-9x9.css, feuille non chargée ici) en carte du cube.
   Texte long en police système. Le titre de chaque ligne (strong) passe à
   la ligne : un gras dans la phrase doit être un b (piège du 10/10). La
   carte défile si l'écran est bas (téléphone, règle .cb-card). */
.cb-howto-card {
  position: relative;
  width: min(92vw, 480px);
  padding: 22px 24px 20px; text-align: left;
}
.cb-howto-card .cb-card-title { margin: 0 34px 14px 0; color: var(--accent-text); }
.cb-close {
  position: absolute; top: 10px; right: 10px;
  width: 40px; height: 40px; padding: 0;
  border: none; border-radius: 6px; background: none;
  color: var(--muted); font-size: 1.15rem; line-height: 1;
  cursor: pointer; transition: color 0.2s;
}
.cb-close:hover { color: var(--text); }
.cb-howto-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.cb-howto-list li {
  padding-left: 14px; border-left: 2px solid var(--border);
  font: 0.88rem/1.55 system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  color: var(--muted);
}
.cb-howto-list li > strong { display: block; margin-bottom: 2px; color: var(--text); }
.cb-howto-list b { color: var(--text); font-weight: 600; }
/* 25/10 (demande JC) : en tête de « ? » des cubes à variantes, le conseil « Jamais joué aux
   variantes ? », trait doré, avec un lien vers la page « Variantes » (sans règle, il serait
   bleu, couleur du navigateur : piège du §3.1 du CLAUDE.md) */
.cb-howto-list li[data-k="learn"] { border-left-color: var(--accent); }
.cb-howto-list a { color: var(--accent-text); font-weight: 600; text-decoration: underline; }

/* ── Réglages ⚙️, Notes auto, statistiques (lot 2) ──
   Lignes et interrupteurs : copie des styles injectés par sudoku-reglages.js
   (.slr-row, .slr-sw), texte en police système (D84). */
.cb-wide-card { width: min(92vw, 420px); }
.cb-prefs-list, .cb-choices, .cb-stats-table, .cb-stats-grid {
  font-family: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}
.cb-prefs-list { margin: 4px 0 14px; text-align: left; }
.cb-pref { display: flex; align-items: center; gap: 14px; padding: 9px 0; border-top: 1px solid var(--border); cursor: pointer; }
.cb-pref:last-child { border-bottom: 1px solid var(--border); }
.cb-pref-txt { flex: 1; display: flex; flex-direction: column; gap: 3px; }
.cb-pref-txt b { font-size: 0.95rem; font-weight: 600; color: var(--text); }
.cb-pref-txt small { font-size: 0.82rem; line-height: 1.4; color: var(--muted); }
/* interrupteur : case à cocher redessinée (reste utilisable au clavier) */
.cb-sw {
  appearance: none; -webkit-appearance: none; flex-shrink: 0; margin: 0; cursor: pointer;
  position: relative; width: 42px; height: 24px; border-radius: 12px;
  background: var(--border); transition: background 0.2s;
}
.cb-sw::after {
  content: ''; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px;
  border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,0.3); transition: left 0.2s;
}
.cb-sw:checked { background: #e8c547; }
.cb-sw:checked::after { left: 21px; }
.cb-sw:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 2px; }

/* Notes auto : 2 gros choix l'un sous l'autre (comme .sla-choice du site,
   retours JC des 09-10/10 : fond clair bordé d'or, or très pâle au survol) */
.cb-choices { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; }
.cb-choice {
  display: flex; flex-direction: column; align-items: center; gap: 4px; width: 100%;
  padding: 12px 14px; border: 2px solid var(--accent); border-radius: 8px;
  background: var(--surface); color: var(--text); font: inherit; cursor: pointer;
}
.cb-choice b { font-size: 1rem; font-weight: 700; }
.cb-choice small { font-size: 0.85rem; line-height: 1.4; color: var(--muted); }
.cb-choice:hover, .cb-choice:focus-visible {
  background: rgba(232,197,71,0.22); border-color: #e8c547; box-shadow: inset 0 0 0 1px #e8c547; outline: none;
}
.cb-choice:hover small, .cb-choice:focus-visible small { color: var(--text); }
/* 24/10 : « Candidats nettoyés » sans indice en réserve (sudoku-cube-jeu.js) */
.cb-choice:disabled, .cb-choice:disabled:hover {
  opacity: 0.5; cursor: not-allowed; background: var(--surface); border-color: var(--accent); box-shadow: none;
}
.cb-choice:disabled:hover small { color: var(--muted); }

/* Statistiques : 3 chiffres (comme .stat-card du 9×9), puis un tableau par niveau */
.cb-stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin: 4px 0 14px; }
.cb-stat { padding: 10px 6px; border: 1px solid var(--border); border-radius: 4px; background: var(--surface); }
.cb-stat-v { font: 700 1.5rem/1 'Playfair Display', serif; color: var(--accent-text); }
.cb-stat-l { margin-top: 5px; font-size: 0.72rem; letter-spacing: 1px; text-transform: uppercase; color: var(--muted); }
.cb-stats-table { width: 100%; margin-bottom: 16px; border-collapse: collapse; font-size: 0.88rem; }
.cb-stats-table th, .cb-stats-table td { padding: 6px 4px; border-bottom: 1px solid var(--border); text-align: right; }
.cb-stats-table th[scope="row"], .cb-stats-table thead th:first-child { text-align: left; }
.cb-stats-table thead th { font-size: 0.7rem; font-weight: 500; letter-spacing: 1px; text-transform: uppercase; color: var(--muted); }
.cb-stats-table tbody th { font-weight: 500; color: var(--text); }
.cb-stats-table td { color: var(--accent-text); font-variant-numeric: tabular-nums; }
.cb-stats-table tr.cur th, .cb-stats-table tr.cur td { font-weight: 700; }

/* Petit écran : un peu moins d'air, pour garder cube + pavé + boutons visibles */
@media (max-width: 480px) {
  .cb-page { gap: 10px; }
  body { padding-top: 16px; }
  .cb-num { height: 42px; }
  /* statut sur une seule ligne malgré le bouton ⏸ (375 px : 343 px de large) */
  .cb-status { gap: 4px 12px; font-size: 0.78rem; }
}

/* ── Sous le jeu, pages du site (24/10, étape 5) ──
   Liens vers les autres cubes, texte et FAQ, pied de page légal : copie de
   sudoku-9x9.css (.footer-links, .seo-content, .faq-mini, .legal-footer), feuille
   non chargée ici. ⚠️ Toute retouche de ces règles là-bas = ici aussi. */
.seo-content { --seo-font: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; }
.seo-content { max-width: 640px; width: 100%; margin: 32px auto 0; text-align: left; position: relative; z-index: 1; }
.seo-content h2 { font-family: 'Playfair Display', serif; font-size: clamp(1.3rem, 4vw, 1.8rem); font-weight: 700; color: var(--text); margin-bottom: 10px; }
.seo-content h3 { font-family: 'DM Mono', monospace; font-size: 0.8rem; letter-spacing: 2px; text-transform: uppercase; color: var(--accent2-text); margin: 24px 0 10px; }
.seo-content p { font-family: var(--seo-font); font-size: 1rem; line-height: 1.7; color: var(--muted); margin-bottom: 10px; }
.seo-content p:last-child { margin-bottom: 0; }
.seo-content a { color: var(--accent-text); font-weight: 600; text-decoration: underline; }
.seo-content p a, .seo-content li a { display: inline-block; padding: 4px 3px; margin: -4px -3px; }
.seo-content ul { list-style: none; display: flex; flex-direction: column; gap: 8px; }
.seo-content li { font-family: var(--seo-font); font-size: 0.95rem; line-height: 1.6; color: var(--muted); background: var(--surface); border: 1px solid var(--border); border-radius: 4px; padding: 10px 14px; }
.seo-content li strong { color: var(--text); }
.faq-mini details { background: var(--surface); border: 1px solid var(--border); border-radius: 4px; padding: 10px 14px; margin-bottom: 8px; }
.faq-mini summary { font-family: var(--seo-font); font-weight: 700; font-size: 1rem; color: var(--text); cursor: pointer; }
.faq-mini p { font-family: var(--seo-font); margin-top: 8px; margin-bottom: 0 !important; }
/* Bloc « les autres cubes et grilles » — vers les autres formats */
.seo-content .format-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
.seo-content .format-card { display: block; background: var(--surface); border: 1px solid var(--border); border-radius: 4px; padding: 12px 14px; text-decoration: none; font-weight: 400; transition: border-color .15s ease, transform .15s ease; }
.seo-content .format-card:hover, .seo-content .format-card:focus-visible { border-color: var(--accent2); transform: translateY(-2px); }
.seo-content .format-card-title { display: block; font-family: 'Playfair Display', serif; font-size: 1rem; font-weight: 700; color: var(--text); margin-bottom: 4px; }
.seo-content .format-card-desc { display: block; font-family: var(--seo-font); font-size: 0.875rem; line-height: 1.5; color: var(--muted); }
@media (max-width: 420px) { .seo-content .format-grid { grid-template-columns: 1fr; } }

.footer-links {
  margin-top: 16px; padding-top: 12px;
  border-top: 1px solid var(--border);
  display: flex; justify-content: center; gap: 20px; flex-wrap: wrap;
}
.footer-link {
  font-family: 'DM Mono', monospace; font-size: 0.75rem;
  letter-spacing: 2px; text-transform: uppercase;
  color: var(--muted); text-decoration: none; transition: color 0.2s;
  padding: 6px 4px; margin: -6px -4px; display: inline-block;
}
.footer-link:hover { color: var(--accent-text); }
@media (pointer: coarse) { .footer-link { padding: 14px 8px; margin: -14px -8px; } }

.legal-footer {
  margin: 40px auto 0; padding-top: 14px;
  border-top: 1px solid var(--border);
  display: flex; justify-content: center; gap: 14px; flex-wrap: wrap;
  max-width: 640px; opacity: 0.55;
}
.legal-footer a, .legal-footer button {
  font-family: 'DM Mono', monospace; font-size: 0.75rem;
  color: var(--muted); text-decoration: none;
  background: none; border: none; cursor: pointer; transition: opacity 0.2s;
  display: inline-block; padding: 7px 6px; margin: -7px -6px;
}
.legal-footer a:hover, .legal-footer button:hover { opacity: 1; text-decoration: underline; }
@media (pointer: coarse) {
  .legal-footer a, .legal-footer button { padding: 14px 8px; margin: -14px -8px; }
}
