/* ==================================================================
   AprendeHDLC — estilos propios sobre Bootstrap 5.3
   ================================================================== */

/* El morado del enunciado como color primario. Bootstrap 5.3 se pinta con
   variables CSS, así que basta redefinirlas: no hace falta recompilar Sass ni
   duplicar reglas de botón. */
:root {
  --bs-primary: #6f42c1;
  --bs-primary-rgb: 111, 66, 193;
  --bs-primary-text-emphasis: #59359a;
  --bs-primary-bg-subtle: #e9e2f7;
  --bs-primary-border-subtle: #c9b8ec;
  --bs-link-color: #6f42c1;
  --bs-link-color-rgb: 111, 66, 193;
  --bs-link-hover-color: #59359a;

  --hdlc-morado: #6f42c1;
  --hdlc-morado-oscuro: #59359a;
  /* Transmisor y receptor van en colores distintos, y simétricos: es lo que
     hace que las dos mitades de la pantalla se distingan de un vistazo. */
  --hdlc-tx-barra: #0d6efd;
  --hdlc-tx-caja: #cfe2ff;
  --hdlc-rx-barra: #198754;
  --hdlc-rx-caja: #d1e7dd;
  /* Los mensajes de MI capa de aplicación y los que llegan dentro de tramas
     son cosas distintas y antes se pintaban igual. Las tramas dejan el verde
     —que ahora es el de los mensajes entrantes— y pasan al naranja quemado:
     no colisiona con el azul del transmisor, el verde del receptor, el morado
     de marca ni el rojo de error, y da 7:1 de contraste con texto blanco. */
  --hdlc-msg: #1b3a6b;
  --hdlc-msg-entrante: #1a5c3a;
  --hdlc-trama: #8f4116;
  --hdlc-aviso: #b8860b;
}

[data-bs-theme="dark"] {
  --bs-primary-bg-subtle: #2c2440;
  --bs-primary-border-subtle: #4b3a76;
  --bs-link-color: #b39ae4;
  --bs-link-color-rgb: 179, 154, 228;
  --bs-link-hover-color: #cbb8ee;
  --hdlc-tx-caja: #1b3358;
  --hdlc-rx-caja: #173d2c;
}

.btn-primary {
  --bs-btn-bg: #6f42c1;
  --bs-btn-border-color: #6f42c1;
  --bs-btn-hover-bg: #59359a;
  --bs-btn-hover-border-color: #59359a;
  --bs-btn-active-bg: #4b2d84;
  --bs-btn-active-border-color: #4b2d84;
  --bs-btn-disabled-bg: #6f42c1;
  --bs-btn-disabled-border-color: #6f42c1;
}

.btn-outline-primary {
  --bs-btn-color: #6f42c1;
  --bs-btn-border-color: #6f42c1;
  --bs-btn-hover-bg: #6f42c1;
  --bs-btn-hover-border-color: #6f42c1;
  --bs-btn-active-bg: #59359a;
  --bs-btn-active-border-color: #59359a;
}

/* Los colores van por las variables de Bootstrap y no con `color` directo: su
   regla `.navbar-nav .nav-link.active` es más específica y pintaba la pestaña
   activa en el casi negro de la barra clara, que sobre morado no se lee. */
.navbar-hdlc {
  background: #6f42c1;
  --bs-navbar-color: rgba(255, 255, 255, .8);
  --bs-navbar-hover-color: #fff;
  --bs-navbar-active-color: #fff;
  --bs-navbar-brand-color: #fff;
  --bs-navbar-brand-hover-color: #fff;
  --bs-navbar-toggler-border-color: rgba(255, 255, 255, .5);
  --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.9%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
}
/* La activa, en píldora clara y negrita: se distingue por dos vías y no sólo
   por el color. El relleno lateral hace falta también en el menú plegado del
   móvil, donde Bootstrap lo quita y la píldora quedaría pegada al texto. */
.navbar-hdlc .navbar-nav .nav-link {
  padding-left: .75rem;
  padding-right: .75rem;
  border-radius: .375rem;
}
/* Desplegada, el profesor tiene seis pestañas más los botones: el relleno
   vuelve al de Bootstrap para que la fila quepa. */
@media (min-width: 992px) {
  .navbar-hdlc .navbar-nav .nav-link { padding-left: .5rem; padding-right: .5rem; }
}
.navbar-hdlc .navbar-nav .nav-link:hover { background: rgba(255, 255, 255, .1); }
.navbar-hdlc .navbar-nav .nav-link.active {
  font-weight: 600;
  background: rgba(255, 255, 255, .2);
}

body { background: var(--bs-body-bg); }

.login-card { max-width: 460px; margin: 6vh auto; }

.mono { font-family: var(--bs-font-monospace); }

/* ==================================================================
   Política de contraseñas (§2.2)
   ================================================================== */

/* Los cuatro requisitos se van marcando en verde a medida que se cumplen, en
   vez de rechazar la contraseña al enviar y obligar a adivinar qué falta. */
.requisitos { list-style: none; padding-left: 0; margin: .35rem 0 0; font-size: .85rem; }
.requisitos li { color: var(--bs-secondary-color); }
.requisitos li::before { content: "○"; display: inline-block; width: 1.2em; }
.requisitos li.cumplido { color: var(--bs-success); }
.requisitos li.cumplido::before { content: "●"; }

/* ==================================================================
   Pantalla de simulación (§6.2)
   ================================================================== */

.panel-titulo {
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  font-weight: 600;
  color: var(--bs-secondary-color);
}

.reloj { font-family: var(--bs-font-monospace); font-size: 1.6rem; line-height: 1.1; }

/* Pares etiqueta/valor de la columna izquierda. Se pintan como datos y no como
   controles a propósito: de las tres variables generales sólo la conexión es
   editable, y las otras dos tienen que verse claramente no manipulables. */
.dato { margin: 0; }
.dato dt {
  font-size: .7rem; font-weight: 600; letter-spacing: .03em;
  text-transform: uppercase; color: var(--bs-secondary-color);
}
.dato dd { margin: 0; font-size: 1.05rem; }

/* Mi dirección va destacada: es lo que el estudiante necesita tener siempre a
   la vista, porque de ella depende si una trama es orden o respuesta. */
.mi-direccion {
  border: 2px solid var(--bs-primary);
  border-radius: .5rem;
  padding: .4rem .6rem;
  background: var(--bs-primary-bg-subtle);
}
.mi-direccion .etiqueta {
  font-size: .7rem; font-weight: 600; letter-spacing: .03em;
  text-transform: uppercase; color: var(--bs-primary-text-emphasis);
}
.mi-direccion .valor {
  font-size: 2rem; font-weight: 700; line-height: 1;
  color: var(--bs-primary-text-emphasis);
}

/* ---------- ventana deslizante ---------- */

/* 16 cuadrados: 0..7 dos veces. Con 8 + W posiciones no cabe una ventana que
   empiece en cualquier N(S), y con menos no se lee.

   El relleno de abajo deja sitio a la banda inferior de barras, que sobresale
   por debajo de las casillas. */
.ventana { position: relative; overflow-x: auto; padding: 18px 0 22px; }
.ventana-celdas { display: flex; width: max-content; position: relative; }

.celda {
  width: 34px; height: 32px;
  border: 1px solid var(--bs-border-color);
  margin-left: -1px;
  display: flex; align-items: center; justify-content: center;
  font-size: .8rem;
  background: var(--bs-body-bg);
  position: relative;
  color: var(--bs-secondary-color);
}
/* Dentro de la ventana: blanco = ya usado (entre las dos rayas);
   sombreado = el resto, que es el hueco disponible. */
.tx .celda.hueco { background: var(--hdlc-tx-caja); }
.rx .celda.hueco { background: var(--hdlc-rx-caja); }

.celda .msg {
  position: absolute; inset: 3px;
  border-radius: 50%;
  background: var(--hdlc-msg); color: #fff;
  font-size: .6rem;
  display: flex; align-items: center; justify-content: center;
  user-select: none;
  z-index: 1;
}
/* Los que llegan dentro de tramas —los del buffer de recepción— son de la OTRA
   capa de aplicación. */
.celda .msg.entrante { background: var(--hdlc-msg-entrante); }
.celda .msg { cursor: grab; }
.celda .msg:focus-visible { outline: 2px solid var(--bs-primary); outline-offset: 1px; }

/* El borrado va en su propio botón y no en el círculo, porque pulsar el círculo
   ya significa «cógeme»: es la mitad de la alternativa de pulsar-pulsar al
   arrastre, que es lo único que hace la pantalla usable en tableta.

   El selector NO va atado a `.celda`: la misma aspa se usa en la carga útil de
   la trama que se compone, y dos aspas con aspecto distinto para la misma
   acción se leerían como dos acciones distintas. Lo único que necesita fuera de
   la casilla es un contenedor posicionado, que es `.con-aspa`. */
.con-aspa { position: relative; display: inline-flex; }
.quitar-msg {
  position: absolute; top: -5px; right: -5px;
  width: 15px; height: 15px; padding: 0;
  border-radius: 50%; border: 1px solid var(--bs-border-color);
  background: var(--bs-body-bg); color: var(--bs-secondary-color);
  font-size: 11px; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  z-index: 4; cursor: pointer;
}
.quitar-msg:hover { color: var(--bs-danger); border-color: var(--bs-danger); }

/* Las marcas se arrastran libremente, incluso a posiciones ilegales: la
   interfaz no restringe nada y lo que esté mal se corrige al pulsar Procesar.

   Son TRES por ventana y se reparten en dos bandas verticales que no se
   solapan: arriba la gruesa (ancla) y el tope, que no pueden coincidir nunca
   porque W >= 1; abajo la tenue, que sí puede coincidir con cualquiera de las
   otras dos —ventana llena— y que por eso necesita su propia banda. Así
   desaparece el problema de tener que apartar una marca para agarrar la de
   debajo. */
.barra {
  position: absolute; top: 4px;
  width: 5px; height: 30px;
  border-radius: 2px;
  cursor: ew-resize;
  z-index: 3;
  touch-action: none;
}
.tx .barra { background: var(--hdlc-tx-barra); }
.rx .barra { background: var(--hdlc-rx-barra); }
/* Banda inferior: sobresale por debajo de la casilla, que es lo que la hace
   agarrable aunque coincida con la gruesa o con el tope. */
.barra.tenue { opacity: .45; width: 4px; z-index: 2; top: 32px; height: 32px; }
/* El tope va en el mismo color pero con trazo más fino y discontinuo: es una
   marca de la misma familia, y a la vez claramente otra cosa. */
.barra.tope { background: none; width: 6px; border-left: 3px dashed; }
.tx .barra.tope { border-color: var(--hdlc-tx-barra); }
.rx .barra.tope { border-color: var(--hdlc-rx-barra); }
.barra:focus-visible { outline: 3px solid var(--bs-primary); outline-offset: 2px; }

.leyenda {
  font-size: .75rem; color: var(--bs-secondary-color);
  display: flex; gap: .9rem; flex-wrap: wrap; margin-top: .25rem;
}
.leyenda i {
  display: inline-block; width: 10px; height: 10px;
  vertical-align: -1px; margin-right: .25rem;
}
/* La muestra del tope reproduce su trazo discontinuo; la del mensaje, su
   círculo. */
.leyenda i.tope { width: 0; border-left: 3px dashed; height: 12px; }
.leyenda i.redonda { border-radius: 50%; }

/* ---------- editor de ejercicios ---------- */

/* Tres columnas: las laterales ANCLADAS y la del medio con scroll propio. Con
   scroll de página, los botones de colocar eventos se irían de la vista justo
   cuando se está mirando dónde soltar uno. */
.editor {
  display: grid;
  /* Las laterales anchas y la del medio con lo que sobre: el cronograma tiene
     scroll propio y aguanta cualquier ancho, mientras que el texto de un evento
     («A · 2,40 s · CA tiene datos → B,I32,P») no se puede recortar sin dejar de
     decir qué evento es. `minmax(0, …)` para que la del medio pueda encogerse:
     sin él, el contenido ancho la infla y se come las laterales. */
  grid-template-columns: 22rem minmax(0, 1fr) 22rem;
  gap: 1rem;
  align-items: start;
}
/* El cronograma, centrado en su marco en vez de pegado a la izquierda. */
.editor-lienzo > svg { display: block; margin-inline: auto; }
/* El evento elegido, entero y legible, debajo del selector que lo recorta. */
.editor-elegido {
  background: var(--bs-primary-bg-subtle);
  border: 1px solid var(--bs-primary-border-subtle);
  border-radius: .375rem;
  padding: .25rem .5rem;
  font-size: .8125rem;
  font-weight: 600;
  overflow-wrap: anywhere;
}
.editor-lado { position: sticky; top: 1rem; }
/* La lista de eventos de cada lado: filas seleccionables con una × para borrar. */
.editor-eventos { max-height: 18rem; overflow-y: auto; }
.editor-evento-texto { color: inherit; overflow-wrap: anywhere; line-height: 1.25; }
.editor-eventos .list-group-item.active .editor-evento-borrar { background: var(--bs-body-bg); }
.editor-evento-borrar { line-height: 1.1; }
.editor-lienzo {
  position: relative;
  max-height: calc(100vh - 9rem);
  overflow-y: auto;
  border: 1px solid var(--bs-border-color);
  border-radius: .375rem;
  background: #fff;
}
/* Los tres botones llevan el color de su tipo de evento, y la línea que se
   arrastra lleva el mismo: sólo el color obliga a mirar la leyenda cada vez, y
   sólo el texto se pierde entre las tramas, así que van los dos. */
.ev-CONEXION { --ev-color: #198754; }
.ev-DATOS { --ev-color: #0d6efd; }
.ev-DESCONEXION { --ev-color: #6f42c1; }
.editor-boton { border-color: var(--ev-color); color: var(--ev-color); }
.editor-boton:hover:not(:disabled) { background: var(--ev-color); color: #fff; }

/* La línea que se arrastra, con su punta de flecha apuntando al cronograma. */
/* `left`/`right` los pone el editor: la línea llega del borde a la estación que
   genera el evento, y hasta dónde depende de dónde haya quedado el SVG. */
.guia {
  position: absolute; height: 0;
  border-top: 2px dashed var(--ev-color);
  cursor: ns-resize; z-index: 5;
}
.guia .punta {
  position: absolute; top: -.55rem; font-size: .7rem; white-space: nowrap;
  background: var(--bs-body-bg); color: var(--ev-color);
  padding: 0 .25rem; font-weight: 600;
}
.guia .punta.izq { left: .25rem; }
.guia .punta.der { right: .25rem; }
/* El evento ya colocado se marca en el lienzo con su propia línea, más tenue. */
/* `left`/`right` los pone el editor: la marca llega del margen a la estación
   que genera el evento, igual que la línea de colocación. Ésta va SÓLIDA
   —el evento ya está puesto— y aquélla punteada. */
.marca-evento {
  position: absolute; height: 0;
  border-top: 2px solid var(--ev-color); opacity: .45; pointer-events: none;
}
.marca-evento.elegida { opacity: 1; border-top-width: 3px; }

/* ---------- franja de gamificación (pie de la pantalla de simulación) ---------- */

/* Fija al pie y con su altura RESERVADA en el cuerpo (`--franja-alto` la mide el
   JS, que también la ve crecer al desplegar el panel): así ni las tramas, ni los
   buffers, ni la ventana ni sus zonas de arrastre quedan nunca debajo. El
   `padding` inferior respeta la barra de gestos de los móviles. */
.franja {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 1030;
  background: var(--bs-body-bg);
  border-top: 1px solid var(--bs-border-color);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
body.con-franja { padding-bottom: var(--franja-alto, 30px); }
/* Lo que se lleva a la vista (foco, scrollIntoView, anclas) no acaba bajo la franja. */
html { scroll-padding-bottom: var(--franja-alto, 0px); }
.franja-barra {
  display: flex; align-items: center; gap: .5rem;
  height: 30px; padding: 0 .75rem; font-size: .8rem; white-space: nowrap;
}
.franja-avisos { display: inline-flex; gap: .35rem; flex-shrink: 0; }
.franja-avisos .badge { font-weight: 600; }
.franja-boton {
  flex: 1 1 auto; min-width: 0; height: 100%;
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  background: none; border: 0; padding: 0; color: var(--bs-body-color); text-align: left;
}
.franja-boton:focus-visible { outline: 2px solid var(--bs-primary); outline-offset: -2px; }
.franja-resumen { overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
.franja-flecha { flex-shrink: 0; color: var(--bs-secondary-color); transition: transform .15s; }
.franja-boton[aria-expanded="true"] .franja-flecha { transform: rotate(180deg); }
.franja-panel { padding: .5rem .75rem; border-bottom: 1px solid var(--bs-border-color); }

/* ---------- marcador de la sesión ---------- */

/* Tres filas, una por nivel, y tres columnas: total, sesión y racha. La rejilla
   va a ancho fijo en las cifras para que las tres filas se lean en columna, que
   es lo que permite compararlas de un vistazo. */
.marcador {
  display: grid;
  grid-template-columns: auto 1fr 1fr 2fr;
  gap: .1rem .9rem;
  align-items: center;
  font-size: .8rem;
}
.marcador .cabecera { color: var(--bs-secondary-color); font-size: .7rem; }
.marcador .cifra { font-family: var(--bs-font-monospace); text-align: right; }
.marcador .nivel { white-space: nowrap; }
/* Una racha que ya no se puede completar en esta sesión se congela: seguir
   enseñándola viva sería prometer algo que ya no se puede cobrar. */
.marcador .congelada { opacity: .4; }
.marcador .punto { letter-spacing: .1em; font-family: var(--bs-font-monospace); }

/* ---------- temporizadores ---------- */

.temps { display: flex; gap: .35rem; flex-wrap: wrap; margin-top: .6rem; }
/* temp_poll no es un temporizador de datos, y arrancarlo por error creyendo que
   lo es no enseña nada. El hueco es lo único que los separa: el nombre
   («temp_poll» junto a «temp_d7») no basta de un vistazo. */
.temps-hueco { flex: 0 0 1.6rem; }
.temp {
  border: 1px solid var(--bs-border-color);
  border-radius: .375rem;
  padding: .2rem .35rem;
  min-width: 5.1rem;
  text-align: center;
  background: var(--bs-body-bg);
}
.temp .nom { font-size: .68rem; color: var(--bs-secondary-color); }
.temp .val { font-family: var(--bs-font-monospace); font-size: .85rem; }
.temp.activo { border-color: var(--hdlc-tx-barra); }
.rx .temp.activo { border-color: var(--hdlc-rx-barra); }
/* Un temporizador que acaba de vencer se muestra a 0 y en rojo, y cuenta como
   parado: rearrancarlo es un arranque normal. */
.temp.vencido { border-color: var(--bs-danger); }
.temp.vencido .val { color: var(--bs-danger); font-weight: 700; }
.temp .aviso-tx { color: var(--hdlc-aviso); cursor: help; }
/* Un temporizador que se ha (re)arrancado DENTRO de este evento no está en el
   mismo estado que uno que venía corriendo: su plazo empieza otra vez desde
   cero, y eso se corrige. Se marca para que la diferencia se vea. */
.temp.rearmado { box-shadow: inset 0 0 0 1px var(--bs-primary); }

/* ---------- piezas que se arrastran ---------- */

.pieza-msg {
  display: inline-flex;
  width: 52px; height: 52px;
  border-radius: 50%;
  background: var(--hdlc-msg); color: #fff;
  align-items: center; justify-content: center;
  cursor: grab; font-size: .9rem; user-select: none;
  flex: 0 0 auto;
}
.pieza-msg.entrante { background: var(--hdlc-msg-entrante); }
.pieza-msg.chica { width: 40px; height: 40px; font-size: .75rem; }
.pieza-trama {
  display: inline-flex;
  padding: .6rem 1.1rem;
  border-radius: .375rem;
  background: var(--hdlc-trama); color: #fff;
  cursor: grab;
  font-family: var(--bs-font-monospace); font-size: .95rem;
  user-select: none;
}
/* Todo lo que se arrastra se puede además pulsar: un clic selecciona la pieza
   y el siguiente la coloca. Es lo único que hace la pantalla usable en
   tableta. */
.pieza.elegida { outline: 3px solid var(--bs-primary); outline-offset: 2px; }
.pieza:focus-visible { outline: 3px solid var(--bs-primary); outline-offset: 2px; }

.zona {
  border: 2px dashed var(--bs-border-color);
  border-radius: .375rem;
  min-height: 60px;
  display: flex; align-items: center; justify-content: center;
  flex-wrap: wrap; gap: .4rem;
  color: var(--bs-secondary-color); font-size: .8rem;
  padding: .4rem;
}
.zona.diana { border-color: var(--bs-primary); background: var(--bs-primary-bg-subtle); }
.zona.llena { border-style: solid; color: var(--bs-body-color); }
/* Una zona de soltar que además contiene una lista numerada tiene que dejar de
   centrar su contenido en cuanto tiene algo dentro. */
.zona.zona-lista.llena { display: block; }

.campos-trama {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(5.2rem, 1fr));
  gap: .5rem;
}
.campos-trama label { font-size: .7rem; color: var(--bs-secondary-color); margin-bottom: .1rem; }

.crc-ok { color: var(--bs-success); font-weight: 600; }
.crc-mal { color: var(--bs-danger); font-weight: 600; }

.salida { list-style: none; margin: 0; padding: 0; }
.salida li {
  display: flex; justify-content: space-between; align-items: center; gap: .5rem;
  padding: .2rem .5rem;
  border: 1px solid var(--bs-border-color);
  border-radius: .25rem;
  margin-bottom: .25rem;
  background: var(--bs-body-bg);
  font-family: var(--bs-font-monospace); font-size: .85rem;
}
.salida .orden { color: var(--bs-secondary-color); font-size: .75rem; }

/* Sin el historial el estudiante pierde el hilo: el tiempo está detenido y los
   eventos son muchos. */
.historial {
  max-height: 190px; overflow-y: auto;
  font-family: var(--bs-font-monospace); font-size: .72rem;
}
.historial div { padding: .1rem 0; border-bottom: 1px solid var(--bs-border-color); }
.historial .t { color: var(--bs-secondary-color); }
/* Un evento que el estudiante se saltó no se lee igual que uno que resolvió:
   el estado con el que empezó el siguiente no fue el que él dejó. */
.historial .resuelto { opacity: .75; }
.historial .marca { color: var(--hdlc-aviso); font-style: italic; }

/* Lo que ha valido el evento, con el color de su nivel. */
.nivel-oro { color: #8a7220; font-weight: 600; }
.nivel-plata { color: #667180; font-weight: 600; }
.nivel-bronce { color: #8c5620; font-weight: 600; }

/* ---------- informe del examen ---------- */

/* Los eventos posteriores a la divergencia se atenúan a propósito: su error
   puede no ser suyo, y darles el mismo peso visual convertiría un fallo en
   seis. */
.examen-evento {
  border: 1px solid var(--bs-border-color);
  border-radius: .375rem;
  padding: .5rem .75rem;
  margin-bottom: .5rem;
}
.examen-evento.divergencia { border-color: var(--bs-danger); border-width: 2px; }
.examen-evento.consecuencia { opacity: .6; }
.examen-evento .pasos { margin: .4rem 0 0; }

/* ---------- informe de ayuda (§5.2) ---------- */

.pasos { list-style: none; padding: 0; margin: .75rem 0; }
.pasos li { display: flex; gap: .5rem; padding: .2rem 0; align-items: baseline; }
.pasos .si { color: var(--bs-success); font-weight: 700; }
.pasos .no { color: var(--bs-danger); font-weight: 700; }

/* ==================================================================
   Medallas y marcador (§7)
   ================================================================== */

.medalla {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.4rem; height: 2.4rem; border-radius: 50%;
  font-size: 1.1rem; border: 2px solid transparent;
}
.medalla.bronce { background: #cd7f3222; border-color: #cd7f32; color: #8c5620; }
.medalla.plata { background: #9aa5b122; border-color: #9aa5b1; color: #667180; }
.medalla.oro { background: #d4af3722; border-color: #d4af37; color: #8a7220; }
.medalla.sin { opacity: .3; filter: grayscale(1); }

/* Icono de información: el texto va en el `title` nativo, así que tiene que
   invitar a posarse encima y ser alcanzable con el teclado. */
.icono-info {
  cursor: help;
  color: var(--bs-primary);
  font-size: .95rem;
  margin-left: .25rem;
}
.icono-info:focus-visible { outline: 2px solid var(--bs-primary); outline-offset: 2px; }

/* El multiplicador del mapa de progreso lleva su desglose en el title: hay que
   decir que se puede consultar, o nadie pasa el ratón por encima. */
.ayuda-multiplicador {
  cursor: help;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
}
.ayuda-multiplicador:focus-visible { outline: 2px solid var(--bs-primary); outline-offset: 2px; }

/* Incrementador propio: dos flechitas pegadas al borde derecho del campo.
   Se dibuja a mano porque los decimales van en un input de TEXTO —hay que
   admitir la coma— y ése no tiene flecha nativa; así enteros y decimales se
   manejan igual. La nativa se esconde para que no salgan dos. */
.campo-pasos { position: relative; display: block; }
.campo-pasos > .form-control { padding-right: 1.5rem; }
.campo-flechas {
  position: absolute; top: 1px; right: 1px; bottom: 1px;
  width: 1.25rem; display: flex; flex-direction: column;
  border-radius: 0 .375rem .375rem 0; overflow: hidden;
}
.campo-flecha {
  flex: 1; border: 0; padding: 0; line-height: 1; font-size: .55rem;
  background: transparent; color: var(--bs-secondary-color); cursor: pointer;
}
.campo-flecha:hover { background: var(--bs-secondary-bg); color: var(--bs-body-color); }
.campo-flecha:active { background: var(--bs-tertiary-bg); }
.sin-flecha-nativa { appearance: textfield; -moz-appearance: textfield; }
.sin-flecha-nativa::-webkit-outer-spin-button,
.sin-flecha-nativa::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* Hueco reservado mientras llega el contenido. El brillo dice que se está
   cargando; sin él, una barra gris quieta parece contenido de verdad. */
.esqueleto {
  border-radius: .375rem;
  margin-bottom: .5rem;
  background: linear-gradient(90deg,
    var(--bs-secondary-bg) 25%, var(--bs-tertiary-bg) 37%, var(--bs-secondary-bg) 63%);
  background-size: 400% 100%;
  animation: esqueleto-brillo 1.4s ease infinite;
}
@keyframes esqueleto-brillo {
  from { background-position: 100% 50%; }
  to { background-position: 0 50%; }
}
@media (prefers-reduced-motion: reduce) { .esqueleto { animation: none; } }

.stat-card .valor { font-size: 1.4rem; font-weight: 600; }
.stat-card .etiqueta { font-size: .75rem; color: var(--bs-secondary-color); }

.barra-progreso { height: .5rem; }

/* ==================================================================
   Cronograma (§6.3)
   ================================================================== */

.svg-panel {
  background: var(--bs-body-bg);
  border: 1px solid var(--bs-border-color);
  border-radius: .5rem;
  width: 100%;
  overflow-x: auto;
}

/* ==================================================================
   Recorrido guiado (tour.js)
   ================================================================== */

/* El hueco iluminado no es un agujero de verdad: es un rectángulo transparente
   con una sombra de radio enorme, que oscurece todo lo que queda fuera. Así
   basta con mover UN elemento para destacar cualquier parte de la pantalla. */
.tour-bloqueo { position: fixed; inset: 0; z-index: 2050; }
.tour-foco {
  position: fixed;
  z-index: 2051;
  border-radius: .5rem;
  box-shadow: 0 0 0 100vmax rgba(0, 0, 0, .55), 0 0 0 2px var(--bs-primary) inset;
  pointer-events: none;
  transition: top .15s, left .15s, width .15s, height .15s;
}
.tour-globo { position: fixed; z-index: 2052; width: min(24rem, calc(100vw - 2rem)); }

/* ==================================================================
   Pensada para PC, pero que no se rompa en tableta
   ================================================================== */

@media (max-width: 767.98px) {
  .celda { width: 30px; height: 28px; }
  .pieza-msg { width: 44px; height: 44px; font-size: .8rem; }
  .pieza-msg.chica { width: 34px; height: 34px; font-size: .7rem; }
}

/* ---------- distribución de tiempos (resolución automatizada) ---------- */
.distribucion-tiempos { display: flex; gap: .25rem; align-items: flex-end; }
.distribucion-tiempos .cuadro { width: 3.1rem; text-align: center; font-size: .65rem; }
.distribucion-tiempos .tiempo-barra {
  background: var(--bs-secondary-color); min-height: 2px; border-radius: 2px 2px 0 0;
}
/* Los tres primeros cuadros —por debajo del mínimo plausible— no parecen humanos. */
.distribucion-tiempos .tiempo-barra.rapida { background: #c2570c; }
.distribucion-tiempos .num { font-weight: 600; }
.distribucion-tiempos .eti { color: var(--bs-secondary-color); white-space: nowrap; }
