@charset "utf-8";

/* ═══════════════════════════════════════════════════════════════════════
   PÓRTICOS · sistema visual

   La idea: una mesa de dibujo, no un panel de control. El dibujo manda y se
   lleva el espacio; el formulario es denso, para llenarlo con el teclado.

   La paleta de acento NO se inventa aquí. Son los nueve colores con los que
   el núcleo pinta los diagramas, que app.js lee de /api/paleta y escribe en
   estas variables al arrancar. Los valores de abajo son solo el respaldo por
   si la petición falla. Así una carga puntual es del mismo rojo en el
   formulario y en la figura, y no pueden separarse nunca.
   ═══════════════════════════════════════════════════════════════════════ */

:root {
  /* — Acento: espejo de core/frame_core.py — */
  --c-puntual:     #8B0000;
  --c-distribuida: #0B3D0B;
  --c-lineal:      #4B0082;
  --c-momento:     #1F4E79;
  --c-interno:     #7A3E00;
  --c-reaccion:    #0B5C8E;
  --c-resultante:  #B45F06;
  --c-cota:        #555555;
  --c-barra:       #111111;

  /* — Superficie: papel cálido, no blanco de pantalla — */
  --fondo:      #F7F5F1;
  --panel:      #FFFFFF;
  --panel-velo: rgba(255, 255, 255, 0.72);
  --hundido:    #F1EEE8;
  --tinta:      #16181A;
  --tinta-2:    #55595E;
  --tinta-3:    #8A8F95;
  --linea:      #E2DED6;
  --linea-2:    #EFECE6;
  --realce:     rgba(11, 92, 142, 0.08);
  /* La mesa donde reposa el plano: casi papel, para que el borde de la
     hoja se insinúe en vez de recortarse. */
  --mesa:       #F2F0EB;
  --mesa-punto: rgba(90, 80, 65, 0.09);

  /* — Sombras: cortas y con poca opacidad; el papel apenas levanta — */
  --sombra-1: 0 1px 2px rgba(30, 25, 15, 0.05);
  --sombra-2: 0 1px 2px rgba(30, 25, 15, 0.06), 0 4px 12px rgba(30, 25, 15, 0.06);
  --sombra-3: 0 2px 4px rgba(30, 25, 15, 0.06), 0 12px 32px rgba(30, 25, 15, 0.10);

  /* — Curvas: LA LISTA ES CERRADA —
     No son «curvas propias»: son las mismas que define el sistema de diseño
     del sitio, en `pagina web/DESIGN.md`, sección 5. Ahí están como
     `--ease-out` y `--ease-in-out`.

     NO SE INVENTAN CURVAS NUEVAS. Ya pasó: se añadieron dos a ojo para una
     animación y el archivo acabó con cuatro donde debía haber dos, sin que
     nadie se enterara. Si una animación parece pedir otra curva, casi siempre
     lo que pide es otra duración.

     `ease-in` está prohibido en interfaz: retrasa justo el instante que el
     usuario está mirando. */
  --sal:     cubic-bezier(0.23, 1, 0.32, 1);      /* entra / responde */
  --vaiven:  cubic-bezier(0.77, 0, 0.175, 1);     /* se mueve en pantalla */

  /* — Tiempos: nada de interfaz pasa de 300 ms —
     Tabla de DESIGN.md §5: pulsación 140, tooltip 160, desplegable 200,
     modal 280. Lo que dura más no es respuesta de interfaz sino animación
     explicativa —el paracaídas de la descarga— y eso sí puede pasarse. */
  --t-pulso: 140ms;
  --t-ui:    180ms;
  --t-panel: 260ms;

  --radio:   9px;
  --radio-s: 6px;

  --tipo: ui-sans-serif, system-ui, -apple-system, "Segoe UI Variable Text",
          "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --tipo-num: ui-monospace, "Cascadia Mono", "SF Mono", "Segoe UI Mono",
              "Roboto Mono", Menlo, Consolas, monospace;

  /* Ancho comun de los dos flotantes de la esquina: la barra de zoom y la
     tarjeta de descarga. Van uno encima del otro, y con anchos distintos se
     veia desalineado. Sale de lo que mide la barra por su contenido (179 px,
     estable: el porcentaje no la ensancha). */
  --ancho-flotante: 179px;

  --columna: 384px;
  --barra-alto: 56px;

  color-scheme: light dark;
}

/* LOS CONTROLES QUE PINTA EL NAVEGADOR, NO NOSOTROS
   Las flechitas de subir y bajar de un campo numérico, las barras de
   desplazamiento y el calendario de una fecha no leen nuestras
   variables: leen `color-scheme`. Con «light dark» siguen al sistema, así
   que al forzar el tema con el botón se quedaban al revés —flechas
   negras sobre un formulario claro, y al contrario— aunque todo lo demás
   de la página hubiera cambiado. Elegir el tema a mano tiene que
   decírselo también al navegador. */
:root[data-tema="claro"]  { color-scheme: light; }
:root[data-tema="oscuro"] { color-scheme: dark; }

:root[data-tema="oscuro"],
:root:not([data-tema="claro"]) {
  /* Se redefine dentro del bloque de abajo; aquí no se pisa nada. */
}

@media (prefers-color-scheme: dark) {
  :root:not([data-tema="claro"]) {
    --fondo:      #131416;
    --panel:      #1B1D1F;
    --panel-velo: rgba(27, 29, 31, 0.72);
    --hundido:    #202325;
    --tinta:      #E9E7E4;
    --tinta-2:    #A3A7AB;
    --tinta-3:    #71767B;
    --linea:      #2E3134;
    --linea-2:    #26292B;
    --realce:     rgba(96, 173, 224, 0.12);
    /* En oscuro la mesa se aclara mucho: el salto de la mesa al papel
       blanco es lo que deslumbraba. */
    --mesa:       #1F2225;
    --mesa-punto: rgba(255, 255, 255, 0.055);
    --sombra-1: 0 1px 2px rgba(0, 0, 0, 0.35);
    --sombra-2: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 12px rgba(0, 0, 0, 0.32);
    --sombra-3: 0 2px 4px rgba(0, 0, 0, 0.45), 0 12px 32px rgba(0, 0, 0, 0.45);
    /* Los colores de tinta se aclaran para sobrevivir al fondo oscuro.
       Los del dibujo NO se tocan: la hoja sigue siendo blanca. */
    --c-puntual:     #E06B62;
    --c-distribuida: #64B96B;
    --c-lineal:      #A98CE8;
    --c-momento:     #6BA9DE;
    --c-interno:     #D19A5C;
    --c-reaccion:    #5EB2E0;
    --c-resultante:  #E39B4E;
    --c-cota:        #9AA0A6;
    --c-barra:       #D8D6D3;
  }
}

:root[data-tema="oscuro"] {
  --fondo:      #131416;
  --panel:      #1B1D1F;
  --panel-velo: rgba(27, 29, 31, 0.72);
  --hundido:    #202325;
  --tinta:      #E9E7E4;
  --tinta-2:    #A3A7AB;
  --tinta-3:    #71767B;
  --linea:      #2E3134;
  --linea-2:    #26292B;
  --realce:     rgba(96, 173, 224, 0.12);
  --mesa:       #1F2225;
  --mesa-punto: rgba(255, 255, 255, 0.055);
  --sombra-1: 0 1px 2px rgba(0, 0, 0, 0.35);
  --sombra-2: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 12px rgba(0, 0, 0, 0.32);
  --sombra-3: 0 2px 4px rgba(0, 0, 0, 0.45), 0 12px 32px rgba(0, 0, 0, 0.45);
  --c-puntual:     #E06B62;
  --c-distribuida: #64B96B;
  --c-lineal:      #A98CE8;
  --c-momento:     #6BA9DE;
  --c-interno:     #D19A5C;
  --c-reaccion:    #5EB2E0;
  --c-resultante:  #E39B4E;
  --c-cota:        #9AA0A6;
  --c-barra:       #D8D6D3;
}

/* ─── Base ────────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  font-family: var(--tipo);
  font-size: 14px;
  line-height: 1.5;
  color: var(--tinta);
  background: var(--fondo);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow: hidden;
}

h1, h2, h3 { margin: 0; font-weight: 600; letter-spacing: -0.011em; }

button, input, select { font: inherit; color: inherit; }

/* Todo número se alinea en columna: es una herramienta de cálculo. */
.num, input[inputmode="decimal"], .valor, .sello, .boton-escala {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

:focus-visible {
  outline: 2px solid var(--c-reaccion);
  outline-offset: 2px;
  border-radius: var(--radio-s);
}

.saltar {
  position: absolute; left: 8px; top: -60px; z-index: 100;
  padding: 8px 14px; border-radius: var(--radio-s);
  background: var(--panel); color: var(--tinta);
  box-shadow: var(--sombra-2); text-decoration: none;
  transition: top var(--t-ui) var(--sal);
}
.saltar:focus { top: 8px; }

/* ─── Barra superior ──────────────────────────────────────────────── */

.barra {
  position: fixed; inset: 0 0 auto 0; z-index: 30;
  height: var(--barra-alto);
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 0 16px;
  background: var(--panel-velo);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border-bottom: 1px solid var(--linea);
}

.marca { display: flex; align-items: center; gap: 10px; min-width: 0; }

/* CAMBIAR DE HERRAMIENTA
   Los dos solvers viven en el mismo servidor y hasta ahora no había forma de
   pasar de uno a otro: quien entraba a pórticos no sabía que existían las
   armaduras. El enlace es RELATIVO a propósito, igual que las llamadas a la
   API, para que funcione tanto en local («/») como servido bajo
   «/herramientas/porticos/». */
.cambiar {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px;
  border: 1px solid var(--linea);
  border-radius: 999px;
  color: var(--tinta-2);
  font-size: 12px; text-decoration: none; white-space: nowrap;
  transition: border-color var(--t-ui) var(--sal), color var(--t-ui) var(--sal);
}
.cambiar svg { width: 14px; height: 14px; flex: none; }
@media (hover: hover) and (pointer: fine) {
  .cambiar:hover { border-color: var(--tinta-3); color: var(--tinta); }
}
/* En estrecho la barra ya va justa: se queda el icono, que con el title basta. */
/* EL ORDEN EN QUE SE CEDE SITIO, MEDIDO
   La barra de la izquierda pide 621 px con todas sus etiquetas y solo los
   tiene por encima de ~1400. Por debajo se queda corta, y como recorta con
   `overflow: hidden` lo que sobra DESAPARECE SIN AVISO: a 1100 px se comían
   51 px de «Armaduras» y los 131 de las redes enteras, sin que nada lo
   indicara. Un enlace que se esfuma es peor que uno que se estrecha.

   Ahora se suelta lastre a tiempo y en un orden pensado: primero las
   palabras de los enlaces a las otras herramientas (quedan sus iconos, que
   siguen siendo pulsables), luego la de «volver», y las redes las últimas,
   porque son parte de lo que se está promocionando. */
@media (max-width: 1300px) { .cambiar span { display: none; } }

.marca-signo { width: 26px; height: 26px; flex: none; color: var(--tinta); }

.marca-texto {
  display: flex; flex-direction: column; line-height: 1.15;
  min-width: 0; white-space: nowrap;
}
.marca-texto h1 {
  margin: 0;
  font-size: 15px; font-weight: 650;
  letter-spacing: -0.02em;             /* texto grande: tracking negativo */
}
.marca-texto span {
  font-size: 10.5px; color: var(--tinta-3);
  letter-spacing: 0.06em;              /* texto pequeño: tracking positivo */
  text-transform: uppercase;
}

/* El nombre de la herramienta se retira por partes.
   VA AQUÍ, DESPUÉS de las reglas de arriba: puestas antes, `display: flex`
   de `.marca-texto` las anulaba por orden de cascada, con la misma
   especificidad. Pasó exactamente eso.

   Con el enlace a la otra herramienta la barra ganó un elemento y, entre 720
   y 900 px, la marca se quedaba en ONCE píxeles de ancho: su texto se salía
   de la caja y se leía encima de lo de al lado. `min-width: 0` la deja
   encogerse hasta nada, así que hay que quitarla antes de llegar a eso. */
@media (max-width: 1000px) { .marca-texto span { display: none; } }
@media (max-width: 880px) { .marca-texto { display: none; } }

.barra-acciones { display: flex; align-items: center; gap: 8px; }

.campo-inline { display: flex; align-items: center; gap: 7px; }
.campo-inline .etiqueta-mini { margin: 0; }

/* ─── Controles ───────────────────────────────────────────────────── */

.etiqueta-mini {
  display: block;
  font-size: 10.5px; font-weight: 600;
  letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--tinta-3);
  margin-bottom: 5px;
}

.control {
  appearance: none;
  height: 32px; padding: 0 26px 0 10px;
  border: 1px solid var(--linea);
  border-radius: var(--radio-s);
  background: var(--panel);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='7' viewBox='0 0 10 7'%3E%3Cpath d='M1 1.5 5 5.5 9 1.5' fill='none' stroke='%238A8F95' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 9px center;
  font-size: 13px;
  cursor: pointer;
  transition: border-color var(--t-ui) var(--sal), background-color var(--t-ui) var(--sal);
}
@media (hover: hover) and (pointer: fine) {
  .control:hover { border-color: var(--tinta-3); }
}

/* Campo escribible con sugerencias: sin flecha de lista, porque no lo es. */
.control-texto {
  padding: 0 10px;
  background-image: none;
  cursor: text;
  min-width: 0;
}
.control-texto::-webkit-calendar-picker-indicator { display: none; }
.control-texto:focus { border-color: var(--c-reaccion); outline: none; }

.boton {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  height: 32px; padding: 0 13px;
  border: 1px solid var(--linea);
  border-radius: var(--radio-s);
  background: var(--panel);
  font-size: 13px; font-weight: 550;
  cursor: pointer;
  white-space: nowrap;
  /* Solo transform y opacity se mueven: van por GPU. */
  transition: transform var(--t-pulso) var(--sal),
              background-color var(--t-ui) var(--sal),
              border-color var(--t-ui) var(--sal),
              opacity var(--t-ui) var(--sal);
}
/* La respuesta llega al PULSAR, no al soltar. */
.boton:active { transform: scale(0.97); }
.boton:disabled { opacity: 0.45; cursor: default; }
.boton:disabled:active { transform: none; }

@media (hover: hover) and (pointer: fine) {
  .boton:hover:not(:disabled) { background: var(--hundido); border-color: var(--tinta-3); }
}

.boton-icono { width: 32px; padding: 0; }

/* El texto de los botones de la barra se retira cuando no cabe, pero
   el icono y su etiqueta emergente se quedan. */
@media (max-width: 1080px) { .solo-ancho { display: none; } }
.boton-icono svg { width: 17px; height: 17px; }

.boton-primario {
  background: var(--tinta); color: var(--fondo);
  border-color: var(--tinta);
}
@media (hover: hover) and (pointer: fine) {
  .boton-primario:hover:not(:disabled) { background: var(--tinta-2); border-color: var(--tinta-2); }
}

.boton-ayuda {
  background: rgba(209, 154, 92, 0.12);
  color: var(--c-interno);
  border-color: rgba(209, 154, 92, 0.38);
  font-weight: 600;
}
@media (hover: hover) and (pointer: fine) {
  .boton-ayuda:hover:not(:disabled) {
    background: rgba(209, 154, 92, 0.22);
    border-color: var(--c-interno);
  }
}
@media (max-width: 1180px) { .texto-ayuda-largo { display: none; } }
@media (max-width: 960px) { .solo-ancho-ayuda { display: none; } }

.icono-luna { display: none; }
:root[data-tema="oscuro"] .icono-sol { display: none; }
:root[data-tema="oscuro"] .icono-luna { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-tema="claro"]) .icono-sol { display: none; }
  :root:not([data-tema="claro"]) .icono-luna { display: block; }
}

/* ─── Estructura ──────────────────────────────────────────────────── */

.taller {
  --ancho-modelo: minmax(300px, var(--columna));
  display: grid;
  /* La columna cede antes de romper: a 900 px sigue habiendo dos paneles. */
  grid-template-columns: var(--ancho-modelo) minmax(0, 1fr);
  height: 100%;
  padding-top: var(--barra-alto);
  transition: grid-template-columns var(--t-ui) var(--sal);
}

.taller.plegado {
  --ancho-modelo: 0px;
}

.modelo {
  border-right: 1px solid var(--linea);
  background: var(--panel);
  min-height: 0;
  display: flex; flex-direction: column;
  overflow: hidden;
  transition: opacity var(--t-ui) var(--sal), visibility var(--t-ui) var(--sal);
}

.taller.plegado .modelo {
  opacity: 0;
  visibility: hidden;
}

.palanca-modelo {
  position: absolute;
  top: 50%;
  left: 0;
  transform: translateY(-50%);
  width: 24px;
  height: 56px;
  background: var(--panel);
  border: 1px solid var(--linea);
  border-left: none;
  border-radius: 0 var(--radio) var(--radio) 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--tinta-2);
  cursor: pointer;
  z-index: 100;
  transition: background var(--t-ui) ease, color var(--t-ui) ease;
  box-shadow: 2px 0 4px rgba(0,0,0,0.03);
}
@media (hover: hover) and (pointer: fine) {
  .palanca-modelo:hover { background: var(--hundido); color: var(--tinta); }
}

.modelo-desliz {
  overflow-y: auto; overscroll-behavior: contain;
  padding: 4px 0 40px;
  /* Difumina el borde superior al desplazar, en vez de una raya dura. */
  mask-image: linear-gradient(to bottom, transparent 0, #000 12px);
}

/* ─── Grupos del formulario ───────────────────────────────────────── */

.grupo { padding: 14px 16px; border-bottom: 1px solid var(--linea-2); }
.grupo:last-child { border-bottom: 0; }

.grupo-titulo {
  display: flex; align-items: center; gap: 8px;
  font-size: 11px; font-weight: 650;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--tinta-2);
  margin-bottom: 10px;
}

.punto {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--punto); flex: none;
}

.contador {
  margin-left: auto;
  min-width: 20px; padding: 0 6px; height: 18px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 9px;
  background: var(--hundido); color: var(--tinta-3);
  font-size: 11px; font-weight: 600; letter-spacing: 0;
  font-variant-numeric: tabular-nums;
}

.campo-ancho { display: block; margin-bottom: 10px; }
.campo-ancho .control { width: 100%; }

.unidades { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

/* Se avisa solo al cambiar de sistema, y se retira: es una aclaración, no
   una advertencia permanente. */
.nota-unidades {
  margin: 9px 0 0; font-size: 11.5px; line-height: 1.45;
  color: var(--tinta-3);
  animation: entra-nota 200ms var(--sal) both;
}
.nota-unidades[hidden] { display: none; }
@keyframes entra-nota { from { opacity: 0; } to { opacity: 1; } }
.unidades .control { width: 100%; }

/* ─── Rejillas de datos ───────────────────────────────────────────── */

.rejilla { font-size: 13px; }

.rejilla-cabecera {
  display: grid; gap: 6px;
  padding: 0 4px 6px;
  font-size: 10px; font-weight: 600;
  letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--tinta-3);
}
.rejilla-cabecera .num { text-align: right; padding-right: 8px; }

.rejilla-nodos .rejilla-cabecera,
.rejilla-nodos .fila        { grid-template-columns: 1fr 1fr 1fr 26px; }
.rejilla-barras .rejilla-cabecera,
.rejilla-barras .fila       { grid-template-columns: 1fr 1fr 1fr 26px; }
.rejilla-apoyos .rejilla-cabecera,
.rejilla-apoyos .fila       { grid-template-columns: 1fr 1.5fr 46px 26px; }

/* LAS DOS REJILLAS DE LA VIGA
   Una rótula interna solo tiene nombre y posición. Una carga tiene tipo,
   los dos extremos del tramo y su valor —dos valores si es triangular, que
   comparten la última casilla—, así que pide una columna más. */
/* LAS REJILLAS DE VIGAS LLEVAN NOMBRE PROPIO
   Se llamaban como las de pórticos —`.rejilla-rotulas`—, y la regla de
   pórticos, que va más abajo, ganaba: la rótula de una viga se quedaba con
   dos columnas en vez de tres, la x en 26 px y el botón de quitar en una
   segunda línea. */
.rejilla-rotulas-viga .rejilla-cabecera,
.rejilla-rotulas-viga .fila { grid-template-columns: minmax(0, 1fr) 84px 26px; }
/* Nombre, tipo y posición. `minmax(0, …)` porque un `select` con
   «empotramiento» pide más ancho del que tiene y, sin eso, empujaba la x
   fuera del panel. */
.rejilla-apoyos-viga .rejilla-cabecera,
.rejilla-apoyos-viga .fila  { grid-template-columns: minmax(0, .8fr) minmax(0, 1.3fr) 72px 26px; }
.rejilla-apoyos-viga .fila > *,
.rejilla-rotulas-viga .fila > * { min-width: 0; }

/* Una tarjeta por carga, con solo los campos de su tipo. */
.cargas-viga { display: flex; flex-direction: column; gap: 6px; margin-bottom: 8px; }
.carga-viga {
  display: flex; flex-direction: column; gap: 6px;
  padding: 6px 8px 8px;
  border: 1px solid var(--linea-2); border-radius: var(--radio-s);
}
.carga-viga-cabeza { display: flex; align-items: center; justify-content: space-between; }
.carga-viga-campos {
  display: grid; gap: 6px;
  grid-template-columns: repeat(auto-fit, minmax(76px, 1fr));
}
.campo-carga { display: flex; flex-direction: column; min-width: 0; }
.campo-carga .etiqueta-mini {
  margin-bottom: 3px; letter-spacing: .03em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.campo-carga .celda { width: 100%; min-width: 0; }
/* La longitud de la viga: una casilla como las demás, no un desplegable. */
.campo-largo { width: 100%; height: 32px; font-size: 13px; }
/* El tipo no se edita: es el título de la tarjeta. */
.tipo-carga {
  display: flex; align-items: center;
  font-size: 11.5px; font-weight: 650; color: var(--tinta-2);
}
.anadir-cargas { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; }

/* Botón de giro del apoyo. Muestra el ángulo actual y suma un cuarto de vuelta
   en cada pulsación, así que es a la vez mando e indicador: sin el número, no
   habría forma de distinguir 0 de 180, que se dibujan distinto pero calculan
   igual. */
/* LAS DOS FLECHAS DE GIRAR UN APOYO
   Comparten el hueco de una sola casilla, así que ninguna puede pedir
   ancho propio: reparten el que haya. */
.giro-apoyo { display: inline-flex; gap: 2px; align-items: center; width: 100%; }
.giro-apoyo .boton-giro { width: auto; flex: 1; min-width: 0; padding: 0 2px; font-size: 13px; }

.boton-giro {
  height: 30px; width: 100%;
  display: inline-flex; align-items: center; justify-content: center; gap: 2px;
  font-size: 11.5px; font-variant-numeric: tabular-nums;
  border: 1px solid var(--linea); border-radius: 7px;
  background: var(--hundido); color: var(--tinta-2);
  cursor: pointer;
}
@media (hover: hover) and (pointer: fine) {
  .boton-giro:hover { background: var(--realce); color: var(--tinta); }
}
.boton-giro:focus-visible { outline: 2px solid var(--c-reaccion); outline-offset: 1px; }
.rejilla-rotulas .rejilla-cabecera,
.rejilla-rotulas .fila      { grid-template-columns: 1fr 26px; }
.rejilla-puntuales .rejilla-cabecera,
.rejilla-puntuales .fila    { grid-template-columns: 1fr .88fr .62fr .75fr .75fr 26px; }
.rejilla-distribuidas .rejilla-cabecera,
.rejilla-distribuidas .fila { grid-template-columns: 1.15fr .8fr .8fr .9fr .9fr 26px; }
.rejilla-momentos .rejilla-cabecera,
.rejilla-momentos .fila     { grid-template-columns: 1fr .95fr .7fr .95fr 26px; }

.rejilla-cuerpo { display: flex; flex-direction: column; gap: 4px; }

.fila {
  display: grid; gap: 6px; align-items: center;
  padding: 2px 4px;
  border-radius: var(--radio-s);
  transition: background-color var(--t-ui) var(--sal);
}
@media (hover: hover) and (pointer: fine) {
  .fila:hover { background: var(--hundido); }
}

/* Entra desde 0.98 y no desde cero: nada aparece de la nada. */
.fila[data-nueva] { animation: entra-fila var(--t-panel) var(--sal) both; }
@keyframes entra-fila {
  from { opacity: 0; transform: translateY(-4px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

.celda {
  width: 100%; height: 29px;
  padding: 0 8px;
  border: 1px solid transparent;
  border-radius: var(--radio-s);
  background: var(--hundido);
  font-size: 13px;
  transition: border-color var(--t-ui) var(--sal), background-color var(--t-ui) var(--sal);
}
@media (hover: hover) and (pointer: fine) {
  .celda:hover { border-color: var(--linea); }
}
.celda:focus { background: var(--panel); border-color: var(--c-reaccion); outline: none; }
.celda.num { text-align: right; font-family: var(--tipo-num); font-size: 12.5px; }
/* Una carga distribuida ocupa dos líneas: la de cifras y la que dice hacia
   dónde va y respecto de qué longitud se mide. La segunda decide si hay
   proyección, así que se deja a la vista y no escondida tras un desplegable. */
.fila-carga {
  border-radius: var(--radio-s);
  padding-bottom: 4px;
  transition: background-color var(--t-ui) var(--sal);
}
@media (hover: hover) and (pointer: fine) {
  .fila-carga:hover { background: var(--hundido); }
  .fila-carga:hover .fila:hover { background: transparent; }
}

.fila-detalle {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  padding: 2px 4px 0 4px;
}
.fila-detalle .celda { width: auto; flex: 1 1 118px; min-width: 0; height: 26px; font-size: 12px; }

/* Módulo y ángulo de una carga puntual: la letra delante identifica el dato
   sin gastar una fila de encabezados, y son cortos, así que ocupan menos
   espacio que los selectores que van al lado. */
.campito {
  display: inline-flex; align-items: center; gap: 5px;
  flex: 0 1 92px; min-width: 0;
}
.campito > span {
  font-size: 11.5px; color: var(--tenue, #7A7A7A);
  font-family: var(--tipo-num); flex: 0 0 auto;
}
.campito .celda { flex: 1 1 auto; }

.casilla {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 0 4px; height: 26px;
  font-size: 12px; color: var(--tinta-2);
  cursor: pointer; white-space: nowrap;
}
.casilla input { accent-color: var(--c-reaccion); margin: 0; cursor: pointer; }

/* Cuando hay proyección se dice cuánto vale realmente sobre la barra: es la
   cifra con la que se calcula, y verla evita la sorpresa. */
.proyectada {
  flex: 1 1 100%;
  padding: 1px 4px 0;
  font-size: 11.5px; color: var(--c-resultante);
  font-variant-numeric: tabular-nums;
}

.celda.inerte {
  opacity: 0.4; cursor: not-allowed; background: transparent;
}
.celda.mal { border-color: var(--c-puntual); background: color-mix(in srgb, var(--c-puntual) 7%, var(--hundido)); }

select.celda {
  appearance: none; cursor: pointer;
  padding-right: 17px;
  padding-left: 7px;
  text-overflow: ellipsis;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='9' height='6' viewBox='0 0 10 7'%3E%3Cpath d='M1 1.5 5 5.5 9 1.5' fill='none' stroke='%238A8F95' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 6px center;
}

.quitar {
  width: 24px; height: 24px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: var(--radio-s);
  background: transparent; color: var(--tinta-3);
  cursor: pointer; opacity: 0;
  transition: opacity var(--t-ui) var(--sal), transform var(--t-pulso) var(--sal),
              color var(--t-ui) var(--sal), background-color var(--t-ui) var(--sal);
}
.quitar:active { transform: scale(0.9); }
/* El foco de teclado va SUELTO y el hover tras la guarda: si se metieran
   los dos dentro, quien navega con el tabulador dejaria de ver el boton. */
.quitar:focus-visible { opacity: 1; }
@media (hover: hover) and (pointer: fine) { .fila:hover .quitar { opacity: 1; } }
@media (hover: none) { .quitar { opacity: 1; } }
@media (hover: hover) and (pointer: fine) {
  .quitar:hover { color: var(--c-puntual); background: color-mix(in srgb, var(--c-puntual) 10%, transparent); }
}
.quitar svg { width: 14px; height: 14px; }

.boton-anadir {
  width: 100%; margin-top: 8px; height: 30px;
  border-style: dashed; color: var(--tinta-2);
  font-size: 12.5px; font-weight: 550;
  background: transparent;
}
.boton-anadir span { font-size: 15px; line-height: 1; }

/* ─── Tablero ─────────────────────────────────────────────────────── */

.tablero {
  position: relative;
  display: grid;
  /* Cuatro filas: pestañas, mandos de la etapa, escenario y resultados.
     Solo el escenario crece. */
  grid-template-rows: auto auto minmax(0, 1fr) auto;
  min-height: 0; min-width: 0;
}

/* ─── Pestañas de vista ───────────────────────────────────────────── */

.vistas {
  position: relative;
  display: flex; gap: 2px;
  padding: 8px 14px;
  border-bottom: 1px solid var(--linea);
  overflow-x: auto;
  scrollbar-width: none;
  /* Se desvanece por los bordes en vez de cortarse en seco: así se ve que
     hay más pestañas a un lado, sin añadir flechas ni barra. */
  mask-image: linear-gradient(to right, transparent 0, #000 14px,
                              #000 calc(100% - 22px), transparent 100%);
}
.vistas::-webkit-scrollbar { display: none; }

.vista {
  position: relative; z-index: 1;
  height: 30px; padding: 0 13px;
  border: 0; border-radius: var(--radio-s);
  background: transparent;
  color: var(--tinta-2);
  font-size: 13px; font-weight: 550;
  cursor: pointer; white-space: nowrap;
  transition: color var(--t-ui) var(--sal);
}
.vista[aria-selected="true"] { color: var(--tinta); font-weight: 600; }
@media (hover: hover) and (pointer: fine) {
  .vista:not([aria-selected="true"]):hover { color: var(--tinta); }
}

/* El indicador se desliza entre pestañas. Es una pastilla, no un subrayado:
   se mueve en pantalla, así que lleva ease-in-out y no ease-out. */
.vistas-marca {
  position: absolute; top: 8px; left: 0;
  height: 30px; border-radius: var(--radio-s);
  background: var(--hundido);
  transition: transform var(--t-ui) var(--vaiven), width var(--t-ui) var(--vaiven);
  will-change: transform, width;
}
.vistas-marca[data-quieto] { transition: none; }

/* ─── Lámina y hoja ───────────────────────────────────────────────── */

.escenario { position: relative; min-height: 0; display: grid; }

/* ─── Entrada al cambiar de etapa ───────────────────────────────────
   Cambiar de pestaña pasa decenas de veces por sesión, así que esto tiene
   que ser breve y casi imperceptible: su único trabajo es que el contenido
   no se teletransporte. 170 ms, solo opacidad y desplazamiento, y nunca al
   reeditar el modelo —eso ocurre en cada tecla y marearía—.
   Es una animación CSS a propósito: corre fuera del hilo principal, así que
   no compite con el dibujo que está llegando del servidor. */
.escenario > [data-llegando] {
  animation: llega-escena 170ms var(--sal) both;
}
@keyframes llega-escena {
  from { opacity: 0; transform: translateY(5px); }
  to   { opacity: 1; transform: none; }
}

/* Los mandos de la etapa acompañan, un pelo más tarde y más corto: si
   entraran a la vez que el contenido se leerían como un solo bloque que
   salta. */
.submandos[data-llegando] > * {
  animation: llega-mando 150ms var(--sal) both;
  animation-delay: 40ms;
}
@keyframes llega-mando {
  from { opacity: 0; transform: translateY(3px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .escenario > [data-llegando],
  .submandos[data-llegando] > * { animation: none; }
}
.escenario > * { grid-area: 1 / 1; min-height: 0; }

.lamina {
  position: relative;
  overflow: hidden;
  /* La mesa vive cerca del papel a propósito. Antes era el gris de la
     aplicación y el salto hasta el blanco del plano resultaba violento: en
     oscuro se pasaba de #131416 a #FFFFFF de golpe. Ahora la mesa se aclara
     hasta quedar a media distancia, y los puntos apenas se insinúan. */
  background:
    radial-gradient(circle at 1px 1px, var(--mesa-punto) 1px, transparent 0) 0 0 / 26px 26px;
  background-color: var(--mesa);
  touch-action: none;
  cursor: grab;
  min-height: 0;
}
.lamina[data-arrastrando] { cursor: grabbing; }
.lamina:focus { outline: none; }

/* El plano se dibuja SOBRE la mesa, no encima como una foto pegada. El SVG
   viene con fondo transparente y su tinta se traduce al tema en app.js, así
   que aquí no hace falta ni papel ni sombra: lo que se ve es el trazo. */
.hoja {
  position: absolute; top: 50%; left: 50%;
  transform-origin: 0 0;
  background: transparent;
}

/* La capa propia del compositor SOLO mientras dura el gesto. Fuera de él
   estorba: el navegador conserva el mapa de bits rasterizado a la escala
   vieja y el texto sale borroso justo al acercarse a leerlo. */
.hoja[data-moviendo] { will-change: transform; }

.hoja-lienzo { display: block; }
.hoja-lienzo svg { display: block; max-width: none; height: auto; }

.hoja[data-cargando] { opacity: 0.55; }

/* Al añadir una barra, un apoyo o una carga, el plano entra en vez de
   aparecer de golpe: confirma que lo que acabas de escribir llegó al dibujo.
   Desde 0.985, nunca desde cero: nada surge de la nada. */
.hoja[data-entrando] { animation: entra-hoja 260ms var(--sal) both; }
@keyframes entra-hoja {
  from { opacity: 0.35; transform-origin: center; }
  to   { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .hoja[data-entrando] { animation: none; }
}
.hoja { transition: opacity var(--t-ui) var(--sal); }

/* Estado inicial: la mesa vacía no explica nada, esto sí. */
.lamina-inicio {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; padding: 24px;
  text-align: center; pointer-events: none;
  color: var(--tinta-3);
  animation: aparecer var(--t-panel) var(--sal) both;
}
.lamina[data-con-dibujo] .lamina-inicio { display: none; }
.inicio-signo { width: 108px; height: 76px; opacity: 0.34; margin-bottom: 6px; }
.inicio-titulo {
  margin: 0; font-size: 14px; font-weight: 600; color: var(--tinta-2);
  letter-spacing: -0.008em;
}
.inicio-texto {
  margin: 0; max-width: 306px; font-size: 12.5px; line-height: 1.55;
}
@keyframes aparecer { from { opacity: 0; transform: scale(0.985); } to { opacity: 1; } }

/* Sin dibujo no hay nada que arrastrar ni que ampliar. */
.lamina:not([data-con-dibujo]) { cursor: default; }
.lamina:not([data-con-dibujo]) .lamina-mandos,
.lamina:not([data-con-dibujo]) .lamina-pista { display: none; }
.lamina:not([data-con-dibujo]) .hoja { display: none; }

.lamina-mandos {
  position: absolute; right: 14px; bottom: 14px;
  width: var(--ancho-flotante); justify-content: space-between;
  display: flex; align-items: center; gap: 5px;
  padding: 5px;
  border-radius: 11px;
  background: var(--panel-velo);
  backdrop-filter: blur(18px) saturate(180%);
  -webkit-backdrop-filter: blur(18px) saturate(180%);
  border: 1px solid var(--linea);
  box-shadow: var(--sombra-2);
}
.boton-flotante { border: 0; background: transparent; height: 28px; }
@media (hover: hover) and (pointer: fine) {
  .boton-flotante:hover { background: var(--hundido) !important; }
}
.boton-escala {
  min-width: 56px; padding: 0 8px;
  font-size: 12px; font-weight: 600; color: var(--tinta-2);
}

.lamina-pista {
  position: absolute; left: 14px; bottom: 18px; margin: 0;
  /* Nunca debe meterse debajo de los mandos de zoom, que viven a la derecha. */
  max-width: calc(100% - 210px);
  font-size: 11.5px; color: var(--tinta-3);
  pointer-events: none;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: opacity var(--t-panel) var(--sal);
}
.lamina-pista[data-oculta] { opacity: 0; }

/* Por debajo de este ancho no cabe sin estorbar, y quien llega hasta aquí
   ya sabe arrastrar. */
@media (max-width: 1100px) { .lamina-pista { display: none; } }

/* ─── Segunda fila de mandos ──────────────────────────────────────── */

.submandos {
  display: flex; align-items: center; gap: 14px;
  padding: 8px 14px;
  border-bottom: 1px solid var(--linea);
  overflow-x: auto; scrollbar-width: none;
  min-height: 46px;
}
.submandos[data-desnudo] { min-height: 0; padding: 5px 14px; }
.submandos::-webkit-scrollbar { display: none; }
.submandos > .sello { margin-left: auto; padding-left: 12px; white-space: nowrap; }

/* Interruptor segmentado: Diagrama / Solución, o N / V / M. */
.grupo-segmentado {
  display: inline-flex; gap: 2px;
  padding: 2px;
  border-radius: 8px;
  background: var(--hundido);
}
.grupo-segmentado[hidden] { display: none; }

/* ─── Menú de archivo ─────────────────────────────────────────────────
   Importar, exportar y guardar en la nube bajo un solo botón. Ver
   web/menu-archivo.js para el porqué y para lo poco que hace falta en JS. */
.menu-archivo { position: relative; }
.menu-archivo > summary {
  list-style: none;                 /* fuera el triangulito del navegador */
  cursor: pointer;
}
.menu-archivo > summary::-webkit-details-marker { display: none; }
.menu-archivo > summary::marker { content: ""; }
.menu-archivo[open] > summary { background: var(--hundido); }

.menu-archivo-panel {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 60;
  min-width: 208px;
  display: flex; flex-direction: column; gap: 2px;
  padding: 6px;
  /* VARIABLES QUE EXISTEN
     Decía `--superficie` y `--borde`, que no están definidas en ninguna
     parte: el fondo salía TRANSPARENTE y el borde no se dibujaba, así que
     el panel dejaba ver lo que tenía detrás —las pestañas, los campos— y se
     leía encima de ellas. Le pasaba al menú de archivo desde el primer día.
     Los nombres de verdad son `--panel` y `--linea`. */
  background: var(--panel);
  border: 1px solid var(--linea);
  border-radius: var(--radio-m, 10px);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.22);
}
.menu-archivo-panel button {
  display: flex; align-items: center; gap: 10px;
  width: 100%; height: 34px; padding: 0 10px;
  border: 0; border-radius: var(--radio-s);
  background: transparent; color: var(--tinta);
  font: inherit; font-size: 12.5px; text-align: left;
  cursor: pointer;
}
.menu-archivo-panel button:hover { background: var(--hundido); }
.menu-archivo-panel button:focus-visible {
  outline: 2px solid var(--c-reaccion); outline-offset: -2px;
}
.menu-archivo-panel button svg { width: 16px; height: 16px; flex: none; }

/* EL MENÚ DE HERRAMIENTAS
   Mismo mecanismo que el de archivo —<details>, y el mismo guion lo cierra
   al pulsar fuera o con Escape—, pero se abre hacia la DERECHA, porque vive
   en el lado izquierdo de la barra. */
.menu-herramientas { position: relative; min-width: 0; }
/* La marca es el mando: se le da sitio para pulsar y un realce al pasar por
   encima, que es lo que dice que se puede pulsar. */
.menu-herramientas > summary.marca {
  padding: 4px 8px; margin: -4px 0 -4px -8px;
  border-radius: 10px;
  transition: background-color var(--t-ui) var(--sal);
}
@media (hover: hover) and (pointer: fine) {
  .menu-herramientas > summary.marca:hover { background: var(--hundido); }
}
.menu-herramientas[open] > summary.marca { background: var(--hundido); }
.menu-herramientas > summary.marca:focus-visible {
  outline: 2px solid var(--c-reaccion); outline-offset: 2px;
}
.marca-punta {
  width: 13px; height: 13px; flex: none; margin-left: 2px;
  color: var(--tinta-3);
  transition: transform var(--t-ui) var(--sal);
}
.menu-herramientas[open] .marca-punta { transform: rotate(180deg); }

.menu-herramientas-panel { left: 0; right: auto; min-width: 248px; }

.menu-herramienta {
  display: flex; align-items: center; gap: 10px;
  height: 40px; padding: 0 10px;
  border-radius: var(--radio-s);
  color: var(--tinta); text-decoration: none;
  font-size: 12.5px;
}
.menu-herramienta svg { width: 17px; height: 17px; flex: none; color: var(--tinta-2); }
@media (hover: hover) and (pointer: fine) {
  a.menu-herramienta:hover { background: var(--hundido); }
}
.menu-herramienta:focus-visible { outline: 2px solid var(--c-reaccion); outline-offset: -2px; }
.menu-herramienta-texto { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }
.menu-herramienta-texto b { font-weight: 600; }
.menu-herramienta-texto small { font-size: 10.5px; color: var(--tinta-3); }
/* La actual se queda a la vista y marcada: un menú de navegación también
   sirve para decir dónde estás. */
.menu-herramienta.actual { cursor: default; background: var(--hundido); }
.menu-herramienta-aqui {
  margin-left: auto; font-size: 10px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--c-reaccion);
}

/* `hidden` es un atributo, y el navegador lo aplica con `display: none` en su
   hoja por omisión —que pierde contra CUALQUIER regla de clase, incluida la de
   arriba—. En pórticos nunca se notó porque su barra de submandos no se oculta
   jamás; en propiedades geométricas sí se oculta en la pestaña de Geometría, y
   ahí la barra seguía a la vista ocupando sus 46 px pese a estar marcada como
   oculta. Se declara explícitamente, igual que se hizo con el segmentado. */
.submandos[hidden] { display: none; }

.segmento {
  height: 26px; padding: 0 12px;
  border: 0; border-radius: 6px;
  background: transparent; color: var(--tinta-2);
  font-size: 12.5px; font-weight: 550;
  cursor: pointer; white-space: nowrap;
  transition: transform var(--t-pulso) var(--sal),
              background-color var(--t-ui) var(--sal), color var(--t-ui) var(--sal);
}
.segmento:active { transform: scale(0.97); }
.segmento[aria-selected="true"] {
  background: var(--panel); color: var(--tinta); font-weight: 600;
  box-shadow: var(--sombra-1);
}
@media (hover: hover) and (pointer: fine) {
  .segmento:not([aria-selected="true"]):hover { color: var(--tinta); }
}

.mandos-corte { display: flex; align-items: center; gap: 12px; }
.mandos-corte[hidden] { display: none; }
.control-compacto { height: 28px; font-size: 12.5px; padding: 0 24px 0 9px; }

/* ─── Desarrollo escrito ──────────────────────────────────────────── */

.desarrollo {
  overflow-y: auto; overscroll-behavior: contain;
  background: var(--fondo);
  padding: 18px 20px 40px;
}
.desarrollo[hidden] { display: none; }

.desarrollo-cuerpo {
  max-width: 900px; margin: 0 auto;
  display: flex; flex-direction: column; gap: 14px;
}

/* Cada bloque del núcleo —«Resultantes», «Ecuaciones de equilibrio»— es
   una ficha. Se numeran para que se lea como un desarrollo, no como una
   lista suelta de fórmulas. */
.ficha {
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  background: var(--panel);
  padding: 14px 16px 12px;
  counter-increment: paso;
}
.ficha-titulo {
  display: flex; align-items: baseline; gap: 9px;
  font-size: 12px; font-weight: 650;
  letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--tinta-2);
  margin: 0 0 10px;
}
.ficha-titulo::before {
  content: counter(paso);
  flex: none;
  min-width: 19px; height: 19px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 5px;
  background: var(--realce); color: var(--c-reaccion);
  font-size: 11px; font-weight: 700; letter-spacing: 0;
  font-variant-numeric: tabular-nums;
}
.desarrollo-cuerpo { counter-reset: paso; }

.ficha-nota {
  margin: -4px 0 10px;
  font-size: 12.5px; color: var(--tinta-2); line-height: 1.5;
}

/* El desarrollo tarda cerca de un segundo en llegar. Que las fichas entren
   escalonadas evita el golpe de que aparezcan seis de una vez, y hace legible
   que es una secuencia de pasos. Es ocasional —solo al abrir «Solución»—, así
   que se puede permitir. */
/* El escalonado solo al ENTRAR en la solución. Sin esta condición se
   repetía en cada tecla —editar el modelo rehace el desarrollo entero— y las
   nueve fichas volvían a caer una tras otra mientras escribías. */
.desarrollo[data-llegando] .ficha {
  animation: entra-ficha 240ms var(--sal) both;
  animation-delay: calc(var(--turno, 0) * 45ms);
}
@keyframes entra-ficha {
  from { opacity: 0; transform: translateY(7px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .ficha { animation: none; }
}

.formulas { display: flex; flex-direction: column; gap: 9px; }

/* La fórmula es un SVG sin color propio: hereda el del texto, así que se
   lee igual en claro y en oscuro. Se desplaza sola si no cabe, en vez de
   encoger hasta ser ilegible. */
.formula {
  overflow-x: auto; overflow-y: hidden;
  padding: 2px 0;
  scrollbar-width: thin;
}
.formula svg {
  display: block;
  color: var(--tinta);
  max-width: none;
}

/* Las fórmulas se veían GRISES al lado de los títulos, y no era el color: el
   relleno ya es la misma tinta casi negra, medido sobre el fondo da 18:1 de
   contraste. Era el GROSOR. La fuente matemática tiene astas mucho más finas
   que la tipografía de interfaz, y a este tamaño el suavizado se las come.

   Engordarlas con un trazo del mismo color arregla la lectura sin tocar el
   tamaño ni la maquetación, y sirve igual en claro y en oscuro porque hereda
   `currentColor`. Con `paint-order` el trazo va DEBAJO del relleno, así que la
   silueta de cada letra no se emborrona.

   El recuadro del lienzo que matplotlib mete en cada SVG queda excluido: si no,
   el trazo lo hacía visible y cada fórmula salía dentro de una caja. */
.formula svg use,
.formula svg path {
  stroke: currentColor;
  stroke-width: 0.35;
  paint-order: stroke fill;
}
.formula svg g[id^="patch"] path,
.formula svg path[style*="fill: none"] { stroke: none; }

.ficha-lienzo {
  overflow-x: auto;
  padding: 4px 0 2px;
  text-align: center;
}
.ficha-lienzo svg { max-width: 100%; height: auto; display: inline-block; }

.desarrollo-vacio {
  margin: 0; padding: 34px 0;
  text-align: center; color: var(--tinta-3); font-size: 13.5px;
}

.desarrollo-carga {
  display: flex; flex-direction: column; gap: 10px;
}
.desarrollo-carga-titulo {
  font-size: 11px; font-weight: 650;
  letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--tinta-3);
  padding-top: 6px;
}

/* Esqueleto mientras llegan las fórmulas: el desarrollo tarda ~1 s la
   primera vez, y una pantalla en blanco durante un segundo parece rota. */
.esqueleto { display: flex; flex-direction: column; gap: 14px; }
.esqueleto-ficha {
  height: 108px; border-radius: var(--radio);
  border: 1px solid var(--linea-2);
  background: linear-gradient(100deg, var(--panel) 30%, var(--hundido) 50%, var(--panel) 70%)
              0 0 / 300% 100%;
  animation: recorrer 1.4s linear infinite;
}
@keyframes recorrer { to { background-position: -300% 0; } }
@media (prefers-reduced-motion: reduce) {
  .esqueleto-ficha { animation: none; background: var(--hundido); }
}

/* ─── Resultados ──────────────────────────────────────────────────── */

.resultados {
  border-top: 1px solid var(--linea);
  background: var(--panel);
  max-height: 40vh; min-height: 0;
  display: flex; flex-direction: column;
}

.resultados-cabecera {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 16px 8px;
  flex: none;
}
.resultados-cabecera h2 {
  font-size: 11px; font-weight: 650;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--tinta-2);
}
.sello { font-size: 11px; color: var(--tinta-3); }

.boton-plegar {
  margin-left: auto;
  width: 26px; height: 26px; padding: 0;
  border: 0; background: transparent; color: var(--tinta-3);
}
.boton-plegar svg { transition: transform var(--t-ui) var(--vaiven); }
.boton-plegar[aria-expanded="false"] svg { transform: rotate(-90deg); }

/* Plegar los resultados devuelve toda la altura al dibujo. */
.resultados[data-plegado] { max-height: none; }
.resultados[data-plegado] .resultados-cuerpo { display: none; }

.resultados-cuerpo {
  overflow-y: auto; overscroll-behavior: contain;
  padding: 0 16px 16px;
}

.vacio { margin: 0; color: var(--tinta-3); font-size: 13px; }

.bloques {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(232px, 1fr));
  gap: 18px;
}

.bloque-titulo {
  font-size: 10.5px; font-weight: 650;
  letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--tinta-3);
  margin: 0 0 7px;
}

table.datos { width: 100%; border-collapse: collapse; font-size: 12.5px; }
table.datos th {
  text-align: right; font-weight: 600; color: var(--tinta-3);
  font-size: 10.5px; letter-spacing: 0.05em; text-transform: uppercase;
  padding: 0 0 5px; border-bottom: 1px solid var(--linea-2);
}
table.datos th:first-child, table.datos td:first-child { text-align: left; }
table.datos td {
  padding: 5px 0; text-align: right;
  font-family: var(--tipo-num); font-size: 12px;
  font-variant-numeric: tabular-nums;
  border-bottom: 1px solid var(--linea-2);
}
table.datos td:first-child { font-family: var(--tipo); font-weight: 550; }
table.datos tr:last-child td { border-bottom: 0; }

.marca-color {
  display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  margin-right: 6px; vertical-align: 1px;
  background: var(--c-reaccion);
}

/* ─── Editor de etiquetas ─────────────────────────────────────────── */

.boton-modo[aria-pressed="true"] {
  background: var(--c-reaccion); border-color: var(--c-reaccion); color: #fff;
}
.boton-modo[hidden] { display: none; }

.etiquetas-mandos { display: flex; align-items: center; gap: 7px; }
.etiquetas-mandos[hidden] { display: none; }
.etiquetas-cuenta { font-size: 11.5px; color: var(--tinta-3); white-space: nowrap; }
.boton-menudo { height: 26px; padding: 0 10px; font-size: 12px; }
.etiquetas-grupo { display: inline-flex; gap: 3px; }
.etiquetas-grupo[hidden] { display: none; }
.etiquetas-grupo .boton-menudo { min-width: 30px; padding: 0 7px; }


/* La caja de agarre la dibuja el propio editor (ver editor.js): la estructura
   interna de una etiqueta varía —unas traen recuadro de fondo y otras no—, así
   que estilar «el primer hijo» pintaba el punteado sobre las letras en la
   mitad de los casos. */
.lamina[data-etiquetas] .etq { cursor: grab; }

.etq-caja {
  fill: transparent;
  stroke: var(--c-reaccion);
  stroke-width: 0.7;
  stroke-dasharray: 2.5 2.5;
  opacity: 0.45;
  pointer-events: all;             /* toda la caja agarra, no solo las letras */
  transition: opacity var(--t-ui) var(--sal), stroke-width var(--t-ui) var(--sal);
}
@media (hover: hover) and (pointer: fine) {
  .lamina[data-etiquetas] .etq:hover .etq-caja {
    opacity: 1; fill: color-mix(in srgb, var(--c-reaccion) 8%, transparent);
  }
}
.lamina[data-etiquetas] .etq:focus-visible { outline: none; }
.lamina[data-etiquetas] .etq:focus-visible .etq-caja {
  opacity: 1; stroke-width: 1.3; stroke-dasharray: none;
}

/* Al agarrar, la etiqueta se levanta un punto: confirma que la tienes. */
.lamina[data-etiquetas] .etq-agarrada {
  cursor: grabbing;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.28));
}
.lamina[data-etiquetas] .etq-agarrada .etq-caja {
  opacity: 1; stroke-dasharray: none;
}
.lamina[data-moviendo] { cursor: grabbing; }

/* Las fuerzas internas se agarran igual, pero se distinguen: no son
   rótulos, son parte del dibujo. */
.etq-elemento .etq-caja {
  stroke: var(--c-interno);
  stroke-dasharray: 4 2;
}

/* Las ya recolocadas se distinguen de las automáticas. */
.lamina[data-etiquetas] .etq-movida .etq-caja {
  stroke: var(--c-resultante);
  stroke-dasharray: none;
  opacity: 0.85;
}

/* ─── Tarea en marcha ─────────────────────────────────────────────── */

.tarea {
  /* A la derecha y por encima de los mandos del lienzo. Estaba abajo a la
     izquierda y tapaba las tablas justo cuando hace falta mirarlas.
     Los mandos ocupan 14 px de margen mas ~40 de alto: 62 la deja
     apoyada encima sin tocarlos. */
  position: fixed; right: 14px; bottom: 62px; z-index: 40;
  width: var(--ancho-flotante);
  padding: 11px 14px 12px;
  border-radius: 11px;
  border: 1px solid var(--linea);
  background: var(--panel-velo);
  backdrop-filter: blur(18px) saturate(180%);
  -webkit-backdrop-filter: blur(18px) saturate(180%);
  box-shadow: var(--sombra-3);
  transform: translateY(0) scale(1);
  opacity: 1;
  transition: opacity var(--t-panel) var(--sal), transform var(--t-panel) var(--sal);
}
.tarea[hidden] { display: none; }
.tarea[data-saliendo] { opacity: 0; transform: translateY(8px) scale(0.98); }

@starting-style {
  .tarea { opacity: 0; transform: translateY(6px) scale(0.98); }
}

.tarea-texto {
  display: flex; flex-direction: column; gap: 1px;
  margin-bottom: 9px;
}
.tarea-texto > span:first-child { font-size: 13px; font-weight: 550; }
.tarea-nota { font-size: 11.5px; color: var(--tinta-3); }

@media (max-width: 760px) {
  .tarea { right: 12px; left: auto; width: var(--ancho-flotante); bottom: 58px; }
}

/* ─── Aviso de error ──────────────────────────────────────────────── */

.aviso {
  position: fixed; left: 50%; bottom: 22px; z-index: 40;
  display: flex; align-items: flex-start; gap: 9px;
  max-width: min(520px, calc(100vw - 32px));
  padding: 11px 15px;
  border-radius: 11px;
  border: 1px solid color-mix(in srgb, var(--c-puntual) 35%, var(--linea));
  background: var(--panel-velo);
  backdrop-filter: blur(18px) saturate(180%);
  -webkit-backdrop-filter: blur(18px) saturate(180%);
  box-shadow: var(--sombra-3);
  color: var(--tinta);
  font-size: 13px; line-height: 1.45;
  transform: translate(-50%, 0) scale(1);
  opacity: 1;
  transition: opacity var(--t-panel) var(--sal), transform var(--t-panel) var(--sal);
}
.aviso svg { color: var(--c-puntual); flex: none; margin-top: 1px; }
.aviso[hidden] { display: none; }
.aviso[data-saliendo] { opacity: 0; transform: translate(-50%, 6px) scale(0.98); }

@starting-style {
  .aviso { opacity: 0; transform: translate(-50%, 6px) scale(0.98); }
}

/* ─── Pantallas estrechas ─────────────────────────────────────────── */

@media (max-width: 760px) {
  body { overflow: auto; }
  .taller { grid-template-columns: 1fr; height: auto; }
  .modelo { border-right: 0; border-bottom: 1px solid var(--linea); }
  .modelo-desliz { overflow: visible; mask-image: none; }
  .tablero { grid-template-rows: auto auto 62vh auto; }
  .resultados { max-height: none; }
  .lamina-pista { display: none; }

  /* Apilado, los campos no deben estirarse a lo ancho de la pantalla: una
     casilla de 700 px para escribir «4» es ridícula y cuesta apuntar. */
  .grupo { max-width: 620px; margin-inline: auto; width: 100%; }
}

/* El editor de etiquetas de escritorio cabe en una tableta; el móvil no da
   para una tabla de seis columnas, así que las cargas distribuidas se
   reordenan en dos líneas en vez de encogerse hasta ser ilegibles. */
@media (max-width: 460px) {
  .rejilla-distribuidas .rejilla-cabecera { display: none; }
  .rejilla-distribuidas .fila {
    grid-template-columns: 1fr 1fr 26px;
    row-gap: 4px;
    padding: 6px 4px;
    background: var(--hundido);
  }
  .rejilla-distribuidas .fila > :first-child { grid-column: 1 / 3; }
  .rejilla-distribuidas .quitar { grid-row: 1; grid-column: 3; opacity: 1; }
}

/* ─── Preferencias del sistema ────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  /* No es «sin señal»: se conserva el cambio de opacidad, se quita el
     movimiento, que es lo que marea. */
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 120ms !important;
  }
  .fila[data-nueva] { animation: none; }
  .vistas-marca { transition: none; }
  .boton:active { transform: none; }
}

@media (prefers-reduced-transparency: reduce) {
  .barra, .lamina-mandos, .aviso {
    background: var(--panel);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}

@media (prefers-contrast: more) {
  :root { --linea: #9A958C; --linea-2: #B5B0A6; --tinta-3: #5A5F64; }
  .celda { border-color: var(--linea); }
  .boton { border-color: var(--tinta-2); }
}

@media print {
  .barra, .modelo, .vistas, .lamina-mandos, .lamina-pista { display: none; }
  .taller { display: block; padding: 0; }
  .hoja { position: static; transform: none !important; box-shadow: none; }
}

/* Casilla de «también en diagramas». Se alinea con los selectores de al lado
   en vez de heredar el hueco de la etiqueta-mini, que la dejaría flotando. */
.campo-casilla {
  flex-direction: row; align-items: center; gap: 7px;
  align-self: end; padding-bottom: 7px;
  font-size: 12px; color: var(--tinta-2); cursor: pointer;
}
.campo-casilla input { accent-color: var(--c-reaccion); cursor: pointer; }

/* Casilla «Flecha y letra juntas», en la barra del editor de etiquetas. */
.etiquetas-casilla {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; color: var(--tinta-2); white-space: nowrap; cursor: pointer;
}
.etiquetas-casilla input { accent-color: var(--c-reaccion); cursor: pointer; }

/* Enlace de vuelta al sitio. Discreto: es una salida, no una acción del
   programa, así que no compite con «Informe» ni con la marca. */
.volver {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 9px 5px 6px; margin-right: 4px;
  border: 1px solid var(--linea); border-radius: var(--radio-s);
  font-size: 12px; color: var(--tinta-2); text-decoration: none;
  white-space: nowrap;
}
@media (hover: hover) and (pointer: fine) {
  .volver:hover { background: var(--hundido); color: var(--tinta); }
}
@media (max-width: 1150px) { .volver span { display: none; } }

/* ─── Diálogo del informe ─────────────────────────────────────────── */

.dialogo {
  border: 1px solid var(--linea); border-radius: var(--radio);
  padding: 0; background: var(--panel); color: var(--tinta);
  box-shadow: var(--sombra-3); max-width: min(440px, calc(100vw - 32px));
}
.dialogo::backdrop { background: rgba(0, 0, 0, 0.42); }
.dialogo-caja { display: flex; flex-direction: column; gap: 12px; padding: 18px 20px 16px; }
.dialogo-titulo { font-size: 15px; font-weight: 600; }

/* El título es el asa: por ahí se aparta la ventana para poder mirar el
   dibujo que hay detrás. `touch-action` es lo que impide que el gesto se
   lo quede el navegador para desplazar la página en un móvil. */
.dialogo[data-arrastrable] .dialogo-titulo {
  cursor: move; user-select: none; touch-action: none;
}
.dialogo-nota { margin: 0; font-size: 12.5px; color: var(--tinta-2); }
.dialogo-atajos { display: flex; gap: 6px; }

/* La lista se desplaza sola: un pórtico con muchos cortes no debe empujar los
   botones de Generar y Cancelar fuera de la pantalla. */
.dialogo-cortes {
  display: flex; flex-direction: column; gap: 6px;
  max-height: min(46vh, 320px); overflow-y: auto;
  padding: 8px; border: 1px solid var(--linea-2); border-radius: var(--radio-s);
  background: var(--hundido);
}
.dialogo-corte {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  gap: 9px; font-size: 12.5px;
}
.dialogo-corte input[type="checkbox"] { accent-color: var(--c-reaccion); cursor: pointer; }
.dialogo-corte select { height: 28px; font-size: 12px; }
.dialogo-corte[data-fuera] { opacity: 0.45; }
.dialogo-error { margin: 0; font-size: 12.5px; color: var(--c-puntual); }
.dialogo-pie { display: flex; justify-content: flex-end; gap: 8px; margin-top: 2px; }

/* El enlace de vuelta y la marca, juntos a la izquierda. Antes eran dos hijos
   sueltos de una barra con «space-between», así que la marca quedaba a medio
   camino: ni pegada al enlace ni centrada de verdad. */
.barra-izquierda { display: flex; align-items: center; gap: 14px; min-width: 0; }

/* ─── Globo de ayuda del botón «Etiquetas» ────────────────────────── */

/* Antes esto era una franja de texto que se desplegaba bajo la barra y empujaba
   el dibujo hacia abajo. Ahora flota encima y no ocupa sitio en la maqueta:
   `position: absolute` lo saca del flujo, así que aparecer y desaparecer no
   mueve nada de lo que hay alrededor. */
.ayuda-globo { position: relative; display: inline-flex; }
.ayuda-globo[hidden] { display: none; }
.boton-signo { min-width: 26px; padding: 0; font-weight: 600; }

/* POR QUE «fixed» Y COLGADO DEL BODY
   La barra de submandos lleva «overflow-x: auto» para poder desplazarse en
   pantallas estrechas, y eso crea una caja que RECORTA todo lo que sobresalga,
   posicionado o no. Con el globo dentro, se hacia visible pero quedaba cortado
   por el borde inferior de la barra. Colgarlo del body y colocarlo con
   coordenadas fijas —que calcula editor.js— lo saca de ese recorte. */
.ayuda-texto {
  position: fixed; z-index: 60;
  width: max-content; max-width: min(340px, calc(100vw - 32px));
  padding: 9px 11px;
  border: 1px solid var(--linea); border-radius: var(--radio-s);
  background: var(--panel); color: var(--tinta-2);
  box-shadow: var(--sombra-2);
  font-size: 12px; line-height: 1.5;
  /* Invisible pero presente: así puede animarse. `visibility` es lo que impide
     que siga capturando el ratón mientras está oculto. */
  opacity: 0; visibility: hidden;
  transform: translateY(-4px);
  transition: opacity var(--t-ui) var(--sal),
              transform var(--t-ui) var(--sal),
              visibility 0s linear var(--t-ui);
  pointer-events: none;
}
.ayuda-texto b { font-weight: 600; color: var(--tinta); }

/* Con el ratón encima o con el teclado en el botón. El `:focus-visible` no es
   un adorno: sin él la ayuda solo existiría para quien puede usar el ratón. */
.ayuda-texto[data-visible] {
  opacity: 1; visibility: visible;
  transform: translateY(0);
  transition-delay: 0s;
}


@media (prefers-reduced-motion: reduce) {
  .ayuda-texto { transition: opacity 1ms, visibility 1ms; transform: none; }
}

/* ─── Paracaídas de la descarga ───────────────────────────────────── */

.tarea-cielo {
  position: relative;
  /* Alto para que la caida se lea. Con 62 px el recorrido era tan corto que
     el movimiento parecia un temblor en vez de un descenso. */
  height: 138px;
  overflow: hidden;
}

/* El suelo: la línea sobre la que aterriza la carga. */
.tarea-suelo {
  position: absolute; left: 6px; right: 6px; bottom: 0;
  height: 2px; border-radius: 1px;
  background: var(--linea);
}

/* Capa 1: la caída. */
.tarea-caida {
  /* 6 px de aire arriba: al mecerse, la caja girada del dibujo sobresale por
     encima de su propio borde y el cielo la recortaba. */
  position: absolute; top: 6px; left: 50%;
  margin-left: -19px;
  display: block; width: 38px; height: 43px;
  animation: tp-cae 50s var(--sal) forwards;
}

/* CAE DESDE EL PRIMER INSTANTE, PERO NUNCA LLEGA
   El vaiven de antes subia y bajaba, que es lo que se veia repetitivo. Ahora
   desciende de verdad, y la curva —muy frenada al final— hace que avance
   rapido los primeros segundos y luego apenas se mueva. Asi parece que sigue
   cayendo por larga que sea la espera, sin tocar el suelo antes de tiempo: el
   suelo significa «ya esta», y llegar sin haber terminado seria mentir.
   El tope son 73 px de los 96 que hay hasta el suelo. */
@keyframes tp-cae {
  from { transform: translateY(0); }
  to   { transform: translateY(73px); }
}

/* Capa 2: el balanceo, que es lo que le da vida. Solo gira. */
.tarea-paracaidas {
  display: block; width: 38px; height: 43px;
  transform-origin: 50% 14%;
  animation: tp-mece 3.6s ease-in-out infinite alternate;
}
@keyframes tp-mece {
  from { transform: rotate(-7deg); }
  to   { transform: rotate(7deg); }
}

.tp-vela    { fill: var(--c-reaccion); opacity: 0.9; }
.tp-cuerdas { fill: none; stroke: var(--c-reaccion); stroke-width: 1.1; opacity: 0.5; }
.tp-carga   { fill: var(--c-reaccion); }

/* AL TERMINAR: EL ATERRIZAJE
   Lo anima app.js con `animate()`, partiendo de la posición exacta que tuviera
   en ese instante. Esta regla es solo el reposo para cuando no hay animaciones
   disponibles o se pidió menos movimiento. */
.tarea[data-hecho] .tarea-caida { animation: none; transform: translateY(96px); }
.tarea[data-hecho] .tarea-paracaidas { animation: none; transform: rotate(0deg); }
.tarea[data-hecho] .tp-vela {
  opacity: 0.28;
  transform: translateY(-3px) scaleY(0.72);
  transform-origin: 50% 30%;
  transition: opacity 700ms var(--sal), transform 900ms var(--sal);
}
.tarea[data-hecho] .tarea-suelo { background: var(--c-reaccion); opacity: 0.75; }

@media (prefers-reduced-motion: reduce) {
  .tarea-caida, .tarea-paracaidas { animation: none; }
  .tarea[data-hecho] .tp-vela { transition: none; }
}

/* ─── Redes en la barra ───────────────────────────────────────────── */

/* Separadas de la marca por una linea fina: son de «Ayuda en Ingenieria», no
   del solver, y esa raya lo dice sin necesidad de un rotulo. */
.redes {
  display: flex; align-items: center; gap: 2px;
  margin-left: 12px; padding-left: 12px;
  border-left: 1px solid var(--linea);
}

.red {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px;
  border-radius: var(--radio-s);
  color: var(--tinta-3);
  text-decoration: none;
  transition: color var(--t-ui) var(--sal), background var(--t-ui) var(--sal);
}
/* En reposo van todas en gris: cuatro logos de colores en la cabecera de una
   herramienta compiten con el trabajo. El color aparece al apuntar, que es
   cuando la marca ayuda a reconocer el destino.

   Tras la guarda de puntero fino, como manda DESIGN.md: en una tableta un
   :hover sin guarda se queda pegado despues de tocar. */
@media (hover: hover) and (pointer: fine) {
  .red:hover           { background: var(--hundido); }
  .red-tiktok:hover    { color: #00C4C4; }
  .red-instagram:hover { color: #C13584; }
  .red-facebook:hover  { color: #1877F2; }
  .red-whatsapp:hover  { color: #25D366; }
}

/* En pantallas estrechas la barra ya va justa: manda la herramienta. Las redes
   siguen estando en el pie del PDF y en el sitio. */
/* Medido: a 930 px la barra ya iba con 16 px de holgura y el subtitulo de
   la marca se partia en dos lineas. Por debajo de 1080 manda la
   herramienta y las redes se retiran; siguen en el pie del PDF y en el
   sitio. */
/* 1120 y no menos: por debajo de ahí la barra izquierda ya lo tiene todo en
   su mínimo —la marca a cero, los enlaces reducidos a su icono— y el hueco
   que falta se lo comería a las redes, dejándolas a medias. Medido en
   pórticos a 1100: se recortaban 11 px. Mejor retirarlas enteras que
   enseñar tres iconos y medio. */
@media (max-width: 1120px) { .redes { display: none; } }


/* --- ESTILOS APPLE PARA DRIVER.JS (ONBOARDING) --- */
.driver-popover {
  background: var(--panel) !important;
  color: var(--tinta) !important;
  border: 1px solid var(--linea) !important;
  border-radius: 16px !important;
  box-shadow: var(--sombra-3) !important;
  font-family: var(--tipo) !important;
  padding: 16px !important;
}

/* Remover flecha del popover para un look más flotante estilo menú iOS */
.driver-popover-arrow {
  display: none !important;
}

/* Título */
.driver-popover-title {
  font-weight: 650 !important;
  font-size: 16px !important;
  margin-bottom: 8px !important;
}

/* Descripción */
.driver-popover-description {
  color: var(--tinta-2) !important;
  font-size: 14px !important;
  line-height: 1.4 !important;
}

/* Footer y Progress */
.driver-popover-footer {
  margin-top: 16px !important;
}
.driver-popover-progress-text {
  color: var(--tinta-3) !important;
  font-size: 12px !important;
}

/* Botones */
.driver-popover-footer button {
  background: var(--hundido) !important;
  color: var(--tinta) !important;
  border: none !important;
  border-radius: 8px !important;
  padding: 8px 12px !important;
  font-weight: 600 !important;
  transition: transform 140ms var(--sal), background 140ms var(--sal) !important;
  text-shadow: none !important;
  font-family: var(--tipo) !important;
  box-shadow: none !important;
}

.driver-popover-footer button:active {
  transform: scale(0.96) !important;
  background: var(--linea) !important;
}

.driver-popover-footer .driver-popover-next-btn {
  background: var(--tinta) !important;
  color: var(--fondo) !important;
}
.driver-popover-footer .driver-popover-next-btn:active {
  background: var(--tinta-2) !important;
}

/* --- MEJORAS APPLE-DESIGN --- */
/* Animación suave para el plegado de la barra lateral (fluid motion) */
.taller {
  transition: grid-template-columns var(--t-panel) var(--sal);
}

.modelo {
  transition: opacity var(--t-panel) var(--sal), visibility var(--t-panel) var(--sal);
}

/* Físicas y tacto en botones (direct manipulation / feedback on down) */
.boton {
  transition: transform 140ms var(--sal), background-color 140ms var(--sal), color 140ms var(--sal);
}
.boton:active {
  transform: scale(0.97);
  transition-duration: 0ms;
}

/* Tacto en pestañas de la barra de acciones */
.vista {
  transition: transform 140ms var(--sal), background-color 140ms var(--sal), color 140ms var(--sal);
}
.vista:active {
  transform: scale(0.95);
  transition-duration: 0ms;
}

/* Efecto translúcido y desenfoque en la barra de acciones superior (Glassmorphism) */
.barra {
  background: var(--panel-velo);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
}

/* Estilos para aviso de exito */
.aviso[data-tipo="exito"] { border-color: color-mix(in srgb, #10b981 35%, var(--linea)); }
.aviso[data-tipo="exito"] svg { color: #10b981; }
