/* ═══════════════════════════════════════════════════════════════════════════
   ritual.css — La Mesa del Practicante · Grimorium
   Estética: realismo oscuro gótico, luz de vela, oro viejo.
   Móvil-first. Animaciones solo con transform/opacity (GPU). Sin JS continuo.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── Paletas FIJAS: fuente ÚNICA de cada color. Los componentes referencian TOKENS,
        nunca hex. --d-* = paleta OSCURA (identidad de La Mesa: escena y tarjetas la usan
        siempre); --l-* = paleta CLARA (pergamino viejo) que SOLO el chrome usa en tema
        claro. Cada literal aparece una sola vez aquí. ── */
  --d-bg: #0b0703; --d-bg2: #120b05; --d-panel: #170f07; --d-panel2: #1f150b;
  --d-ink: #ecdfc2; --d-ink-soft: #b5a48b; --d-linea: #3a2c18; --d-sombra: rgba(0, 0, 0, .55);
  --d-screen-veil:
    radial-gradient(120% 80% at 50% 30%, rgba(5,3,1,.25), transparent 55%),
    linear-gradient(180deg, rgba(5,3,1,.82), rgba(5,3,1,.38) 38%, rgba(5,3,1,.55) 65%, rgba(5,3,1,.9));
  --l-bg: #e7d8b8; --l-bg2: #ddcaa2; --l-panel: #f1e7cd; --l-panel2: #e6d7b4;
  --l-ink: #2b2011; --l-ink-soft: #6a5730; --l-linea: #c3aa78; --l-sombra: rgba(120,88,36,.16);
  --l-screen-veil:
    radial-gradient(120% 80% at 50% 30%, rgba(233,220,190,.15), transparent 55%),
    linear-gradient(180deg, rgba(233,220,190,.74), rgba(233,220,190,.32) 38%, rgba(233,220,190,.52) 65%, rgba(233,220,190,.86));

  /* ── Tokens EFECTIVOS (lo que consumen los componentes). El tema los reasigna a la
        paleta clara; por defecto apuntan a la oscura. ── */
  --bg: var(--d-bg); --bg2: var(--d-bg2); --panel: var(--d-panel); --panel2: var(--d-panel2);
  --ink: var(--d-ink); --ink-soft: var(--d-ink-soft); --linea: var(--d-linea); --sombra: var(--d-sombra);
  --screen-veil: var(--d-screen-veil);
  --screen-bg-op: 1; --screen-bg-blend: normal;
  /* Acentos compartidos por AMBOS temas (el oro es el oro): un solo valor. */
  --oro: #c9a253;
  --oro-bright: #e2bf6c;
  --vela: #e2bf6c;
  --sin: #cd5b4b;
  --glow: #c9a253;
  /* Acento FRÍO/plateado: identidad de la PRÁCTICA MODERNA (Azazel), deliberadamente
     distinta del oro goético. Compartido por ambos temas (como el oro). */
  --frio: #8fa3b3;
  --frio-bright: #d3e2ee;
  --negro: #000;   /* vacío absoluto: fondo base de la escena del rito (siempre oscuro) */
  --d-bg-deep: #0a0705;   /* fondo profundo de la escena (bgwrap) — superficie, siempre oscuro */
  /* Colores del DIBUJO A TIZA y del cue del trazo (efecto de escena; repetidos → un solo token). */
  --tiza: #e8dcc0;        /* blanco hueso del trazado a tiza (mezclado con oro) */
  --cue: #ffe6a6;         /* glow del indicador «empieza aquí» (punto/aro/flecha) */
  --cue-label: #f2e6c4;   /* texto del cue */
  /* Tamaño de la vela (token → se reduce en móvil/pantalla baja para no dominar la escena). */
  --candle-w: 46px; --candle-h: 92px;
  --safe-b: env(safe-area-inset-bottom, 0px);
  /* Estado del TRANCE (rito moderno): lo conduce JS. --trance 0→1 (visión de túnel),
     --breath 0→1 (ciclo respiratorio), --mx/--my = centro del espejo en pantalla. */
  --trance: 0; --breath: 0; --mx: 50%; --my: 72%;
  /* Grimorio: se personaliza por demonio vía --book-accent/--book-vela */
  --book-leather: #24180b;
  --book-leather2: #3a2410;
  --book-parchment: #f2e3c0;
  --book-parchment2: #d2b987;
  --book-accent: #8a6a2f;
  --book-ink: #33220f;
  --book-ink-soft: #593c18;   /* tinta suave algo más oscura → legible con multiply+moteado */
  --book-leaf: #cdb789;       /* color base de la hoja que gira (leaf-face) */

  /* ── Design system / tokens ──────────────────────────────────────────────
     Un solo lugar para escala, ritmo, capas y estilo de controles. Ningún
     componente hardcodea estos valores: todos se derivan de aquí. */
  --font-display: "Cinzel", Georgia, serif;
  --font-body: "EB Garamond", Georgia, serif;
  /* Fuente MODERNA (sans-serif del sistema): identidad de la práctica contemporánea
     (Azazel), deliberadamente distinta de las serif góticas. Sin dependencias externas. */
  --font-modern: system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  /* espaciado (escala 4) */
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 24px; --sp-6: 32px;
  /* radios */
  --r-sm: 3px; --r-md: 6px; --r-lg: 12px; --r-pill: 999px;
  /* movimiento */
  --dur-fast: .16s; --dur-mid: .3s; --dur-slow: .5s;
  --ease: cubic-bezier(.36, .12, .2, 1);
  /* capas (z-index) — una escala legible, sin números mágicos dispersos */
  --z-scene: 0; --z-content: 2; --z-fx: 7; --z-trace: 8;
  --z-hud: 20; --z-overlay: 60; --z-modal: 100; --z-toast: 120;
  /* controles (botones y pestañas comparten esta familia) */
  --ctl-font: var(--font-display);
  --ctl-tracking: .14em;
  --ctl-radius: var(--r-md);
  --ctl-border: color-mix(in srgb, var(--oro) 42%, transparent);
  --ctl-bg: rgba(201, 162, 83, .05);
  --ctl-bg-hover: rgba(201, 162, 83, .13);
  --ctl-fg: var(--ink-soft);
  --ctl-fg-hover: var(--oro-bright);
  /* estado destacado (CTA primario y pestaña activa: el MISMO lenguaje). Tokens de ESTADO
     que el tema reasigna: en oscuro = oro sobre fondo translúcido; en claro = tinta oscura
     sobre ORO SÓLIDO (legible sobre pergamino). */
  --ctl-on-border: var(--oro);
  --ctl-on-bg: linear-gradient(180deg, rgba(201, 162, 83, .20), rgba(201, 162, 83, .08));
  --ctl-on-bg-hover: linear-gradient(180deg, rgba(226, 191, 108, .30), rgba(201, 162, 83, .14));
  --ctl-on-fg: var(--oro-bright);
}

/* ═══ TEMA del CHROME de interfaz (opt-in por sistema o toggle #btnTema) ═══════════════
   Reutiliza EXACTAMENTE el mecanismo de la web principal: <html data-theme> + localStorage
   "grim-theme"; default por sistema. SOLO afecta a la interfaz (intro/selección/estudio
   exterior/modales/controles/buscador). La ESCENA del rito (#s-ritual, más abajo) reafirma
   tokens oscuros y NUNCA se aclara: la vela, el humo y el pergamino se conservan intactos.
   Paleta clara = pergamino viejo con tinta oscura y el MISMO oro (identidad premium). */
:root { color-scheme: dark; }
/* Tema claro: reasigna los tokens EFECTIVOS a la paleta clara (--l-*). Sin literales:
   solo referencias a los tokens definidos una vez arriba. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    color-scheme: light;
    --bg: var(--l-bg); --bg2: var(--l-bg2); --panel: var(--l-panel); --panel2: var(--l-panel2);
    --ink: var(--l-ink); --ink-soft: var(--l-ink-soft); --linea: var(--l-linea); --sombra: var(--l-sombra);
    --screen-veil: var(--l-screen-veil); --screen-bg-op: .12; --screen-bg-blend: multiply;
    --ctl-on-fg: var(--l-ink); --ctl-on-bg: linear-gradient(180deg, var(--oro-bright), var(--oro));
    --ctl-on-bg-hover: linear-gradient(180deg, var(--oro-bright), var(--oro-bright));
    --ctl-fg-hover: var(--l-ink);
  }
}
:root[data-theme="light"] {
  color-scheme: light;
  --ctl-on-fg: var(--l-ink); --ctl-on-bg: linear-gradient(180deg, var(--oro-bright), var(--oro));
  --ctl-on-bg-hover: linear-gradient(180deg, var(--oro-bright), var(--oro-bright));
  --ctl-fg-hover: var(--l-ink);
  --bg: var(--l-bg); --bg2: var(--l-bg2); --panel: var(--l-panel); --panel2: var(--l-panel2);
  --ink: var(--l-ink); --ink-soft: var(--l-ink-soft); --linea: var(--l-linea); --sombra: var(--l-sombra);
  --screen-veil: var(--l-screen-veil); --screen-bg-op: .12; --screen-bg-blend: multiply;
}
/* La ESCENA del rito es SIEMPRE oscura, gane lo que gane el tema del chrome: reafirma los
   tokens oscuros (--d-*) en el contenedor → todos sus descendientes los heredan. Sin JS,
   sin flash, sin tocar coordenadas ni repositionOverlays. */
#s-ritual {
  --bg: var(--d-bg); --bg2: var(--d-bg2); --panel: var(--d-panel); --panel2: var(--d-panel2);
  --ink: var(--d-ink); --ink-soft: var(--d-ink-soft); --linea: var(--d-linea); --sombra: var(--d-sombra);
  --screen-veil: var(--d-screen-veil);
}
/* Móvil / pantalla baja: velas más pequeñas para que no dominen la escena ni choquen con
   el banner (el reparto en el suelo lo ajusta buildCandles según el viewport). */
@media (max-width: 760px), (max-height: 560px) { :root { --candle-w: 34px; --candle-h: 68px; } }

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body {
  margin: 0; width: 100%; max-width: 100%; height: 100%; overflow: hidden;
  overscroll-behavior: none; touch-action: manipulation;
  -webkit-text-size-adjust: 100%;
  /* SUELO SIEMPRE OSCURO: la Mesa es una escena ceremonial oscura y #app mide 100dvh (por el
     fix de fullscreen horizontal). En móvil el viewport de layout (100vh) es más alto que el
     visible (100dvh) → asomaba una FRANJA con el --bg claro del tema bajo #app (auditoría real
     Xiaomi: codex + deepseek-vision, ALTA x3). Las .screen cubren el body salvo esa franja, así
     que fijar el suelo en --d-bg solo afecta a la franja: pasa a negro de escena, no crema. */
  background: var(--d-bg);
}
.grimorio, .grid { scrollbar-width: thin; scrollbar-color: var(--linea) transparent; }
.grimorio::-webkit-scrollbar, .grid::-webkit-scrollbar { width: 6px; }
.grimorio::-webkit-scrollbar-thumb, .grid::-webkit-scrollbar-thumb { background: var(--linea); border-radius: 3px; }
.grimorio::-webkit-scrollbar-track, .grid::-webkit-scrollbar-track { background: transparent; }
body {
  background: var(--d-bg);   /* suelo oscuro de escena (ver nota en html,body): la franja bajo #app no debe asomar el tema claro */
  color: var(--ink);
  font-family: "EB Garamond", Georgia, serif;
  font-size: 18px;
  line-height: 1.55;
  overscroll-behavior: none;
}
button { font-family: inherit; color: inherit; cursor: pointer; }
a { color: var(--oro); }

/* Altura DINÁMICA (dvh), no svh: al entrar a fullscreen en horizontal, svh a veces no se
   actualiza y #app quedaba MÁS CORTO que la pantalla → elementos comprimidos/mal ubicados. dvh
   sigue el viewport visible real (fullscreen o no) y dispara resize → recoloca la geometría. */
#app { position: fixed; inset: 0; overflow: hidden; height: 100vh; height: 100dvh; }

/* ─────────────────────────── Pantallas ─────────────────────────── */
.screen {
  position: absolute; inset: 0; overflow: hidden;
  display: flex; flex-direction: column;
  opacity: 0; visibility: hidden;
  transition: opacity .45s ease, visibility .45s;
  background:
    radial-gradient(1200px 600px at 15% -5%, rgba(201,162,83,.10), transparent 60%),
    radial-gradient(900px 500px at 100% 0%, rgba(205,91,75,.07), transparent 55%),
    var(--bg);
}
.screen.active { opacity: 1; visibility: visible; z-index: 10; }

/* Fondo ambiental de cada pantalla (assets GPT Image, sin texto) */
.screen-bg {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-size: cover; background-position: center 45%;
  opacity: var(--screen-bg-op); mix-blend-mode: var(--screen-bg-blend);
}
#s-intro .screen-bg { background-image: url(/r/assets/ritual-portrait.webp); }
#s-select .screen-bg { background-image: url(/r/assets/ritual-portrait.webp); }
#s-result .screen-bg { background-image: url(/r/assets/ritual-portrait.webp); }
@media (orientation: landscape) {
  #s-intro .screen-bg, #s-select .screen-bg, #s-result .screen-bg { background-image: url(/r/assets/ritual-landscape.webp); }
}
/* Overlays para que el texto siga siendo legible sobre el arte */
#s-intro::after, #s-select::after, #s-result::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: var(--screen-veil);
}
#s-intro .intro-inner, #s-select .topbar, #s-select .select-head, #s-select .mesa-streamtabs, #s-select .mesa-search, #s-select .grid, #s-select .foot-note,
#s-result .result-inner { position: relative; z-index: 2; }
/* En pantallas muy bajas, intro y resultado pueden necesitar scroll interno; el scroll
   queda contenido y sin rebote (nada de scroll de página). */
#s-intro, #s-result { overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; }

/* ─────────────────────────── Botones ─────────────────────────── */
[hidden] { display: none !important; }   /* el atributo hidden debe vencer a .btn/inline-flex */
/* Controles: botones y pestañas son la MISMA familia (mismos tokens), solo
   cambian de tamaño. El CTA primario y la pestaña activa comparten el estado
   destacado, así nada "choca" entre pantallas. */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--ctl-h, 48px); padding: 0 var(--ctl-px, var(--sp-5));
  border-radius: var(--ctl-radius);
  font-family: var(--ctl-font); font-size: var(--ctl-fz, .7rem); font-weight: 600;
  letter-spacing: var(--ctl-tracking); text-transform: uppercase;
  border: 1px solid var(--ctl-border); text-decoration: none; cursor: pointer;
  color: var(--ctl-fg); background: var(--ctl-bg);
  transition: transform var(--dur-fast), background var(--dur-fast), border-color var(--dur-fast), color var(--dur-fast);
}
.btn:hover { background: var(--ctl-bg-hover); border-color: var(--oro); color: var(--ctl-fg-hover); }
.btn:active { transform: scale(.97); }
.btn:focus-visible, .ghostbtn:focus-visible, .iconbtn:focus-visible, .card:focus-visible,
.tradbtn:focus-visible, .opt:focus-visible, .candle:focus-visible, .modal-x:focus-visible {
  outline: 2px solid var(--oro-bright); outline-offset: 2px;
}
/* CTA primario = mismo lenguaje que la pestaña activa (oro-borde + relleno cálido). */
.btn-oro {
  border-color: var(--ctl-on-border); color: var(--ctl-on-fg);
  background: var(--ctl-on-bg);
  box-shadow: inset 0 0 0 1px rgba(201, 162, 83, .16), 0 6px 18px rgba(0, 0, 0, .34);
}
.btn-oro:hover { border-color: var(--oro-bright); color: var(--ctl-on-fg);
  background: var(--ctl-on-bg-hover); }
.btn-ghost { border-color: var(--linea); color: var(--ink); background: transparent; box-shadow: none; }
.btn-ghost:hover { border-color: var(--oro); color: var(--ctl-fg-hover); background: var(--ctl-bg-hover); }
.ghostbtn {
  background: transparent; border: 1px solid var(--linea); color: var(--ink-soft);
  font-family: "Cinzel", serif; font-size: .62rem; letter-spacing: .1em;
  text-transform: uppercase; padding: 8px 12px; border-radius: 3px; min-height: 44px;
}
.ghostbtn:hover { color: var(--oro-bright); border-color: var(--oro); }
.iconbtn {
  background: transparent; border: 1px solid var(--linea); color: var(--oro);
  width: 44px; height: 44px; border-radius: 50%; font-size: 1.05rem;
  display: inline-flex; align-items: center; justify-content: center; padding: 0;
}
.iconbtn svg { width: 17px; height: 20px; display: block; }
.iconbtn:hover { border-color: var(--oro); }
.iconbtn.off { opacity: .45; }

/* ─────────────────────────── Pantalla 0 · Intro ─────────────────────────── */
#s-intro { align-items: center; justify-content: center; text-align: center; padding: 24px; }
.intro-inner { max-width: 430px; animation: introFade 1.2s ease both; }
.intro-sello { font-size: 2.1rem; color: var(--oro); animation: selloPulse 5s ease-in-out infinite; }
.kicker {
  font-family: "Cinzel", serif; font-size: .66rem; letter-spacing: .32em;
  text-transform: uppercase; color: var(--oro); margin: 22px 0 10px;
}
.intro-titulo {
  font-family: "Cinzel", serif; font-weight: 700;
  font-size: clamp(2.4rem, 9vw, 4rem); line-height: 1.04;
  margin: 0; letter-spacing: .02em;
  text-shadow: 0 0 40px rgba(201,162,83,.25);
}
.intro-lead { color: var(--ink-soft); font-style: italic; font-size: 1.12rem; margin: 14px 0 26px; }
.intro-disc {
  color: var(--ink-soft); font-size: .86rem; max-width: 40ch; margin: 0 auto 30px;
  border-top: 1px solid var(--linea); border-bottom: 1px solid var(--linea);
  padding: 14px 4px;
}
@keyframes introFade { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes selloPulse { 0%, 100% { text-shadow: 0 0 12px rgba(201,162,83,.4); } 50% { text-shadow: 0 0 30px rgba(226,191,108,.85); } }

/* ─────────────────────────── Pantalla 1 · Selección ─────────────────────────── */
#s-select {
  padding-bottom: calc(16px + var(--safe-b));
  background:
    radial-gradient(60% 50% at 50% 0%, rgba(201,162,83,.06), transparent 70%),
    radial-gradient(120% 90% at 50% 110%, rgba(201,162,83,.04), transparent 60%),
    var(--bg);
}
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: calc(14px + env(safe-area-inset-top, 0px)) 18px 10px; gap: 10px;
}
.brand {
  font-family: "Cinzel", serif; font-size: .66rem; letter-spacing: .2em;
  text-transform: uppercase; color: var(--oro); text-decoration: none;
}
.top-actions { display: flex; gap: 8px; }
.select-head { text-align: center; padding: 6px 20px 4px; }
.select-head h2 {
  font-family: "Cinzel", serif; font-size: 1.5rem; font-weight: 600; margin: 0;
}
.select-head .sub { color: var(--ink-soft); font-size: .9rem; margin: 8px auto 0; max-width: 46ch; }

/* Buscador rápido de MIEMBRO (solo visible con sesión) — reutiliza el patrón .search de la
   web principal, adaptado al tamaño de La Mesa. Sin chips ni paneles: un campo discreto. */
.mesa-search { position: relative; z-index: 2; width: 100%; max-width: 560px; margin: 0 auto; padding: 2px 20px 8px; }
.mesa-search[hidden] { display: none !important; }
.search { display: flex; align-items: center; gap: 10px; background: var(--panel); border: 1px solid var(--linea);
  border-radius: var(--r-sm); padding: 9px 13px; box-shadow: 0 1px 0 var(--sombra); }
.search svg { width: 18px; height: 18px; flex: none; color: var(--oro); }
.search input { border: 0; background: transparent; color: var(--ink); font-family: var(--font-body);
  font-size: 1rem; width: 100%; min-width: 0; outline: none; }
.search input::placeholder { color: var(--ink-soft); opacity: .75; }
.search:focus-within { outline: 2px solid var(--oro); outline-offset: 2px; }
.grid-empty { grid-column: 1 / -1; text-align: center; color: var(--ink-soft); font-size: .85rem; padding: 24px 8px; margin: 0; }
.grid-empty[hidden] { display: none !important; }
.grid {
  flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain; touch-action: pan-y; scrollbar-width: none;
  max-width: 100%;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(92px, 1fr));
  grid-auto-rows: max-content;          /* evita que las tarjetas colapsen (bug móvil) */
  gap: 10px; padding: 14px 16px 8px; align-content: start;
}
.grid::-webkit-scrollbar { display: none; }
/* Las TARJETAS son objetos oscuros premium (como la escena del rito): su superficie es
   oscura en AMBOS temas. Reafirman los tokens oscuros para que el nombre y el borde no se
   pierdan (tinta oscura sobre tarjeta oscura) cuando el chrome está en tema claro. */
.card { --ink: var(--d-ink); --ink-soft: var(--d-ink-soft); --linea: var(--d-linea); --panel: var(--d-panel); }
.card {
  position: relative; background:
    linear-gradient(160deg, rgba(201,162,83,.10), rgba(23,15,7,.92) 38%, rgba(10,6,3,.96)),
    var(--panel);
  border: 1px solid var(--linea);
  border-radius: 10px; padding: 14px 8px 12px; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  transition: border-color .18s, transform .18s, box-shadow .18s;
  overflow: hidden;
  box-shadow:
    inset 0 0 0 1px rgba(201,162,83,.04),
    inset 0 12px 28px rgba(0,0,0,.35),
    0 10px 26px rgba(0,0,0,.5);
}
.card::before, .card::after {
  content: ""; position: absolute; width: 16px; height: 16px;
  border: 0 solid var(--oro); opacity: .55; pointer-events: none;
}
.card::before { top: 5px; left: 5px; border-top-width: 1px; border-left-width: 1px; }
.card::after { bottom: 5px; right: 5px; border-bottom-width: 1px; border-right-width: 1px; }
.card:active { transform: scale(.96); }
.card.free {
  border-color: color-mix(in srgb, var(--oro) 70%, var(--linea));
  box-shadow:
    inset 0 0 0 1px rgba(201,162,83,.06),
    inset 0 12px 28px rgba(0,0,0,.35),
    0 0 0 1px rgba(201,162,83,.22),
    0 8px 30px rgba(0,0,0,.45),
    0 0 22px rgba(201,162,83,.06);
}
.card.free:hover {
  border-color: var(--oro); transform: translateY(-2px);
  box-shadow:
    inset 0 0 0 1px rgba(201,162,83,.08),
    inset 0 12px 28px rgba(0,0,0,.3),
    0 0 0 1px rgba(201,162,83,.4),
    0 8px 30px rgba(0,0,0,.5),
    0 0 34px rgba(201,162,83,.16);
}
.card.locked { opacity: .6; background: linear-gradient(160deg, rgba(30,22,12,.6), rgba(8,5,2,.94)); }
.card.locked::after {
  content: "🔒"; position: absolute; top: 8px; right: 8px; font-size: .72rem;
  filter: grayscale(1); opacity: .85;
}
.card .sig {
  flex: none;                          /* no colapsar dentro del flex-column */
  width: 64px; height: 64px; background: var(--oro);
  -webkit-mask: var(--m) center/contain no-repeat;
  mask: var(--m) center/contain no-repeat;
  filter: drop-shadow(0 0 6px rgba(201,162,83,.25));
}
.card.locked .sig { filter: grayscale(.9) blur(.6px) opacity(.55); }
.card .cn { font-family: "Cinzel", serif; font-size: .82rem; line-height: 1.2; }
.card .cr { font-size: .66rem; color: var(--ink-soft); letter-spacing: .06em; text-transform: uppercase; }
.card .cdone { position: absolute; bottom: 4px; left: 0; right: 0; font-size: .6rem; color: var(--oro); letter-spacing: .14em; text-transform: uppercase; }
/* ── Azazel · entrada premium ESPECIAL (fuera de los 72) ──────────────────────
   Práctica MODERNA (Koetting): identidad híbrida. Base OSCURA como las cards
   (objeto premium, oscuro en ambos temas) pero lenguaje visual MODERNO/minimal
   —sans-serif, acento frío/plateado, geometría sobria, sin oro ni esquineros
   góticos— para separarla inequívocamente de la Ars Goetia. */
.special-row { flex: none; width: 100%; max-width: 100%; padding: 4px 16px 10px; }
.special-row[hidden] { display: none; }
.azcard {
  --ink: var(--d-ink); --ink-soft: var(--d-ink-soft); --linea: var(--d-linea); --panel: var(--d-panel);
  position: relative; width: 100%; text-align: left; cursor: pointer;
  display: grid; grid-template-columns: auto 1fr; column-gap: var(--sp-4); align-items: center;
  padding: var(--sp-4) var(--sp-4) var(--sp-4) var(--sp-5);
  /* Sheen frío arriba (vidrio negro) + degradado del cuerpo. Más presencia sin oro. */
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--frio) 14%, transparent), transparent 34%),
    linear-gradient(150deg, color-mix(in srgb, var(--frio) 12%, transparent), rgba(11,14,18,.94) 48%, rgba(6,8,11,.97)),
    var(--panel);
  border: 1px solid color-mix(in srgb, var(--frio) 46%, var(--linea));
  border-radius: var(--r-lg);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, var(--frio-bright) 22%, transparent),   /* filo superior tenue = vidrio */
    inset 0 0 0 1px color-mix(in srgb, var(--frio) 9%, transparent),
    inset 0 12px 28px rgba(0,0,0,.4),
    0 0 0 1px color-mix(in srgb, var(--frio) 12%, transparent),               /* halo frío en reposo (premium/especial) */
    0 8px 26px rgba(0,0,0,.5),
    0 0 22px color-mix(in srgb, var(--frio) 8%, transparent);
  transition: border-color var(--dur-fast), transform var(--dur-fast), box-shadow var(--dur-fast);
}
/* Barra geométrica fría a la izquierda (marcador «aparte/moderno», no un sello). */
.azcard::before {
  content: ""; position: absolute; left: 0; top: 12%; bottom: 12%; width: 3px; border-radius: var(--r-pill);
  background: linear-gradient(180deg, transparent, var(--frio), transparent); opacity: .8; pointer-events: none;
}
.azcard:hover {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--frio) 70%, var(--linea));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--frio) 10%, transparent), inset 0 12px 28px rgba(0,0,0,.35), 0 0 0 1px color-mix(in srgb, var(--frio) 34%, transparent), 0 10px 30px rgba(0,0,0,.55), 0 0 30px color-mix(in srgb, var(--frio) 14%, transparent);
}
.azcard:active { transform: scale(.99); }
.azcard .az-eyebrow {
  grid-column: 2; font-family: var(--font-modern); font-size: .64rem; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase; color: var(--frio-bright);
  text-shadow: 0 0 12px color-mix(in srgb, var(--frio) 26%, transparent);
}
.azcard .az-name {
  grid-column: 2; font-family: var(--font-modern); font-weight: 400; font-size: 1.55rem;
  letter-spacing: .04em; line-height: 1.05;
  color: color-mix(in srgb, var(--frio-bright) 68%, var(--ink));   /* nombre con frío tenue: presente, no apagado */
  text-shadow: 0 0 18px color-mix(in srgb, var(--frio) 28%, transparent);
}
.azcard .az-sub {
  grid-column: 2; font-family: var(--font-modern); font-size: .72rem; font-weight: 400;
  color: var(--ink-soft); letter-spacing: .01em;
}
/* Glifo frío geométrico a la izquierda (círculo fino + punto): abstracto, no mágico. */
.azcard::after {
  content: ""; grid-column: 1; grid-row: 1 / span 3; width: 46px; height: 46px; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--frio) 55%, transparent);
  box-shadow: inset 0 0 0 4px rgba(0,0,0,.4), 0 0 14px color-mix(in srgb, var(--frio) 22%, transparent);
  background: radial-gradient(circle at 50% 50%, var(--frio-bright) 0 2.5px, transparent 3px);
}

/* ── §B · BUNE · PATRONO del proyecto (rito de OFRENDA, devoción moderna) ────────────
   Mismo chasis que .azcard pero tema ORO cálido (aliado, no el frío-azul moderno);
   redefinir --frio/--frio-bright recolorea todo el chasis. Fuentes de MARCA. */
.bune-patron-row { padding: 6px 16px 16px; }                    /* respira: separa de la búsqueda y del grid */
.azcard.bunecard { --frio: #b98b34; --frio-bright: #e2bf6c; }
.azcard.bunecard::after { display: none; }                     /* sin glifo frío: van los sellos en oro */
/* Tipografía de MARCA (Cinzel/EB Garamond), como .flcard/.alcard — NO la sans moderna. */
.azcard.bunecard .az-eyebrow { font-family: var(--font-display); letter-spacing: .18em; }
.azcard.bunecard .az-name { font-family: var(--font-display); font-weight: 600; letter-spacing: .06em; }
.azcard.bunecard .az-sub { font-family: var(--font-body); font-size: .76rem; line-height: 1.36; }
/* Sellos del patrono en la tarjeta: ORO sobre transparente (máscara + --oro), CERO recuadro blanco. */
.bunecard .bune-seals { grid-column: 1; grid-row: 1 / span 3; display: flex; flex-direction: column; gap: 6px; align-self: center; }
.bunecard .bune-seals .sig { width: 42px; height: 42px; background: var(--oro);
  -webkit-mask: var(--m) center/contain no-repeat; mask: var(--m) center/contain no-repeat;
  filter: drop-shadow(0 0 6px color-mix(in srgb, var(--oro) 34%, transparent)); }
/* §B — El sello de Bune se GRABA en su propio paso «sello» (buildDrawSeal / .seal-stage), como en
   cualquier rito: en la escena, en perspectiva, por acto del practicante. Ya NO hay overlay plano
   de sellos flotantes ni una manifestación de solo-resplandor: Bune se manifiesta con la máquina
   canónica (showApparition), velado por .aparicion.gentle. */
.bune-scene-aviso { max-width: 30em; margin: 0 auto 10px; text-align: center; font-family: var(--font-body);
  font-size: .74rem; line-height: 1.5; color: var(--ink-soft); opacity: .9; }
/* §B — Figura TENUE (Bune): «presencia apenas distinguible» — velo + leve desenfoque para que el
   contorno de las tres cabezas se PERCIBA antes que se vea del todo. La opacidad (aún más baja) va
   con más especificidad tras las reglas .show (ver «.aparicion.gentle.show» abajo). */
.aparicion.gentle { filter: saturate(.86) brightness(.9) blur(1.1px); }

/* ── FLORON · scrying HISTÓRICO (Cecco 1327 + Wellcome MS 110) ──────────────────────
   Mismo chasis que .azcard, pero tema ACERO/PELTRE MEDIEVAL (no el frío-azul moderno de
   Azazel) y tipografía SERIF histórica (Cinzel), no el sans moderno. Redefinir --frio en
   el propio tile recalcula todos los color-mix del chasis con el nuevo acero. */
.azcard.flcard {
  --frio: #97a1a3;          /* peltre/acero pulido, gris cálido (no azul) */
  --frio-bright: #d6ddda;   /* filo de espejo */
}
.azcard.flcard .az-eyebrow { font-family: var(--font-display); letter-spacing: .18em; }
.azcard.flcard .az-name { font-family: var(--font-display); font-weight: 600; letter-spacing: .06em; }
.azcard.flcard .az-sub { font-family: var(--font-body); font-size: .76rem; }
/* Glifo = ESPEJO ovalado (óvalo fino con reflejo), no el círculo-punto abstracto de Azazel. */
.azcard.flcard::after {
  border-radius: 50% / 62%;
  background:
    radial-gradient(60% 40% at 42% 32%, color-mix(in srgb, var(--frio-bright) 70%, transparent) 0, transparent 60%),
    linear-gradient(150deg, color-mix(in srgb, var(--frio) 22%, transparent), rgba(6,8,11,.9) 70%);
}
/* La fila de especiales aloja dos tiles: se apilan bien en móvil, lado a lado en ancho. */
/* Rótulo de la sección: marca las 3 entradas como APARTE de la rejilla de los 72 (no las
   tapa: la rejilla es lo principal; esto es un estante secundario, más compacto). */
.special-lead {
  margin: 22px 0 9px; display: flex; align-items: center; gap: 12px; justify-content: center;
  font-family: var(--font-modern); font-size: .64rem; font-weight: 600; letter-spacing: .18em;
  text-transform: uppercase; color: var(--d-ink-soft);
}
.special-lead::before, .special-lead::after {
  content: ""; height: 1px; flex: 1 1 auto; max-width: 88px;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--d-ink-soft) 42%, transparent));
}
.special-lead::before { background: linear-gradient(270deg, transparent, color-mix(in srgb, var(--d-ink-soft) 42%, transparent)); }
/* Estante COMPACTO: 3 columnas en ancho; en móvil, tira con scroll horizontal y snap → se
   entiende como algo aparte, más pequeño que las tarjetas de la rejilla, sin dominar la vista. */
/* Repisa: las 3 tarjetas se APOYAN (sombra de contacto bajo la fila) → objetos sobre un estante,
   no tarjetas web flotando (auditoría DeepSeek). */
#azazelSpecial.special-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; position: relative; }
#azazelSpecial.special-row::after {
  content: ""; position: absolute; left: 3%; right: 3%; bottom: -8px; height: 11px; pointer-events: none;
  background: radial-gradient(70% 100% at 50% 0, rgba(0,0,0,.55), transparent 72%);
}
#azazelSpecial.special-row > .azcard { box-shadow: 0 9px 16px -7px rgba(0,0,0,.7), inset 0 1px 0 color-mix(in srgb, var(--frio-bright) 14%, transparent); }
#azazelSpecial.special-row > .azcard {
  padding: var(--sp-3) var(--sp-3) var(--sp-3) var(--sp-4); column-gap: var(--sp-3);
}
#azazelSpecial .az-name { font-size: 1.1rem; }
#azazelSpecial .az-eyebrow { font-size: .55rem; letter-spacing: .12em; }
#azazelSpecial .az-sub { font-size: .64rem; line-height: 1.32; }
#azazelSpecial .azcard::after { width: 34px; height: 34px; }
@media (max-width: 620px) {
  #azazelSpecial.special-row {
    grid-auto-flow: column; grid-template-columns: none; grid-auto-columns: 76%;
    overflow-x: auto; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch;
    padding-bottom: 5px; scrollbar-width: thin;
  }
  #azazelSpecial.special-row > .azcard { scroll-snap-align: start; }
}
/* Escena de scrying: el tag histórico en tono acero (no el frío-azul del moderno). */
#s-ritual.is-scrying #ritualModernTag {
  color: color-mix(in srgb, #d6ddda 78%, var(--ink));
  border-color: color-mix(in srgb, #97a1a3 55%, transparent);
}
#s-ritual.is-scrying #ritualStepTitulo { font-family: var(--font-display); font-weight: 600; letter-spacing: .03em; }

/* Almadel (3ª entrada especial) — tema ANGÉLICO: oro pálido/vela cálida, tipografía serif.
   Redefine --frio con un dorado luminoso para recalcular todo el chasis .azcard. */
.azcard.alcard {
  --frio: #cbb26a;          /* oro pálido angélico (cálido, no azul) */
  --frio-bright: #f2e6b8;   /* destello de vela */
}
.azcard.alcard .az-eyebrow { font-family: var(--font-display); letter-spacing: .18em; }
.azcard.alcard .az-name { font-family: var(--font-display); font-weight: 600; letter-spacing: .06em; }
.azcard.alcard .az-sub { font-family: var(--font-body); font-size: .76rem; }
/* Glifo = TABLILLA cuadrada (esquinas suaves), no el óvalo-espejo ni el círculo-punto. */
.azcard.alcard::after {
  border-radius: 14%;
  background:
    radial-gradient(52% 52% at 50% 42%, color-mix(in srgb, var(--frio-bright) 66%, transparent) 0, transparent 62%),
    linear-gradient(150deg, color-mix(in srgb, var(--frio) 24%, transparent), rgba(10,9,6,.9) 72%);
}
/* Escena del Almadel: el tag angélico en oro pálido (no el frío-azul moderno ni el acero). */
#s-ritual.is-almadel #ritualModernTag {
  color: color-mix(in srgb, #f2e6b8 78%, var(--ink));
  border-color: color-mix(in srgb, #cbb26a 55%, transparent);
}
#s-ritual.is-almadel #ritualStepTitulo { font-family: var(--font-display); font-weight: 600; letter-spacing: .03em; }
/* §V — Verum (Grimorium Verum · De Secretis): tema pergamino/oro, distinto del sepia goético. */
#s-ritual.is-verum #ritualModernTag {
  color: color-mix(in srgb, #e8c874 80%, var(--ink));
  border-color: color-mix(in srgb, #c9a253 55%, transparent);
}
#s-ritual.is-verum #ritualStepTitulo { font-family: var(--font-display); font-weight: 600; letter-spacing: .03em; }
/* botón «Comenzar la operación» del estudio Verum */
.vm-begin { margin: 26px 0 8px; text-align: center; }
.vm-beginbtn { font-family: "Cinzel", Georgia, serif; font-size: .82rem; letter-spacing: .08em; text-transform: uppercase;
  padding: 12px 26px; border-radius: 999px; border: 1.5px solid var(--oro);
  background: var(--oro); color: #1a1408; font-weight: 700; cursor: pointer; transition: filter .18s, transform .1s; }
.vm-beginbtn:hover { filter: brightness(1.08); }
.vm-beginbtn:active { transform: translateY(1px); }
.vm-beginbtn:focus-visible { outline: 2px solid var(--oro-b, var(--oro)); outline-offset: 3px; }

/* Tablilla de cera del Almadel — losa REAL apoyada en la superficie (perspectiva + grosor +
   sombra de contacto), no una hoja plana pegada. El COLOR de la cera lo fija el rito por Altitud
   (var --wax); el grabado va en oro (--seal-gold), como los sellos goéticos. SVG inline. */
/* Posición FIJA en el centro-alto: así queda por ENCIMA de las opciones (abajo) en los pasos de
   elegir y sólo el banner superior (que se atenúa a los 2.4s) la roza. La vela persistente se
   ancla a esta misma tablilla, por eso no la reposicionamos por paso (evita que se desprenda). */
.almadel-stage {
  position: absolute; left: 50%; bottom: 27%; transform: translateX(-50%);
  width: min(26vw, 38vh, 176px); aspect-ratio: 1 / 1; z-index: 6; pointer-events: none;
  --wax: #efe7d3; --seal-gold: #d8b25a;
  perspective: 660px;
  animation: almadelIn 1.15s ease both;
}
.almadel-stage[hidden] { display: none; }
/* La tablilla se ACUESTA sobre el plano del suelo (rotateX con origen en la base) y gana grosor
   de cera con una pila de box-shadows en el color de la cera → losa con peso, no papel. */
.almadel-stage .almadel-img {
  width: 100%; height: 100%; display: block;
  transform: rotateX(56deg); transform-origin: 50% 94%; border-radius: 7%;
  box-shadow:
    0 2px 0 color-mix(in srgb, var(--wax) 72%, #000),
    0 4px 0 color-mix(in srgb, var(--wax) 58%, #000),
    0 6px 0 color-mix(in srgb, var(--wax) 44%, #000),
    0 8px 1px color-mix(in srgb, var(--wax) 32%, #000),
    0 15px 24px rgba(0,0,0,.6);
  filter: drop-shadow(0 0 9px color-mix(in srgb, var(--seal-gold) 22%, transparent));
}
/* Sombra de contacto en el suelo (peso/gravedad): más ancha y oscura, apoyada bajo la losa. */
.almadel-stage::after {
  content: ""; position: absolute; left: 50%; bottom: -10%; width: 98%; height: 20%;
  transform: translateX(-50%); border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(0,0,0,.72), rgba(0,0,0,.34) 45%, transparent 74%);
  filter: blur(4px); z-index: -1;
}
@keyframes almadelIn { from { opacity: 0; transform: translateX(-50%) translateY(10px); } to { opacity: 1; transform: translateX(-50%) translateY(0); } }
@media (prefers-reduced-motion: reduce) { .almadel-stage { animation: none; opacity: 1; } }
/* Vela de cera SOBRE la tablilla (rito del Almadel): reutiliza el chasis .candle; se posiciona
   por JS en el centro de la tablilla. Humo de almáciga: pálido, continuo, se eleva de la cera. */
.almadel-smoke {
  position: absolute; z-index: 8; pointer-events: none; transform: translate(-50%, -100%);
  width: min(11vw, 74px); height: min(34vh, 230px);
  background:
    radial-gradient(38% 15% at 50% 92%, rgba(236,230,214,.5), transparent 72%),
    radial-gradient(30% 13% at 44% 62%, rgba(222,214,196,.28), transparent 72%),
    radial-gradient(30% 13% at 58% 40%, rgba(222,214,196,.2), transparent 72%);
  filter: blur(7px); mix-blend-mode: screen; opacity: 0;
  animation: incenseRise 6.5s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) { .almadel-smoke { animation: none; opacity: .3; } }
/* La vela del Almadel SIN encender debe NOTARSE (el usuario debe saber que hay algo que tocar):
   pálpito cálido hasta que se enciende. Al encender, gana el .candle.lit normal. */
.candle.candle-almadel:not(.lit) { animation: almCandleBeacon 1.9s ease-in-out infinite; }
@keyframes almCandleBeacon {
  0%, 100% { filter: brightness(.82) saturate(.95) drop-shadow(0 0 3px rgba(240,214,110,.28)); }
  50%      { filter: brightness(1.05) saturate(1) drop-shadow(0 0 10px rgba(240,214,110,.62)); }
}
@media (prefers-reduced-motion: reduce) { .candle.candle-almadel:not(.lit) { animation: none; filter: brightness(1) drop-shadow(0 0 6px rgba(240,214,110,.45)); } }
/* Resplandor angélico del descenso (manifestación del Almadel): halo cálido que crece sobre la
   tablilla antes del resultado → cierre no abrupto. */
.almadel-halo {
  position: absolute; z-index: 7; pointer-events: none; transform: translate(-50%, -50%);
  width: min(60vw, 90vh, 520px); aspect-ratio: 1/1; border-radius: 50%;
  background: radial-gradient(circle at 50% 50%, color-mix(in srgb, var(--seal-gold,#d8b25a) 42%, transparent) 0, color-mix(in srgb, var(--seal-gold,#d8b25a) 12%, transparent) 34%, transparent 66%);
  mix-blend-mode: screen; opacity: 0; animation: almadelHalo 3s ease-out forwards;
}
@keyframes almadelHalo { 0%{opacity:0;transform:translate(-50%,-50%) scale(.5)} 40%{opacity:.9} 100%{opacity:.7;transform:translate(-50%,-50%) scale(1.15)} }
@media (prefers-reduced-motion: reduce) { .almadel-halo { animation: none; opacity: .7; } }

/* Marcado de PRÁCTICA MODERNA en la cabecera del rito (eyebrow frío sobre el nombre). */
.ritual-demon-wrap { display: inline-flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.ritual-modern-tag {
  font-family: var(--font-modern); font-size: .58rem; font-weight: 500; letter-spacing: .14em;
  text-transform: uppercase; color: var(--frio-bright); opacity: .92;
}
.ritual-modern-tag[hidden] { display: none; }

.foot-note { text-align: center; color: var(--ink-soft); font-size: .72rem; padding: 6px 16px 0; margin: 0; }

/* ─────────────────────────── Pantalla 2 · Estudio ─────────────────────────── */
#s-study { background: var(--bg); background-size: cover; background-position: center 55%; }
/* Fondos generados con gpt-image: misma mesa del ritual, por orientación.
   El libro real (marco) se dibuja encima con .grimorio, no va fundido en el fondo. */
#s-study.has-study-bg { background-image: url(/r/assets/ritual-landscape.webp); }
@media (orientation: portrait) {
  #s-study.has-study-bg { background-image: url(/r/assets/ritual-portrait.webp); }
}
#s-study::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, rgba(5,3,1,.78), rgba(5,3,1,.30) 32%, rgba(5,3,1,.42) 58%, rgba(5,3,1,.82));
  z-index: 0;
}
#s-study > *:not(.topbar):not(.tradrow):not(.bookwrap):not(.bottombar):not(.pagenum) { position: relative; z-index: 1; }
#s-study .topbar, #s-study .tradrow, #s-study .bookwrap, #s-study .bottombar, #s-study .pagenum { position: relative; z-index: 2; }
.top-title { font-family: "Cinzel", serif; font-size: .78rem; letter-spacing: .2em; text-transform: uppercase; color: var(--oro); }
.top-spacer { width: 74px; }
/* Selector de tradición: antiguo / moderno / ambos */
.tradrow {
  display: flex; gap: var(--sp-2); justify-content: center; align-items: center;
  padding: var(--sp-1) var(--sp-3) 2px;
}
.tradbtn {
  font-family: var(--ctl-font); font-size: .62rem; letter-spacing: var(--ctl-tracking);
  text-transform: uppercase; font-weight: 600; cursor: pointer;
  min-height: 36px; padding: var(--sp-2) var(--sp-3); border-radius: var(--ctl-radius);
  border: 1px solid var(--ctl-border); background: var(--ctl-bg); color: var(--ctl-fg);
  transition: border-color var(--dur-fast), color var(--dur-fast), background var(--dur-fast);
}
.tradbtn:hover { border-color: var(--oro); color: var(--ctl-fg-hover); background: var(--ctl-bg-hover); }
.tradbtn.active { border-color: var(--ctl-on-border); color: var(--ctl-on-fg); background: var(--ctl-on-bg); }
/* Etiquetas Antiguo/Moderno dentro del grimorio */
.trad-badge {
  display: inline-block; font-size: .52rem; letter-spacing: .14em; text-transform: uppercase;
  padding: 2px 7px; border-radius: 2px; vertical-align: middle; margin-right: 6px; border: 1px solid;
}
.trad-badge.antiguo { color: var(--book-ink); border-color: var(--book-accent); background: color-mix(in srgb, var(--book-accent) 22%, transparent); }
.trad-badge.moderno { color: var(--book-ink-soft); border-color: var(--book-ink-soft); background: rgba(107,74,34,.12); }
/* El libro: contenedor con página que voltea en 3D */
/* ═══════════ El grimorio: libro físico real (asset + hojas calibradas) ═══════════
   El libro lo aporta el asset fotográfico (cuero, grosor, canto, lomo). Las hojas
   de tinta se posicionan en % sobre las páginas del asset, así el ajuste es
   intrínseco a su proporción (aspect-ratio) y correcto a cualquier tamaño. */
.bookwrap {
  flex: 1; min-height: 0;
  display: flex; align-items: center; justify-content: center;
  gap: clamp(4px, 1.4vw, 16px);
  padding: clamp(6px, 1.4vh, 14px) clamp(8px, 1.8vw, 24px);
}
.pagebtn {
  flex: none; align-self: center;
  width: clamp(34px, 3.2vw, 46px); height: clamp(60px, 26%, 200px);
  border: 1px solid var(--linea); border-radius: 8px;
  background: rgba(20,12,4,.34); color: var(--oro); font-size: 1.7rem; line-height: 1;
  display: flex; align-items: center; justify-content: center; padding: 0;
  transition: background .18s, color .18s, opacity .18s;
}
.pagebtn:hover:not(:disabled) { background: rgba(201,162,83,.14); color: var(--oro-bright); }
.pagebtn:disabled { opacity: .22; cursor: default; }

.grimorio {
  /* Hueco de páginas dentro del asset (porcentajes del propio libro). */
  --pad-top: 14%; --pad-bottom: 18.5%; --pad-side: 15.5%; --gutter: 4.5%;
  --book-accent: #8a6a2f;
  position: relative; margin: auto;
  aspect-ratio: 1600 / 900; height: 100%; width: auto;
  max-width: min(94vw, 1560px); max-height: 100%;
  background: center / 100% 100% no-repeat;
  background-image: url(/r/assets/grimorio-libro.webp);
  border-radius: var(--r-md);
  perspective: 2400px;
  cursor: grab; touch-action: pan-y;
  /* Pasar página no debe seleccionar el texto de la hoja. */
  user-select: none; -webkit-user-select: none;
  filter: drop-shadow(0 24px 44px rgba(0,0,0,.6));
}
.grimorio.dragging { cursor: grabbing; user-select: none; -webkit-user-select: none; }
/* Móvil / vertical: una sola hoja del grimorio (asset de página única). */
.grimorio.is-single {
  aspect-ratio: 1080 / 1440;
  --pad-top: 17%; --pad-bottom: 19%; --pad-side: 18%; --gutter: 0%;
  /* Borde de la LÁMINA con marco (para la hoja que gira): un pelo por fuera del marco
     ornamental del asset, para que el giro arrastre el marco y parezca una hoja entera. */
  --flip-top: 10%; --flip-bottom: 13%; --flip-side: 11.5%;
  background-image: url(/r/assets/grimorio-pagina-movil.webp);
}

/* Hojas de contenido: la tinta vive aquí; el pergamino lo da el asset. */
.leaf {
  position: absolute; z-index: 2; overflow: hidden;
  top: var(--pad-top); bottom: var(--pad-bottom);
  color: var(--book-ink); font-family: "EB Garamond", Georgia, serif;
}
.is-spread .leaf-left  { left: var(--pad-side); right: calc(50% + var(--gutter) / 2); }
.is-spread .leaf-right { left: calc(50% + var(--gutter) / 2); right: var(--pad-side); }
.is-single .leaf-left  { left: var(--pad-side); right: var(--pad-side); }
.is-single .leaf-right { display: none; }
/* Curvatura hacia el lomo: sombra sutil en el borde interior de la hoja. */
.leaf::after { content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none; }
.is-spread .leaf-left::after  { background: linear-gradient(90deg, transparent 72%, rgba(58,38,14,.20)); }
.is-spread .leaf-right::after { background: linear-gradient(270deg, transparent 72%, rgba(58,38,14,.20)); }

.leaf-ink {
  box-sizing: border-box; height: 100%;
  padding: clamp(8px, 1.6vw, 24px) clamp(12px, 2vw, 32px);
  font-size: clamp(.84rem, 1.02vw, 1.05rem); line-height: 1.62;
}
.leaf-foot { display: block; text-align: center; color: var(--book-accent); opacity: .4; letter-spacing: .4em; margin: .75em 0 0; font-size: .82em; }

/* Profundidad del lomo (solo pliego): sombra simétrica, nunca una barra negra. */
.is-spread::after {
  content: ""; position: absolute; z-index: 3; pointer-events: none;
  top: var(--pad-top); bottom: var(--pad-bottom);
  left: calc(50% - var(--gutter)); width: calc(var(--gutter) * 2);
  background: linear-gradient(90deg, transparent, rgba(40,24,8,.22) 42%, rgba(40,24,8,.30) 50%, rgba(40,24,8,.22) 58%, transparent);
}

/* La hoja que gira: dos caras texturizadas de pergamino, pivote en el lomo. */
.leaf-flip { position: absolute; z-index: 6; display: none; transform-style: preserve-3d; transform: rotateY(var(--turn, 0deg)); }
.leaf-flip.active { display: block; }
/* Peso de hoja real: ARRANQUE SUAVE (la hoja se levanta despacio desde su borde libre) →
   acelera al cruzar la vertical → asentamiento suave. Curva simétrica (ease-in-out) para
   que el levante y la caída se vean por igual: al RETROCEDER se ve empezar desde la
   IZQUIERDA (antes, con arranque rápido, la fase izquierda pasaba volando y parecía
   "anclada a la derecha"). */
.leaf-flip.animate { transition: transform .66s cubic-bezier(.42, 0, .2, 1); }
/* La hoja que gira ocupa la HOJA real del libro (no solo el hueco de texto): en móvil se
   expande al pergamino con su MARCO (`--flip-*` = borde de la lámina); en pliego coincide
   con el hueco de texto (esas páginas no llevan marco). El pivote es el lomo/encuadernado. */
.leaf-flip.side-right { top: var(--flip-top, var(--pad-top)); bottom: var(--flip-bottom, var(--pad-bottom)); right: var(--flip-side, var(--pad-side)); left: calc(50% + var(--gutter) / 2); transform-origin: left center; }
.leaf-flip.side-left  { top: var(--flip-top, var(--pad-top)); bottom: var(--flip-bottom, var(--pad-bottom)); left: var(--flip-side, var(--pad-side)); right: calc(50% + var(--gutter) / 2); transform-origin: right center; }
.is-single .leaf-flip.side-right { left: var(--flip-side, var(--pad-side)); }
.is-single .leaf-flip.side-left  { right: var(--flip-side, var(--pad-side)); }
.leaf-face {
  position: absolute; inset: 0; overflow: hidden; backface-visibility: hidden;
  /* El pergamino REAL del libro (con su marco/ornamentación) lo pinta el JS como fondo
     ALINEADO a la posición del libro → la hoja que gira ES la misma hoja del grimorio, no
     una lámina lisa distinta. Este color es solo reserva si el asset no cargara. */
  background: var(--book-leaf) no-repeat;
  /* sombra de CONTACTO (la hoja proyecta sobre el libro) + curvatura hacia el lomo */
  box-shadow: 0 7px 22px rgba(0,0,0,.5), inset 10px 0 26px rgba(70,48,16,.16);
}
/* Hueco de texto dentro de la hoja que gira (JS lo posiciona en la zona de texto real
   cuando la cara se expande al marco). La tinta vive dentro, con su padding habitual. */
.face-ink-pos { position: absolute; inset: 0; }
.leaf-back { box-shadow: 0 7px 22px rgba(0,0,0,.5), inset -10px 0 26px rgba(70,48,16,.16); }
.leaf-back { transform: rotateY(180deg); }
/* VOLUMEN de la hoja al girar: cuanto más vertical (--p→.5), más sombra de pliegue Y un
   filo de luz en el borde que se levanta → la hoja tiene grosor/arqueo, no es papel plano.
   La sombra crece y decrece en el giro (máx a medio camino). Solo opacity animada. */
.leaf-face::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  opacity: calc(var(--fold, var(--p, 0)) * .72);
  background:
    linear-gradient(90deg, rgba(0,0,0,.6), rgba(0,0,0,.06) 40%, rgba(0,0,0,.42)),
    linear-gradient(90deg, rgba(255,244,214,.14), transparent 18%);
}

/* (Se retiró el triángulo de "pliegue": parecía un error suelto, no una hoja del
   libro. La afordancia de pasar página son las flechas ‹ ›, el teclado y el
   arrastre/swipe sobre el libro.) */
.book-curl { display: none; }
.pagenum { text-align: center; color: var(--ink-soft); font-size: .72rem; margin: 2px 0 0; text-shadow: 0 1px 4px rgba(0,0,0,.9); }

/* Tinta del grimorio: oscura sobre pergamino, jerarquía editorial, acento por demonio.
   Tamaños en em/clamp → escalan con la hoja, sin overrides por dispositivo. */
/* TINTA SECA INCRUSTADA EN LAS FIBRAS DEL PAPEL: la tinta se ABSORBE en el pergamino
   con `multiply` (varía con la textura real de la hoja, no flota encima). SIN sombra,
   glow, emboss ni desenfoque. Los TÍTULOS llevan además un microdesplazamiento (tinta
   absorbida desigual → bordes con desgaste), no un blur. El cuerpo queda limpio para
   máxima legibilidad en móvil. */
.grimorio .gname, .grimorio h3, .grimorio .gsec p, .grimorio li,
.grimorio .gfuente, .grimorio figcaption, .grimorio .fisico-badge,
.grimorio .leaf-foot, .grimorio .genn {
  mix-blend-mode: multiply;
}
/* Títulos (nombre del demonio + encabezados): microdesplazamiento de tinta. */
/* TÍTULOS: irregularidad de tinta algo mayor. CUERPO y demás texto: sangrado capilar
   fino + borde desigual → toda la letra se siente tinta seca ABSORBIDA en la fibra, no
   texto HTML nítido encima. (Estático: sin coste por frame; legibilidad conservada.) */
.grimorio .gname, .grimorio h3 { filter: url(#inkPaper); }
.grimorio .gsec p, .grimorio li, .grimorio .gfuente, .grimorio .genn,
.grimorio figcaption, .grimorio .gmeta, .grimorio .gapp, .grimorio .leaf-foot {
  filter: url(#inkAbsorb);
}
/* Título: el acento dorado del demonio (--book-accent) se oscurece hacia la tinta para que SIEMPRE
   contraste sobre el pergamino claro (los glows brillantes se lavaban con multiply). Conserva el matiz. */
.grimorio h3 { font-family: "Cinzel", serif; color: color-mix(in srgb, var(--book-accent) 42%, var(--book-ink)); font-weight: 600; font-size: clamp(.58rem, .82vw, .76rem); letter-spacing: .18em; text-transform: uppercase; margin: 0 0 .55em; break-after: avoid; }
.grimorio .gsec { margin: 0 0 .9em; }
.grimorio .gsec:last-child { margin-bottom: 0; }
.grimorio .gsec p { margin: 0 0 .5em; color: var(--book-ink); text-align: justify; hyphens: auto; }
.grimorio .gsec p:last-child { margin-bottom: 0; }
/* Línea de PREPARACIÓN práctica (incienso + color de vela): destacada como una nota accionable. */
.grimorio .gsec .prep-line { text-indent: 0; border-left: 2px solid var(--book-accent, #c9a253); padding-left: .7em; margin: .55em 0; font-style: italic; }
.grimorio .gsec-head p:not(:first-of-type), .grimorio .gsec-cont p + p, .grimorio .gsec p + p { text-indent: 1.3em; }
.grimorio ol { margin: .3em 0; padding-left: 1.35em; }
.grimorio li { margin: .35em 0; color: var(--book-ink); text-align: justify; }
.grimorio .gfuente { font-size: .85em; color: var(--book-ink-soft); font-style: italic; }
.grimorio .ghonest { border-left: 2px solid var(--book-accent); padding: .4em .7em; color: var(--book-accent); font-size: .92em; margin: .6em 0; background: color-mix(in srgb, var(--book-accent) 8%, transparent); }
.grimorio .genn { font-size: .95em; color: var(--book-ink); font-style: italic; margin: .4em 0; }
.grimorio .gsec-moderno h3 { color: var(--book-ink-soft); }
.grimorio .gsec-moderno .ghonest { border-left-color: var(--book-ink-soft); color: var(--book-ink-soft); background: rgba(107,74,34,.08); }

/* Portada del demonio: sello + nombre + rango + apariencia, centrada como guarda. */
.grimorio .gsec-cover { height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; margin: 0; }
.grimorio .gname { font-family: "Cinzel", serif; color: var(--book-ink); font-size: clamp(1.5rem, 2.7vw, 2.4rem); letter-spacing: .05em; margin: .12em 0 .05em; }
.grimorio .gmeta { color: var(--book-ink-soft); font-size: clamp(.8rem, .95vw, .95rem); margin: 0 0 .9em; font-style: italic; }
.grimorio .page-seal { width: clamp(84px, 10vw, 136px); aspect-ratio: 1; margin: 0 auto .55em; background: var(--book-accent); -webkit-mask: var(--m) center/contain no-repeat; mask: var(--m) center/contain no-repeat; filter: drop-shadow(0 2px 4px rgba(0,0,0,.4)); }
/* .gsec-cover .gapp: sube especificidad para VENCER a `.gsec p{text-align:justify}` (si no,
   la aparición se justifica y en columnas estrechas abre ríos/huecos horribles). */
.grimorio .gsec-cover .gapp { font-style: italic; color: var(--book-ink-soft); font-size: clamp(.95rem, 1.1vw, 1.12rem); line-height: 1.66; max-width: 30ch; margin: .3em auto 0; text-align: center; }

/* Portada divisoria (modo «Ambos»): marca claramente el paso a lo moderno. */
.grimorio .gsec-divider { justify-content: center; }
.grimorio .gsec-divider .divider-mark { font-size: clamp(2rem, 5vw, 3.4rem); line-height: 1; color: var(--book-accent); opacity: .82; margin-bottom: .15em; }
.grimorio .gsec-divider.gsec-moderno .divider-mark { color: var(--book-ink-soft); }

/* Comparación física del demonio: cómo se le describió (antiguo vs moderno). */
/* Bloque centrado verticalmente: así la leyenda queda AL PIE de cada imagen con
   aire por debajo, sin pegarse al borde del pergamino. */
.grimorio .gsec-fisico { height: 100%; min-height: 0; display: flex; flex-direction: column; justify-content: center; gap: .35em; margin: 0; }
.grimorio .gsec-fisico > h3 { flex: none; text-align: center; margin: 0 0 .5em; color: var(--book-ink); font-size: clamp(.62rem, .86vw, .8rem); }
/* Las dos imágenes tienen EXACTAMENTE el mismo tamaño (aspect-ratio 3/4 = 900×1200)
   y se alinean arriba → simetría perfecta aunque las leyendas midan distinto. */
.fisico-par { flex: 0 1 auto; width: 100%; min-height: 0; display: flex; gap: clamp(6px, 2vw, 16px); align-items: flex-start; justify-content: center; }
.fisico-fig { flex: 1 1 0; min-width: 0; max-width: 49%; min-height: 0; display: flex; flex-direction: column; align-items: center; margin: 0; }
/* Grabado sepia con fondo TRANSPARENTE (PNG): la tinta se funde en el pergamino
   con multiply y el fondo deja ver la hoja → parece dibujado en el grimorio. */
.fisico-fig .fisico-img {
  width: 100%; height: auto; aspect-ratio: 1 / 1; flex: none; max-height: none;
  object-fit: contain;
  /* Grabado IMPRESO en el pergamino, no pegado: multiply funde la tinta con la textura;
     sepia+contraste bajo mata el negro digital puro y lo integra con el tono del papel;
     opacidad <1 deja respirar la fibra a través del trazo. Filtro ESTÁTICO (barato). */
  mix-blend-mode: multiply;
  filter: sepia(.18) contrast(.92);
  opacity: 0; transition: opacity .5s ease;   /* fade-in tras cargar (con skeleton) */
}
.fisico-fig.loaded .fisico-img { opacity: .88; }
/* SKELETON del grabado: marco de tiza tenue con shimmer cálido mientras carga. */
.fisico-fig.is-loading { position: relative; }
.fisico-fig.is-loading::before {
  content: ""; position: absolute; left: 0; right: 0; top: 1.6em;
  aspect-ratio: 1 / 1; max-height: 44vh; border-radius: 6px;
  border: 1px solid color-mix(in srgb, var(--book-accent) 30%, transparent);
  background: linear-gradient(115deg, transparent 30%, color-mix(in srgb, var(--book-accent) 16%, transparent) 50%, transparent 70%),
              color-mix(in srgb, var(--book-parchment2) 40%, transparent);
  background-size: 300% 100%, 100% 100%;
  animation: fisicoShimmer 1.4s linear infinite;
  pointer-events: none;
}
.fisico-fig.loaded::before { display: none; }
@keyframes fisicoShimmer { 0% { background-position: 120% 0, 0 0; } 100% { background-position: -120% 0, 0 0; } }
@media (prefers-reduced-motion: reduce) { .fisico-fig.is-loading::before { animation: none; } }
.fisico-badge { font-family: var(--font-display); font-weight: 600; font-size: .58rem; letter-spacing: .14em; text-transform: uppercase; color: var(--book-accent); margin-bottom: .4em; }
.fisico-badge.moderno { color: var(--book-ink-soft); }
.fisico-fig figcaption { flex: none; font-size: .82em; font-style: italic; color: var(--book-ink); text-align: center; margin-top: .45em; line-height: 1.35; }

/* Introducción de cada tradición: se abre con capitular iluminada. */
.grimorio .gsec-intro h3 { margin: 0 0 .6em; }
.grimorio .gsec-intro.gsec-head p:first-of-type::first-letter {
  font-family: "Cinzel", serif; float: left;
  font-size: 3em; line-height: .8; font-weight: 600;
  margin: .04em .12em 0 0; color: var(--book-accent);
  mix-blend-mode: multiply;
}
.bottombar { padding: 12px 16px calc(12px + var(--safe-b)); display: flex; justify-content: center; gap: 10px; }

/* ─────────────────────────── Pantalla 3 · Ritual (POV) ─────────────────────────── */
#s-ritual { background: var(--negro); }
/* M6 · ENTRADA CEREMONIAL — al entrar al rito, un velo negro se disipa lento (~1.7 s) y el
   altar «cobra presencia» desde la oscuridad: cruzar de lo mundano a lo sagrado, no cambiar
   de pestaña. Solo opacity (barato). No bloquea el toque salvo el primer instante. */
#s-ritual::before {
  content: ""; position: absolute; inset: 0; z-index: 40; background: var(--negro);
  opacity: 0; pointer-events: none;
}
#s-ritual.entering::before { animation: ritualEnter 1.7s cubic-bezier(.22,.61,.36,1) forwards; }
@keyframes ritualEnter { 0% { opacity: 1; } 8% { opacity: 1; } 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { #s-ritual.entering::before { animation: none; opacity: 0; } }
.scene { position: absolute; inset: 0; overflow: clip; contain: paint; }
/* Sin menú contextual/«descargar imagen» ni selección al mantener pulsado en el rito
   (el orbe del enn y el trazo requieren long-press sin que salte el menú de Chrome). */
.scene, .scene img, .intone, .intone-orb, .intone-orb *, .seal-stage, .seal-stage * {
  -webkit-touch-callout: none; -webkit-user-select: none; user-select: none;
}
#bgLayer { pointer-events: none; -webkit-user-drag: none; }
.bgwrap {
  position: absolute; inset: 0;
  overflow: hidden;
  will-change: transform;
  transition: transform .35s ease-out;
  background: var(--negro);
}
/* Relleno desenfocado detrás de la imagen (evita bandas negras en vertical) */
.bgwrap::before {
  content: "";
  position: absolute; inset: -12%;
  background-image: var(--bgimg, none);
  background-size: cover;
  background-position: center;
  filter: blur(22px) brightness(.45) saturate(.9);
  transform: scale(1.06);
  pointer-events: none;
}
#bgLayer {
  position: relative; z-index: 1;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 50% 55%;
  display: block;
  filter: var(--filtro, none);
  transition: opacity .5s ease;   /* fade-in cuando termina de cargar (con skeleton) */
}
/* SKELETON de la escena: shimmer cálido oro/negro (nuestro sello) mientras carga el
   fondo del rito, en vez de un hueco negro. Se retira al hacer onload la imagen. */
.bgwrap.bg-loading::before { opacity: 0; }
.bgwrap.bg-loading::after {
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background-color: var(--d-bg-deep);
  background-image:
    radial-gradient(120% 85% at 50% 46%, rgba(48,33,12,.7), rgba(8,6,3,.97) 72%),
    repeating-linear-gradient(115deg, transparent 0 24%, rgba(201,162,83,.08) 30%, transparent 36%);
  background-size: 100% 100%, 300% 100%;
  background-position: 0 0, 0 0;
  animation: bgShimmer 1.5s linear infinite;
}
@keyframes bgShimmer { 0% { background-position: 0 0, 120% 0; } 100% { background-position: 0 0, -120% 0; } }
@media (prefers-reduced-motion: reduce) { .bgwrap.bg-loading::after { animation: none; } }
/* En vertical la imagen se mantiene a sangre completa (cover) para que el círculo
   de juego coincida con el del arte; se añade un degradado que integra el HUD y
   se recomienda girar el móvil (overlay de orientación). */
@media (max-width: 820px) and (orientation: portrait) {
  #bgLayer { object-fit: cover; object-position: 50% 52%; }
  .bgwrap::after {
    content: "";
    position: absolute; inset: 0; z-index: 2;
    background: linear-gradient(180deg, rgba(0,0,0,.62), transparent 24%, transparent 58%, rgba(0,0,0,.82));
    pointer-events: none;
  }
  .circle-glow { top: 42%; width: min(56vw, 400px); }
}
.circle-glow {
  position: absolute; left: 50%; top: 45%; width: min(44vw, 420px); aspect-ratio: 1 / 0.62;
  transform: translate(-50%, -50%); border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--glow) 22%, transparent) 0 30%, transparent 70%);
  animation: glowPulse 5.5s ease-in-out infinite; pointer-events: none;
}
@keyframes glowPulse {
  0%, 100% { opacity: .55; transform: translate(-50%,-50%) scale(1); }
  50% { opacity: .95; transform: translate(-50%,-50%) scale(1.06); }
}

/* Manos vectoriales antiguas: se eliminan porque degradan la escena fotorealista.
   La referencia POV queda representada por el fondo y el círculo interactivo. */
.hands { display: none !important; }
.hand { position: absolute; bottom: -2%; filter: drop-shadow(0 10px 18px rgba(0,0,0,.6)); }
.hand-l { left: -4%; width: clamp(150px, 34vw, 270px); }
.hand-r { right: -4%; width: clamp(150px, 34vw, 270px); }
.hand .sleeve { fill: #171009; }
.hand .skin { fill: #241708; stroke: rgba(226,191,108,.14); stroke-width: 1; }
.hand .ring { fill: #c9a253; opacity: .8; }
.hand .metal { fill: #8d7a4a; }
.hand .metal.dark { fill: #4a3b1e; }
.hand-sway-l { animation: handBreathL 9s ease-in-out infinite; transform-origin: 90% 100%; }
.hand-sway-r { animation: handBreathR 11s ease-in-out infinite; transform-origin: 10% 100%; }
.finger-l2, .finger-r2 { animation: fingerTap 7s ease-in-out infinite; transform-origin: center bottom; }
.finger-r3 { animation: fingerTap 8.5s ease-in-out .6s infinite; transform-origin: center bottom; }
.stylus { animation: stylusSway 10s ease-in-out infinite; transform-origin: 20% 80%; }
@keyframes handBreathL { 0%,100% { transform: translate(0,0) rotate(0); } 50% { transform: translate(2px,-3px) rotate(-1.1deg); } }
@keyframes handBreathR { 0%,100% { transform: translate(0,0) rotate(0); } 50% { transform: translate(-2px,-3px) rotate(1.2deg); } }
@keyframes fingerTap { 0%,100% { transform: translateY(0); } 46% { transform: translateY(0); } 52% { transform: translateY(-2.4px); } 58% { transform: translateY(0); } }
@keyframes stylusSway { 0%,100% { transform: rotate(0); } 50% { transform: rotate(-2.4deg); } }

/* Canvas de FX (humo/brasas) */
#fxCanvas { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 7; }

/* Trazado del círculo: una sola geometría SVG compartida por base/progreso/hit-area.
   ritual-base  → grabado del suelo (parte del arte, no flota).
   ritual-progress → ilumina solo la sección ya recorrida.
   ritual-hit-area → zona táctil invisible, más ancha que el trazo visual. */
/* El SVG se mezcla en screen con el suelo: el negro del asset desaparece y el
   oro (arte + trazo) se suma como brasa mágica sobre la piedra. */
.trace-svg { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 8; touch-action: none; overflow: visible; mix-blend-mode: screen; }
/* Círculo mágico HISTÓRICO dibujado en SVG (anillos + nombres divinos + hexagramas
   de Salomón), fiel a los grimorios. Trazo blanco-tiza con tenue resplandor: se lee
   como dibujado/grabado en el suelo (el blend screen lo funde con la piedra). */
/* Suelo: charco de luz cálida + grano de piedra/polvo de tiza. Asientan el círculo
   sobre las losas (matan el look «vector flotando»); el blend screen los funde. */
.trace-svg .ritual-floor { fill: url(#floorGrad); opacity: .55; }
.trace-svg .ritual-floortex { fill: #fff; opacity: .05; }
/* Arte de tiza realista (PNG transparente): se suma como polvo claro sobre el suelo
   oscuro (blend screen del SVG). Ligera calidez para no verse azulado/plano. */
.trace-svg .ritual-circ-img, .trace-svg .ritual-tri-img {
  opacity: .8;
  filter: sepia(.42) saturate(.95) brightness(.86) drop-shadow(0 0 4px rgba(226,191,108,.16));
}
/* Paso SELLO: se atenúa el círculo (ya trazado) y el Triángulo del Arte se AGRANDA y
   pasa al frente para grabar el sello dentro. Transición suave de la geometría SVG. */
.trace-svg .ritual-tri-img {
  transition: x .5s ease, y .5s ease, width .5s ease, height .5s ease, opacity .5s ease, filter .5s ease;
}
.trace-svg.seal-mode .ritual-circ-img,
.trace-svg.seal-mode .ritual-floor,
.trace-svg.seal-mode .ritual-floortex,
.trace-svg.seal-mode .ritual-progress { opacity: .3; transition: opacity .5s ease; }
.trace-svg.seal-mode .ritual-tri-img.tri-focus {
  opacity: 1;
  filter: sepia(.34) saturate(1) brightness(1.02) drop-shadow(0 0 10px rgba(233,206,140,.45));
}
/* Lienzo del sello: se posiciona SOBRE el triángulo (coords de escena), tiza. */
/* El sigilo/sello se GRABA ACOSTADO en la superficie (perspectiva de suelo): aplanado,
   no frontal ni flotando. transform-origin arriba → el borde lejano se comprime más. */
.seal-stage { position: absolute; z-index: 9; pointer-events: none;
  transform: scaleY(.56); transform-origin: 50% 44%; }
/* GUÍA tenue integrada en la superficie (NO un disco/parche oscuro): apenas una marca
   de tiza base que ayuda a ver el sigilo sin parecer pegado encima. */
.seal-stage::before {
  content: ""; position: absolute; inset: -6%; z-index: 0; border-radius: 50%;
  background: radial-gradient(circle, rgba(12,8,4,.34) 28%, rgba(12,8,4,.14) 54%, transparent 74%);
}
.seal-stage { --intone: 0; }
.seal-stage canvas {
  position: relative; z-index: 1;
  width: 100%; height: 100%; touch-action: none; cursor: crosshair; pointer-events: auto;
  /* TIZA: bordes irregulares + polvo (dibujado a mano) + leve resplandor. Filtro ESTÁTICO
     (no se anima por frame → no re-rasteriza en móvil). */
  filter: url(#chalkSeal) drop-shadow(0 0 7px rgba(233,206,140,.45));
}
.seal-stage.sealed canvas { filter: url(#chalkSeal) drop-shadow(0 0 20px rgba(244,236,214,.85)); }
/* ENTONAR el enn: el sigilo se ENCIENDE de forma diegética. La luz es una capa APARTE
   (radial cálida, screen) cuya OPACITY = --intone (0→1): solo se compone opacity → barato.
   El resplandor nace del centro del sigilo y crece con el canto, como brasa que prende. */
.seal-stage::after {
  content: ""; position: absolute; inset: -30%; z-index: 2; pointer-events: none;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255,226,150,.9) 0%, rgba(233,196,110,.5) 34%, rgba(226,150,60,.18) 58%, transparent 74%);
  mix-blend-mode: screen;
  opacity: calc(var(--intone, 0) * .9);
  transition: opacity .18s linear;
}
.seal-stage.intoned::after { opacity: .95; }
.seal-stage.charging { animation: sealCharge 1.6s ease-in-out infinite; }
@keyframes sealCharge { 0%, 100% { opacity: .97; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .seal-stage.charging { animation: none; } }

/* Paso MODERNO: ENTONAR el enn. SIN anillo/UI: el área de toque es INVISIBLE y cubre el
   propio sigilo; la única respuesta visible es el SIGILO encendiéndose (ver --intone en
   .seal-stage) + el enn debajo. Así se siente cantar con la mano sobre el altar, no pulsar
   un botón. */
.intone-stage {
  position: absolute; z-index: 10; cursor: pointer;
  touch-action: none; -webkit-tap-highlight-color: transparent;
}
.intone-enn {
  position: absolute; left: 50%; top: calc(100% + 10px); transform: translateX(-50%);
  font-family: "Cinzel", serif; color: var(--oro-bright); font-size: clamp(.82rem, 1.9vw, 1.05rem);
  letter-spacing: .05em; text-align: center; white-space: nowrap; line-height: 1.2;
  text-shadow: 0 1px 10px rgba(0,0,0,.95), 0 0 14px rgba(0,0,0,.85);
  animation: ennBreath 2.4s ease-in-out infinite;
}
.intone-stage.holding .intone-enn { animation-duration: 1s; color: var(--cue); }
/* sigilo en la mitad baja → el enn se muestra ENCIMA para no cortarse por el borde inferior */
.intone-stage.enn-arriba .intone-enn { top: auto; bottom: calc(100% + 10px); }
@keyframes ennBreath { 0%,100% { opacity: .74; } 50% { opacity: 1; } }
.intone-hint {
  position: absolute; left: 50%; top: calc(100% + 36px); transform: translateX(-50%);
  font-size: .66rem; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-soft); white-space: nowrap;
  transition: opacity .4s ease;
}
.intone-stage.holding .intone-hint { opacity: 0; }
@media (prefers-reduced-motion: reduce) { .intone-enn { animation: none; } }
.trace-svg .ritual-ring {
  fill: none;
  stroke: color-mix(in srgb, var(--oro-bright) 48%, var(--tiza));
  stroke-width: 1.8; opacity: .5;
  stroke-linecap: round;
  filter: url(#chalk);
}
.trace-svg .ring-outer { stroke-width: 2.6; opacity: .72; }
.trace-svg .ring-inner { opacity: .42; }
.trace-svg .ritual-namepath { fill: none; stroke: none; }
.trace-svg .ritual-names {
  fill: color-mix(in srgb, var(--oro-bright) 72%, #f2ead6);
  font-family: "Cinzel", serif; font-size: 13px; letter-spacing: 1.5px; opacity: .72;
  filter: url(#chalkSoft);
}
.trace-svg .ritual-names.small { font-size: 10px; letter-spacing: 1px; opacity: .6; }
.trace-svg .ritual-hex {
  fill: none; stroke: color-mix(in srgb, var(--oro) 60%, var(--tiza));
  stroke-width: 1.5; opacity: .58; stroke-linejoin: round; stroke-linecap: round;
  filter: url(#chalk);
}
.trace-svg .ritual-hex.center { stroke-width: 1.8; opacity: .74; }
/* Triángulo del Arte (fuera del círculo, hacia el espectador): aquí va el sello. */
.trace-svg .ritual-triangle { fill: none; stroke: color-mix(in srgb, var(--oro-bright) 48%, var(--tiza)); stroke-width: 2.2; opacity: .62; stroke-linejoin: round; stroke-linecap: round; filter: url(#chalk); }
.trace-svg .ritual-tricircle { fill: none; stroke: color-mix(in srgb, var(--oro) 55%, var(--tiza)); stroke-width: 1.3; opacity: .46; filter: url(#chalkSoft); }
.trace-svg .ritual-trinames { fill: color-mix(in srgb, var(--oro-bright) 70%, #fff); font-family: "Cinzel", serif; font-size: 8px; letter-spacing: .4px; opacity: .58; text-anchor: middle; }
.trace-svg .ritual-triseal { display: none; }   /* el sello se dibuja en el paso «sello» (canvas .sealdraw) */
/* Paso «dibujar el sello»: lienzo donde el practicante graba el sello con el dedo. */
.sealdraw { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.sealdraw canvas { width: min(48vw, 260px); aspect-ratio: 1; touch-action: none; cursor: crosshair; filter: drop-shadow(0 0 8px rgba(226,191,108,.28)); transition: filter .45s ease; }
.sealdraw.sealed canvas { filter: drop-shadow(0 0 24px rgba(226,191,108,.85)); }
@media (max-height: 520px) { .sealdraw canvas { width: min(30vh, 200px); } }
/* Trazo del practicante: TIZA fresca (hueso). Línea limpia y BARATA (sin filtros de
   turbulencia por frame → sin jank en móvil). La textura de tiza ya la da el arte del
   círculo debajo; este trazo es el «reforzado» que se enciende al recorrerlo. */
.trace-svg .ritual-progress {
  fill: none;
  stroke: #f4ecd6;
  stroke-width: 6;
  stroke-linecap: round;
  filter: drop-shadow(0 0 5px rgba(233,206,140,.6));
}
.trace-svg .ritual-hit-area {
  fill: transparent;
  stroke: none;
  pointer-events: all;   /* toda la elipse rellena es táctil/clicable (mouse y touch) */
  cursor: crosshair;
}
.trace-svg .ritual-hit-area.passive { pointer-events: none; }
/* Indicador de INICIO y DIRECCIÓN del trazo (guía al practicante). */
.trace-svg .ritual-startcue { transition: opacity .3s ease; pointer-events: none; }
.trace-svg .cue-dot { fill: var(--cue); opacity: .32; filter: drop-shadow(0 0 8px rgba(233,206,140,.9)); animation: cuePulse 1.5s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
.trace-svg .cue-chalk { filter: drop-shadow(0 2px 5px rgba(0,0,0,.85)) drop-shadow(0 0 8px rgba(233,206,140,.45)); animation: cuePulse 1.5s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
.trace-svg .cue-ring { fill: none; stroke: var(--cue); stroke-width: 2; opacity: .7; transform-box: fill-box; transform-origin: center; animation: cueRing 1.8s ease-out infinite; }
.trace-svg .cue-arrow { fill: none; stroke: var(--cue); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; filter: drop-shadow(0 0 4px rgba(233,206,140,.55)); opacity: .58; }
/* Guía discreta (auditoría DeepSeek): la etiqueta no debe dominar el círculo → más pequeña y tenue. */
.trace-svg .cue-label { fill: var(--cue-label); font-family: "Cinzel", serif; font-size: 9.5px; letter-spacing: 1.2px; text-anchor: middle; text-transform: uppercase; opacity: .7; filter: drop-shadow(0 1px 3px rgba(0,0,0,.9)); }
.trace-svg .cue-chalk { opacity: .78; }
@keyframes cuePulse { 0%,100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.35); opacity: .75; } }
@keyframes cueRing { 0% { transform: scale(1); opacity: .7; } 100% { transform: scale(2.6); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .trace-svg .cue-dot, .trace-svg .cue-ring, .trace-svg .cue-chalk { animation: none; } }
.trace-svg .ringtip {
  fill: #fbf4e2;
  filter: drop-shadow(0 0 5px rgba(244,236,214,.9)) drop-shadow(0 0 9px rgba(233,206,140,.5));
  pointer-events: none;
}

/* Velas del círculo */
.candles { position: absolute; inset: 0; z-index: 5; pointer-events: none; }
/* BRASA de la escena (M4 iter.2): con las velas encendidas, un lavado cálido sube del altar y
   baña el círculo, el sello y la aparición con la luz del fuego — todo respira con --flame (reloj
   Ambient), pero SOLO por opacidad (compositor, barato, sin jank; NO se anima ningún filter).
   Invisible sin velas (--flame=0). La transición suaviza el parpadeo compartido. */
.candles::before {
  content: ""; position: absolute; left: 50%; bottom: 0; width: 130%; height: 78%;
  transform: translateX(-50%); pointer-events: none;
  background: radial-gradient(60% 70% at 50% 100%, rgba(255,190,110,.5) 0%, rgba(255,150,70,.2) 34%, transparent 72%);
  mix-blend-mode: screen; opacity: calc(.2 * var(--flame, 0)); transition: opacity .5s ease;
}
@media (prefers-reduced-motion: reduce) { .candles::before { transition: none; } }

/* ═══ ESPEJO NEGRO de scrying (rito MODERNO de Azazel) ═══════════════════════════
   Objeto FÍSICO apoyado en la mesa del primer plano, inclinado hacia el espectador
   (mira hacia abajo dentro de él). Posición/tamaño por JS (placeMirror). El realismo
   nace de: sombra de contacto (peso) + reflejo cálido coherente con la vela (abajo-
   dcha) + rim obsidiana con especular sólo en el filo iluminado + viñeta interna de
   profundidad. El interior (glifo/humo/manifestación) se pinta en <canvas>, ya
   escorzado por el rotateX del padre → nunca es un PNG plano encima. */
.mirror-stage { position: absolute; z-index: 6; pointer-events: none; }
.mirror-stage[hidden] { display: none; }
/* Sombra de contacto: DOS capas sobre el plano de la mesa → ancla el peso del objeto.
   (a) sombra proyectada ancha y difusa; (b) oclusión ambiental estrecha y oscura justo
   bajo el borde cercano (donde el cristal toca la superficie). */
.mirror-contact {
  position: absolute; left: 50%; bottom: -6%; width: 120%; height: 42%;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(ellipse at 50% 44%, rgba(0,0,0,.82), rgba(0,0,0,.46) 44%, transparent 72%);
  filter: blur(9px);
}
.mirror-contact::after {
  content: ""; position: absolute; left: 50%; bottom: 30%; transform: translateX(-50%);
  width: 82%; height: 34%; border-radius: 50%;
  background: radial-gradient(ellipse at 50% 60%, rgba(0,0,0,.9), rgba(0,0,0,.5) 40%, transparent 66%);
  filter: blur(4px);
}
/* Soporte discreto: pie/base oscuro que explica físicamente el ángulo (el espejo NO flota). */
.mirror-stand {
  position: absolute; left: 50%; bottom: -2%; transform: translateX(-50%);
  width: 30%; height: 12%; border-radius: 40% 40% 46% 46% / 60% 60% 100% 100%;
  background: linear-gradient(180deg, #14181d, #05070a);
  box-shadow: inset 0 1px 0 rgba(170,190,206,.10), 0 3px 8px rgba(0,0,0,.6);
}
.mirror-body {
  position: absolute; inset: 0;
  transform: perspective(1100px) rotateX(27deg);   /* semi-vertical, recostado hacia el practicante */
  transform-origin: 50% 100%;                        /* pivota desde el pie apoyado en la mesa */
  transform-style: preserve-3d;
}
/* Marco/bisel del espejo: fino y pulido (NO borde grueso de recipiente). */
.mirror-rim {
  position: absolute; inset: -3%;
  border-radius: 50%;
  background: linear-gradient(158deg, #1a1f25, #090b0e 56%, #10141a);
  box-shadow:
    inset 0 1px 2px rgba(184,204,220,.14),          /* filo superior pulido */
    inset 0 -3px 8px rgba(0,0,0,.6),
    0 2px 7px rgba(0,0,0,.5);
}
/* Cristal negro PULIDO: superficie plana (no cuenco). Vignette lateral suave para dar
   volumen sin convertirlo en un cuenco profundo. El interior (humo/forma) vive DETRÁS,
   pintado en el canvas y velado por .mirror-veil → se percibe bajo el vidrio, no encima. */
.mirror-glass {
  position: absolute; inset: 0; border-radius: 50%; overflow: hidden;
  background: radial-gradient(ellipse at 50% 42%, #080b0e 0%, #05070a 62%, #020304 100%);
  box-shadow: inset 0 0 14px 1px rgba(0,0,0,.72);
}
/* Auditoría DeepSeek: el cristal negro parecía un «vacío plano». Se le añade REFLEJO de la
   estancia iluminada por velas (brillo especular frío diagonal + destellos cálidos de las velas
   laterales) → superficie PULIDA reflectante, no un pozo negro. Va SOBRE el interior (z alto),
   sutil para no borrar el humo/forma que emerge detrás. */
.mirror-glass::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%; pointer-events: none; z-index: 4;
  background:
    linear-gradient(150deg, rgba(188,206,224,.16) 0%, rgba(188,206,224,.05) 16%, transparent 30%),
    radial-gradient(9% 15% at 79% 33%, rgba(244,214,142,.24), transparent 68%),
    radial-gradient(6% 11% at 85% 50%, rgba(244,214,142,.17), transparent 70%),
    radial-gradient(8% 14% at 21% 39%, rgba(226,204,152,.13), transparent 72%),
    radial-gradient(70% 60% at 50% 8%, rgba(200,216,230,.08), transparent 60%);
  mix-blend-mode: screen;
}
.mirror-fx { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* Velo de vidrio SOBRE el interior: sella la sensación de «detrás del cristal» (el humo y la
   forma quedan bajo esta capa). Muy sutil para no aclarar el interior. */
.mirror-veil {
  position: absolute; inset: 0; border-radius: 50%; pointer-events: none;
  background: linear-gradient(180deg, rgba(20,28,36,.16), transparent 30%, transparent 76%, rgba(0,0,0,.28));
}
/* Reflejos CONTROLADOS del entorno en el cristal pulido (superficie, encima del velo):
   (a) barrido especular diagonal frío; (b) lumbre cálida de la vela abajo-dcha. Tenues. */
.mirror-reflection {
  position: absolute; inset: 0; border-radius: 50%; pointer-events: none; mix-blend-mode: screen;
  background:
    linear-gradient(148deg, rgba(200,216,228,.12) 0%, transparent 26%),
    radial-gradient(ellipse 26% 30% at 72% 30%, rgba(206,222,234,.10), transparent 60%),
    radial-gradient(ellipse 22% 16% at 68% 82%, rgba(226,191,108,.16), transparent 62%);
  /* LUMINOSIDAD que RESPIRA (no escala): sube al inhalar, baja al exhalar. Rango ±0.06, casi
     subconsciente; visible incluso en reposo (el espejo vive sin que se «lea» la animación). */
  opacity: calc(.78 + var(--breath, .5) * .12);
}
.mirror-gloss {
  position: absolute; inset: 0; border-radius: 50%; pointer-events: none; mix-blend-mode: screen;
  background: linear-gradient(158deg, rgba(210,224,236,.10), transparent 22%);
  opacity: .5;
}
/* al manifestarse la superficie cede a la profundidad, PERO sigue respirando (sutil) → no se «muere» */
.mirror-stage.awake .mirror-reflection { opacity: calc(.44 + var(--breath, .5) * .08); transition: opacity 1.8s ease; }
@media (prefers-reduced-motion: reduce) { .mirror-body { transition: none; } }

/* Aura de RESPIRACIÓN: halo frío que EMANA del espejo y late con --breath (guía diegética,
   no un anillo flotante suelto). Sólo presente en trance (--trance) → inerte en reposo. */
.mirror-breath {
  position: absolute; left: 50%; top: 40%;
  width: 168%; height: 168%; border-radius: 50%; pointer-events: none; mix-blend-mode: screen;
  /* NO escala de bombeo (eso se «lee» como GIF). Micro-onda del radio (±1.5%) + opacidad; el halo
     periférico late suave con la respiración durante el trance (guía diegética), sin latido de disco. */
  transform: translate(-50%, -50%) scale(calc(.985 + var(--breath) * .03));
  background: radial-gradient(circle, transparent 38%, color-mix(in srgb, var(--frio) 34%, transparent) 50%, transparent 64%);
  opacity: calc(var(--trance) * (.12 + var(--breath) * .20));
}
/* Velo de CIERRE: cubre cristal + marco al mantener pulsado en el cierre (--cover 0→1). */
.mirror-cover {
  position: absolute; inset: -3%; border-radius: 50%; pointer-events: none;
  background: radial-gradient(ellipse at 50% 40%, #05070a, #010203 72%);
  opacity: var(--cover, 0);
}
/* VISIÓN DE TÚNEL: la periferia se oscurece con --trance, concentrando la mirada en el
   espejo (centrado en --mx/--my). Inerte fuera del trance. */
.tunnel {
  position: absolute; inset: 0; z-index: 8; pointer-events: none;
  background: radial-gradient(ellipse 62% 56% at var(--mx) var(--my), transparent 0%, transparent 24%, rgba(0,0,0,.66) 60%, rgba(0,0,0,.92) 100%);
  opacity: var(--trance);
  transition: opacity .18s linear;
}

/* ── HUD moderno/minimal del rito de Azazel (trance) ─────────────────────────────
   Sans-serif, sobrio, discreto; no tapa el espejo. Funciona en portrait y landscape. */
.trance-hud { display: flex; flex-direction: column; align-items: center; gap: 8px; font-family: var(--font-modern); width: 100%; }
.trance-phase {
  font-size: .72rem; letter-spacing: .34em; text-transform: uppercase; font-weight: 300;
  color: var(--frio-bright); min-height: 1.1em; text-shadow: 0 0 16px color-mix(in srgb, var(--frio) 40%, transparent);
  transition: opacity .18s;
}
.trance-cue { font-size: .7rem; letter-spacing: .02em; color: var(--ink-soft); font-weight: 400; text-align: center; max-width: 34ch; }
.trance-bar { width: min(240px, 58vw); height: 2px; border-radius: 2px; overflow: hidden; background: color-mix(in srgb, var(--frio) 18%, transparent); }
.trance-bar i { display: block; height: 100%; width: 0; background: linear-gradient(90deg, color-mix(in srgb, var(--frio) 55%, transparent), var(--frio-bright)); box-shadow: 0 0 10px color-mix(in srgb, var(--frio) 45%, transparent); }
/* Tipografía MODERNA también en la instrucción del rito de Azazel (coherencia del HUD). */
#s-ritual.is-modern #ritualStepTitulo { font-family: var(--font-modern); font-weight: 400; letter-spacing: .04em; text-transform: none; }
#s-ritual.is-modern #ritualStepTexto { font-family: var(--font-modern); font-weight: 300; }
/* Vela HIPERREALISTA: cuerpo de cera (imagen con goteos, misma estética del fondo) +
   TINTE planetario del rango (rango→planeta) + llama y resplandor del tinte. */
.candle {
  position: absolute; width: var(--candle-w); height: var(--candle-h);
  /* La BASE de la vela se ancla en el punto de contacto (x,y = suelo); escala por
     profundidad (var --s desde JS). Origen en la base → crece «apoyada», no flotando. */
  transform: translate(-50%, -100%) scale(var(--s, 1)); transform-origin: 50% 100%;
  background: url(/r/assets/vela-cuerpo.webp?v=1) center/contain no-repeat;
  border: 0; padding: 0; pointer-events: auto;
  filter: brightness(.6) saturate(.85) contrast(1.02);   /* apagada: cera en penumbra */
  transition: filter .5s ease;
  -webkit-touch-callout: none; -webkit-user-select: none; user-select: none;
}
.candle.lit { filter: brightness(1.02) saturate(1) contrast(1.02); }
/* SOMBRA DE CONTACTO: charco elíptico oscuro bajo la base (multiply oscurece el suelo)
   → la vela DESCANSA sobre la superficie, no levita. Detrás del cuerpo de cera. */
.candle::after {
  content: ""; position: absolute; left: 50%; bottom: -4px; z-index: -1;
  width: 172%; height: 30px; transform: translateX(-50%);
  background: radial-gradient(50% 50% at 50% 50%, rgba(0,0,0,.72), rgba(0,0,0,.4) 42%, transparent 74%);
  mix-blend-mode: multiply; filter: blur(5px); pointer-events: none;
  opacity: .64; transition: opacity .5s ease;
}
.candle.lit::after { opacity: .84; }
/* GRAVEDAD en suelo OSCURO: una sombra multiply casi no se ve sobre piedra negra → la vela
   ENCENDIDA derrama un charco de LUZ CÁLIDA (tinte planetario del rango) sobre el suelo en su base.
   Eso hace visible el punto de contacto y añade realismo (la vela ilumina lo que la rodea). */
.candle::before {
  content: ""; position: absolute; left: 50%; bottom: -8px; z-index: -1;
  width: 210%; height: 42px; transform: translateX(-50%);
  background: radial-gradient(50% 50% at 50% 50%, color-mix(in srgb, var(--velaColor, #e2bf6c) 42%, #ffcf85) 0%, transparent 70%);
  mix-blend-mode: screen; filter: blur(8px); opacity: 0; transition: opacity .6s ease; pointer-events: none;
}
/* El charco de luz cálida late con la llama compartida (--flame, reloj Ambient). La transición
   de arriba (.6s) suaviza el parpadeo → luz viva, no estrobo. Si no hay reloj, cae a ~.55. */
.candle.lit::before { opacity: calc(.28 + .32 * var(--flame, .84)); }
/* Tinte PLANETARIO del rango sobre la cera, con la FORMA de la vela (máscara). No es el color del demonio. */
.candle .ctint {
  position: absolute; inset: 0; pointer-events: none;
  -webkit-mask: url(/r/assets/vela-cuerpo.webp?v=1) center/contain no-repeat;
  mask: url(/r/assets/vela-cuerpo.webp?v=1) center/contain no-repeat;
  background: var(--velaColor, #e2bf6c);
  mix-blend-mode: color; opacity: .5;
}
.candle.lit .ctint { opacity: .68; }
/* Llama realista sobre el pabilo (parte alta de la vela). */
.candle .flame {
  position: absolute; top: 1px; left: 50%; width: 13px; height: 25px;
  transform: translateX(-50%); transform-origin: 50% 100%;
  border-radius: 50% 50% 50% 50% / 62% 62% 38% 38%;
  background: radial-gradient(circle at 50% 80%, #fffbe8 0 12%, #ffe6a0 32%, #ffb44e 58%, rgba(255,120,20,.4) 80%, transparent);
  opacity: 0; transition: opacity .4s;
  animation: flameFlick 9s ease-in-out infinite; animation-delay: var(--d, 0s);
  filter: drop-shadow(0 0 14px rgba(255,170,60,.95));
}
.candle .flame::after {
  content: ""; position: absolute; left: 50%; bottom: 3px; width: 5px; height: 11px;
  transform: translateX(-50%); border-radius: 50% 50% 45% 45% / 60% 60% 40% 40%;
  background: radial-gradient(circle at 50% 70%, rgba(190,215,255,.9), rgba(120,150,220,.25) 60%, transparent);
  animation: flameFlick 7.3s ease-in-out infinite; animation-delay: calc(var(--d, 0s) + .8s);
}
.candle.lit .flame { opacity: 1; }
/* Resplandor cálido teñido por el tinte planetario del rango. */
.candle .halo {
  position: absolute; top: -18px; left: 50%; transform: translateX(-50%);
  width: 78px; height: 78px; border-radius: 50%; opacity: 0; transition: opacity .5s;
  background: radial-gradient(circle, color-mix(in srgb, var(--velaColor, #e2bf6c) 50%, #ffcf85) 0%, transparent 66%);
  mix-blend-mode: screen;
}
/* El halo late con la MISMA llama compartida (--flame, reloj Ambient), no con un loop CSS fijo
   de 5.8s: todas las velas iluminan a la vez (corriente de aire común), vivas pero no robóticas.
   La transición .5s de arriba suaviza el parpadeo (sin estrobo). Fallback ~.8 si no hay reloj. */
.candle.lit .halo { opacity: calc(.5 + .38 * var(--flame, .84)); }
/* Llama orgánica: ciclo largo, desviaciones minúsculas, sin saltos bruscos.
   Solo transform/opacity (GPU) → barato en móvil. */
@keyframes flameFlick {
  0%   { transform: translateX(-50%) translateY(0) scale(1,1) rotate(-1.2deg); }
  6%   { transform: translateX(-52%) translateY(-.4px) scale(1.03,.97) rotate(-.6deg); }
  12%  { transform: translateX(-49%) translateY(-.8px) scale(.98,1.05) rotate(.8deg); }
  20%  { transform: translateX(-53%) translateY(-.3px) scale(1.05,.96) rotate(-1.4deg); }
  28%  { transform: translateX(-50%) translateY(-1px) scale(.99,1.03) rotate(.4deg); }
  36%  { transform: translateX(-51%) translateY(-.2px) scale(1.02,.98) rotate(1.1deg); }
  45%  { transform: translateX(-49%) translateY(-.9px) scale(.97,1.06) rotate(-.9deg); }
  54%  { transform: translateX(-52%) translateY(0) scale(1.04,.97) rotate(.7deg); }
  63%  { transform: translateX(-50%) translateY(-.5px) scale(.98,1.02) rotate(-1.1deg); }
  72%  { transform: translateX(-51%) translateY(-.7px) scale(1.03,.96) rotate(1.3deg); }
  82%  { transform: translateX(-49%) translateY(-.2px) scale(.99,1.04) rotate(-.5deg); }
  91%  { transform: translateX(-52%) translateY(-.6px) scale(1.02,.98) rotate(.9deg); }
  100% { transform: translateX(-50%) translateY(0) scale(1,1) rotate(-1.2deg); }
}
@keyframes haloPulse { 0%,100% { transform: translateX(-50%) scale(1); opacity: .75; } 50% { transform: translateX(-50%) scale(1.18); opacity: 1; } }

/* Aparición fantasmal del demonio (mix-blend screen sobre la escena) */
.aparicion {
  position: absolute; left: 50%; top: 52%; z-index: 7;
  width: min(68vw, 420px);
  width: min(68dvw, 420px); aspect-ratio: 1;
  transform: translate(-50%, -50%) scale(.82);
  background: center/contain no-repeat;
  mix-blend-mode: screen;
  opacity: 0; pointer-events: none;
  filter: blur(1.5px);
  transition: opacity 1.8s ease, transform 3s ease;
}
.aparicion.show { opacity: .92; transform: translate(-50%, -50%) scale(1.04); animation: aparicionFloat 7s ease-in-out infinite; }
@keyframes aparicionFloat {
  0%,100% { transform: translate(-50%, -50%) scale(1.04) translateY(0); opacity: .92; }
  50%     { transform: translate(-50%, -50%) scale(1.06) translateY(-6px); opacity: 1; }
}

/* Aparición DENTRO del triángulo: el espíritu se condensa del humo y emerge, con
   empuje de cámara. Posición/tamaño los fija showApparition() en px de escena. */
.aparicion.in-triangle {
  position: absolute; z-index: 10;   /* sobre el sello (9) y la viñeta (9): no se ocluye */
  transform: translate(-50%, -30%) scale(.5);   /* nace bajo/dentro del sigilo... */
  transform-origin: 50% 82%;
  background: center bottom / contain no-repeat;
  mix-blend-mode: screen;          /* el negro del arte desaparece → espíritu de oro/luz */
  opacity: 0; pointer-events: none;
  /* Emerge SOLO con opacity+transform (compositor, barato). Sin animar blur (re-rasteriza
     por frame → jank en móvil). El resplandor es una sombra ESTÁTICA. */
  filter: drop-shadow(0 0 14px rgba(233,206,140,.28));
  transition: opacity 1.9s ease, transform 2.8s cubic-bezier(.2,.66,.2,1);
  will-change: transform, opacity;
  /* Disuelve TODOS los bordes del arte para que NUNCA se perciba el rectángulo del webp:
     intersección de (1) viñeta elíptica que apaga las 4 esquinas/lados, (2) fundido
     lateral izq+der para que ninguna forma luminosa toque el borde, (3) fundido de la
     BASE en humo/sombra. Todo estático (sin animar mask → barato en móvil). */
  -webkit-mask-image:
    radial-gradient(66% 72% at 50% 42%, #000 46%, transparent 88%),
    linear-gradient(to right, transparent 0%, #000 15%, #000 85%, transparent 100%),
    linear-gradient(to top, transparent 0%, rgba(0,0,0,.4) 13%, #000 33%);
  mask-image:
    radial-gradient(66% 72% at 50% 42%, #000 46%, transparent 88%),
    linear-gradient(to right, transparent 0%, #000 15%, #000 85%, transparent 100%),
    linear-gradient(to top, transparent 0%, rgba(0,0,0,.4) 13%, #000 33%);
  -webkit-mask-composite: source-in, source-in; mask-composite: intersect;
}
.aparicion.in-triangle.show {
  opacity: .96;
  transform: translate(-50%, -55%) scale(1);   /* ...y SUBE/emerge del sigilo */
  animation: apparBreath 6s ease-in-out 2.8s infinite;
}
/* §B — Figura TENUE de Bune: gana a .aparicion(.in-triangle).show por especificidad (4 clases). */
.aparicion.in-triangle.gentle.show, .aparicion.gentle.show { opacity: .52; }
@keyframes apparBreath {
  0%, 100% { transform: translate(-50%, -55%) scale(1); }
  50%      { transform: translate(-50%, -56.6%) scale(1.014); }
}
/* Humo que asciende del círculo del triángulo (gradientes baratos, sin partículas). */
.ritual-smoke {
  position: absolute; z-index: 7; pointer-events: none;
  transform: translate(-50%, -50%);
  width: var(--w, 160px); height: calc(var(--w, 160px) * 1.5);
  background:
    radial-gradient(46% 34% at 50% 72%, rgba(214,196,158,.55), transparent 72%),
    radial-gradient(34% 26% at 40% 56%, rgba(190,170,130,.4), transparent 72%),
    radial-gradient(34% 26% at 62% 60%, rgba(190,170,130,.36), transparent 72%);
  filter: blur(9px);
  mix-blend-mode: screen;
  opacity: 0;
  animation: smokeRise 4.2s ease-out forwards;
}
@keyframes smokeRise {
  0%   { opacity: 0;  transform: translate(-50%, -34%) scale(.5); }
  28%  { opacity: .95; }
  100% { opacity: .5; transform: translate(-50%, -64%) scale(1.15); }
}
/* Humo DENSO de la aparición: obscurece (blend normal) para CUBRIR el sigilo y dar
   volumen — el demonio emerge de él. z entre el sigilo (9) y el demonio (10). */
.ritual-smoke.dense {
  z-index: 9; mix-blend-mode: normal;
  height: calc(var(--w, 160px) * 2.05);   /* más alto: asciende y envuelve la base del demonio */
  background:
    radial-gradient(54% 30% at 50% 86%, rgba(24,20,16,.82), rgba(36,31,24,.5) 52%, transparent 76%),
    radial-gradient(42% 26% at 40% 66%, rgba(56,50,40,.55), transparent 72%),
    radial-gradient(42% 26% at 60% 62%, rgba(56,50,40,.5), transparent 72%),
    radial-gradient(34% 22% at 52% 44%, rgba(70,63,50,.4), transparent 74%);
  filter: blur(14px);
  animation: smokeRiseDense 4.8s ease-out forwards;
}
@keyframes smokeRiseDense {
  0%   { opacity: 0;   transform: translate(-50%, -18%) scale(.5); }
  32%  { opacity: .96; }
  100% { opacity: .82; transform: translate(-50%, -52%) scale(1.32); }
}
/* Aura/neblina LATERAL de la aparición: luz tenue (screen) MÁS ANCHA que el demonio y
   centrada en su cuerpo, para que sus flancos se fundan en niebla luminosa (nunca un
   borde de PNG). Va DETRÁS del demonio (z8 < demonio z10) → parece emanar del espacio.
   Blur ESTÁTICO (no animado): sólo sube con transform. */
.ritual-smoke.aura {
  z-index: 8; mix-blend-mode: screen;
  height: calc(var(--w, 160px) * 1.05);
  background:
    radial-gradient(46% 42% at 50% 52%, rgba(214,196,158,.30), transparent 70%),
    radial-gradient(28% 48% at 13% 52%, rgba(206,188,148,.26), transparent 72%),
    radial-gradient(28% 48% at 87% 52%, rgba(206,188,148,.26), transparent 72%);
  filter: blur(16px);
  animation: smokeRiseDense 4.8s ease-out forwards;
}
/* Incienso del rito MODERNO: hilo de humo que asciende del altar, teñido por el color
   del demonio (parte del rito devocional: vela de color + incienso). Barato (transform). */
.incense-smoke {
  position: absolute; z-index: 6; pointer-events: none;
  transform: translate(-50%, -100%);
  width: min(9vw, 66px); height: min(28vh, 200px);
  background:
    radial-gradient(38% 16% at 50% 92%, color-mix(in srgb, var(--velaColor, #e2bf6c) 24%, #cdbb90), transparent 72%),
    radial-gradient(30% 13% at 44% 62%, rgba(203,187,150,.22), transparent 72%),
    radial-gradient(30% 13% at 58% 42%, rgba(203,187,150,.18), transparent 72%);
  filter: blur(7px); mix-blend-mode: screen; opacity: 0;
  animation: incenseRise 7s ease-in-out infinite;
}
@keyframes incenseRise {
  0%   { opacity: 0;   transform: translate(-50%, -68%) scale(.68); }
  35%  { opacity: .5; }
  100% { opacity: 0;   transform: translate(-53%, -128%) scale(1.18); }
}
/* §V — humo del Verum: más alto y presente (es el foco del rito, sube sobre el carácter). */
.incense-smoke.verum { width: min(13vw, 96px); height: min(38vh, 260px); z-index: 7; opacity: .95; }
/* §V — figura de aparición del espíritu Verum (grabado sepia): emerge del humo sobre el carácter,
   se eleva y se funde con la escena por los flancos (aura de humo), sin borde duro del PNG. */
.verum-apar {
  position: absolute; z-index: 8; pointer-events: none;
  width: min(46vmin, 380px); height: min(54vmin, 440px);   /* fallback (si aún no hay triBox): vmin = eje corto → en vertical no se sale por arriba, como .aparicion goética. En el flujo real layoutVerumApparition fija width/height inline a partir de tb.seal. */
  transform: translate(-50%, -84%) translateY(14px) scale(.98);
  background-repeat: no-repeat; background-position: center bottom; background-size: contain;
  opacity: 0; mix-blend-mode: screen;   /* figura ORO sobre NEGRO → el negro desaparece, como .aparicion goética */
  filter: brightness(1.06) drop-shadow(0 0 22px rgba(232,200,116,.4));
  /* la niebla dorada de la imagen llena el marco → bajo screen se veía un rectángulo tenue; esta
     máscara radial disuelve el borde del cuadro dejando solo la figura+humo emergiendo. */
  -webkit-mask-image: radial-gradient(66% 76% at 50% 44%, #000 52%, transparent 100%);
          mask-image: radial-gradient(66% 76% at 50% 44%, #000 52%, transparent 100%);
  transition: opacity 1.6s ease, transform 1.9s cubic-bezier(.22,.61,.36,1);
}
.verum-apar.show { opacity: 1; transform: translate(-50%, -84%) translateY(0) scale(1); }
@media (prefers-reduced-motion: reduce) { .verum-apar { transition: opacity .4s ease; transform: translate(-50%, -84%); } }
/* ═══ §V realismo (auditoría deepseek 2026-09-08): peso, sombras de contacto, humo, menos «UI» ═══ */
/* Carácter Verum: sombra de contacto en el suelo → lo ANCLA (ya va con scaleY de suelo, pero flotaba). */
#s-ritual.is-verum .seal-stage::before {
  content: ""; position: absolute; left: 50%; bottom: 3%; width: 84%; height: 26%;
  transform: translateX(-50%); z-index: -1; pointer-events: none; filter: blur(4px);
  background: radial-gradient(ellipse at 50% 100%, rgba(0,0,0,.62), rgba(0,0,0,.3) 46%, transparent 74%);
}
/* Humo del incienso Verum: MÁS denso y visible (el auditor lo vio imperceptible). */
.incense-smoke.verum { animation: incenseRiseVerum 6.4s ease-in-out infinite; }
@keyframes incenseRiseVerum {
  0%   { opacity: 0;   transform: translate(-50%, -62%) scale(.72); }
  30%  { opacity: .8; }
  100% { opacity: 0;   transform: translate(-52%, -134%) scale(1.3); }
}
/* (La figura Verum ahora es ORO-sobre-NEGRO con mix-blend-mode:screen como la goética: EMERGE del
   humo, no es una cartulina; una sombra de contacto oscura sería invisible bajo screen y sobra.) */
/* Velas: sombra de contacto un poco más presente (algunas se veían ingrávidas). */
.candle::after { background: radial-gradient(50% 50% at 50% 50%, rgba(0,0,0,.8), rgba(0,0,0,.46) 42%, transparent 76%); }
/* Sello del RESULTADO: glow más contenido (como brasa/tinta), menos «halo de UI moderna». */
.result-sello { filter: drop-shadow(0 0 12px rgba(201,162,83,.32)); }
@media (prefers-reduced-motion: reduce) { .incense-smoke { animation: none; opacity: .28; } }
/* CÁMARA/POV reutilizable: un único transform sobre .scene (setCamera en JS fija scale +
   transform-origin en el altar). Transición LENTA y continua entre pasos → movimiento
   físico, no zoom de UI. `will-change` SOLO cuando la cámara está activa (no reserva capa
   el resto del tiempo). El HUD (fuera de .scene) no se escala. */
.scene { transform-origin: 0 0; transition: transform 1.7s cubic-bezier(.33, 0, .2, 1); }
.scene.cam-on { will-change: transform; }
@media (prefers-reduced-motion: reduce) {
  .scene { transition: none; }
  .scene.cam-on { transform: none !important; }
  .ritual-smoke, .aparicion.in-triangle.show { animation: none; }
}
.vineta { position: absolute; inset: 0; pointer-events: none; z-index: 9;
  background: radial-gradient(120% 90% at 50% 42%, transparent 55%, rgba(0,0,0,.62) 100%); }

/* HUD del ritual */
.ritual-top {
  position: absolute; top: 0; left: 0; right: 0; z-index: 12;
  display: flex; align-items: center; gap: 12px;
  padding: calc(12px + env(safe-area-inset-top, 0px)) 14px 8px;
  background: linear-gradient(180deg, rgba(0,0,0,.42), transparent);
}
/* Auditoría (usuario + DeepSeek): los controles del rito leían como «UI de navegador plana» y
   rompían la inmersión. Se hacen DIEGÉTICOS: sin caja, oro grabado tenue que se realza al
   enfocar/hover (foco accesible intacto por la regla global :focus-visible). */
.ritual-top .ghostbtn {
  background: transparent; border: 0; padding: 8px 6px;
  color: color-mix(in srgb, var(--oro) 58%, transparent);
  text-shadow: 0 1px 7px rgba(0,0,0,.9); opacity: .74;
  transition: opacity var(--dur-fast), color var(--dur-fast);
}
.ritual-top .ghostbtn:hover, .ritual-top .ghostbtn:focus-visible { color: var(--oro-bright); opacity: 1; border: 0; }
.ritual-modern-tag { opacity: .82; }
.stepper { display: flex; gap: 5px; flex: 1; justify-content: center; }
.stepper .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--linea); transition: background .3s, box-shadow .3s; }
.stepper .dot.done { background: var(--oro); }
.stepper .dot.now { background: var(--oro-bright); box-shadow: 0 0 10px rgba(226,191,108,.9); }
.ritual-demon { font-family: "Cinzel", serif; font-size: .62rem; letter-spacing: .18em; text-transform: uppercase; color: var(--oro); }

.ritual-instr {
  position: absolute; top: 72px; left: 0; right: 0; z-index: 12;
  text-align: center; padding: 0 20px; pointer-events: none;
}
/* El banner ORIENTA y DESAPARECE DEL TODO (no queda semitransparente: eso molestaba y no informaba).
   La duración antes de irse la fija el JS según cuánto texto tenga (tiempo de lectura pausada). */
.ritual-instr.fade-out { opacity: 0; pointer-events: none; visibility: hidden; transition: opacity .5s ease, visibility 0s linear .5s; }
.ritual-instr h3 { font-family: "Cinzel", serif; color: var(--oro-bright); font-size: 1rem; letter-spacing: .08em; margin: 0 0 4px; text-shadow: 0 1px 8px rgba(0,0,0,.8); }
.ritual-instr p { color: var(--ink); font-size: .95rem; margin: 0 auto; max-width: 44ch; text-shadow: 0 1px 8px rgba(0,0,0,.9); }

/* ═══ PANEL DE RECITADO ═══════════════════════════════════════════════════════════════
   Las PALABRAS a recitar (conjuro goético / enn moderno / invocación Verum) permanecen
   LEGIBLES para que el practicante recite de verdad (no de memoria). No se atenúa nunca:
   texto ritual siempre a alto contraste. Vertical: abajo. Horizontal: lateral derecho. */
.recitation {
  position: absolute; z-index: 14; pointer-events: auto;
  /* Vertical: sobre la franja inferior de control (barra de espera / «continuar»), sin taparla. */
  left: 12px; right: 12px; bottom: calc(env(safe-area-inset-bottom, 0px) + 82px);
  max-width: 640px; margin: 0 auto;
  background: rgba(14, 10, 6, .94);
  border: 1px solid rgba(232, 200, 116, .28);
  border-radius: 12px;
  box-shadow: 0 10px 34px rgba(0, 0, 0, .58), inset 0 0 0 1px rgba(232, 200, 116, .06);
  overflow: hidden;
}
.recit-toggle {
  display: block; width: 100%; box-sizing: border-box; text-align: left;
  font-family: "Cinzel", serif; font-size: .62rem; letter-spacing: .17em; text-transform: uppercase;
  color: var(--oro-bright); background: rgba(232, 200, 116, .07);
  border: 0; border-bottom: 1px solid rgba(232, 200, 116, .16);
  padding: 8px 15px; cursor: pointer; line-height: 1.2;
}
.recit-toggle::after { content: "▾"; float: right; opacity: .65; font-size: .8em; }
.recitation.collapsed .recit-toggle { border-bottom: 0; }
.recitation.collapsed .recit-toggle::after { content: "▸"; }
.recitation.collapsed .recit-body { display: none; }
.recit-body { padding: 11px 17px 15px; max-height: 22vh; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.recit-kind { display: none; }   /* la etiqueta va en el botón/toggle */
.recit-text {
  margin: 0; color: #f3e7c8; font-size: 1.06rem; line-height: 1.56;
  font-family: var(--font-body);   /* design system: EB Garamond (misma que el resto de la web) */
  text-shadow: 0 1px 6px rgba(0, 0, 0, .7); white-space: pre-line;
}
/* Horizontal: panel lateral derecho, para no tapar el foco ritual (círculo/sigilo/espejo). */
@media (orientation: landscape) {
  .recitation {
    left: auto; right: 12px; top: calc(env(safe-area-inset-top, 0px) + 64px);
    bottom: 68px; width: 34vw; max-width: 340px; margin: 0;
    display: flex; flex-direction: column;
  }
  .recit-body { max-height: none; flex: 1 1 auto; }
}
/* Horizontal corto (móvil apaisado): un poco más estrecho y sin chocar con el botón inferior. */
@media (orientation: landscape) and (max-height: 520px) {
  .recitation { top: 56px; bottom: 60px; width: 32vw; max-width: 300px; }
  .recit-text { font-size: .98rem; line-height: 1.5; }
}
@media (prefers-reduced-motion: reduce) { .recitation { transition: none; } }

.ritual-ui {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 12;
  padding: 12px 14px calc(14px + var(--safe-b));
  background: linear-gradient(0deg, rgba(0,0,0,.78), transparent);
  display: flex; flex-direction: column; gap: 10px; align-items: center;
}
.optrow { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; width: 100%; max-width: 560px; }
/* Auditoría DeepSeek: las opciones eran «cajas opacas gigantes» que aplastaban el primer plano.
   Ahora translúcidas (se ve la escena a través) con degradado en los bordes y blur → legibles
   pero sin tapar el peso del cuarto ni el elemento ritual. */
.opt {
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--panel2) 42%, transparent), color-mix(in srgb, var(--panel2) 58%, transparent));
  backdrop-filter: blur(7px); -webkit-backdrop-filter: blur(7px);
  border: 1px solid color-mix(in srgb, var(--oro) 30%, transparent); border-radius: 8px; color: var(--ink);
  padding: 13px 16px; font-size: .95rem; min-height: 50px; text-align: center;
  text-shadow: 0 1px 6px rgba(0,0,0,.85);
  transition: border-color .18s, transform .15s, background .18s;
}
.opt:hover, .opt:focus-visible { background: linear-gradient(180deg, color-mix(in srgb, var(--panel2) 56%, transparent), color-mix(in srgb, var(--panel2) 72%, transparent)); }
.opt:active { transform: scale(.97); }
.opt:hover { border-color: var(--oro); }
.opt .nota { display: block; font-size: .68rem; color: var(--ink-soft); letter-spacing: .08em; text-transform: uppercase; }
.opt.seal { display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 92px; }
.opt.seal .sig { width: 52px; height: 52px; background: var(--oro); -webkit-mask: var(--m) center/contain no-repeat; mask: var(--m) center/contain no-repeat; }
.opt.wrong-anim { animation: shake .4s ease; border-color: var(--sin); }
@keyframes shake { 0%,100% { transform: translateX(0); } 25% { transform: translateX(-6px); } 75% { transform: translateX(6px); } }

/* (La barra de espera .waiter se retiró: la manifestación llega en tiempo real, sin barra de progreso — M21.) */
/* «continuar» discreto: aparece tras ~60% de la espera para no ATRAPAR al impaciente (opcional). */
.wait-continue {
  margin-top: 14px; font-family: "Cinzel", serif; font-size: .64rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--oro); background: transparent; border: 1px solid rgba(232, 200, 116, .4);
  border-radius: 999px; padding: 7px 20px; cursor: pointer; opacity: .82;
  transition: opacity .3s ease, background .3s ease, color .3s ease;
}
.wait-continue:hover { opacity: 1; background: rgba(232, 200, 116, .12); color: var(--oro-bright); }

/* ─────────────────────────── Pantalla 4 · Resultado ─────────────────────────── */
#s-result { align-items: center; justify-content: center; text-align: center; padding: 24px; }
.result-inner { max-width: 430px; animation: introFade .8s ease both; }
.result-sello { width: 110px; height: 110px; margin: 0 auto 18px; background: var(--oro); -webkit-mask: var(--m) center/contain no-repeat; mask: var(--m) center/contain no-repeat; filter: drop-shadow(0 0 26px rgba(201,162,83,.5)); }
.result-sello.apagada { background: #3a2c18; filter: none; animation: sealStamp .7s ease both; }
.result-sello.encendida { animation: sealStamp .9s cubic-bezier(.2,1.6,.4,1) both; }
@keyframes sealStamp { from { transform: scale(1.7); opacity: 0; } to { transform: scale(1); opacity: 1; } }
.result-titulo { font-family: "Cinzel", serif; font-size: 1.7rem; margin: 0 0 10px; }
.result-texto { color: var(--ink-soft); font-size: 1rem; margin: 0 0 18px; }
/* Guía tras un fallo: pergamino sobrio con el diagnóstico del paso quebrado. */
.result-feedback {
  text-align: left; max-width: 400px; margin: 0 auto 22px;
  padding: 14px 16px; border-radius: 8px;
  background: rgba(201,162,83,.07); border: 1px solid rgba(201,162,83,.28);
  border-left: 3px solid var(--oro);
}
.result-feedback p { margin: 0 0 8px; }
.result-feedback p:last-child { margin-bottom: 0; }
.result-feedback .fb-linea { font-family: "Cinzel", serif; color: var(--oro); font-size: .95rem; letter-spacing: .02em; }
.result-feedback .fb-correcta { color: var(--ink); font-size: 1rem; }
.result-feedback .fb-estudia { color: var(--ink-soft); font-size: .9rem; font-style: italic; }
.result-ctas { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }
/* Apaisado en móvil (poca altura): el panel de resultado excedía el viewport y los CTA inferiores
   (Compartir/Atrás) quedaban recortados fuera de pantalla (auditoría deepseek-vision 2026-09-09).
   Top-align + margin auto centra cuando cabe y permite scroll cuando no; sello y tipos más
   compactos; safe-area inferior para alcanzar los botones. */
@media (orientation: landscape) and (max-height: 560px) {
  #s-result { justify-content: flex-start; padding: 14px 24px calc(18px + env(safe-area-inset-bottom, 0px)); }
  #s-result .result-inner { margin: auto 0; }
  #s-result .result-sello { width: 76px; height: 76px; margin-bottom: 10px; }
  #s-result .result-titulo { font-size: 1.35rem; margin-bottom: 6px; }
  #s-result .result-texto { font-size: .92rem; margin-bottom: 12px; }
  #s-result .result-feedback { margin-bottom: 14px; }
}

/* ─────────────────────────── Modal ─────────────────────────── */
.modal { position: fixed; inset: 0; z-index: 50; display: flex; align-items: center; justify-content: center; padding: 20px; background: rgba(0,0,0,.72); backdrop-filter: blur(4px); }
.modal[hidden] { display: none; }
.modal-card {
  background: var(--panel); border: 1px solid var(--oro); border-radius: 8px;
  padding: 26px 22px 22px; max-width: 360px; width: 100%; text-align: center;
  position: relative; box-shadow: 0 20px 60px rgba(0,0,0,.6), 0 0 40px rgba(201,162,83,.08);
  animation: introFade .35s ease both;
}
.modal-x { position: absolute; top: 10px; right: 12px; background: none; border: 0; color: var(--ink-soft); font-size: 1.05rem; }
.modal-card h3 { font-family: "Cinzel", serif; color: var(--oro); margin: 0 0 8px; font-size: 1.15rem; }
.modal-text { color: var(--ink-soft); font-size: .9rem; margin: 0 0 16px; }
.modal-input {
  width: 100%; background: var(--bg2); border: 1px solid var(--linea); border-radius: 4px;
  color: var(--ink); font-family: "EB Garamond", serif; font-size: 1rem;
  padding: 13px 12px; text-align: center; letter-spacing: .06em; margin-bottom: 14px; outline: none;
}
.modal-input:focus { border-color: var(--oro); }
/* Widget Turnstile dentro de la modal de desbloqueo: centrado, espacio reservado para
   evitar salto de layout (CLS) mientras carga el reto. */
.turnstile-box { display: flex; justify-content: center; margin: 0 0 14px; min-height: 66px; }
.modal-err { color: var(--sin); font-size: .85rem; margin: 10px 0 0; }
.modal-acciones { display: flex; gap: var(--sp-2); justify-content: flex-end; margin-top: var(--sp-4); }
.modal-acciones .btn { min-height: 42px; padding: 0 var(--sp-4); }
.modal-onboard { max-width: 460px; text-align: left; }
.modal-onboard h3 { text-align: center; margin: 0 0 var(--sp-3); font-size: 1.2rem; }
.onboard-p { color: var(--ink-soft); font-size: .9rem; line-height: 1.58; margin: 0 0 var(--sp-3); }
.onboard-small { font-size: .82rem; opacity: .85; }
.modal-onboard .btn { width: 100%; margin-top: var(--sp-2); }

/* ─────────────────────────── Toast ─────────────────────────── */
.toast {
  position: fixed; left: 50%; bottom: calc(24px + var(--safe-b)); z-index: 60;
  transform: translateX(-50%); background: var(--panel2); color: var(--ink);
  border: 1px solid var(--oro); border-radius: 6px; padding: 12px 20px;
  font-size: .92rem; box-shadow: 0 10px 30px rgba(0,0,0,.5);
  animation: introFade .3s ease both; max-width: 86vw; text-align: center;
}
.toast[hidden] { display: none; }

/* ─────────────────────────── Aviso de orientación (móvil) ─────────────────────────── */
.rotate-overlay {
  position: fixed; inset: 0; z-index: 80;
  display: none; place-items: center; padding: 24px;
  background:
    linear-gradient(180deg, rgba(5,3,1,.72), rgba(5,3,1,.45) 40%, rgba(5,3,1,.86)),
    url(/r/assets/ritual-portrait.webp) center 40%/cover no-repeat,
    rgba(0,0,0,.9);
  backdrop-filter: blur(6px);
  text-align: center; color: var(--ink);
}
.rotate-overlay[hidden] { display: none; }
.rotate-card { max-width: 340px; width: 100%; }
.rotate-icon {
  font-size: 3rem; line-height: 1; color: var(--oro-bright); margin-bottom: 12px;
  display: inline-block; animation: rotateHint 3.2s ease-in-out infinite;
}
@keyframes rotateHint { 0%,100% { transform: rotate(0); } 50% { transform: rotate(90deg); } }
.rotate-card h3 { font-family: "Cinzel", serif; color: var(--oro); margin: 0 0 10px; font-size: 1.2rem; }
.rotate-card p { color: var(--ink-soft); font-size: .95rem; margin: 0 0 22px; }
@media (max-width: 900px) and (orientation: portrait) {
  body.ritual-active .rotate-overlay:not([hidden]) { display: grid; }
}

/* Móvil vertical: compactar HUD del ritual y ajustar el libro para evitar scroll interno */
@media (max-width: 640px) and (orientation: portrait) {
  .ritual-top { padding: 10px 10px 6px; gap: 8px; }
  .ritual-instr { top: 58px; padding: 0 12px; }
  .ritual-instr h3 { font-size: .84rem; }
  .ritual-instr p { font-size: .84rem; max-width: 34ch; }
  .ritual-ui { padding: 10px 10px calc(16px + var(--safe-b)); }
  .opt { max-width: 100%; font-size: .84rem; padding: 10px 12px; }
  /* El libro ya es responsive intrínseco (clamp + aspect-ratio); sin overrides px. */
}

/* Pantallas bajas (móvil horizontal): el libro ocupa toda la pantalla y el HUD flota */
@media (max-height: 520px) {
  #s-study .topbar { position: absolute; top: 0; left: 0; right: 0; z-index: 20; background: linear-gradient(180deg, rgba(0,0,0,.72), transparent); padding: 8px 10px 20px; }
  #s-study .pagenum { position: absolute; bottom: 78px; left: 0; right: 0; z-index: 20; background: rgba(0,0,0,.55); border-radius: 4px; padding: 2px 10px; width: max-content; margin: 0 auto; }
  #s-study .bottombar { position: absolute; bottom: 0; left: 0; right: 0; z-index: 20; background: linear-gradient(0deg, rgba(0,0,0,.72), transparent); padding: 18px 10px calc(6px + var(--safe-b)); }
  #s-study .tradrow { position: absolute; top: 42px; left: 0; right: 0; z-index: 19; }
  #s-study .bookwrap { position: absolute; inset: 0; padding: 72px 0 52px; }
  /* El libro se recalcula solo (aspect-ratio); sin overrides px. */
  /* HUD del ritual compacto en horizontal — con fondo para que se lea como HUD y
     no como texto suelto sobre el círculo (el círculo baja en pantallas cortas). */
  .ritual-top { padding: 6px 8px 4px; }
  /* Instrucción PEGADA AL BORDE SUPERIOR y compacta → nunca invade el centro donde vive el
     elemento ritual (círculo/sello/tablilla/espejo). Auditoría (usuario + DeepSeek): el banner
     no debe tapar el rito. Altura acotada; si el texto es largo, cuerpo más pequeño. */
  .ritual-instr { top: 4px; padding: 4px 12px; width: max-content; max-width: 78vw; margin: 0 auto; left: 0; right: 0;
    max-height: 27vh; overflow: hidden;
    background: rgba(8,5,2,.5); border: 1px solid rgba(201,162,83,.18); border-radius: 11px; backdrop-filter: blur(5px); }
  .ritual-instr h3 { font-size: .7rem; margin: 0 0 1px; }
  .ritual-instr p { font-size: .68rem; line-height: 1.28; max-width: 52ch; }
  .ritual-ui {
    padding: 2px 8px calc(2px + var(--safe-b));
    background: transparent;
  }
  .ritual-ui .hint {
    display: inline-block;
    background: rgba(0,0,0,.6);
    border: 1px solid rgba(201,162,83,.28);
    border-radius: 14px;
    padding: 2px 12px;
    font-size: .7rem;
    backdrop-filter: blur(4px);
  }
  .opt { font-size: .8rem; padding: 8px 10px; min-height: 40px; }
}

/* MÓVIL HORIZONTAL (pliego): el libro abierto debe llenar el alto como en desktop. Se
   recupera vertical compactando el chrome (barras translúcidas y flotantes sobre el
   BORDE ornamental del libro, no sobre el texto) para que el pliego crezca, no quede
   diminuto. La tipografía de hoja se ajusta al ancho de página más estrecho del pliego. */
@media (max-height: 520px) and (orientation: landscape) {
  #s-study .topbar { padding: 3px 10px 8px; }
  #s-study .top-title { font-size: .64rem; }
  #s-study .tradrow { top: 24px; transform: scale(.8); transform-origin: top center; }
  #s-study .pagenum { bottom: 38px; }
  #s-study .bottombar { padding: 6px 10px calc(3px + var(--safe-b)); }
  #s-study .bottombar .btn { min-height: 34px; font-size: .62rem; }
  /* El libro llena casi todo el alto, pero su ZONA DE TEXTO (leaf, a 14% del borde) debe
     empezar POR DEBAJO de la fila de pestañas flotante: por eso el padding-top deja sitio
     a topbar+tradrow; el borde ornamental superior del libro sí queda tras ellas. */
  #s-study .bookwrap { padding: 52px max(6px, env(safe-area-inset-right, 0px)) 20px max(6px, env(safe-area-inset-left, 0px)); }
  /* Página del pliego estrecha en móvil: cuerpo más pequeño y sin hifenación. */
  .is-spread .leaf-ink { font-size: clamp(.62rem, 1.45vw, .86rem); line-height: 1.38; }
  /* Columnas del pliego móvil son ESTRECHAS: el texto justificado abre ríos/huecos feos.
     Se alinea a la IZQUIERDA (borde derecho irregular, como un libro real de columna
     angosta) y se permiten guiones → palabras parejas, sin huecos. Solo en este landscape
     corto; el desktop (columnas anchas) mantiene su justificado. */
  .is-spread .gsec p, .is-spread li { text-align: left; hyphens: auto; }
  /* Portada compacta: la hoja es baja en horizontal, el sigilo grande la desbordaba y
     empujaba «Bael/Rey» fuera del recorte. NOTA: `.is-spread` ES el propio `.grimorio`
     (la clase va en #grimorioBook), por eso NO se escribe `.is-spread .grimorio .x`. */
  .is-spread .gname { font-size: clamp(1rem, 2.7vw, 1.36rem); margin: 0 0 .02em; }
  .is-spread .page-seal { width: clamp(32px, 7.5vh, 48px); margin-bottom: .18em; }
  .is-spread .gmeta { font-size: .72rem; margin-bottom: .18em; }
  /* Aparición: algo menor y compacta para que quepa ENTERA (antes se cortaba la última
     línea de la descripción a 360px). Centrada (gana a .gsec p justify por especificidad). */
  .is-spread .gsec-cover .gapp { font-size: .7rem; line-height: 1.3; margin-top: .1em; max-width: 32ch; }
  .is-spread .gsec-cover { justify-content: flex-start; padding-top: .1em; }
}

/* ─────────────────────────── Accesibilidad / bajo consumo ─────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
  .hand-sway-l, .hand-sway-r, .finger-l2, .finger-r2, .finger-r3, .stylus { animation: none !important; }
  .circle-glow { animation: none !important; }
}
/* Safe areas: en landscape no pegar los HUDs al borde físico */
@media (orientation: landscape) {
  .topbar, .bottombar, .tradrow, .ritual-top, .ritual-ui {
    padding-left: max(12px, env(safe-area-inset-left, 0px));
    padding-right: max(12px, env(safe-area-inset-right, 0px));
  }
  #s-study .bookwrap { padding-left: max(8px, env(safe-area-inset-left, 0px)); padding-right: max(8px, env(safe-area-inset-right, 0px)); }
}

/* ═══════════ Fase 3e · GATE CONTEXTUAL (espíritu premium sin sesión) ═══════════ */
.modal-gate { max-width: 460px; text-align: left; }
.gate-head { display: flex; align-items: center; gap: 16px; margin: 4px 0 14px; }
.gate-seal { flex: none; width: 66px; height: 66px; background: var(--oro);
  -webkit-mask: var(--m) center/contain no-repeat; mask: var(--m) center/contain no-repeat;
  filter: drop-shadow(0 0 6px rgba(201,162,83,.28)); }
.gate-seal.azazel { background: none; border: 2px solid var(--sin, #cd5b4b); border-radius: 50%;
  -webkit-mask: none; mask: none; position: relative; }
.gate-seal.azazel::before { content: ""; position: absolute; left: 12px; right: 12px; top: 50%;
  height: 2px; background: var(--sin, #cd5b4b); transform: rotate(-30deg); }
.gate-id { min-width: 0; }
.gate-eyebrow { display: block; font-family: "Cinzel", Georgia, serif; font-size: .6rem;
  letter-spacing: .18em; text-transform: uppercase; color: var(--oro); margin-bottom: 3px; }
.gate-name { margin: 0; font-family: "Cinzel", Georgia, serif; font-size: 1.5rem; line-height: 1.1; }
.gate-rango { display: block; font-size: .82rem; color: var(--ink-soft, #b5a48b); margin-top: 3px; }
.gate-requiere { margin: 0 0 12px; font-size: .95rem; line-height: 1.5;
  color: var(--ink, #ecdfc2); padding: 9px 12px; border-radius: 10px;
  background: color-mix(in srgb, var(--oro) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--oro) 30%, transparent); }
.modal-gate .onboard-p { text-align: left; }
.modal-gate .btn-oro { margin-top: 14px; width: 100%; }

/* ══ OBJETO físico de los flujos variados (anillo/vara/ofrenda) — realismo: peso, perspectiva,
      gravedad. El asset (gpt-image) va en /r/assets/obj/<obj>.png; hasta entonces, placeholder CSS. ══ */
/* Tamaño SIEMPRE limitado por el ALTO del viewport (vh): en apaisado móvil el alto es corto
   (~200px CSS) y un tamaño solo-vw desbordaba y CORTABA el objeto. Anclado bajo, sobre la mesa. */
.objeto-stage { position: absolute; left: 50%; bottom: 14%; width: min(30vw, 56vh, 200px); aspect-ratio: 1/1;
  transform: translateX(-50%); pointer-events: none; z-index: 7;
  animation: obj-settle .72s cubic-bezier(.22,1.15,.36,1) both; }
.objeto-img { width: 100%; height: 100%; object-fit: contain;
  filter: drop-shadow(0 10px 14px rgba(0,0,0,.65)); }
/* sombra de contacto: elipse baja y ancha que ASIENTA el objeto en el plano de la mesa */
.objeto-stage::after { content:""; position:absolute; left:50%; bottom:-3%; width:64%; height:11%;
  transform:translateX(-50%); background: radial-gradient(ellipse at center, rgba(0,0,0,.6), transparent 72%);
  animation: obj-shadow .72s cubic-bezier(.22,1.15,.36,1) both; }
@keyframes obj-settle {
  0%   { transform: translateX(-50%) translateY(-12%) scale(1.05); opacity: 0; }
  55%  { transform: translateX(-50%) translateY(2%)  scale(.99); opacity: 1; }   /* rebote = peso */
  100% { transform: translateX(-50%) translateY(0)   scale(1);    opacity: 1; }
}
@keyframes obj-shadow { 0%{opacity:0;transform:translateX(-50%) scale(.45);} 100%{opacity:.9;transform:translateX(-50%) scale(1);} }
/* posición y actitud por objeto (todos con tope de ALTO para no cortarse en apaisado corto) */
.obj-anillo  { bottom: 24%; width: min(20vw, 40vh, 132px); }            /* alzado, ante el rostro */
.obj-vara    { bottom: 15%; width: min(46vw, 78vh, 300px); }            /* apuntando (palo largo) */
.obj-vara .objeto-img { transform: rotate(19deg); }
.obj-ofrenda { bottom: 11%; width: min(30vw, 50vh, 196px); }           /* cuenco posado sobre la mesa */
.obj-ofrenda .objeto-img { transform: scaleY(.9);                       /* leve compresión: visto desde arriba, yace en el plano */
  /* PERTENECE a la mesa (auditoría codex): doble sombra —contacto corto + proyectada larga— para
     que el cuenco no se lea como asset recortado y pegado, sino asentado con peso en el altar. */
  filter: drop-shadow(0 5px 7px rgba(0,0,0,.6)) drop-shadow(0 16px 22px rgba(0,0,0,.5)); }
/* sombra de CONTACTO del cuenco: núcleo MUY oscuro y ceñido al PIE (oclusión de contacto) + halo
   ancho y difuso → el pie "toca" la mesa y el cuenco deja de leerse como recorte flotante. */
.obj-ofrenda::after { width: 50%; height: 12%; bottom: 1%; filter: blur(2.5px);
  background:
    radial-gradient(ellipse at 50% 55%, rgba(0,0,0,.9) 0%, rgba(0,0,0,.55) 34%, transparent 62%),
    radial-gradient(ellipse at 50% 60%, rgba(0,0,0,.4) 0%, transparent 80%);
  box-shadow: 0 0 26px 14px rgba(0,0,0,.42); }
/* OCLUSIÓN baja: la base del cuenco se hunde levemente en la penumbra de la mesa (no recorte limpio). */
.obj-ofrenda::before { content:""; position:absolute; left:50%; bottom:3%; width:88%; height:30%;
  transform:translateX(-50%); pointer-events:none; z-index:-1;
  background: radial-gradient(ellipse at 50% 100%, rgba(6,4,2,.55), rgba(6,4,2,.22) 46%, transparent 72%); }
/* placeholder (silueta) hasta que exista el asset gpt-image */
.obj-placeholder::before { content:""; position:absolute; inset:20%; border:3px solid rgba(201,162,83,.55);
  border-radius:50%; box-shadow: inset 0 0 18px rgba(201,162,83,.25), 0 9px 14px rgba(0,0,0,.5); }
.obj-vara.obj-placeholder::before { inset:45% 6%; border-radius:6px; border-width:4px; transform:rotate(19deg); }
.obj-ofrenda.obj-placeholder::before { inset:34% 15% 20%; border-radius:0 0 46% 46%; }
@media (prefers-reduced-motion: reduce) { .objeto-stage, .objeto-stage::after { animation-duration: .01ms; } }

/* ═══════════════ GRIMORIUM VERUM · corriente de Syrach (De Secretis) ═══════════════
   Familia textual DISTINTA de la Ars Goetia. Toggle de corriente + pantalla propia #s-verum
   (presentación honesta: carácter/sigilo + oficio + operación documentada). */
.mesa-streamtabs { display:flex; gap:8px; justify-content:center; flex-wrap:wrap; margin:2px auto 14px; }
.streamtab { font-family:"Cinzel",Georgia,serif; font-size:.76rem; letter-spacing:.09em; text-transform:uppercase;
  padding:9px 20px; border-radius:999px; border:1.5px solid #c9a253;
  /* píldora con fondo OSCURO SÓLIDO: legible sobre la imagen de fondo recargada del select
     (el oro semitransparente se perdía sobre el fondo oscuro → «botones oscuros»). */
  background:rgba(20,16,10,.9); color:#e8c874; font-weight:700; cursor:pointer;
  box-shadow:0 2px 10px rgba(0,0,0,.55); text-shadow:0 1px 2px rgba(0,0,0,.6);
  transition:background .2s,color .2s,box-shadow .2s; }
.streamtab.active { background:#c9a253; color:#1a1408; box-shadow:0 0 0 2px rgba(201,162,83,.45),0 2px 10px rgba(0,0,0,.55); text-shadow:none; }
.streamtab:hover:not(.active) { background:rgba(40,32,18,.95); border-color:#e8c874; color:#f2e6b8; }
.streamtab:focus-visible { outline:2px solid #e8c874; outline-offset:2px; }
/* sigilo del Verum en la tarjeta de la grilla: el SVG YA es dorado (#c9a253), así que NO se
   enmascara ni se pinta de oro (evita el «blob» dorado / sigilo invisible sobre oro). */
.card .sig.vsig-mesa { background-color:transparent; -webkit-mask:none; mask:none;
  background-size:contain; background-repeat:no-repeat; background-position:center;
  filter:drop-shadow(0 0 5px rgba(201,162,83,.28)); }

/* pantalla Verum (lectura/estudio De Secretis) */
#s-verum { background:var(--bg); }
#s-verum .verum-scroll { position:absolute; inset:56px 0 0; overflow-y:auto; -webkit-overflow-scrolling:touch; }
.verum-body { max-width:720px; margin:0 auto; padding:22px 20px 64px; color:var(--ink); }
.vm-eyebrow { font-family:"Cinzel",Georgia,serif; font-size:.72rem; letter-spacing:.14em; text-transform:uppercase; color:var(--oro); margin:0 0 4px; }
.vm-name { font-family:"Cinzel",Georgia,serif; font-size:1.7rem; margin:0 0 2px; color:var(--ink); text-wrap:balance; }
.vm-tag { font-family:Georgia,serif; font-size:.7rem; font-weight:400; letter-spacing:.06em; color:var(--ink-soft); text-transform:none; vertical-align:middle; }
.vm-rank { font-style:italic; color:var(--ink-soft); margin:0 0 14px; font-size:.92rem; }
.vm-framing { border-left:2px solid color-mix(in srgb,var(--oro) 50%,transparent); background:color-mix(in srgb,var(--oro) 7%,transparent);
  padding:12px 14px; border-radius:0 6px 6px 0; font-size:.92rem; line-height:1.55; color:var(--ink-soft); margin:0 0 22px; }
.vm-sigfig { display:flex; flex-direction:column; align-items:center; gap:8px; margin:0 0 22px; }
.vm-sig { width:180px; height:180px; object-fit:contain;
  background:color-mix(in srgb,var(--panel) 70%,transparent); border:1px solid var(--linea); border-radius:10px; padding:14px; }
.vm-cite { font-size:.76rem; color:var(--ink-soft); text-align:center; letter-spacing:.02em; margin:0; }
.vm-folio { color:var(--ink-soft); }
.vm-sec { margin:0 0 20px; }
.vm-sec > h3 { font-family:"Cinzel",Georgia,serif; font-size:.86rem; letter-spacing:.08em; text-transform:uppercase; color:var(--oro); margin:0 0 6px; border-bottom:1px solid color-mix(in srgb,var(--oro) 24%,transparent); padding-bottom:4px; }
.vm-prose { line-height:1.6; color:var(--ink); }
.vm-prose p { margin:0 0 8px; }
.vm-prose .vcross { margin-top:12px; padding-top:9px; border-top:1px solid color-mix(in srgb,var(--oro) 24%,transparent); font-size:.9em; color:var(--ink-soft); }
.vm-op .vm-prose { border-left:2px solid color-mix(in srgb,var(--oro) 40%,transparent); padding-left:12px; }
.vm-noop { font-style:italic; color:var(--ink-soft); }
.vm-latin .mslatin { font-style:italic; color:var(--ink-soft); line-height:1.5; }

/* ═══ MODO NOCTURNO (visión escotópica / uso en exteriores de noche) ═══════════════════════════
   Velo fijo que SOLO anima opacity → se compone en GPU, no repinta la escena ni la respiración
   (deepseek: filter/blend repintarían cada frame). Día = invisible; recordado en localStorage. */
#nightVeil {
  position: fixed; inset: 0; z-index: 200; pointer-events: none; will-change: opacity;
  opacity: 0; background: #2a0a00;
  transition: opacity .55s cubic-bezier(.4, 0, .2, 1);   /* SOLO opacity (compositor puro); el color cambia al instante */
}
:root[data-night="warm"] #nightVeil { background: #2a0a00; opacity: .5; }   /* noche cálida: atenúa+calienta */
:root[data-night="red"]  #nightVeil { background: #5a0a00; opacity: .62; }  /* ámbar-rojo funcional: preserva bastones sin matar la legibilidad */
/* Control mínimo (esquina inf-dcha): Día → Noche → Rojo. Muy tenue; sube al tocar. */
#nightToggle {
  position: fixed; z-index: 201;
  right: calc(env(safe-area-inset-right, 0px) + 10px);
  bottom: calc(env(safe-area-inset-bottom, 0px) + 10px);
  width: 40px; height: 40px; border-radius: 50%; border: 0; cursor: pointer; padding: 0;
  background: rgba(20, 14, 8, .5); color: #d8c9a8; font-size: 18px; line-height: 40px; text-align: center;
  opacity: .34; transition: opacity .3s ease; -webkit-tap-highlight-color: transparent;
}
#nightToggle:hover, #nightToggle:focus-visible, #nightToggle.on { opacity: 1; }
:root[data-night="warm"] #nightToggle, :root[data-night="red"] #nightToggle { color: #e6b892; }
#nightToggle::after {
  content: attr(data-lbl); position: absolute; right: 46px; top: 50%; transform: translateY(-50%);
  white-space: nowrap; font: 600 .6rem/1 "Cinzel", serif; letter-spacing: .12em; text-transform: uppercase;
  color: #e6d8bc; background: rgba(12, 8, 4, .85); padding: 5px 9px; border-radius: 6px;
  opacity: 0; transition: opacity .25s ease; pointer-events: none;
}
#nightToggle.label::after { opacity: 1; }
@media (prefers-reduced-motion: reduce) { #nightVeil { transition: opacity .01ms; } }

/* ═══ INMERSIÓN: el chrome superior se desvanece tras la quietud (M14/M9) ══════════════════════
   Reaparece al tocar/mover (JS quita .chrome-off). Solo la barra de navegación: la escena y la
   interacción del paso permanecen. La transición es lenta para que no «parpadee». */
.ritual-top { transition: opacity .9s ease; }
#s-ritual.chrome-off .ritual-top { opacity: 0; pointer-events: none; }
@media (prefers-reduced-motion: reduce) { .ritual-top { transition: opacity .2s ease; } }

/* Sincronización manual de respiración (M19): control tenue dentro del HUD de trance. */
.trance-sync {
  /* Acción real: NO debe leerse como deshabilitada (auditoría real Xiaomi codex+deepseek). Reposo
     legible —borde y texto con presencia sobre la escena oscura— y sutil relleno frío; sigue siendo
     secundaria al hold, pero claramente pulsable. */
  margin-top: 8px; background: rgba(176, 196, 214, .07); border: 1px solid rgba(176, 196, 214, .5);
  color: #cbdbea; font: 500 .6rem/1.2 "Cinzel", serif; letter-spacing: .12em; text-transform: lowercase;
  border-radius: 999px; padding: 6px 14px; cursor: pointer; opacity: 1;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .8);
  transition: opacity .3s ease, border-color .3s ease, color .3s ease, background .3s ease;
}
.trance-sync:hover, .trance-sync:focus-visible { border-color: rgba(176, 196, 214, .72); color: #e6f0f8; background: rgba(176, 196, 214, .14); }

/* LEGIBILIDAD del texto de manifestación/licencia/pentáculo y de la guía de trance: se pinta
   sobre el CENTRO más brillante de la escena (sello luminoso, aparición dorada, halo del espejo)
   y los tonos secundarios se lavaban (reporte real del usuario + auditoría Xiaomi). Un halo oscuro
   heredado los separa del fondo sin subir su color ni romper la atenuación ceremonial. Diegético,
   coste de compositor (solo sombra de texto). */
#ritualUI p, #ritualUI blockquote, .trance-cue, .trance-phase {
  text-shadow: 0 1px 2px rgba(0, 0, 0, .92), 0 0 12px rgba(0, 0, 0, .68);
}

/* ═══ SILENCIO PROGRESIVO (M22): la escena se RETIRA tras quietud sostenida ════════════════════
   Solo opacity (compositor). El velo oscurece la ESCENA (no las palabras a recitar, que quedan
   por encima) → la mesa «se apaga» sin desaparecer; cualquier gesto la reaviva (JS quita la clase). */
#s-ritual::after {
  content: ""; position: absolute; inset: 0; z-index: 6; pointer-events: none;
  background: var(--negro); opacity: 0; transition: opacity 5s ease;
}
#s-ritual.deep-rest::after { opacity: .3; }
@media (prefers-reduced-motion: reduce) { #s-ritual::after { transition: opacity .3s ease; } }

/* ═══ GRIMORIO SILENCIOSO (M20): el teléfono ES el atril — pantalla completa, solo el texto ══════
   Sustituye al libro sobre el atril (deepseek: legitimidad documental). Grande, legible, sin scroll
   mecánico, sin chrome. El velo nocturno (z-200) queda por encima → legible también en rojo. */
#grimoireFull {
  position: fixed; inset: 0; z-index: 150; background: var(--d-bg-deep); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  padding: max(env(safe-area-inset-top), 26px) 26px max(env(safe-area-inset-bottom), 26px);
  animation: grimFade .5s ease;
}
@keyframes grimFade { from { opacity: 0; } to { opacity: 1; } }
#grimoireInner { max-width: 30em; max-height: 100%; overflow-y: auto; -webkit-overflow-scrolling: touch; text-align: center; }
#grimoireKind { display: block; font: 600 .66rem/1 "Cinzel", serif; letter-spacing: .22em; text-transform: uppercase; color: var(--oro, #c9a253); margin: 0 0 1.3em; opacity: .78; }
/* Alineación IZQUIERDA (deepseek-vision): un bloque largo centrado obliga a saltos de ojo y complica
   la lectura EN VOZ ALTA a oscuras; a la izquierda se recita de corrido. */
#grimoireText { margin: 0; text-align: left; font-family: var(--font-body); font-size: clamp(1.5rem, 6.4vw, 2.35rem); line-height: 1.52; color: #efe2c4; white-space: pre-line; text-shadow: 0 1px 10px rgba(0, 0, 0, .6); }
#grimoireKind { text-align: left; }
#grimoireHint { position: absolute; bottom: calc(env(safe-area-inset-bottom, 0px) + 18px); left: 0; right: 0; text-align: center; font: 500 .6rem/1 "Cinzel", serif; letter-spacing: .16em; text-transform: uppercase; color: #8a7c5e; animation: grimHintFade 4.5s ease forwards; }
@keyframes grimHintFade { 0%, 55% { opacity: .7; } 100% { opacity: 0; } }
/* Afordancia mínima en el panel de recitado: indica que se puede ampliar a pantalla completa. */
.recit-expand { position: absolute; top: 6px; right: 10px; background: none; border: 0; color: var(--oro-bright, #e2bf6c); font-size: 13px; opacity: .6; cursor: pointer; padding: 4px; }
.recit-expand:hover { opacity: 1; }