/* styles/views/hexahunt.css
 * ──────────────────────────────────────────────────────────────
 * Mode HexaHunt : trouve la couleur exacte de chaque ligne.
 * Base layout (positionnement + structure). Le thème pinboard
 * apporte le cadre métal brossé + CRT ambre (cf.
 * styles/theme/pinboard/hexahunt.css).
 * ────────────────────────────────────────────────────────────── */

#view-hexahunt{ padding:0; min-height:100vh;min-height:100dvh; position:relative; overflow:hidden; }
#view-hexahunt.active{ display:block; }

/* Easing tokens — courbes custom plus punchy que les built-in CSS
 * (cf. Emil Kowalski / easing.dev). Scopées à la vue pour ne pas
 * polluer le reste de l'app. */
#view-hexahunt{
  --hx-ease-out:    cubic-bezier(0.23, 1, 0.32, 1);
  --hx-ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --hx-ease-spring: cubic-bezier(0.34, 1.25, 0.4, 1);
}

/* Dots plus visibles spécifiquement dans cette vue — mais un poil
 * plus discrets qu'avant : taille + opacité réduites. */
#view-hexahunt.active{
  --dot-color: color-mix(in srgb, var(--fg) 18%, transparent);
}
#view-hexahunt.active::before{
  background-size:22px 22px !important;
  background-image:radial-gradient(circle, var(--dot-color) 1.2px, transparent 1.4px) !important;
  opacity:.7 !important;
  mask-image:none !important;
  -webkit-mask-image:none !important;
}

.hx-shell{
  position:relative;
  width:100%; min-height:100vh;min-height:100dvh;
  display:grid;
  grid-template-columns:minmax(320px, 460px) 1fr;
  grid-template-rows:1fr auto;
  grid-template-areas:
    "brief  picker"
    "brief  actions";
  gap:24px;
  padding:80px 32px 32px;
}

.hx-nav{
  position:absolute; top:16px; left:16px;
  z-index:10;
}

.hx-brief{
  grid-area:brief;
  align-self:start;
  max-width:460px;
  width:100%;
}

.hx-picker-wrap{
  grid-area:picker;
  display:flex; justify-content:center; align-items:start;
}
.hx-picker-card{
  display:flex; flex-direction:column;
  gap:20px;
  width:min(100%, 520px);
}

/* Comparaison cible / proposition */
.hx-compare{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:16px;
}
.hx-compare-col{
  display:flex; flex-direction:column; align-items:center;
  gap:8px;
}
.hx-compare-lbl{
  font-family:'DM Mono','JetBrains Mono',monospace;
  font-size:10px; letter-spacing:2.4px;
  color:var(--muted);
  text-transform:uppercase;
}
.hx-chip{
  width:120px; height:120px;
  border-radius:16px;
  display:flex; align-items:center; justify-content:center;
  font-family:'Oswald','Barlow Semi Condensed',sans-serif;
  font-weight:700; font-size:54px;
  background:#3a3a3a;
  color:#fff;
  border:2px solid rgba(255,255,255,.1);
  transition:background .3s cubic-bezier(.22,.9,.25,1),
             color .3s cubic-bezier(.22,.9,.25,1),
             border-radius .3s cubic-bezier(.22,.9,.25,1);
}
/* Forme signalétique RATP forcée d'après `data-type` posé par
 * hexahunt.js::_applyChipShape à chaque manche. Métro = cercle
 * parfait, RER = carré avec léger border-radius (12% du côté). */
.hx-chip[data-type="metro"]{ border-radius:50%; aspect-ratio:1; }
.hx-chip[data-type="rer"]  { border-radius:14px; }
.hx-chip-target{
  background:repeating-linear-gradient(45deg,
    #2a2a2a 0 8px,
    #333 8px 16px);
  color:transparent;
  position:relative;
}
.hx-chip-target::after{
  content:'?';
  position:absolute;
  inset:0;
  display:flex; align-items:center; justify-content:center;
  color:var(--muted);
  font-size:54px;
}
.hx-chip-target.hx-chip-revealed::after{ content:''; }
.hx-chip-target.hx-chip-revealed{ color:inherit; background:inherit; }

/* Picker : SV square + hue slider + readout hex */
.hx-picker{
  display:flex; flex-direction:column;
  gap:14px;
  background:color-mix(in srgb, var(--panel) 94%, transparent);
  border:1px solid var(--border);
  border-radius:14px;
  padding:16px;
  box-shadow:0 6px 18px rgba(0,0,0,.3);
}

.hx-sv-square{
  position:relative;
  width:100%; aspect-ratio:1;
  background-color:hsl(180, 100%, 50%);
  border-radius:10px;
  overflow:hidden;
  cursor:crosshair;
  touch-action:none;
  user-select:none;
}
.hx-sv-white{
  position:absolute; inset:0;
  background:linear-gradient(90deg, #fff, transparent);
}
.hx-sv-black{
  position:absolute; inset:0;
  background:linear-gradient(0deg, #000, transparent);
}
.hx-sv-cursor{
  position:absolute;
  width:18px; height:18px;
  border:2px solid #fff;
  border-radius:50%;
  box-shadow:0 0 0 1px rgba(0,0,0,.7), 0 2px 6px rgba(0,0,0,.5);
  transform:translate(-50%, -50%);
  pointer-events:none;
}

.hx-hue{
  position:relative;
  height:22px;
  border-radius:8px;
  background:linear-gradient(90deg,
    #f00 0%, #ff0 16.66%, #0f0 33.33%, #0ff 50%,
    #00f 66.66%, #f0f 83.33%, #f00 100%);
  cursor:ew-resize;
  touch-action:none;
  user-select:none;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.25);
}
.hx-hue-cursor{
  position:absolute;
  top:50%; left:0;
  width:10px; height:28px;
  border:2px solid #fff;
  border-radius:4px;
  box-shadow:0 0 0 1px rgba(0,0,0,.6), 0 2px 4px rgba(0,0,0,.5);
  transform:translate(-50%, -50%);
  pointer-events:none;
  background:rgba(255,255,255,.2);
}

.hx-hex-readout{
  display:flex; justify-content:space-between; align-items:center;
  font-family:'DM Mono','JetBrains Mono',monospace;
  font-size:14px; letter-spacing:1.5px;
  color:var(--fg);
  padding:6px 10px;
  background:var(--panel-2, rgba(0,0,0,.2));
  border-radius:6px;
}
.hx-hex-k{ color:var(--muted); font-size:10px; letter-spacing:2px; }
.hx-hex-v{ font-weight:700; }

/* Action bar + reveal */
.hx-actions{
  grid-area:actions;
  display:flex; justify-content:center; gap:12px;
  padding:16px 0 4px;
}

.hx-reveal{
  grid-column:1 / -1;
  display:flex; flex-direction:column; align-items:center;
  gap:6px;
  padding:14px 20px;
  margin:0 auto;
  background:color-mix(in srgb, var(--panel) 96%, transparent);
  border:1px solid var(--border);
  border-radius:10px;
  max-width:520px;
  width:100%;
  font-family:'DM Mono','JetBrains Mono',monospace;
}
.hx-reveal[hidden]{ display:none !important; }
.hx-reveal-title{
  font-size:18px; font-weight:700; letter-spacing:1.5px;
  color:var(--fg);
  font-family:'Oswald','Barlow Semi Condensed',sans-serif;
  text-transform:uppercase;
}
.hx-reveal-msg{
  font-size:12px; letter-spacing:.5px;
  color:var(--fg-dim);
}
.hx-reveal-delta{
  display:flex; align-items:center; gap:10px;
  font-size:13px; letter-spacing:1px;
  color:var(--fg);
  margin-top:4px;
}
.hx-reveal-score{ font-weight:700; }

/* Multi reveal : liste des propositions des joueurs triées par score */
.hx-multi-list{
  display:flex; flex-direction:column;
  gap:6px;
  width:100%;
  margin:8px 0 6px;
}
.hx-multi-row{
  display:grid;
  grid-template-columns:auto 1fr auto;
  gap:12px;
  align-items:center;
  padding:6px 10px;
  background:var(--panel-2, rgba(0,0,0,.15));
  border:1px solid var(--border);
  border-radius:8px;
}
.hx-multi-chip{
  font-family:'DM Mono','JetBrains Mono',monospace;
  font-size:12px; font-weight:700;
  letter-spacing:1.2px;
  padding:6px 10px;
  border-radius:6px;
  border:1px solid rgba(0,0,0,.3);
  min-width:88px;
  text-align:center;
}
.hx-multi-name{
  font-family:'Oswald','Barlow Semi Condensed',sans-serif;
  font-weight:600; font-size:14px; letter-spacing:.5px;
  color:var(--fg);
}
.hx-multi-score{
  font-family:'DM Mono','JetBrains Mono',monospace;
  font-size:12px; letter-spacing:1px;
  color:var(--fg-dim);
  white-space:nowrap;
}
.hx-multi-empty{
  font-family:'DM Mono',monospace;
  font-size:12px; color:var(--muted);
  text-align:center; padding:12px;
}

/* ══════════════════════════════════════════════════════════════
 * COMPLETE MODE — Calibrage Tout Paris
 * Layout minimal : picker flottant au-dessus du tile actif avec
 * flèche pointant vers lui, row horizontale de 21 lignes au centre,
 * CTA sombre en bas. Pas de brief — tout se lit d'un coup d'œil.
 * ══════════════════════════════════════════════════════════════ */
.hx-shell-complete{
  display:flex;
  flex-direction:column;
  grid-template:none;
  grid-template-areas:none;
  gap:0;
  padding:0;
  min-height:100vh;min-height:100dvh;
  position:relative;
}

.hx-shell-complete .hx-nav{
  position:absolute;
  top:20px; left:20px;
  z-index:20;
}

/* Stage central : centre verticalement le GROUPE complet (picker +
 * row). Le picker est un enfant absolute du track mais sa hauteur
 * est réservée via le padding-top du viewport (cf .hx-carousel-
 * viewport plus bas). Du coup la taille totale du carousel inclut
 * l'espace du picker → justify-content:center centre bien les deux
 * ensemble, pas juste la row. */
.hx-complete-stage{
  position:relative;
  flex:1;
  display:flex;
  flex-direction:column;
  justify-content:center;
  align-items:stretch;
  padding:clamp(12px, 2vh, 32px) 24px;
}

/* Picker positionné DANS le track (sibling des tiles, position:absolute).
 * Il hérite du transform du track (translateX) donc bouge avec — et
 * reste pile au-dessus du tile actif même pendant la transition de
 * slide. --picker-anchor-x = position layout du centre du tile actif
 * dans le track, posée par _positionCarousel. */
.hx-picker-float{
  position:absolute;
  left:var(--picker-anchor-x, 50%);
  bottom:calc(100% + var(--tile-size, 54px) * 0.55 + 18px);
  transform:translateX(-50%);
  transform-origin:bottom center;
  z-index:5;
  pointer-events:auto;
  filter:drop-shadow(0 10px 24px rgba(0,0,0,.18));
  transition:opacity 220ms var(--hx-ease-out);
}
.hx-picker-float[hidden]{ display:none; }

@supports (transition-behavior: allow-discrete){
  .hx-picker-float{
    transition:
      opacity 260ms var(--hx-ease-out),
      display 260ms allow-discrete;
  }
  @starting-style{
    .hx-picker-float{
      opacity:0;
      scale:0.96;
    }
  }
}

/* Taille du picker : lit --picker-w (défini sur .hx-carousel) qui est
 * EXCLUSIVEMENT basé sur vh. Le max-width est un garde-fou pour les
 * viewports ultra-étroits, jamais activé sur desktop/mobile normal. */
.hx-picker-mini{
  position:relative;
  width:var(--picker-w, clamp(140px, 30vh, 260px));
  max-width:calc(100vw - 60px);
  background:color-mix(in srgb, var(--panel) 98%, white);
  border:1px solid var(--border);
  border-radius:14px;
  padding:10px 12px;
  display:flex;
  flex-direction:column;
  gap:8px;
}

/* Bandeau supérieur dans le border du picker : toggle à gauche,
 * crédit HexaHunt à droite. Reprend la métaphore d'une barre d'outils
 * type "window chrome" — les deux côtés ne se chevauchent jamais avec
 * le SV square grâce au flex en row qui réserve sa propre hauteur. */
.hx-picker-header{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:10px;
  min-height:22px;
  margin-bottom:2px;
}

/* Toggle mode pad ↔ sliders. L'icône affichée correspond au mode
 * vers lequel on basculera — pattern "show what you'd get". */
.hx-picker-mode-toggle{
  width:22px;
  height:22px;
  display:flex;
  align-items:center;
  justify-content:center;
  flex:0 0 auto;
  padding:0;
  background:color-mix(in srgb, var(--panel-2, rgba(0,0,0,.04)) 80%, transparent);
  border:1px solid color-mix(in srgb, var(--border) 80%, transparent);
  border-radius:6px;
  color:var(--fg-dim);
  cursor:pointer;
  transition:
    background 160ms var(--hx-ease-out),
    color 160ms var(--hx-ease-out),
    transform 160ms var(--hx-ease-out);
}
.hx-picker-mode-toggle:hover{
  background:var(--fg);
  color:var(--panel);
  transform:scale(1.08);
}
.hx-picker-mode-toggle:active{ transform:scale(0.92); }
.hx-mode-icon{ width:14px; height:14px; display:none; }
.hx-picker-mini[data-picker-mode="pad"]     .hx-mode-icon-sliders{ display:block; }
.hx-picker-mini[data-picker-mode="sliders"] .hx-mode-icon-pad    { display:block; }

/* Crédit "Powered by HexaHunt" : tiny label, underline au hover. */
.hx-picker-credit{
  font-family:'DM Mono','JetBrains Mono',monospace;
  font-size:9px;
  letter-spacing:.8px;
  color:var(--fg-dim);
  text-decoration:none;
  opacity:.65;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
  min-width:0;
  transition:opacity 160ms var(--hx-ease-out), color 160ms var(--hx-ease-out);
}
.hx-picker-credit strong{
  font-weight:700;
  color:var(--fg);
}
.hx-picker-credit:hover{
  opacity:1;
  text-decoration:underline;
  text-underline-offset:3px;
}

/* Sections exclusives : on montre pad OU sliders selon le data-attr */
.hx-picker-pad{ display:flex; flex-direction:column; gap:clamp(6px, 1vw, 12px); }
.hx-picker-sliders{ display:none; flex-direction:column; gap:10px; padding:4px 2px; }
.hx-picker-mini[data-picker-mode="sliders"] .hx-picker-pad     { display:none; }
.hx-picker-mini[data-picker-mode="sliders"] .hx-picker-sliders { display:flex; }

/* ── 3 sliders H/S/V ─────────────────────────────────────────── */
.hx-slider-row{
  display:flex;
  align-items:center;
  gap:8px;
}
.hx-slider-label{
  font-family:'DM Mono','JetBrains Mono',monospace;
  font-size:10px;
  font-weight:700;
  letter-spacing:1.5px;
  color:var(--muted);
  width:12px;
  flex:0 0 auto;
}
.hx-slider{
  position:relative;
  flex:1 1 auto;
  height:14px;
  border-radius:7px;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.22);
  cursor:ew-resize;
  touch-action:none;
  user-select:none;
}
/* Hue slider : gradient rainbow statique, posé en CSS (S et V sont
 * posés dynamiquement par refreshPicker). */
.hx-slider-hue{
  background:linear-gradient(90deg,
    #f00 0%, #ff0 16.66%, #0f0 33.33%, #0ff 50%,
    #00f 66.66%, #f0f 83.33%, #f00 100%);
}
.hx-slider-cursor{
  position:absolute;
  top:50%;
  left:0;
  width:10px;
  height:20px;
  border:2px solid #fff;
  border-radius:4px;
  background:rgba(255,255,255,.3);
  box-shadow:0 0 0 1px rgba(0,0,0,.6), 0 2px 4px rgba(0,0,0,.4);
  transform:translate(-50%, -50%);
  pointer-events:none;
}
.hx-picker-mini .hx-sv-square{
  aspect-ratio:1;
  border-radius:10px;
}
.hx-picker-mini .hx-hue{ height:10px; border-radius:6px; }
.hx-picker-mini .hx-hue-cursor{ width:8px; height:16px; }
.hx-picker-mini .hx-hex-readout{
  padding:4px 8px;
  font-size:12px;
  background:transparent;
}

/* Flèche triangulaire sous le picker, pointe vers le tile actif
 * (toujours au centre du viewport). Couleur match le fond de la carte. */
.hx-picker-caret{
  position:absolute;
  left:50%; top:100%;
  transform:translateX(-50%);
  width:0; height:0;
  border-left:9px solid transparent;
  border-right:9px solid transparent;
  border-top:10px solid color-mix(in srgb, var(--panel) 98%, white);
  margin-top:-1px;
  filter:drop-shadow(0 1px 0 var(--border));
}

/* ─── Carousel ─────────────────────────────────────────────────
 * Structure :
 *   .hx-carousel         → flex row : [◀ arrow] [viewport] [▶ arrow]
 *   .hx-carousel-viewport → conteneur avec position:relative, pas
 *                           d'overflow:hidden (les tiles éloignés
 *                           s'effacent via opacity plutôt que clip).
 *                           Contient le picker flottant (absolute) +
 *                           le track.
 *   .hx-carousel-track    → flex nowrap avec les 21 tiles. Translaté
 *                           horizontalement via --track-x (posé par
 *                           _positionCarousel) pour centrer l'active.
 *   .hx-line-tile         → --hx-dist posé inline, opacity calculée
 *                           → fade progressif des voisins (dist 1=80%,
 *                           2=60%, 3=40%, 4=20%, 5+=invisible).
 */
.hx-carousel{
  --tile-size:clamp(38px, 4vw, 54px);
  /* Largeur du picker : DÉPEND UNIQUEMENT DE LA HAUTEUR (vh) pour
   * que le picker rétrécisse sur écran bas. `calc(100vh - 440px)`
   * réserve l'espace pour footer (~120) + row (~54) + marges et gap
   * (~48) + un peu de marge de sécurité. Clampé entre 140 et 260. */
  --picker-w:clamp(140px, calc(100vh - 440px), 260px);
  display:flex;
  /* (le @supports dvh est en fin de fichier — les custom properties
   * n'acceptent pas le fallback en double déclaration) */
  /* flex-end : les flèches s'alignent sur le bas du viewport (=
   * la row), pas sur son centre vertical qui tombe dans l'espace
   * réservé au picker. */
  align-items:flex-end;
  justify-content:center;
  gap:clamp(8px, 1.4vw, 18px);
  width:100%;
  max-width:100%;
}
.hx-carousel-viewport{
  position:relative;
  flex:1 1 auto;
  min-width:0;
  /* overflow visible : les tiles éloignés sont masqués par
   * l'opacity (via --hx-dist) plutôt qu'un clip dur. #view-hexahunt
   * a overflow:hidden qui coupe à l'extérieur de la page. */
  overflow:visible;
  /* RÉSERVE pour le picker au-dessus du track. --picker-reserve est
   * posé par JS (_updatePickerReserve) à la hauteur réelle mesurée
   * du picker → bascule dynamiquement entre mode pad (~300px) et
   * mode sliders (~140px). Le fallback calc(var(--picker-w) + 170px)
   * sert pour le rendu initial avant que JS ait pu mesurer. */
  padding-top:var(--picker-reserve, calc(var(--picker-w) + 170px));
  padding-bottom:12px;
  transition:padding-top 320ms var(--hx-ease-in-out);
}
.hx-carousel-track{
  display:flex;
  flex-wrap:nowrap;
  align-items:flex-end;
  justify-content:flex-start;
  gap:clamp(6px, 1vw, 14px);
  padding:8px 4px;
  width:max-content;
  transform:translateX(var(--track-x, 0px));
  transition:transform 380ms var(--hx-ease-in-out);
  will-change:transform;
}
/* .is-initial : posée au mount pour que le 1er positionnement du
 * track se fasse instantanément (pas de slide depuis 0). Retirée
 * en rAF juste après ; les navigations suivantes animent. */
.hx-carousel-track.is-initial{ transition:none; }

/* ─── Vue GRILLE ────────────────────────────────────────────────
 * Toggle par le lien "VUE GRILLE" dans le footer. _toggleGridView
 * fait un FLIP (capture before, toggle class, capture after, invert +
 * animate vers identity) pour animer toutes les lignes depuis leur
 * position de carousel vers leur place dans la grille.
 *
 * 5 × 5 = 25 slots pour 21 lignes (4 vides en fin de dernière row).
 * sqrt(21) ≈ 4.58 → 5 colonnes est la config la plus proche d'un
 * carré (1:1), plutôt que 7×3 qui serait trop allongé. */
.hx-carousel-track.is-grid{
  display:grid;
  grid-template-columns:repeat(5, clamp(42px, 5vw, 62px));
  grid-auto-rows:clamp(42px, 5vw, 62px);
  gap:clamp(12px, 1.6vw, 22px);
  padding:clamp(16px, 2vh, 32px);
  justify-content:center;
  justify-items:center;
  align-items:center;
  width:auto;
  transform:none;
}
/* En grille : tous les tiles à 100% d'opacité (pas de fade distance),
 * taille de base (pas de scale 1.55 sur l'active), pas de margin
 * latérale sur l'active. La ligne active est juste mise en avant
 * avec un ring + un glow subtil. */
.hx-carousel-track.is-grid .hx-line-tile{
  opacity:1;
  margin-inline:0;
  width:100%;
  height:100%;
}
.hx-carousel-track.is-grid .hx-line-tile.is-active{
  transform:none;
  box-shadow:
    0 0 0 3px color-mix(in srgb, var(--fg) 55%, transparent),
    0 4px 14px rgba(0,0,0,.15);
}
.hx-carousel-track.is-grid .hx-line-tile.is-active:active{
  transform:scale(.94);
}
/* Picker caché en grille (l'édition se fait en carousel). */
.hx-carousel-track.is-grid .hx-picker-float{
  display:none;
}

/* En grille, on supprime le padding-top du viewport (plus besoin
 * de réserver la place au-dessus pour le picker) et on resserre
 * les paddings du stage. */
.hx-shell-complete:has(.hx-carousel-track.is-grid) .hx-complete-stage{
  padding:clamp(20px, 4vh, 48px) 24px;
  transition:padding 300ms var(--hx-ease-out);
}
.hx-shell-complete:has(.hx-carousel-track.is-grid) .hx-carousel-viewport{
  padding-top:0;
  padding-bottom:0;
  transition:padding 300ms var(--hx-ease-out);
}

/* ─── Flèches de navigation ─────────────────────────────────── */
.hx-carousel-arrow{
  flex:0 0 auto;
  width:clamp(38px, 4.2vw, 48px);
  height:clamp(38px, 4.2vw, 48px);
  display:flex;
  align-items:center;
  justify-content:center;
  padding:0;
  background:color-mix(in srgb, var(--panel) 98%, white);
  border:1px solid var(--border);
  border-radius:50%;
  color:var(--fg);
  cursor:pointer;
  box-shadow:0 2px 6px rgba(0,0,0,.06);
  transition:
    transform 160ms var(--hx-ease-spring),
    background 180ms var(--hx-ease-out),
    color 160ms var(--hx-ease-out),
    border-color 160ms var(--hx-ease-out),
    box-shadow 180ms var(--hx-ease-out),
    opacity 160ms var(--hx-ease-out);
}
.hx-carousel-arrow svg{
  width:clamp(16px, 1.8vw, 22px);
  height:clamp(16px, 1.8vw, 22px);
  display:block;
}
@media (hover:hover) and (pointer:fine){
  .hx-carousel-arrow:hover:not(:disabled){
    transform:scale(1.08);
    background:var(--fg);
    color:var(--panel);
    border-color:var(--fg);
    box-shadow:0 4px 12px rgba(0,0,0,.14);
  }
}
.hx-carousel-arrow:active:not(:disabled){
  transform:scale(0.94);
  transition:transform 110ms var(--hx-ease-out);
}
.hx-carousel-arrow:disabled{
  opacity:.28;
  cursor:not-allowed;
  box-shadow:none;
}

/* Tile de ligne : clickable, 3 états (empty/active/filled) et 2
 * formes (métro=rond via data-type / RER=carré arrondi). Taille
 * fluide pour que les 21 tiles tiennent en une row sans scroll.
 *
 * Animation d'entrée : à l'apparition, le tile fade-in + slide-up
 * via @starting-style, avec un stagger personnel posé en inline
 * (--hx-enter-delay défini par JS à la création). Se joue UNE fois,
 * au mount — _renderLinesGrid mute ensuite les classes sans recréer
 * le DOM, donc pas de re-animation à chaque clic. */
.hx-line-tile{
  position:relative;
  flex:0 0 auto;
  width:var(--tile-size);
  height:var(--tile-size);
  display:flex; align-items:center; justify-content:center;
  padding:0; margin:0;
  background:#fff;    /* Par défaut blanc : matche la valeur initiale
                         du picker et la ligne active au chargement. */
  border:2px solid var(--border-strong, var(--border));
  color:var(--fg-dim);
  /* Barlow 800 : le plus proche de la signalétique RATP (Parisine) —
   * sans-serif géométrique aux formes rondes. */
  font-family:'Barlow','Barlow Semi Condensed','Helvetica Neue',sans-serif;
  font-weight:800;
  /* Texte ≈ 62% du diamètre du cercle. */
  font-size:calc(var(--tile-size, 54px) * 0.62);
  cursor:pointer;
  will-change:transform, opacity;
  /* Opacity calée sur la distance à la ligne active (--hx-dist posé
   * inline par _renderLinesGrid). dist 0 = 100%, dist 1 = 80%,
   * dist 2 = 60%, …, dist 5+ = invisible. */
  opacity:max(0, calc(1 - var(--hx-dist, 0) * 0.2));
  transition:
    transform 240ms var(--hx-ease-spring),
    opacity 300ms var(--hx-ease-out),
    border-color 180ms var(--hx-ease-out),
    box-shadow 220ms var(--hx-ease-out),
    background 220ms var(--hx-ease-out),
    color 200ms var(--hx-ease-out);
}
/* Entry animation ONE-SHOT : ne joue qu'avant que JS pose la classe
 * .is-mounted sur le track (cf. hexahunt.js::_renderLinesGrid). Après
 * mount, les transitions ci-dessus pilotent tous les changements
 * d'état sans rejouer l'entrée. */
.hx-carousel-track:not(.is-mounted) .hx-line-tile{
  animation:hx-tile-in 360ms var(--hx-ease-out) both;
  animation-delay:var(--hx-enter-delay, 0ms);
}
.hx-carousel-track:not(.is-mounted) .hx-line-tile.is-active{
  animation:hx-tile-in-active 420ms var(--hx-ease-spring) both;
}
@keyframes hx-tile-in{
  from{ opacity:0; transform:translateY(10px) scale(0.96); }
  /* Le `to` utilise la MÊME formule d'opacité que le style statique
   * (--hx-dist). Sans ça, les tiles terminent leur entrée à opacity:1
   * puis "snap" vers leur opacité de distance quand .is-mounted est
   * posée → tous s'affichent à 100% pendant ~1 seconde. Là, chaque
   * tile arrive directement à son opacité finale. */
  to  {
    opacity:max(0, calc(1 - var(--hx-dist, 0) * 0.2));
    transform:translateY(0) scale(1);
  }
}
/* L'active termine à scale(1.55) pour matcher .is-active et éviter
 * un snap visuel à la fin de l'animation. Opacité 1 (dist 0). */
@keyframes hx-tile-in-active{
  from{ opacity:0; transform:translateY(10px) scale(0.92); }
  to  { opacity:1; transform:translateY(0) scale(1.55); }
}
/* Forme signalétique */
.hx-line-tile[data-type="metro"]{ border-radius:50%; }
.hx-line-tile[data-type="rer"]  { border-radius:10px; }

/* État "vide" : fond blanc pur, bord gris clair, chiffre muet — on
 * part du blanc par défaut pour matcher la sémantique "pas encore
 * calibrée" (le blanc est aussi la valeur initiale du picker). */
.hx-line-tile.is-empty{
  background:#fff;
  color:var(--fg-dim);
  border-color:color-mix(in srgb, var(--border-strong, var(--border)) 80%, transparent);
}
/* État "rempli" : la couleur de la PROPOSITION du joueur est posée
 * inline via JS. Bord sombre + léger relief. */
.hx-line-tile.is-filled{
  border-color:rgba(0,0,0,.35);
  box-shadow:
    inset 0 1px 2px rgba(255,255,255,.25),
    inset 0 -1px 2px rgba(0,0,0,.2),
    0 2px 4px rgba(0,0,0,.12);
}
/* État "active" : scale marqué + margin-inline pour écarter les
 * voisins et éviter qu'ils soient recouverts par le scale 1.55.
 *   - transform-origin:bottom center → grandit vers le haut, bas
 *     aligné avec les autres tiles.
 *   - margin-inline sans transition (change instantanément quand la
 *     classe bouge, sinon getBoundingClientRect lirait la mauvaise
 *     position pendant la transition). */
.hx-line-tile.is-active{
  border-color:rgba(0,0,0,.55);
  transform:scale(1.55);
  transform-origin:bottom center;
  margin-inline:calc(var(--tile-size, 54px) * 0.32);
  box-shadow:
    0 0 0 2px color-mix(in srgb, var(--panel) 98%, white),
    0 6px 14px rgba(0,0,0,.22),
    inset 0 1px 2px rgba(255,255,255,.3),
    inset 0 -1px 2px rgba(0,0,0,.2);
  z-index:3;
}
/* Hover non-actif : on ramène la tile à 100% d'opacité + petit
 * lift pour signaler qu'elle est cliquable même quand elle est
 * fade par la formule --hx-dist. */
@media (hover:hover) and (pointer:fine){
  .hx-line-tile:not(.is-active):hover{
    transform:translateY(-3px);
    border-color:var(--fg);
    box-shadow:0 4px 10px rgba(0,0,0,.1);
    opacity:1;
  }
}
/* Tiles totalement invisibles en mode carousel (dist ≥ 5 → opacity 0) :
 * plus aucune interaction. data-hidden posé par _renderLinesGrid. */
.hx-line-tile[data-hidden]{
  pointer-events:none;
}
/* En mode grille par contre, TOUS les tiles sont visibles (override
 * opacity:1 dans .is-grid) → ils doivent aussi tous être cliquables,
 * même ceux qui étaient data-hidden en carousel. */
.hx-carousel-track.is-grid .hx-line-tile[data-hidden]{
  pointer-events:auto;
}
/* Feedback press : léger squeeze. */
.hx-line-tile:active{
  transform:scale(.94);
  transition:transform 110ms var(--hx-ease-out);
}
.hx-line-tile.is-active:active{
  transform:scale(1.48);
}

.hx-chip-shadow{ display:none !important; }

/* ── Footer : toggle "VUE GRILLE" (lien stylé) + CTA sombre dessous. ── */
.hx-complete-footer{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:14px;
  padding:24px 16px 36px;
}
.hx-view-toggle{
  background:transparent;
  border:0;
  padding:4px 8px;
  font-family:'DM Mono','JetBrains Mono',monospace;
  font-size:11px;
  font-weight:600;
  letter-spacing:2.4px;
  text-transform:uppercase;
  color:var(--fg);
  text-decoration:underline;
  text-underline-offset:4px;
  text-decoration-thickness:1px;
  cursor:pointer;
  transition:
    opacity 160ms var(--hx-ease-out),
    letter-spacing 260ms var(--hx-ease-out),
    text-underline-offset 200ms var(--hx-ease-out);
}
@media (hover:hover) and (pointer:fine){
  .hx-view-toggle:hover{
    opacity:.65;
    letter-spacing:2.8px;
    text-underline-offset:6px;
  }
}
.hx-view-toggle:active{
  transform:translateY(1px);
}
.hx-diag-btn{
  display:inline-flex;
  align-items:center;
  gap:14px;
  padding:9px 10px 9px 20px;
  background:#1a1a1a;
  color:#f2f2f2;
  border:1px solid rgba(0,0,0,.4);
  border-radius:8px;
  font-family:'DM Mono','JetBrains Mono',monospace;
  font-size:11px;
  font-weight:600;
  letter-spacing:2.4px;
  text-transform:uppercase;
  cursor:pointer;
  box-shadow:0 4px 14px rgba(0,0,0,.18), inset 0 1px 0 rgba(255,255,255,.08);
  transition:transform .15s, box-shadow .15s, filter .15s;
}
.hx-diag-btn{
  transition:
    transform 160ms var(--hx-ease-out),
    box-shadow 180ms var(--hx-ease-out),
    filter 160ms ease;
}
@media (hover:hover) and (pointer:fine){
  .hx-diag-btn:hover:not(:disabled){
    transform:translateY(-1px);
    box-shadow:0 6px 18px rgba(0,0,0,.22), inset 0 1px 0 rgba(255,255,255,.1);
    filter:brightness(1.12);
  }
}
.hx-diag-btn:active:not(:disabled){
  transform:scale(0.97);
  transition:transform 110ms var(--hx-ease-out);
}
.hx-diag-btn:disabled{ opacity:.55; cursor:not-allowed; }
/* L'attribut `hidden` seul ne suffit pas : notre `.hx-diag-btn { display:
 * inline-flex }` a la même spécificité que le [hidden] de l'UA stylesheet
 * → l'author gagne et le bouton reste visible. On force le display:none
 * avec une spécificité plus haute. */
.hx-diag-btn[hidden]{ display:none !important; }
.hx-diag-btn .hx-diag-count{
  padding:3px 9px;
  background:rgba(0,0,0,.55);
  color:rgba(255,255,255,.55);
  border-radius:6px;
  font-size:10px;
  letter-spacing:1.6px;
  transition:color 220ms ease, background 220ms ease;
}
/* Quand le bouton est enabled (21/21), on le met en avant */
.hx-diag-btn:not(:disabled) .hx-diag-count{
  color:rgba(255,255,255,.9);
  background:rgba(255,255,255,.12);
}

/* Breathing subtil sur le curseur du SV square : signale que le
 * picker est vivant / draggable. Se coupe au hover/drag pour ne pas
 * gêner la lecture de la couleur. */
@keyframes hx-sv-breath{
  0%, 100%{ box-shadow:0 0 0 1px rgba(0,0,0,.7), 0 2px 6px rgba(0,0,0,.5), 0 0 0 0 rgba(255,255,255,0); }
  50%     { box-shadow:0 0 0 1px rgba(0,0,0,.7), 0 2px 6px rgba(0,0,0,.5), 0 0 0 5px rgba(255,255,255,.18); }
}
.hx-picker-mini .hx-sv-cursor{
  animation:hx-sv-breath 2.6s ease-in-out infinite;
}
.hx-picker-mini:hover .hx-sv-cursor,
.hx-picker-mini:active .hx-sv-cursor,
.hx-sv-square:active ~ * .hx-sv-cursor{
  animation:none;
}

/* Respect prefers-reduced-motion : neutralise les animations non
 * essentielles dans la vue. On garde opacity (aide à la compré-
 * hension) mais on coupe transforms et keyframes. */
@media (prefers-reduced-motion: reduce){
  #view-hexahunt .hx-line-tile,
  #view-hexahunt .hx-picker-float,
  #view-hexahunt .hx-diag-btn,
  #view-hexahunt .hx-sv-cursor{
    animation:none !important;
    transition-duration:120ms !important;
  }
  #view-hexahunt .hx-line-tile.is-active{
    /* Garde le scale pour l'indication d'état, sans l'animer */
    transition:none !important;
  }
}

/* ══════════════════════════════════════════════════════════════
 * DIAGNOSTIC REVEAL — grille target ↔ guess ↔ score par ligne
 * ══════════════════════════════════════════════════════════════ */
.hx-shell-diagnostic{
  display:flex; flex-direction:column;
  gap:20px;
  padding:80px clamp(16px, 4vw, 40px) 32px;
  min-height:100vh;min-height:100dvh;
  max-width:960px;
  margin:0 auto;
}
.hx-diag-head{
  display:flex; justify-content:space-between; align-items:flex-end;
  gap:20px;
  padding-bottom:14px;
  border-bottom:1px solid var(--border);
}
.hx-diag-title{
  font-family:'Oswald','Barlow Semi Condensed',sans-serif;
  font-weight:700; font-size:clamp(20px, 3vw, 32px);
  letter-spacing:1.4px;
  color:var(--fg);
  text-transform:uppercase;
}
.hx-diag-avg{
  display:flex; align-items:baseline; gap:10px;
  font-family:'Oswald','Barlow Semi Condensed',sans-serif;
}
.hx-diag-avg-num{ font-size:48px; font-weight:700; color:var(--accent, #e8a23a); line-height:1; }
.hx-diag-avg-unit{ font-size:16px; color:var(--fg-dim); }
.hx-diag-avg-verdict{
  font-family:'DM Mono','JetBrains Mono',monospace;
  font-size:12px; letter-spacing:2px;
  padding:6px 12px;
  border:2px solid currentColor;
  color:var(--accent, #e8a23a);
  text-transform:uppercase;
}

.hx-diag-grid{
  display:flex; flex-direction:column;
  gap:6px;
}
.hx-diag-row{
  display:grid;
  grid-template-columns:40px 56px 20px 56px 1fr auto;
  align-items:center;
  gap:12px;
  padding:10px 14px;
  background:color-mix(in srgb, var(--panel) 94%, transparent);
  border:1px solid var(--border);
  border-radius:10px;
  transition:transform .12s ease;
}
.hx-diag-row:hover{ transform:translateX(2px); }
.hx-diag-name{
  font-family:'Oswald','Barlow Semi Condensed',sans-serif;
  font-weight:700; font-size:16px;
  color:var(--fg);
}
.hx-diag-chip{
  width:56px; height:56px;
  display:inline-flex; align-items:center; justify-content:center;
  font-family:'Oswald','Barlow Semi Condensed',sans-serif;
  font-weight:700; font-size:22px;
  border:1px solid rgba(0,0,0,.3);
  box-shadow:
    inset 0 1px 2px rgba(255,255,255,.25),
    inset 0 -1px 2px rgba(0,0,0,.25),
    0 2px 3px rgba(0,0,0,.35);
}
.hx-diag-chip[data-type="metro"]{ border-radius:50%; aspect-ratio:1; }
.hx-diag-chip[data-type="rer"]  { border-radius:10px; }
.hx-diag-arrow{
  font-size:18px; color:var(--muted);
  text-align:center;
}
.hx-diag-hex{
  font-family:'DM Mono','JetBrains Mono',monospace;
  font-size:13px; letter-spacing:1.5px;
  color:var(--fg-dim);
}
.hx-diag-score{
  font-family:'Oswald','Barlow Semi Condensed',sans-serif;
  font-weight:700; font-size:22px;
  min-width:52px; text-align:right;
  color:var(--fg);
}
/* Teintes du score selon tier */
.hx-diag-row[data-tier="s"] .hx-diag-score{ color:#0f8a3d; }
.hx-diag-row[data-tier="a"] .hx-diag-score{ color:#1f8a2a; }
.hx-diag-row[data-tier="b"] .hx-diag-score{ color:#d89623; }
.hx-diag-row[data-tier="c"] .hx-diag-score{ color:#d96b2b; }
.hx-diag-row[data-tier="d"] .hx-diag-score{ color:#c13a2e; }

/* ══════════════════════════════════════════════════════════════
 * SOLO / MULTI MODE — DA alignée avec le mode Toutes les lignes.
 * Structure : kicker (ligne cible) → arena (2 tiles cible/guess,
 * picker absolute au-dessus du guess) → reveal (score après valid).
 * ══════════════════════════════════════════════════════════════ */
.hx-shell-solo{
  /* Tokens propres au solo : tiles plus grosses que dans le carousel
   * (on a 2 tiles seulement, ils sont le focal point), et picker width
   * ajustée (plus de place en bas que dans le carousel → on peut être
   * un peu plus grand). */
  --tile-size:clamp(74px, 11vh, 128px);
  --picker-w:clamp(140px, calc(100vh - 480px), 260px);
  display:flex;
  flex-direction:column;
  min-height:100vh;min-height:100dvh;
  position:relative;
}
.hx-shell-solo .hx-nav{
  position:absolute;
  top:20px; left:20px;
  z-index:20;
}

/* Kicker en haut du stage : "LIGNE CIBLE" · MÉTRO · 4 · stats */
.hx-solo-kicker{
  text-align:center;
  padding:0 24px 12px;
  font-family:'DM Mono','JetBrains Mono',monospace;
}
.hx-solo-kicker-label{
  font-size:10px;
  letter-spacing:2.6px;
  color:var(--muted);
  text-transform:uppercase;
}
.hx-solo-kicker-title{
  margin-top:4px;
  font-family:'Oswald','Barlow Semi Condensed',sans-serif;
  font-size:clamp(18px, 2.4vh, 26px);
  font-weight:700;
  letter-spacing:1.6px;
  color:var(--fg);
  text-transform:uppercase;
}
.hx-solo-kicker-stats{
  display:flex;
  justify-content:center;
  gap:20px;
  margin-top:8px;
  font-size:10px;
  letter-spacing:1.6px;
  color:var(--fg-dim);
}
.hx-solo-kicker-stats strong{
  font-weight:700;
  color:var(--fg);
}

/* Arena : 2 colonnes côte à côte (Cible / Ta couleur). Le picker est
 * absolute au-dessus du tile guess — ancré en CSS via le wrap qui a
 * position:relative. Pas de calcul JS ici. */
.hx-solo-arena{
  display:flex;
  align-items:flex-end;
  justify-content:center;
  gap:clamp(28px, 5vw, 80px);
  padding:var(--picker-reserve, calc(var(--picker-w) + 170px)) 24px clamp(16px, 3vh, 32px);
  transform:scale(1);
  transform-origin:center;
  transition:
    padding-top 320ms var(--hx-ease-in-out),
    gap 320ms var(--hx-ease-in-out),
    transform 460ms cubic-bezier(0.34, 1.3, 0.4, 1);
}
/* Après validation, l'arène scale up → les deux ronds grossissent
 * ensemble. Le padding-top, qui réservait l'espace du picker au-dessus,
 * retombe à la même valeur que le padding-bottom → l'arène devient
 * symétrique et les tiles se re-centrent verticalement dans le stage
 * (qui a justify-content:center). */
.hx-solo-arena.is-revealed{
  transform:scale(1.3);
  padding-top:clamp(16px, 3vh, 32px);
}
/* Avant validation, la colonne CIBLE est masquée (pas de "?" visible).
 * Après _showReveal, JS ajoute .is-revealed à l'arène → la colonne
 * apparaît avec un pop-in qui crée l'effet de révélation. */
.hx-solo-arena:not(.is-revealed) .hx-solo-col-target{
  display:none;
}
.hx-solo-arena.is-revealed .hx-solo-col-target{
  animation:hx-solo-target-in 540ms cubic-bezier(0.34, 1.3, 0.4, 1) both;
}
@keyframes hx-solo-target-in{
  from{ opacity:0; transform:translateY(14px) scale(0.78); }
  to  { opacity:1; transform:translateY(0) scale(1); }
}
.hx-solo-col{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:10px;
}
.hx-solo-col-lbl{
  font-family:'DM Mono','JetBrains Mono',monospace;
  font-size:10px;
  letter-spacing:2.4px;
  color:var(--muted);
  text-transform:uppercase;
}

/* Wrap autour du tile guess → containing block du picker absolute. */
.hx-solo-tile-wrap{
  position:relative;
  display:flex;
  align-items:flex-end;
  justify-content:center;
}
.hx-solo-tile-wrap .hx-picker-float{
  position:absolute;
  left:50%;
  bottom:calc(100% + var(--tile-size) * 0.15 + 18px);
  transform:translateX(-50%);
  top:auto;
}

/* Chips solo : plus gros que les tiles de carousel. Pas de fade-dist
 * (opacity:1 forcé), pas de margin-inline sur l'active (1 seul tile
 * actif, pas de voisins à écarter). */
.hx-shell-solo .hx-line-tile.hx-solo-chip{
  width:var(--tile-size);
  height:var(--tile-size);
  /* Même ratio que les tiles carousel (62% du diamètre). */
  font-size:calc(var(--tile-size, 100px) * 0.62);
  border-width:2px;
  opacity:1;
  margin-inline:0;
  will-change:transform;
}
.hx-shell-solo .hx-line-tile.hx-solo-chip.is-active{
  transform:scale(1.05);
  transform-origin:bottom center;
  box-shadow:
    0 0 0 2px color-mix(in srgb, var(--panel) 98%, white),
    0 6px 14px rgba(0,0,0,.18),
    inset 0 1px 2px rgba(255,255,255,.3),
    inset 0 -1px 2px rgba(0,0,0,.2);
  z-index:2;
}
.hx-shell-solo .hx-line-tile.hx-solo-chip:not(.is-active):hover{
  transform:translateY(-2px);
}

/* État "mystery" du tile cible : hachures avant le reveal. */
.hx-line-tile.is-mystery{
  background:repeating-linear-gradient(45deg,
    rgba(0,0,0,.05) 0 9px,
    rgba(0,0,0,.015) 9px 18px);
  color:var(--fg-dim);
  border-color:color-mix(in srgb, var(--border-strong) 70%, transparent);
  border-style:dashed;
}
.hx-line-tile.is-revealed{
  border-style:solid;
  transition:background 380ms var(--hx-ease-out), color 380ms var(--hx-ease-out), border-color 380ms var(--hx-ease-out);
}

/* Reveal solo = fiche listing-report (même DA que tracé free). Le look
 * et les animations (lr-print / lr-print-out) sont définis dans
 * styles/theme/pinboard/listing-report.css — ici on ne fait que la
 * positionner pour la vue hexahunt : overlay fixe bas-centre, au-dessus
 * du footer, masquée par défaut, fade-in via .show. */
#view-hexahunt #hxReveal.trace-score{
  position:fixed;
  /* top/left explicitement auto : la règle de base `.trace-score`
   * (styles/views/trace.css) pose `top:210px; left:16px` — sans ça,
   * combiné avec mon right/bottom, le picker est sur-contraint et
   * s'ancre en haut-gauche. */
  top:auto;
  left:auto;
  right:clamp(12px, 2vw, 24px);
  bottom:clamp(12px, 2vh, 24px);
  z-index:60;
  opacity:0;
  pointer-events:none;
  transition:opacity 220ms ease;
}
#view-hexahunt #hxReveal.trace-score.show{
  opacity:1;
  pointer-events:auto;
}
#view-hexahunt #hxReveal.trace-score[hidden]{ display:none !important; }

/* Variante "ghost" du bouton footer — action secondaire (Ligne suivante). */
.hx-diag-btn.hx-diag-btn-ghost{
  background:transparent;
  color:var(--fg);
  border-color:var(--border-strong, var(--border));
  box-shadow:none;
}
.hx-diag-btn.hx-diag-btn-ghost:hover:not(:disabled){
  background:color-mix(in srgb, var(--fg) 8%, transparent);
  filter:none;
}
.hx-diag-btn.hx-diag-btn-ghost .hx-diag-label{ color:var(--fg); }

/* Crédit "Powered by HexaHunt" en bas du mode-config hexahunt.
 * Scopé au view #view-mode-config pour ne pas polluer le reste. */
/* ─── Sticker "Powered by Hexahunt" — façon autocollant die-cut pill,
 *     collé sous le coin inférieur-droit de la plaque titre. Couleurs
 *     (`--s-bg` / `--s-fg`) piochées au hasard côté JS à chaque render
 *     (cf. hexa-config.js::STICKER_COLORS). Lien vers hexahunt.xyz. ─ */
/* mc-head au-dessus des sections suivantes (bt-toggle + posters) dans
 * l'empilement : sinon le sticker, qui dépasse sous le panneau, se
 * fait recouvrir par les éléments-frères qui interceptent les clics. */
#view-mode-config .mc-head{ position:relative; z-index:10; }
#view-mode-config .hx-sticker{
  position:absolute;
  /* Petit badge die-cut qui DÉBORDE le coin inférieur-droit de la plaque
   * vers l'extérieur (bas + droite, dans le « mur »). Il se loge dans la
   * zone vide à droite du titre/sous-titre (tous deux centrés) et reste à
   * droite + au-dessus de la rangée de contrôles SOLO/MULTI/RÉGLAGES → il
   * ne recouvre ni le titre ni les boutons. */
  top:auto;
  bottom:-6px;
  right:-16px;
  z-index:5;
  /* La plaque issue d'un clic landing porte .mc-head-plate { pointer-events
   * :none } : sans ce reset, le lien <a> vers hexahunt.xyz n'est PAS
   * cliquable. On réactive explicitement les events sur le sticker. */
  pointer-events:auto;
  display:inline-flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  padding:6px 12px 7px;
  /* Shape "die-cut" qui suit le contour général du texte : rounded
   * rectangle serré autour du bloc texte (pas une pill, pour que la
   * forme reste lisible comme "sticker texte"). Outline blanche
   * autour = le bord papier typique d'un sticker découpé. */
  border-radius:12px;
  background:var(--s-bg, #6b4716);
  /* Texte = même teinte que le fond, tinté pour lisibilité.
   * Tous les bgs de la palette sont foncés (luminance < .35) →
   * 30% bg + 70% blanc donne un pale-wash de la même couleur avec
   * contraste ~5:1 sur le fond, lisible et monochrome. */
  color:color-mix(in srgb, var(--s-bg, #6b4716) 30%, white);
  outline:3px solid #f6efdd;               /* halo papier cut-out */
  outline-offset:-1px;
  text-decoration:none;
  box-shadow:
    0 4px 8px rgba(0,0,0,.35),
    0 10px 22px rgba(0,0,0,.22),
    inset 0 1px 0 rgba(255,255,255,.1),
    inset 0 -2px 0 rgba(0,0,0,.22);
  transform:rotate(-4deg);
  transform-origin:100% 100%;   /* pivot sur le coin bas-droite (ancrage bottom) */
  cursor:pointer;
  transition:
    transform 220ms cubic-bezier(.34,1.3,.4,1),
    box-shadow 220ms ease;
}
#view-mode-config .hx-sticker:hover{
  transform:rotate(-1deg) scale(1.05);
  box-shadow:
    0 6px 14px rgba(0,0,0,.4),
    0 16px 30px rgba(0,0,0,.28),
    inset 0 1px 0 rgba(255,255,255,.14),
    inset 0 -2px 0 rgba(0,0,0,.25);
}
#view-mode-config .hx-sticker:active{
  transform:rotate(-4deg) scale(0.96);
}
#view-mode-config .hx-sticker-kicker{
  font-family:'DM Mono','JetBrains Mono',monospace;
  font-size:clamp(7px, .65vw, 8px);
  font-weight:500;
  letter-spacing:1.5px;
  text-transform:uppercase;
  opacity:.88;
  margin-bottom:1px;
  line-height:1;
}
#view-mode-config .hx-sticker-brand{
  font-family:'Barlow','Barlow Semi Condensed','Helvetica Neue',sans-serif;
  font-weight:900;
  font-size:clamp(13px, 1.3vw, 16px);
  line-height:.95;
  letter-spacing:-.3px;
  color:inherit;
  text-shadow:0 1px 0 rgba(0,0,0,.25);
}

/* Responsive : sticker plus compact sur mobile. Overhang réduit pour
 * rester dans le viewport à 320px. */
@media (max-width: 640px){
  #view-mode-config .hx-sticker{
    top:auto;
    bottom:-5px;
    right:-8px;
    padding:5px 10px 6px;
    border-radius:10px;
  }
  #view-mode-config .hx-sticker-kicker{ font-size:7px; letter-spacing:1.2px; }
  #view-mode-config .hx-sticker-brand{ font-size:13px; }
}

/* Responsive : stack vertical sur mobile / tablette */
@media (max-width: 900px){
  .hx-shell{
    grid-template-columns:1fr;
    grid-template-rows:auto auto auto;
    grid-template-areas:
      "brief"
      "picker"
      "actions";
    padding:64px 16px 20px;
    gap:16px;
  }
  .hx-chip{ width:90px; height:90px; font-size:40px; }
  .hx-shell-complete{ padding:0; }
  /* Override des tokens au breakpoint mobile */
  .hx-carousel{ --tile-size:44px; gap:8px; }
  .hx-carousel-track{ gap:10px; }
  /* font-size inherit de la règle principale (calc(tile*0.68) = 30px) */
  .hx-line-tile{ border-width:2px; }
  .hx-complete-footer{ padding:16px 16px 28px; }
  .hx-diag-row{
    grid-template-columns:32px 48px 16px 48px 1fr auto;
    gap:8px; padding:8px 10px;
  }
  .hx-diag-chip{ width:48px; height:48px; font-size:18px; }
}

/* ══ Viewport dynamique mobile ═══════════════════════════════════
 * Les --picker-w dépendent de la hauteur visible : sur mobile, 100vh
 * inclut la zone derrière la barre du navigateur → picker trop grand.
 * (@supports requis : une custom property invalide ne retombe pas sur
 * la déclaration précédente, contrairement aux propriétés normales.) */
@supports (height: 100dvh){
  .hx-carousel{ --picker-w:clamp(140px, calc(100dvh - 440px), 260px); }
  .hx-shell-solo{ --picker-w:clamp(140px, calc(100dvh - 480px), 260px); }
}
