/* ============================================================
   MOTOR COMPARTIDO · PIZARRA
   Extraído del prototipo pizarra-M3S19.html (tarjeta 2, M3.S19).
   Todo lo que es forma, no contenido: cada lección solo aporta su
   config (PASOS, problema, audio) a través de pizarra-engine.js.
   No tocar por lección — si hace falta un ajuste visual, es aquí.
   ============================================================ */

/* Paleta calcada de :root en web/index.html (la app real), no una propia.
   --bg-deep es la única excepción a propósito: en la app es un overlay
   traslúcido pensado para sentarse sobre --bg-gradient; aquí no hay
   gradiente de fondo, así que se mantiene como color sólido — mismo
   papel (panel del tablero, más oscuro que la tarjeta), otro cálculo. */

/* --mono se define AQUÍ y no se hereda del host. Este archivo la usa en cada
   `font:` de la pizarra (tokens, pasos, cartelones), y ni web/index.html ni
   la app React la declaraban: como `font:` es un atajo, una variable vacía
   invalida la declaración ENTERA y el navegador la tira. El resultado era
   que toda la tipografía de la pizarra caía al font heredado sin que se
   notara de dónde venía. Con el fallback local el archivo es autónomo, y si
   el host define su propia --mono, esa gana. */
:root{--mono:ui-monospace,"SF Mono",SFMono-Regular,Menlo,monospace}


.nota{
  font-size:13px;color:var(--label3);border:1px dashed var(--hair);
  border-radius:var(--r-sm);padding:12px 14px;margin-bottom:28px;line-height:1.55}
.nota b{color:var(--label2)}
.numbloque{display:flex;align-items:center;gap:11px;margin:0 0 14px 2px}
.numbloque .n{
  width:26px;height:26px;border-radius:50%;background:var(--fill);
  display:grid;place-items:center;font:700 12px/1 var(--mono);color:var(--label2)}
.numbloque .t{font-size:12.5px;font-weight:700;letter-spacing:.9px;text-transform:uppercase;color:var(--label3)}


.g{background:var(--card);border:1px solid var(--hair);border-radius:16px;
   box-shadow:var(--sh-card);overflow:hidden;margin-bottom:24px}

.cerrada{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px;padding:16px 18px;cursor:pointer;
  transition:background .18s}
.cerrada:hover{background:var(--fill2)}
.cerrada .play{
  width:34px;height:34px;flex:0 0 auto;border-radius:50%;background:var(--accent);
  color:#fff;display:grid;place-items:center;font-size:13px;padding-left:2px}
.cerrada .tit{flex:1;min-width:120px}
.cerrada .tit b{display:block;font-size:15.5px;font-weight:600}
.cerrada .tit span{display:block;font-size:13px;color:var(--label3);margin-top:2px}
.cerrada .res{
  flex:0 0 auto;margin-left:auto;max-width:100%;text-align:right;white-space:normal;
  font:600 15px/1.3 var(--mono);color:var(--ok);background:var(--ok-bg);
  border:1px solid var(--ok-brd);border-radius:var(--r-xs);padding:7px 10px}

.abierta{display:none}
.abierta.on{display:block}
.cab{display:flex;align-items:center;gap:12px;padding:15px 18px;border-bottom:1px solid var(--hair-soft)}
.cab .tit{flex:1;font-size:15.5px;font-weight:600}
.cab .prob{font:600 14px/1 var(--mono);color:var(--label3)}

.profe{
  padding:20px 22px;background:var(--card2);border-bottom:1px solid var(--hair-soft);
  font-size:16.5px;line-height:1.62;color:var(--label2);min-height:104px;
  display:flex;align-items:center}
.profe p{margin:0}
.profe b{color:var(--label);font-weight:600}
.profe .em{color:var(--accent);font-weight:600}
.profe .q{color:var(--warn);font-weight:600}

.tablero{background:var(--bg-deep);padding:26px 18px 22px;overflow:hidden}
.fila{
  display:grid;grid-template-columns:30px 1fr auto 1fr;align-items:center;
  column-gap:10px;padding:8px 0;font:600 clamp(20px,4.4vw,30px)/1.3 var(--mono);
  letter-spacing:-.5px;
  transition:opacity .34s cubic-bezier(.2,.8,.2,1)}
.fila .paso{font:600 11px/1 var(--mono);color:var(--label3);opacity:.55;text-align:right}
/* nowrap a propósito, mismo criterio que .fx-operacion más abajo: una fila
   con muchos términos partiéndose en dos líneas se leía como si el
   ejercicio "continuara" en otra fila. `.fila-md`/`.fila-sm` (calculadas en
   JS por longitud de contenido, ver claseTamFila en PizarraBlock.jsx)
   achican la letra ANTES de que haga falta partir nada. */
.fila .izq{text-align:right;display:flex;justify-content:flex-end;flex-wrap:nowrap;gap:2px}
.fila .der{text-align:left;display:flex;justify-content:flex-start;flex-wrap:nowrap;gap:2px}
.fila .ig{color:var(--label3);padding:0 2px}
.fila.fila-md{font-size:clamp(15px,3.6vw,22px)}
.fila.fila-sm{font-size:clamp(12px,3vw,17px)}

/* El token en sí SÍ puede partir su propio texto en varias líneas
   (`white-space:normal`) — a diferencia de `.fila .izq`/`.der`, que siguen
   en `nowrap` a propósito (ver el comentario de arriba: una fila con varios
   términos separándose en dos líneas confunde). Acá es un solo token con
   una frase larga (el resumen final "A) ... · C) ... · D) ..."): sin esto,
   `overflow:hidden` del `.tablero` lo recortaba en pantallas angostas — se
   perdía la mitad del texto sin ningún aviso. Reportado por Daniel: "hay
   textos que no se muestran completas, no son adaptativas al teléfono".
   Confirmado en 320px de ancho: se cortaban 54.8px del token, literalmente
   "D) 12 hours" quedaba invisible. */
.t{display:inline-block;padding:3px 7px;border-radius:8px;white-space:normal;
   overflow-wrap:break-word;max-width:100%;flex-shrink:0;
   transition:color .25s,background .25s,box-shadow .25s}
.t.warn{color:var(--warn);background:var(--warn-bg);box-shadow:inset 0 0 0 1px var(--warn-brd)}
.t.err{color:var(--err);background:var(--err-bg);box-shadow:inset 0 0 0 1px var(--err-brd)}
.t.hl{color:var(--ok);background:var(--ok-bg);box-shadow:inset 0 0 0 1px var(--ok-brd)}
.t.dim{color:var(--label3);opacity:.5}
.t.mira{color:var(--accent);background:var(--accent-soft);
        box-shadow:inset 0 0 0 1px var(--accent)}

.pie{display:flex;align-items:center;gap:9px;padding:14px 18px;border-top:1px solid var(--hair-soft)}
.btn{
  border:1px solid var(--hair);background:var(--card);color:var(--label);
  border-radius:var(--r-sm);padding:9px 15px;font:500 14.5px/1 inherit;cursor:pointer;
  transition:background .15s,transform .12s}
.btn:hover:not(:disabled){background:var(--fill2)}
.btn:active:not(:disabled){transform:scale(.97)}
.btn:disabled{opacity:.38;cursor:default}
.btn.pri{background:var(--accent);border-color:transparent;color:#fff}
.hueco{flex:1}

/* Fase 5 de plan/v11-tutor-ia.md: el botón vive DENTRO de la tarjeta, pegado
   a la explicación del paso actual — nunca una caja de chat suelta en otro
   lado de la app (ver "por qué no hay bypass posible" en el plan).
   El botón y la tarjeta comparten `layoutId` en PizarraBlock.jsx — Framer
   Motion interpola tamaño/posición/radio entre los dos automáticamente,
   el mismo truco de "morph" que usan los popover de Vercel/cult-ui, sin
   traer Tailwind ni Radix (el proyecto ya usa motion/react en toda la
   pizarra: PizarraFX, las filas que se acumulan, etc.). */
/* Ya no tiene tamaño propio: solo aloja el popup (`position:fixed`), el
   disparador se mudó a `.pie`. */
.tutor-zona{display:contents}
.pie .tutor-magico{width:34px;height:34px}

.tutor-magico{
  position:relative;width:40px;height:40px;border-radius:12px;
  border:none;background:var(--card2);cursor:pointer;
  display:grid;place-items:center;overflow:visible}
.tutor-magico-glow{
  position:absolute;inset:-2px;border-radius:14px;
  background:conic-gradient(from 0deg,#8b5cf6,#ec4899,#f59e0b,#8b5cf6);
  animation:tutorGiro 3.2s linear infinite;
  -webkit-mask:padding-box,linear-gradient(#000,#000);
  -webkit-mask-composite:xor;
  mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  mask-composite:exclude;
  padding:2px}
.tutor-magico-icono{position:relative;font-size:16px;line-height:1;filter:drop-shadow(0 0 4px rgba(139,92,246,.6))}
.tutor-magico:hover{transform:scale(1.06)}
.tutor-magico:active{transform:scale(.96)}
@keyframes tutorGiro{to{transform:rotate(360deg)}}

/* Popup real: `fixed` + centrado en el viewport, con fondo oscuro detrás.
   No vive DENTRO de la tarjeta de pizarra (que tiene `overflow:hidden` y la
   recortaría) — se superpone a toda la pantalla, como pidió Daniel. El
   `layoutId` compartido con `.tutor-magico` sigue funcionando igual: Framer
   Motion calcula el rect real de cada uno sin importar si uno es relative
   y el otro fixed. */
.tutor-fondo{
  position:fixed;inset:0;z-index:200;background:rgba(0,0,0,.45);
  -webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);
  display:flex;align-items:center;justify-content:center;padding:16px}
/* Sin `transform` propio a propósito: el centrado lo hace el flex del
   `.tutor-fondo` de arriba, no un `translate(-50%,-50%)` — si esta regla
   también trajera `transform`, competiría con el que aplica Framer Motion
   para el morph animado y rompería la posición final. */
.tutor-tarjeta{
  position:relative;z-index:201;
  width:min(420px,calc(100vw - 32px));border-radius:16px;overflow:hidden;
  background:var(--card2);box-shadow:var(--sh-raise),0 0 0 1px var(--hair-soft)}
.tutor-tarjeta-in{display:flex;flex-direction:column}
.tutor-cab{display:flex;align-items:center;gap:8px;padding:12px 14px;border-bottom:1px solid var(--hair-soft)}
.tutor-cab-icono{font-size:15px}
.tutor-cab-tit{flex:1;font:600 13.5px/1.2 inherit;color:var(--label)}
.tutor-cerrar{
  border:none;background:none;color:var(--label3);font-size:20px;line-height:1;
  width:24px;height:24px;border-radius:50%;cursor:pointer;display:grid;place-items:center}
.tutor-cerrar:hover{background:var(--fill2);color:var(--label)}
.tutor-hilo{padding:14px 14px 0;max-height:220px;overflow-y:auto}
.tutor-respuesta{margin:0 0 12px;font-size:14.5px;line-height:1.55;color:var(--label2)}
.tutor-respuesta.tutor-pensando{color:var(--label3);font-style:italic}
.tutor-respuesta.tutor-err{color:var(--err)}
.tutor-form{display:flex;gap:8px;padding:14px}
.tutor-input{
  flex:1;border:1px solid var(--hair);background:var(--card);color:var(--label);
  border-radius:var(--r-sm);padding:9px 12px;font:400 14px/1 inherit}
.tutor-input:disabled{opacity:.6}
.pips{display:flex;gap:4px}
.pip{width:13px;height:4px;border-radius:2px;background:var(--label3);opacity:.28;transition:.28s}
.pip.on{opacity:1;background:var(--accent);width:22px}
.pip.past{opacity:.6}

.guion-activa{
  position:fixed; top:0; left:0; width:100%; height:100dvh; z-index:9999;
  background:#000; overflow-y:auto; overflow-x:hidden;
  display:flex; justify-content:center; align-items:center; padding: 20px;
  /* La tarjeta (`.g`) toma su fondo de `--chrome` (index.css:379-380), NO de
     `--card` — ese fue el primer intento fallido de este fix, apuntaba a la
     variable equivocada. `--chrome` en tema claro es blanco TRANSLÚCIDO
     (`rgba(255,255,255,0.5)`, pensado para apoyarse sobre el fondo blanco
     de la página normal). Acá el fondo detrás es negro puro (arriba) — ese
     blanco translúcido se ve gris/caqui en vez de blanco limpio (reportado
     por Daniel: "se ve diferente estilo de tarjeta, de otros colores").
     Se fuerza una versión opaca solo dentro de este wrapper — con
     `!important` porque `:root[data-theme="dark"] .app.lesson-cult` (más
     específico que una simple clase) redefine `--chrome-solid` y, sin esto,
     esa regla gana y el fix no se nota en modo oscuro. */
  --chrome:#f7f6f2 !important; --chrome-solid:#f7f6f2 !important;
  --card:#f7f6f2 !important; --card2:#efeee7 !important;
  --fill:#e9e8e2 !important; --fill2:#eeede7 !important;
  --hair:rgba(0,0,0,.12) !important; --hair-soft:rgba(0,0,0,.08) !important;
}
.guion-activa .nota,.guion-activa .numbloque,.guion-activa .otra{display:none}
.guion-activa .g{width:min(1240px,95vw);margin:auto;border:none;border-radius:22px;box-shadow:none;max-height:100%;overflow-y:auto}
.guion-activa .profe{font-size:25px;min-height:146px;padding:30px 44px}
.guion-activa .fila{font-size:clamp(26px,3.6vw,44px);grid-template-columns:40px 1fr auto 1fr}
.guion-activa .fila.fila-md{font-size:clamp(19px,2.9vw,32px)}
.guion-activa .fila.fila-sm{font-size:clamp(15px,2.3vw,24px)}
.guion-activa .tablero{padding:38px 30px 32px}
.guion-activa .pie{opacity:.22;transition:opacity .2s}
.guion-activa .pie:hover{opacity:1}
.salir{
  position:fixed;top:14px;right:14px;z-index:99999;display:none;
  align-items:center;gap:7px;
  background:rgba(255,255,255,.1);color:#fff;border:none;border-radius:9px;
  padding:8px 13px;font:500 13px/1 inherit;cursor:pointer}
.guion-activa .salir{display:flex}
/* La X es el blanco táctil real: 44px es el mínimo recomendado para el dedo,
   el padding del botón la completa. El texto "Esc" es una pista de más,
   no el único disparador — por eso no depende de teclado para cerrarse. */
.salir-x{
  width:28px;height:28px;flex:0 0 auto;border-radius:50%;
  background:rgba(255,255,255,.14);display:grid;place-items:center;
  font-size:15px;line-height:1}
.salir-txt{white-space:nowrap}
@media (max-width:640px){
  .salir{padding:11px;border-radius:50%}
  .salir-txt{display:none}
  .guion-activa{padding:0}
  .guion-activa .g{width:100%;max-width:100%;border-radius:0}
  .guion-activa .profe{font-size:17px;padding:18px 20px;min-height:auto}
  .guion-activa .fila{font-size:clamp(18px,6.2vw,26px);grid-template-columns:26px 1fr auto 1fr}
  .guion-activa .fila.fila-md{font-size:clamp(14px,5vw,19px)}
  .guion-activa .fila.fila-sm{font-size:clamp(11px,4vw,15px)}
  .guion-activa .tablero{padding:18px 14px 14px}
  .guion-activa .mockbar{padding:12px 16px}
}

.otra{margin-top:34px;font-size:14.5px;color:var(--label3);line-height:1.68}
.otra b{color:var(--label2)}
.otra code{font:600 13px var(--mono);background:var(--fill2);padding:2px 5px;border-radius:5px}

/* ============================================================
   PIZARRA MAC-STYLE OVERRIDES (All-in-One Card)
   ============================================================ */
.pizarra-mac.g {
  /* Inherits everything from .g in index.html */
  box-shadow:var(--sh-raise), inset 0 1px 1px rgba(255,255,255,0.1);
}

.pizarra-mac .mockbar {
  display: flex; align-items: center; padding: 14px 20px;
  background: var(--fill2); border-bottom: 1px solid var(--hair-soft);
}
.pizarra-mac .mac-dots { display: flex; gap: 8px; flex: 1; }
.pizarra-mac .mac-dots i { width: 12px; height: 12px; border-radius: 50%; display: block; }
.pizarra-mac .mac-dots i:nth-child(1) { background: #ff5f56; }
.pizarra-mac .mac-dots i:nth-child(2) { background: #ffbd2e; }
.pizarra-mac .mac-dots i:nth-child(3) { background: #27c93f; }

.pizarra-mac .cerrada { padding: 32px 20px; justify-content: center; background: transparent; border-bottom: none; }
.pizarra-mac .cerrada .play { width: 44px; height: 44px; font-size: 16px; background: var(--fill2); color: var(--label); transition: background 0.2s; }
.pizarra-mac .cerrada:hover .play { background: var(--fill); }

.pizarra-mac .cab { padding: 24px 32px 0; border-bottom: none; }
.pizarra-mac .cab .tit { font-size: 16px; color: var(--label); }
.pizarra-mac .cab .prob { font-size: 14px; color: var(--label3); }

.pizarra-mac .tablero { padding: 20px 48px 16px; }

.pizarra-mac .profe {
  background: transparent; border-bottom: none; padding: 0 48px 32px;
  min-height: auto; font-size: 16.5px; color: var(--label2); display: block;
  position: relative; z-index: 8; isolation: isolate;
}
.pizarra-mac .profe p{display:block;position:static;margin:0;max-width:none}
/* `q` también se usa en otros bloques de la app. Dentro del subtítulo solo
   marca una palabra: nunca debe convertirse en una caja ni alterar el flujo. */
.pizarra-mac .profe .q{
  display:inline;position:static;margin:0;padding:0;border:0;
  background:none;box-shadow:none;color:var(--warn);font-weight:600;
}

.pizarra-mac .pie { background: var(--fill2); border-top: 1px solid var(--hair-soft); }
.pizarra-mac .btn { background: var(--card); border: 1px solid var(--hair); color: var(--label); }
.pizarra-mac .btn:hover:not(:disabled) { background: var(--fill2); }
.pizarra-mac .btn.pri { background: var(--accent); border-color: transparent; color: #fff; }

.pizarra-mac .pip { width: 4px; height: 13px; border-radius: 2px; }
.pizarra-mac .pip.on { width: 4px; height: 20px; background: var(--accent); }

.pizarra-mac .prob-note {
  background: rgba(255, 204, 0, 0.08); 
  color: #ffcc00;
  padding: 12px 24px;
  border-radius: 8px;
  margin: 16px 48px 0;
  font-size: 14px;
  font-weight: 500;
  border-left: 3px solid #ffcc00;
}

.guion-activa .pizarra-mac.g {
  /* Restored default behavior: centered card */
}

@keyframes fadeText {
  0% { opacity: 0; transform: translateY(4px); }
  100% { opacity: 1; transform: translateY(0); }
}
.pizarra-mac .profe.fade-text {
  animation: fadeText 0.25s ease-out forwards;
}

/* ============================================================
   CAPA DE EFECTOS EXPLICATIVOS (PizarraFX.jsx)
   ------------------------------------------------------------
   Pedido de Daniel: el tablero mostraba el RESULTADO de cada
   paso, pero no explicaba la operación mientras el audio la
   contaba. Esta capa se dibuja ENCIMA del tablero y muestra en
   grande el concepto ("está sumando → la contraria es restar"),
   la cuenta que se resuelve ("12 − 5 = 7") y el tachado de los
   términos que se cancelan.
   ============================================================ */
.tablero{position:relative;min-height:180px;
  display:flex;flex-direction:column;justify-content:center}
.guion-activa .tablero{min-height:260px}

/* Los efectos explicativos NO tapan el tablero: viven en una banda arriba,
   sobre el área que el propio tablero reserva. Antes se centraban sobre las
   filas con un velo oscuro encima y el resultado era que la cuenta quedaba
   cruzada por las letras/cartelones — Daniel: «todo se interpone, todo se
   cruza». La única excepción es el sello de veredicto, que sí es un sello y
   va centrado (.fx-capa-sello). */
.fx-capa{
  position:absolute;left:0;right:0;top:0;z-index:5;
  display:flex;align-items:flex-start;justify-content:center;
  padding-top:10px;
  pointer-events:none;
  background:none}

.fx-capa-flecha{background:none;backdrop-filter:none}

.fx-capa-sello{
  inset:0;align-items:center;padding-top:0;
  background:color-mix(in srgb, var(--bg-deep) 62%, transparent);
  backdrop-filter:blur(2px)}

.fx-concepto{text-align:center;line-height:1}
.fx-simbolo{
  font:800 clamp(54px,13vw,86px)/1 var(--mono);
  letter-spacing:-2px;
  filter:drop-shadow(0 0 22px currentColor)}
.fx-label{
  margin-top:10px;
  font:700 clamp(13px,3vw,17px)/1 var(--mono);
  text-transform:uppercase;letter-spacing:2px;opacity:.9}

/* nowrap a propósito: «4 × 4 = 16» partiéndose en dos líneas se ve roto.
   Si no entra, el texto se achica (clamp) antes que partirse. */
.fx-operacion{
  display:flex;align-items:center;gap:7px;flex-wrap:nowrap;
  justify-content:center;max-width:94%;
  font:700 clamp(17px,4.4vw,32px)/1 var(--mono);
  color:var(--label);white-space:nowrap;
  padding:8px 14px;border-radius:12px;
  background:color-mix(in srgb, var(--bg-deep) 92%, transparent);
  box-shadow:inset 0 0 0 1px var(--hair)}
.fx-parte{display:inline-block}
.fx-parte.res{
  color:var(--ok);
  padding:2px 12px;border-radius:10px;
  background:var(--ok-bg);box-shadow:inset 0 0 0 1.5px var(--ok-brd)}

.fx-flecha{
  font:800 clamp(34px,8vw,52px)/1 var(--mono);
  color:var(--accent);
  filter:drop-shadow(0 0 14px var(--accent))}

/* el tachado que se dibuja sobre un token que se cancela */
.t-tachon{
  position:absolute;left:4%;right:4%;top:50%;height:3px;
  transform-origin:left center;
  background:var(--err);border-radius:2px;
  box-shadow:0 0 8px var(--err);
  pointer-events:none}
.t.t-cancelando{color:var(--err);background:var(--err-bg);
  box-shadow:inset 0 0 0 1px var(--err-brd)}

/* ============================================================
   Acercamiento del tablero. El zoom se aplica a las filas, no al
   contenedor, para que la capa de marcas mida posiciones visuales
   reales sin tener que dividir por el factor de escala.
   ============================================================ */
.tablero-zoom{transform-origin:center center;will-change:transform}

/* ============================================================
   PEMDAS en pantalla, con las letras que importan encendidas.
   ============================================================ */
.fx-pemdas-wrap{text-align:center}
.fx-pemdas{display:flex;gap:clamp(4px,1.6vw,12px);justify-content:center}
.fx-letra{
  display:inline-block;
  font:800 clamp(20px,5vw,34px)/1 var(--mono);
  color:var(--label);
  padding:4px 7px;border-radius:8px}
.fx-letra.on{
  color:var(--accent);
  background:var(--accent-soft);
  box-shadow:inset 0 0 0 2px var(--accent);
  filter:drop-shadow(0 0 16px var(--accent))}
.fx-pemdas-label{
  margin-top:14px;
  font:700 clamp(12px,3vw,16px)/1.35 var(--mono);
  text-transform:uppercase;letter-spacing:1.5px;
  color:var(--label);opacity:.92}

/* ============================================================
   El sello de correcto / incorrecto.
   ============================================================ */
/* Insignia, no sello: se lee al lado de la cuenta y no la tapa. */
.fx-veredicto-chip{
  display:inline-flex;align-items:center;gap:9px;
  padding:8px 15px;border-radius:999px;
  background:color-mix(in srgb, var(--bg-deep) 92%, transparent)}
.fx-veredicto-chip.malo{box-shadow:inset 0 0 0 1.5px var(--err)}
.fx-veredicto-chip.bueno{box-shadow:inset 0 0 0 1.5px var(--ok)}
.fx-veredicto-ico{
  font:800 clamp(19px,4.4vw,26px)/1 var(--mono);
  filter:drop-shadow(0 0 10px currentColor)}
.fx-veredicto-txt{
  font:800 clamp(11px,2.6vw,14px)/1 var(--mono);
  text-transform:uppercase;letter-spacing:2px;color:var(--label)}

/* ============================================================
   El clon que baja de una fila a la siguiente: «se duplica, se
   sombrea y baja». Vuela por encima del tablero sin capturar
   clics y se apaga al aterrizar.
   ============================================================ */
.fx-vuelos{position:absolute;inset:0;z-index:7;pointer-events:none}
.fx-vuelo{
  position:absolute;top:0;left:0;
  display:flex;align-items:center;justify-content:center;
  font:600 clamp(20px,4.4vw,30px)/1.3 var(--mono);
  color:var(--accent);
  border-radius:8px;
  background:var(--accent-soft);
  box-shadow:0 0 0 1.5px var(--accent), 0 0 22px var(--accent)}

/* ============================================================
   Marcas ancladas a un token concreto: etiqueta + línea guía +
   halo alrededor del token. A diferencia del resto de efectos,
   esta capa NO tapa el tablero: lo señala.
   ============================================================ */
/* El tablero recorta (overflow:hidden), así que necesita alto de sobra para
   que las etiquetas escalonadas por encima de la expresión no queden
   cortadas. Solo se reserva cuando de verdad hay marcas en el paso. */
.tablero:has(.fx-marca){min-height:250px;padding-top:92px}
.guion-activa .tablero:has(.fx-marca){min-height:320px;padding-top:104px}

/* Mismo criterio para los cartelones de la banda superior (opera, pemdas):
   el tablero les reserva sitio arriba en vez de dejar que se sienten encima
   de la cuenta. El sello de veredicto no cuenta: ese sí va centrado. */
/* Solo lo que el cartelón necesita de verdad. Reservar de más aprieta el
   tablero cuando la pizarra ya acumuló varias filas. */
.tablero:has(.fx-capa:not(.fx-capa-sello)){padding-top:66px}
.tablero:has(.fx-pemdas){padding-top:88px}
.guion-activa .tablero:has(.fx-capa:not(.fx-capa-sello)){padding-top:76px}
.guion-activa .tablero:has(.fx-pemdas){padding-top:100px}

.fx-marcas{position:absolute;inset:0;z-index:6;pointer-events:none}
/* El ancla posiciona (transform propio del CSS); el hijo .fx-marca es el que
   anima. Van separados porque motion escribe `transform` inline y pisaría el
   translate de posicionamiento. */
.fx-marca-ancla{position:absolute;transform:translate(-50%,-100%)}
.fx-marca{
  display:flex;flex-direction:column;align-items:center;
  padding-bottom:4px}
.fx-marca-txt{
  font:700 clamp(10px,2.4vw,13px)/1 var(--mono);
  text-transform:uppercase;letter-spacing:1.2px;
  padding:5px 10px;border-radius:8px;white-space:nowrap;
  color:var(--accent);
  background:color-mix(in srgb, var(--bg-deep) 86%, transparent);
  box-shadow:inset 0 0 0 1.5px var(--accent)}
.fx-marca-linea{
  width:2px;height:10px;border-radius:1px;
  background:var(--accent)}
.tono-warn .fx-marca-txt{color:var(--warn);box-shadow:inset 0 0 0 1.5px var(--warn)}
.tono-warn .fx-marca-linea{background:var(--warn)}
.tono-ok .fx-marca-txt{color:var(--ok);box-shadow:inset 0 0 0 1.5px var(--ok)}
.tono-ok .fx-marca-linea{background:var(--ok)}

/* mismo patrón ancla/animado que las marcas */
.fx-halo-ancla{position:absolute;pointer-events:none;display:block}
.fx-halo{
  position:absolute;inset:0;border-radius:10px;pointer-events:none;
  box-shadow:0 0 0 2px var(--accent), 0 0 18px var(--accent);
  opacity:.9}
.fx-halo.tono-warn{box-shadow:0 0 0 2px var(--warn), 0 0 18px var(--warn)}
.fx-halo.tono-ok{box-shadow:0 0 0 2px var(--ok), 0 0 18px var(--ok)}

@media(prefers-reduced-motion:reduce){
  .fx-capa,.fx-simbolo,.fx-operacion{animation:none!important}
  .tablero-zoom{transform:none!important}
  .fx-letra,.fx-halo{animation:none!important}
}
