/* DCVisuals Pixelverse — thème sombre lab.dcvisuals.fr */
:root {
  --pv-bg: #050505;
  --pv-panel: #0e1013;
  --pv-panel-2: #14171c;
  --pv-line: #23272e;
  --pv-ink: #edeae4;
  --pv-ink-dim: #9aa0a6;
  --pv-amber: #f5a83c;
  --pv-cyan: #4fd8cf;
  --pv-red: #e0524d;
  --pv-green: #59c98a;
  --pv-mono: "JetBrains Mono", "SFMono-Regular", Consolas, monospace;
  --pv-sans: "Inter", system-ui, -apple-system, sans-serif;
  --pv-radius: 6px;
}
* { box-sizing: border-box; }
/* Garantit que l'attribut hidden masque réellement l'élément même si une classe (ex.
   .editor-panel, .timeline-bar) déclare son propre `display` — sinon la règle UA
   [hidden]{display:none} perd contre le CSS auteur à spécificité égale et l'élément
   reste visible (vide) dans la mise en page. */
[hidden] { display: none !important; }
html, body { margin: 0; padding: 0; background: var(--pv-bg); color: var(--pv-ink); font-family: var(--pv-sans); }
body { min-height: 100vh; }
a { color: var(--pv-cyan); text-decoration: none; }
a:hover { text-decoration: underline; }
:focus-visible { outline: 2px solid var(--pv-amber); outline-offset: 2px; }
button { font-family: inherit; }

/* Header compact orienté jeu */
.pv-header {
  display: flex; align-items: center; gap: 14px; padding: 8px 16px;
  background: var(--pv-panel); border-bottom: 1px solid var(--pv-line);
  position: sticky; top: 0; z-index: 40; font-size: 14px;
}
.pv-header .logo { font-family: var(--pv-mono); font-weight: 700; color: var(--pv-amber); letter-spacing: 0.5px; }
.pv-header nav { display: flex; gap: 12px; flex: 1; }
.pv-header nav a { color: var(--pv-ink-dim); padding: 4px 6px; border-radius: 4px; }
.pv-header nav a.active, .pv-header nav a:hover { color: var(--pv-ink); background: var(--pv-panel-2); text-decoration: none; }
.pv-header nav .nav-disabled { color: #55595f; padding: 4px 6px; cursor: not-allowed; }
.pv-header .actions { display: flex; gap: 8px; }

.pv-btn {
  background: var(--pv-panel-2); color: var(--pv-ink); border: 1px solid var(--pv-line);
  border-radius: var(--pv-radius); padding: 6px 12px; cursor: pointer; font-size: 13px;
}
.pv-btn:hover { border-color: var(--pv-amber); }
.pv-btn.primary { background: var(--pv-amber); color: #16130b; border-color: var(--pv-amber); font-weight: 600; }
.pv-btn.danger { border-color: var(--pv-red); color: var(--pv-red); }
.pv-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.pv-btn.small { padding: 3px 8px; font-size: 12px; }
.pv-btn[aria-pressed="true"] { border-color: var(--pv-cyan); color: var(--pv-cyan); }

.pv-input, .pv-select {
  background: var(--pv-bg); color: var(--pv-ink); border: 1px solid var(--pv-line);
  border-radius: var(--pv-radius); padding: 6px 10px; font-size: 13px; font-family: var(--pv-mono);
}
.pv-input:focus { border-color: var(--pv-cyan); outline: none; }

.pv-panel { background: var(--pv-panel); border: 1px solid var(--pv-line); border-radius: var(--pv-radius); padding: 14px; }
.pv-badge { font-family: var(--pv-mono); font-size: 11px; padding: 2px 7px; border-radius: 999px; border: 1px solid var(--pv-line); color: var(--pv-ink-dim); }
.pv-badge.open { border-color: var(--pv-green); color: var(--pv-green); }
.pv-badge.teaser { border-color: var(--pv-amber); color: var(--pv-amber); }
.pv-badge.frozen { border-color: var(--pv-cyan); color: var(--pv-cyan); }

/* Hub mini-games */
.hub-wrap { max-width: 1100px; margin: 0 auto; padding: 28px 18px 60px; }
.hub-hero h1 { font-family: var(--pv-mono); font-size: clamp(26px, 4vw, 40px); margin: 0 0 6px; }
.hub-hero h1 em { color: var(--pv-amber); font-style: normal; }
.hub-hero p { color: var(--pv-ink-dim); max-width: 640px; }
.hub-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; margin: 26px 0; }
.game-card { display: flex; flex-direction: column; gap: 10px; transition: border-color 0.15s; }
.game-card:hover { border-color: var(--pv-amber); }
.game-card h2 { margin: 0; font-size: 18px; font-family: var(--pv-mono); }
.game-card .thumb { aspect-ratio: 16/9; border-radius: 4px; background: var(--pv-panel-2); display: grid; place-items: center; overflow: hidden; image-rendering: pixelated; }
.game-card .thumb canvas, .game-card .thumb img { width: 100%; height: 100%; object-fit: cover; image-rendering: pixelated; }
.game-card.soon { opacity: 0.6; }
.hub-stats { display: flex; gap: 24px; flex-wrap: wrap; font-family: var(--pv-mono); font-size: 14px; }
.hub-stats b { color: var(--pv-cyan); font-size: 20px; display: block; }
.recent-list { display: flex; gap: 10px; flex-wrap: wrap; }
.recent-list img { width: 64px; height: 64px; image-rendering: pixelated; border: 1px solid var(--pv-line); border-radius: 4px; }

/* Layout Pixelverse */
.pv-layout { display: grid; grid-template-columns: 1fr; gap: 12px; padding: 12px; max-width: 1500px; margin: 0 auto; }
@media (min-width: 1000px) { .pv-layout.editing { grid-template-columns: 1fr 380px; } }
.wall-toolbar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 8px; }
.wall-stage { position: relative; background: #030304; border: 1px solid var(--pv-line); border-radius: var(--pv-radius); overflow: hidden; touch-action: none; }
.wall-stage canvas { display: block; width: 100%; height: 100%; cursor: grab; }
.wall-stage.selecting canvas { cursor: crosshair; }
.wall-hud { position: absolute; left: 10px; bottom: 10px; font-family: var(--pv-mono); font-size: 12px; color: var(--pv-ink-dim); background: rgba(5,5,5,0.75); padding: 4px 8px; border-radius: 4px; pointer-events: none; }
.wall-live { position: absolute; right: 10px; top: 10px; font-family: var(--pv-mono); font-size: 11px; padding: 3px 8px; border-radius: 999px; background: rgba(5,5,5,0.75); }
.wall-live.on { color: var(--pv-green); } .wall-live.off { color: var(--pv-red); }

/* Éditeur */
.editor-panel { display: flex; flex-direction: column; gap: 10px; }
.editor-tools { display: flex; flex-wrap: wrap; gap: 6px; }
.editor-canvas-wrap { position: relative; border: 1px solid var(--pv-line); border-radius: 4px; align-self: center; }
.editor-canvas-wrap canvas { display: block; image-rendering: pixelated; touch-action: none; cursor: crosshair; }
.palette { display: flex; flex-wrap: wrap; gap: 4px; }
.palette .swatch { width: 24px; height: 24px; border-radius: 4px; border: 1px solid var(--pv-line); cursor: pointer; padding: 0; }
.palette .swatch[aria-selected="true"] { outline: 2px solid var(--pv-amber); outline-offset: 1px; }
.editor-guidance { display: flex; flex-direction: column; gap: 4px; font-family: var(--pv-mono); font-size: 11px; color: var(--pv-ink-dim); }
.editor-guidance-swatches { display: flex; gap: 4px; flex-wrap: wrap; }
.editor-guidance-swatches .swatch { width: 22px; height: 22px; border-radius: 4px; border: 1px solid var(--pv-line); cursor: pointer; padding: 0; }
.editor-guidance-swatches .swatch.guidance-main { outline: 2px solid var(--pv-cyan); outline-offset: 1px; }
.editor-guidance-swatches .swatch[aria-selected="true"] { outline: 2px solid var(--pv-amber); outline-offset: 1px; }
.editor-meta { display: flex; align-items: center; gap: 10px; font-family: var(--pv-mono); font-size: 12px; color: var(--pv-ink-dim); }
.editor-preview { width: 48px; height: 48px; image-rendering: pixelated; border: 1px solid var(--pv-line); border-radius: 4px; }

/* Détail case / dialogues — z-index au-dessus de .mini-shell-header (z-index:200, sticky,
   shared/styles/mini-games.css) : sinon un dialogue assez grand pour atteindre le haut du
   viewport voit ses boutons du haut interceptés par l'en-tête sticky, cliquable mais invisible
   au-dessus de lui — bug latent révélé par le viewer Musée (plus grand que les dialogues
   existants). */
.pv-dialog { position: fixed; inset: 0; background: rgba(0,0,0,0.6); display: grid; place-items: center; z-index: 210; padding: 16px; }
.pv-dialog .inner { max-width: 460px; width: 100%; max-height: 85vh; overflow: auto; }
.pv-dialog .inner.wide { max-width: 1100px; width: 92vw; }
.pv-dialog img.big { width: 100%; image-rendering: pixelated; border: 1px solid var(--pv-line); border-radius: 4px; }
.detail-meta { font-family: var(--pv-mono); font-size: 12px; color: var(--pv-ink-dim); line-height: 1.8; }
.detail-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }

/* Musée */
.museum-card { position: relative; }
.museum-empty { color: var(--pv-ink-dim); font-size: 14px; grid-column: 1 / -1; }
.museum-cell-panel { position: fixed; right: 16px; bottom: 16px; max-width: 280px; z-index: 220; }
.museum-demo-badge { border-color: var(--pv-cyan); color: var(--pv-cyan); }

/* Viewer de démonstration Musée (révélation pseudo-aléatoire des micro-toiles) : même esprit
   visuel que .ts-sim-stage (atelier admin) — conteneur fixe, deux canvases 1024×1024 empilés
   (image + grille), mis à l'échelle uniquement via la transformation CSS de pan-zoom.ts. */
.museum-demo-stage { overflow: hidden; max-width: 100%; border: 1px solid var(--pv-line); border-radius: var(--pv-radius); background: #000; position: relative; touch-action: none; }
/* Le plein écran cible #md-fs-root (stage + barre de contrôle), jamais le stage seul : l'API
   Fullscreen ne rend que le sous-arbre de l'élément demandé, sinon #md-controls (un frère du
   stage) deviendrait invisible/inaccessible pendant la lecture en plein écran. */
.museum-demo-fs-root:fullscreen { display: flex; flex-direction: column; background: #000; width: 100%; height: 100%; padding: 12px; box-sizing: border-box; }
.museum-demo-fs-root:fullscreen .museum-demo-stage { flex: 1; height: auto; margin-top: 0; }
.museum-demo-fs-root:fullscreen .timeline-bar { flex: 0 0 auto; }
.museum-demo-layer { position: absolute; top: 0; left: 0; width: 1024px; height: 1024px; }
.museum-demo-layer canvas { position: absolute; top: 0; left: 0; width: 1024px; height: 1024px; cursor: grab; }
.museum-demo-layer canvas:active { cursor: grabbing; }
.museum-demo-layer canvas#md-grid-canvas { pointer-events: none; }

/* Timeline */
.timeline-bar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 8px; }
.timeline-bar input[type="range"] { flex: 1; min-width: 160px; accent-color: var(--pv-amber); }

/* Teaser secret */
.teaser-card { position: relative; overflow: hidden; }
.teaser-lock { font-size: 28px; }
.teaser-card .mist { position: absolute; inset: 0; background: repeating-linear-gradient(45deg, rgba(245,168,60,0.04) 0 12px, transparent 12px 24px); pointer-events: none; }

.toast { position: fixed; bottom: 18px; left: 50%; transform: translateX(-50%); background: var(--pv-panel-2); border: 1px solid var(--pv-line); color: var(--pv-ink); padding: 10px 16px; border-radius: var(--pv-radius); z-index: 230; font-size: 14px; max-width: 90vw; }
.toast.err { border-color: var(--pv-red); }
.toast.ok { border-color: var(--pv-green); }

.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* Tables admin */
.pv-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.pv-table th, .pv-table td { text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--pv-line); }
.pv-table th { color: var(--pv-ink-dim); font-family: var(--pv-mono); font-weight: 500; }

/* Atelier cible admin (mode secret) */
.ts-view-label { font-size: 12px; color: var(--pv-ink-dim); margin-bottom: 4px; }
.ts-sliders { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px; margin-top: 10px; }
.ts-sliders label { font-size: 12px; color: var(--pv-ink-dim); display: flex; flex-direction: column; gap: 2px; }
.ts-sliders input[type="range"] { width: 100%; accent-color: var(--pv-amber); }
.ts-sliders output { font-family: var(--pv-mono); color: var(--pv-ink); }
.ts-btn-group { display: inline-flex; gap: 2px; padding: 2px; border: 1px solid var(--pv-line); border-radius: var(--pv-radius); }
.ts-btn-group .pv-btn[aria-pressed="true"] { background: var(--pv-panel-2); border-color: var(--pv-cyan); color: var(--pv-cyan); }
.ts-canvas-scroll { overflow: auto; max-width: 100%; max-height: 420px; border: 1px solid var(--pv-line); border-radius: var(--pv-radius); background: #000; }
.ts-sim-stage { overflow: hidden; max-width: 100%; height: 420px; border: 1px solid var(--pv-line); border-radius: var(--pv-radius); background: #000; position: relative; touch-action: none; }
.ts-sim-stage canvas { cursor: grab; }
.ts-sim-stage canvas:active { cursor: grabbing; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; scroll-behavior: auto !important; }
}

/* ---------- Mode présentation (?presentation=1) — capture vidéo ---------- */
/* Affiche principalement la fresque : masque le chrome autour d'elle, ne garde que la barre
   de présentation (Ajuster/1×/2×/4×/Relancer/Quitter). Purement visuel, aucune donnée
   modifiée — la fresque affichée reste la même vue publique que hors présentation. */
body.pv-presentation .mini-shell-header,
body.pv-presentation .gshell-footer,
body.pv-presentation #layout > section > h1,
body.pv-presentation #layout > section > p,
body.pv-presentation #museum {
  display: none;
}
body.pv-presentation #layout { padding: 0; max-width: none; }
body.pv-presentation .wall-stage { border-radius: 0; }

