:root {
  /* Paleta Claude Code */
  --fondo: #1b1917;
  --fondo-2: #21201d;
  --panel: #262421;
  --borde: #35322e;
  --borde-claro: #46423c;
  --texto: #f0eee6;
  --tenue: #a39d94;
  --acento: #d97757;
  --acento-fuerte: #c2603f;
  --ok: #7fa87f;
  --error: #d2694f;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

/* Modo claro (icono del sol en la cabecera de Ajustes). Toda la interfaz
   usa variables, así que basta con redefinir la paleta. Los acentos van un
   punto más oscuros: sobre blanco, los originales perdían contraste.
   La TERMINAL sigue oscura a propósito: es una terminal, y lo que pinta
   dentro (tmux, Claude Code) trae sus propios colores oscuros. */
html.claro {
  --fondo: #f4f2ee;
  --fondo-2: #eae7e0;
  --panel: #ffffff;
  --borde: #d5d0c7;
  --borde-claro: #b9b3a8;
  --texto: #161412;
  --tenue: #6e675e;
  --acento: #c25a38;
  --acento-fuerte: #a94a2c;
  --ok: #44793f;
  --error: #b03a20;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

/* Oculto genérico. OJO: nada de style="display:none" en el HTML — la CSP
   (style-src 'self') bloquea los atributos style y el elemento nacería
   VISIBLE. Siempre esta clase; el JS puede seguir usando .style por CSSOM. */
.oculto { display: none; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--fondo);
  color: var(--texto);
  font-family: var(--mono);
  overscroll-behavior: none;
  -webkit-text-size-adjust: 100%;
  /* El documento no se mueve nunca: así la barra superior no se va arriba
     cuando el teclado del móvil obliga a desplazar la página. Cada pantalla
     tiene su propia zona con scroll (.lista, .pantalla, la terminal). */
  overflow: hidden;
}

body {
  height: 100dvh;
  display: flex;
  flex-direction: column;
}

/* Enfoque visible con teclado o mando, sin ensuciar el uso táctil */
:focus-visible {
  outline: 2px solid var(--acento);
  outline-offset: 2px;
  border-radius: 6px;
}

/* El cursor de escritura parpadea en el naranja Claude en todos los campos */
input, textarea { caret-color: var(--acento); }

/* ------------------------------------------------- efecto láser de los botones */

/* Al pulsar CUALQUIER botón, un trazo naranja recorre su borde completo en el
   sentido de las agujas del reloj. Se dibuja como trazo de SVG (efectos.js
   añade el svg al vuelo): funciona igual en todos los botones y navegadores,
   sin depender de trucos de CSS que fallaban según el botón. */

@keyframes laser-trazo {
  to { stroke-dashoffset: 0; }
}

button, a.icono-boton { position: relative; }

svg.laser-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
}
svg.laser-svg rect {
  fill: none;
  stroke: var(--acento);
  stroke-width: 2.5;
  stroke-linejoin: round;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  animation: laser-trazo 0.55s linear forwards;
  filter: drop-shadow(0 0 5px var(--acento));
}
/* En los botones de navegación va más despacio, para saborearlo */
.barra-superior svg.laser-svg rect { animation-duration: 0.8s; }

/* Reloj de carga: cuando algo tarda, la chispa de Claude aparece en el centro
   de la pantalla y su contorno se ilumina en naranja claro, en el sentido de
   las agujas del reloj, una y otra vez hasta que la operación termina.
   No captura toques: solo informa. */
.espera-carga {
  position: fixed;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  z-index: 60;
}
.espera-carga.visible { display: flex; }
.espera-carga svg { width: 58px; height: 58px; overflow: visible; }
.espera-carga path {
  fill: none;
  stroke: #f0a380;
  stroke-width: 1.6;
  stroke-linejoin: round;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  animation: laser-trazo 0.9s linear infinite;
  filter: drop-shadow(0 0 8px rgba(240, 163, 128, 0.85));
}

/* El mismo reloj de carga, en pequeño y dentro del botón: mientras el servidor
   comprueba la contraseña, el botón enseña la chispa iluminándose, para que se
   vea que está trabajando y no parezca que el toque no ha entrado. */
button.cargando {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
}
button.principal:disabled.cargando { opacity: 0.85; }
.chispa-cargando {
  width: 17px;
  height: 17px;
  overflow: visible;
  flex: none;
}
.chispa-cargando path {
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linejoin: round;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  animation: laser-trazo 0.9s linear infinite;
}
/* Sin animaciones, la chispa se queda dibujada entera en vez de desaparecer. */
@media (prefers-reduced-motion: reduce) {
  .chispa-cargando path { stroke-dashoffset: 0; }
  /* Sin animaciones, el reloj de carga central debe verse igualmente:
     el trazo se pinta completo en vez de dibujarse girando. */
  .espera-carga path { stroke-dashoffset: 0; }
}

/* Cuadro de eco: enseña lo que se está escribiendo cuando el teclado lo tapa */
.eco-escritura {
  position: fixed;
  top: calc(env(safe-area-inset-top) + 46px);
  left: 12px;
  right: 12px;
  z-index: 26;
  background: var(--panel);
  border: 2px solid var(--acento);
  border-radius: 10px;
  padding: 9px 12px;
  font-family: var(--mono);
  font-size: 14px;
  line-height: 1.45;
  color: var(--texto);
  max-height: 22dvh;
  overflow-y: auto;
  white-space: pre-wrap;
  word-break: break-word;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
}
.eco-escritura::after {
  content: '▍';
  color: var(--acento);
  animation: latido-punto 1s ease-in-out infinite;
}

/* Aviso flotante breve. Reglas fijas: TODOS los avisos tienen el mismo tamaño
   y la misma posición (arriba, justo bajo la barra de GitHub/Ficheros/Más),
   duran 6 segundos y NO bloquean nada (pointer-events: none deja pasar los
   toques, así se puede seguir pulsando botones y escribiendo debajo). */
.toast {
  position: fixed;
  top: calc(env(safe-area-inset-top) + 52px);
  left: 12px;
  right: 12px;
  min-height: 58px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  pointer-events: none;
  background: var(--panel);
  border: 1px solid var(--acento-fuerte);
  color: var(--texto);
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.4;
  padding: 9px 13px;
  border-radius: 10px;
  z-index: 40;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
}
.toast.bueno { border-color: var(--ok); }

/* El cuadro de «actualizado»: verde de verdad, con su hora y con sitio para
   leerla. Es la respuesta a algo que has pulsado tu, no un aviso de paso. */
.toast.actualizado {
  flex-direction: column;
  gap: 4px;
  min-height: 0;
  padding: 13px 15px;
  border-width: 2px;
  border-color: var(--ok);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .35), 0 10px 30px rgba(0, 0, 0, .45);
  background:
    linear-gradient(180deg, rgba(127, 168, 127, .18), rgba(127, 168, 127, .06)),
    var(--panel);
}
.toast.actualizado .toast-titulo {
  color: var(--ok);
  font-size: 15px;
  letter-spacing: .12em;
}
.toast.actualizado .toast-reloj {
  color: var(--texto);
  font-size: 13.5px;
  font-variant-numeric: tabular-nums;
}
.toast.actualizado .toast-detalle {
  color: var(--tenue);
  font-size: 11.5px;
  line-height: 1.35;
}

/* --------------------------------------------------------- pantallas de acceso */

.pantalla {
  flex: 1;
  display: flex;
  flex-direction: column;
  /* Todo arranca más abajo, unas cuatro líneas (a gusto de Pedro, 24/08/2026).
     Se pasa de «center» a «flex-start» a propósito: centrando, subir el hueco
     de arriba solo desplaza la mitad, y el resultado no era predecible. La
     pantalla tiene scroll propio, así que en un móvil bajito no se pierde nada. */
  justify-content: flex-start;
  /* Subido 5 líneas y luego 2 más (a gusto de Pedro, 24/08/2026): 118 → 40 → 8px. */
  padding: calc(8px + env(safe-area-inset-top)) 22px calc(26px + env(safe-area-inset-bottom));
  max-width: 470px;
  width: 100%;
  margin: 0 auto;
  /* Scroll propio: el documento está bloqueado, y con el teclado abierto
     los campos de acceso tienen que seguir alcanzándose. */
  min-height: 0;
  overflow-y: auto;
  /* Aura sutil del acento tras la marca, como en Claude Code */
  background:
    radial-gradient(420px 280px at 18% 22%, rgba(217, 119, 87, 0.07), transparent 70%),
    radial-gradient(360px 260px at 88% 92%, rgba(217, 119, 87, 0.04), transparent 70%);
}

.chispa {
  width: 34px;
  height: 34px;
  margin-bottom: 18px;
  display: block;
  /* La estrella de la portada late igual que la chispa cuando Claude trabaja */
  animation: chispa-zoom 1.6s ease-in-out infinite;
  transform-origin: center;
}

.marca h1 {
  font-size: 25px;
  line-height: 1.2;
  letter-spacing: -0.015em;
  margin: 0 0 8px;
  font-weight: 600;
}
.marca h1 span { color: var(--acento); }

.marca p {
  margin: 0 0 26px;
  color: var(--tenue);
  font-size: 14px;
  line-height: 1.55;
  max-width: 38ch;
}

.estado-servidor {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--tenue);
  margin-bottom: 16px;
}

.punto {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--tenue);
  flex: 0 0 auto;
}
/* La luz de estado (verde, ámbar o roja) late de forma bien visible */
@keyframes latido-punto {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.3; transform: scale(1.3); }
}
.punto.activo,
.punto.ambar,
.punto.error {
  width: 10px;
  height: 10px;
  animation: latido-punto 1.2s ease-in-out infinite;
}
.punto.activo { background: var(--ok); box-shadow: 0 0 0 4px rgba(127, 168, 127, 0.22); }
.punto.ambar { background: #d9a55f; box-shadow: 0 0 0 4px rgba(217, 165, 95, 0.22); }
.punto.error { background: var(--error); box-shadow: 0 0 0 4px rgba(210, 105, 79, 0.22); }

.tarjeta {
  background: var(--panel);
  border: 1px solid var(--borde);
  border-radius: 12px;
  /* Más estrecha y recogida (a gusto de Pedro): el circuito asoma debajo
     sin tener que hacer scroll en la portada. */
  padding: 12px 14px;
  max-width: 330px;
  width: 100%;
  margin: 0 auto;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25);
}

.campo { margin-bottom: 10px; }
.campo.oculto { display: none; }

.campo label {
  display: block;
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--tenue);
  margin-bottom: 7px;
}

.campo input {
  width: 100%;
  background: var(--fondo-2);
  border: 1px solid var(--borde-claro);
  border-radius: 9px;
  color: var(--texto);
  font-size: 16px; /* 16px evita el zoom automático de iOS */
  font-family: var(--mono);
  padding: 10px 12px;
  outline: none;
  transition: border-color 0.15s ease;
}
.campo input:focus { border-color: var(--acento); }

.campo input.codigo {
  letter-spacing: 0.42em;
  text-align: center;
  font-size: 22px;
  padding: 14px;
}

button.principal {
  width: 100%;
  border: none;
  border-radius: 9px;
  background: var(--acento);
  color: #20130d;
  font-size: 15.5px;
  font-weight: 650;
  font-family: var(--mono);
  padding: 14px;
  margin-top: 4px;
  cursor: pointer;
}
button.principal:active { background: var(--acento-fuerte); }
button.principal:disabled { opacity: 0.5; }
button.principal.oculto, .separador-o.oculto { display: none; }

/* Conmutador de Face ID de la portada: verde activado, ámbar desactivado */
.boton-fid { display: block; }
.boton-fid.elegido { border-color: var(--ok); color: var(--ok); }
.boton-fid.ambar { border-color: #d9a55f; color: #d9a55f; }

.separador-o {
  text-align: center;
  color: var(--tenue);
  font-size: 11.5px;
  margin: 12px 0;
}

button.secundaria {
  width: 100%;
  margin-top: 10px;
  border: 1px solid var(--borde-claro);
  border-radius: 9px;
  background: transparent;
  color: var(--tenue);
  font-family: var(--mono);
  font-size: 13.5px;
  padding: 11px;
  cursor: pointer;
}

.aviso {
  margin-top: 13px;
  font-size: 13px;
  line-height: 1.45;
  padding: 11px 12px;
  border-radius: 8px;
  display: none;
}
.aviso.visible { display: block; }
.aviso.malo { background: rgba(210, 105, 79, 0.12); border: 1px solid rgba(210, 105, 79, 0.4); color: #eda891; }
.aviso.bueno { background: rgba(127, 168, 127, 0.12); border: 1px solid rgba(127, 168, 127, 0.4); color: #a8ccA8; }

.pie {
  margin-top: 20px;
  font-size: 11px;
  color: #6b655d;
  text-align: center;
  letter-spacing: 0.06em;
}
/* En la portada, el pie va bien abajo, muy separado del dibujo */
.pie.pie-abajo { margin-top: 164px; }

/* El circuito de la portada, al MISMO tamaño que el de Salud.
   CUIDADO, que esto costó tres intentos: el ancho NUNCA fue el problema.
   `main.pantalla` es un flex en columna, y este SVG es uno de sus hijos. Como
   lleva `aspect-ratio`, cuando el contenido de la portada no cabe a lo alto
   (título, texto, estado, usuario, contraseña, Entrar, Face ID y pie) el
   navegador ENCOGE el SVG en vertical y el aspect-ratio arrastra el ancho
   detrás: quedaba en ~90px en el iPhone. En pantalla ancha sí cabía, por eso
   al probarlo en el PC parecía correcto.
   La cura es `flex: none`, que le prohíbe encogerse. La portada ya tiene
   scroll propio (overflow-y: auto), así que no se pierde nada de vista.
   NO quitar `flex: none` ni volver a tocar el ancho creyendo que es eso. */
main.pantalla .circuito-portada {
  flex: none;
  width: 100%;
  max-width: 430px;
  margin: 20px auto 0;
}
main.pantalla .circuito-portada .diagrama-salud {
  width: 100%;
  max-width: none;
  margin: 0;
  /* Proporción del lienzo de la portada: alto real garantizado */
  aspect-ratio: 780 / 552;
}
/* Letras y líneas a juego con los iconos agrandados del propio SVG */
/* Las dos versiones comparten ya el mismo lienzo de 780 de ancho, así que el
   tamaño del texto lo pone la regla general: aquí no se toca. */
main.pantalla .diagrama-salud .flujo { stroke-width: 2; }

/* --------------------------------------------------------- alta del código */

.pasos {
  counter-reset: paso;
  margin: 0 0 18px;
  padding: 0;
  list-style: none;
}
.pasos li {
  counter-increment: paso;
  position: relative;
  padding-left: 26px;
  margin-bottom: 9px;
  color: var(--tenue);
  font-size: 13.5px;
  line-height: 1.5;
}
.pasos li::before {
  content: counter(paso);
  position: absolute;
  left: 0;
  top: 1px;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  border: 1px solid var(--borde-claro);
  color: var(--acento);
  font-size: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.qr {
  width: 100%;
  max-width: 250px;
  margin: 0 auto 14px;
  display: block;
  border-radius: 10px;
  background: #f0eee6;
  padding: 8px;
}

.clave-manual {
  text-align: center;
  font-size: 12.5px;
  color: var(--tenue);
  word-break: break-all;
  line-height: 1.6;
  margin-bottom: 16px;
}
.clave-manual b { color: var(--texto); font-weight: 600; letter-spacing: 0.06em; }

/* --------------------------------------------------------- terminal */

.barra-superior {
  display: flex;
  align-items: center;
  /* Todo más recogido a la izquierda para que quepa «claude code» en vertical */
  gap: 6px;
  /* Los laterales respetan la zona de la muesca: en horizontal, el botón «Más»
     ya no queda escondido en el borde derecho. */
  padding: calc(env(safe-area-inset-top) + 8px) calc(8px + env(safe-area-inset-right)) 8px calc(8px + env(safe-area-inset-left));
  background: var(--fondo-2);
  border-bottom: 1px solid var(--borde);
  flex: 0 0 auto;
  /* Siempre visible aunque se haga scroll */
  position: sticky;
  top: 0;
  z-index: 30;
}

/* Botones de la barra más compactos (misma letra, menos aire) */
.barra-superior .icono-boton { padding: 5px 7px; }

.barra-superior .chispa-mini { width: 16px; height: 16px; flex: 0 0 auto; }

/* La luz de estado y el texto «Conectado» van medio carácter a la derecha */
.barra-superior .punto { margin-left: 0.5ch; }

/* La chispa late mientras Claude trabaja, como en claude.ai */
@keyframes chispa-zoom {
  0%, 100% { transform: scale(1); opacity: 1; }
  50%      { transform: scale(1.45); opacity: 0.75; }
}
.barra-superior .chispa-mini.trabajando { animation: chispa-zoom 0.9s ease-in-out infinite; }

/* GitHub, Ficheros y Más: ajuste fino de su sitio en la barra */
.barra-superior .icono-boton:last-of-type { margin-right: 7px; }

.barra-superior .titulo {
  font-size: 12.5px;
  color: var(--texto);
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  line-height: 1;
  /* Media línea más abajo y media más a la derecha (pedido por Pedro,
     26/08/2026): antes iba a -2px, alineado a ras con los botones. */
  margin-top: 4px;
  padding-left: 6px;
}
.barra-superior .titulo em { font-style: normal; color: var(--tenue); }
/* «TERMINAL» en naranja, en su propia línea debajo de «claude code» y con su
   mismo tamaño (12,5 px, heredado de .titulo): mientras estés DENTRO de la
   terminal de root. display:block es lo que lo baja de línea, sin tocar el
   nowrap del título. */
.barra-superior .titulo .marca-root {
  display: block;
  color: var(--acento);
  font-weight: 700;
  letter-spacing: 0.09em;
  line-height: 1.2;
  margin-top: 3px;
}
/* El título es pulsable: tocarlo abre la salud del servidor */
.barra-superior .titulo { cursor: pointer; }

.icono-boton {
  background: transparent;
  border: 1px solid var(--borde-claro);
  color: var(--tenue);
  border-radius: 8px;
  font-size: 12px;
  font-family: var(--mono);
  padding: 6px 10px;
  cursor: pointer;
}
.icono-boton:active { background: var(--panel); color: var(--texto); }

/* Botón de vuelta a la terminal: destaca sin gritar */
.icono-boton.acento-suave { color: var(--acento); border-color: var(--acento-fuerte); }

/* Botón que existe pero aún no puede actuar (p. ej. web sin publicar) */
.icono-boton.apagado { opacity: 0.55; }

/* Botones de navegación: nada de relleno al pulsar — el láser recorre el
   borde en sentido horario hasta completarlo (su ritmo, arriba con el láser). */
.barra-superior .icono-boton:active { background: transparent; }

/* Opción vigente (p. ej. el modelo de Claude en uso): marcada en verde */
.rejilla button.elegido {
  border-color: var(--ok);
  background: rgba(127, 168, 127, 0.14);
  color: var(--ok);
}
.rejilla button.elegido small { color: rgba(127, 168, 127, 0.85); }

/* Opción desactivada pero disponible (Face ID, doble verificación): ámbar */
.rejilla button.ambar {
  border-color: #d9a55f;
  background: rgba(217, 165, 95, 0.12);
  color: #d9a55f;
}
.rejilla button.ambar small { color: rgba(217, 165, 95, 0.85); }

/* Opción seleccionada: naranja suave latiendo hasta que se vuelva a pulsar */
.rejilla button.seleccionado {
  border-color: var(--acento);
  background: rgba(217, 119, 87, 0.16);
  color: var(--acento);
  animation: latido-suave 2s ease-in-out infinite;
}
.rejilla button.seleccionado small { color: rgba(217, 119, 87, 0.85); }

/* Botón de emergencia: naranja degradado latiendo suave, abajo del todo */
@keyframes latido-suave {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.72; }
}
.rejilla button.panico {
  background: linear-gradient(135deg, var(--acento), var(--acento-fuerte));
  border-color: var(--acento-fuerte);
  color: #20130d;
  font-weight: 650;
  text-align: center;
  animation: latido-suave 2s ease-in-out infinite;
}
.rejilla button.panico small { color: rgba(32, 19, 13, 0.75); }

/* «Subir fichero»: como sus vecinos pero con borde naranja y fondo de tecla */
#acciones #btnSubir {
  border-color: var(--acento);
  background: var(--panel);
  color: var(--texto);
}

/* Los botones de abajo de Ficheros se reparten en dos filas: todos a la
   vista, sin arrastrar de lado. Y el bloque baja todo lo que el borde del
   iPhone permite: se come casi todo el hueco reservado al gesto de inicio. */
#acciones {
  flex-wrap: wrap;
  overflow-x: visible;
  padding-bottom: max(6px, calc(env(safe-area-inset-bottom) - 14px));
}
#acciones button {
  flex: 1 1 30%;
  min-width: 104px;
}

#terminal {
  flex: 1 1 auto;
  min-height: 0;
  padding: 6px 4px 0 8px;
  background: var(--fondo);
}

.teclas {
  flex: 0 0 auto;
  display: flex;
  gap: 6px;
  padding: 7px 8px calc(7px + env(safe-area-inset-bottom));
  background: var(--fondo-2);
  border-top: 1px solid var(--borde);
  overflow-x: auto;
  scrollbar-width: none;
}
.teclas::-webkit-scrollbar { display: none; }

.teclas button {
  /* Mantener pulsado repite la tecla: sin lupa ni menú de iOS por medio */
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  flex: 0 0 auto;
  /* Txt+ / Txt− (fila de arriba) mueven --escala-teclas (0,7 a 1,6; la
     guarda app.js en localStorage): las DOS barras crecen o encogen a la
     vez, alto, letra y anchura. La terminal se reencaja sola. */
  min-width: calc(42px * var(--escala-teclas, 1));
  height: calc(37px * var(--escala-teclas, 1));
  border-radius: 8px;
  border: 1px solid var(--borde-claro);
  background: var(--panel);
  color: var(--texto);
  font-family: var(--mono);
  font-size: calc(13px * var(--escala-teclas, 1));
  padding: 0 calc(10px * var(--escala-teclas, 1));
  cursor: pointer;
}
.teclas button:active { background: var(--acento); color: #20130d; border-color: var(--acento); }
.teclas button.destacada { color: var(--acento); border-color: var(--acento-fuerte); }

/* Botones naranjas de la fila de herramientas (órdenes y memoria) */
.teclas button.naranja {
  background: var(--acento);
  color: #20130d;
  border-color: var(--acento);
  font-weight: 650;
}
.teclas button.naranja:active { background: var(--acento-fuerte); }

/* Botón «teclado»: fundido del color de panel al naranja, latiendo despacio.
   El naranja se queda muy bajo de opacidad a propósito: se ve que respira sin
   competir con los dos botones naranjas de al lado. La animación se detiene
   sola con prefers-reduced-motion (bloque del final). */
.teclas button.latido {
  border-color: var(--acento-fuerte);
  background-image: linear-gradient(160deg, rgba(217, 119, 87, 0) 45%, rgba(217, 119, 87, 0.10) 100%);
  animation: latido-teclado 3.4s ease-in-out infinite;
}
.teclas button.latido:active { background-image: none; }

/* Tecla fija («teclado»): pegada a la izquierda pase lo que pase; el resto de
   la fila hace scroll por debajo. El fondo opaco y la sombra la despegan de
   los botones que pasan por detrás. */
.teclas button.fija {
  position: sticky;
  left: 0;
  z-index: 2;
  background-color: var(--fondo-2);
  box-shadow: 6px 0 10px -2px rgba(0, 0, 0, 0.6);
}

@keyframes latido-teclado {
  0%, 100% {
    background-image: linear-gradient(160deg, rgba(217, 119, 87, 0) 45%, rgba(217, 119, 87, 0.10) 100%);
  }
  50% {
    background-image: linear-gradient(160deg, rgba(217, 119, 87, 0.05) 45%, rgba(217, 119, 87, 0.32) 100%);
  }
}

/* Catálogo de órdenes de Claude Code */
.lista-ordenes {
  max-height: 52dvh;
  overflow-y: auto;
  margin: 0 0 12px;
  border: 1px solid var(--borde);
  border-radius: 8px;
  background: var(--fondo);
}
.grupo-ordenes {
  position: sticky;
  top: 0;
  padding: 8px 10px 5px;
  background: var(--fondo);
  color: var(--acento);
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--borde);
}
/* Raya de separación por arriba: p. ej. el título GitHub tras el diagrama,
   para que no parezca parte del dibujo. */
.grupo-ordenes.con-raya { border-top: 1px solid var(--borde); }
.fila-orden {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 8px 10px;
  border-bottom: 1px solid var(--borde);
  font-size: 12.5px;
  line-height: 1.4;
}
.fila-orden:last-child { border-bottom: 0; }
.fila-orden button {
  flex: 0 0 auto;
  align-self: center;
  border: 1px solid var(--acento-fuerte);
  border-radius: 7px;
  background: transparent;
  color: var(--acento);
  font-family: var(--mono);
  font-size: 11px;
  padding: 5px 8px;
  cursor: pointer;
}
.fila-orden button:active { background: var(--acento); color: #20130d; }
.fila-orden code { color: var(--texto); font-weight: 600; flex: 0 1 auto; min-width: 0; overflow-wrap: anywhere; }
.fila-orden span { color: var(--tenue); min-width: 0; overflow-wrap: anywhere; }
.fila-orden small { color: var(--tenue); }

/* Punto rojo en «Más» cuando la salud detecta problemas */
.icono-boton.alerta { position: relative; }
.icono-boton.alerta::after {
  content: '';
  position: absolute;
  top: -4px;
  right: -4px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--error);
  border: 2px solid var(--fondo-2);
}

/* Puntos de la pantalla de salud */
.punto-salud {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex: 0 0 auto;
  margin-top: 5px;
}
.punto-salud.bien { background: var(--ok); }
.punto-salud.mal { background: var(--error); box-shadow: 0 0 0 3px rgba(210, 105, 79, 0.18); }

/* Editor de ficheros */
.editor {
  width: 100%;
  min-height: 42dvh;
  background: var(--fondo);
  border: 1px solid var(--borde);
  border-radius: 8px;
  color: var(--texto);
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.5;
  padding: 10px;
  margin: 0 0 12px;
  resize: vertical;
  caret-color: var(--acento);
}
.editor:focus { outline: none; border-color: var(--acento); }

/* Visor de imágenes */
.imagen-vista {
  display: block;
  max-width: 100%;
  max-height: 55dvh;
  margin: 0 auto 12px;
  border-radius: 8px;
  background: var(--fondo);
}

/* Con dos filas de teclas, solo la última lleva el margen del borde inferior */
.teclas.fila-1 { padding-bottom: 5px; border-top: 1px solid var(--borde); }
/* La fila de abajo aprovecha el hueco del borde inferior: solo se reserva lo
   justo de la zona del gesto de inicio, sin dejar una línea en blanco. */
#teclas2 { border-top: 0; padding-top: 0; padding-bottom: max(5px, calc(env(safe-area-inset-bottom) - 14px)); }
#teclas2 button { height: calc(34px * var(--escala-teclas, 1)); font-size: calc(12.5px * var(--escala-teclas, 1)); }

/* El cuadro de Acciones ocupa la pantalla entera con tres zonas fijas:
   título arriba (siempre visible, nunca cortado), lista de botones en medio
   con su propio scroll y CADA BOTÓN con su texto entero (las filas crecen lo
   que haga falta, nada se corta por abajo), y abajo del todo, siempre a la
   vista, «Volver a la terminal» y el botón de emergencia. */
/* El cuadro empieza claramente por debajo del reloj y la muesca: el hueco
   superior nunca baja de 126px (a gusto de Pedro: dos líneas más abajo que
   la primera versión). El sitio se recupera con un «Volver a la terminal»
   menos alto (ver .pie-menu). */
/* Por abajo, casi al borde: Pedro pidió (26/08/2026) estirar el cuadro dos
   líneas para que «Cerrar TODAS las sesiones» y «Volver» bajen; el hueco del
   gesto de inicio se aprovecha entero salvo 4px. */
#capaMenu { align-items: stretch; padding: max(calc(env(safe-area-inset-top) + 70px), 126px) 10px max(0px, calc(env(safe-area-inset-bottom) - 30px)); }

/* Salud del servidor manda: arriba del todo y con semáforo. Sin clase de
   estado (aún sin comprobar, o la comprobación falló): el naranja latiendo
   de siempre — el «no lo sé» JAMÁS se pinta de verde. */
#capaMenu #btnSalud {
  border-color: var(--acento);
  background: rgba(217, 119, 87, 0.16);
  color: var(--acento);
  animation: latido-suave 1.6s ease-in-out infinite;
}
#capaMenu #btnSalud small { color: rgba(217, 119, 87, 0.85); }
/* Verde fijo: todo bien. Ámbar fijo: algo pendiente (repos con trabajo sin
   subir o traer). Rojo parpadeando: alguna revisión ha fallado. */
#capaMenu #btnSalud.estado-bien {
  border-color: var(--ok); background: rgba(127, 168, 127, 0.14); color: var(--ok); animation: none;
}
#capaMenu #btnSalud.estado-bien small { color: rgba(127, 168, 127, 0.85); }
#capaMenu #btnSalud.estado-pendiente {
  border-color: #d9a55f; background: rgba(217, 165, 95, 0.14); color: #d9a55f; animation: none;
}
#capaMenu #btnSalud.estado-pendiente small { color: rgba(217, 165, 95, 0.85); }
#capaMenu #btnSalud.estado-mal {
  border-color: var(--error); background: rgba(210, 105, 79, 0.16); color: var(--error);
  animation: parpadeo-estado 0.7s ease-in-out infinite;
}
#capaMenu #btnSalud.estado-mal small { color: var(--error); }
#capaMenu .caja {
  max-width: 480px;
  width: 100%;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 12px 14px 4px;
}
#capaMenu .caja { position: relative; }
#capaMenu .caja h2 { font-size: 13px; margin-bottom: 2px; flex: 0 0 auto; }
/* Idioma: icono de globo arriba a la derecha (antes era un botón de la rejilla) */
.boton-idioma-cabecera {
  position: absolute;
  top: 26px;
  right: 10px;
  width: 34px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--borde-claro);
  border-radius: 8px;
  background: var(--fondo-2);
  cursor: pointer;
  z-index: 1;
}
.boton-idioma-cabecera svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: var(--acento);
  stroke-width: 1.6;
}
.boton-idioma-cabecera:active { border-color: var(--acento); }

/* La campana del aviso de fin: mismo estilo que el icono de idioma, a su
   izquierda. Encendida (hay sonido o vibración elegidos) se pinta de acento;
   apagada, tachada en gris. */
.boton-campana { right: 50px; }
.boton-tema { right: 90px; }
.boton-tema.encendida { border-color: var(--acento); }
.boton-tema.encendida svg { stroke: var(--acento); }

/* SERVIDOR, en una barra propia debajo de los tres iconos (v1.60.2).
   Antes era un cuarto icono, pero nacía en el mismo right:10px que el del
   idioma y el globo, que va después en el HTML, lo tapaba ENTERO: el botón
   estaba puesto y no se veía. Ahora ocupa justo el ancho de los tres iconos,
   del borde izquierdo del primero al borde derecho del último:
   right:10px + 114px de ancho = hasta los 124px donde empieza el del tema. */
.boton-servidor-cabecera {
  position: absolute;
  top: 62px;
  right: 10px;
  width: 114px;
  /* Crece hacia ABAJO (a gusto de Pedro, 26/08/2026): un 70 % más alto que los
     28 px que tenía. Los tres iconos de arriba no se mueven, porque cuelga de
     su misma línea y solo se alarga por el pie. */
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border: 1px solid var(--borde-claro);
  border-radius: 8px;
  background: var(--fondo-2);
  color: var(--texto);
  font-family: var(--mono);
  font-size: 11.5px;
  cursor: pointer;
  z-index: 1;
}
.boton-servidor-cabecera svg {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: var(--acento);
  stroke-width: 1.6;
  flex: 0 0 auto;
}
.boton-servidor-cabecera:active { border-color: var(--acento); }

/* Con los iconos arriba y la barra debajo, la frase baja dos líneas: sin eso
   la rejilla —que sí va a todo el ancho— se metía debajo de la barra. Y sigue
   con hueco a la derecha para romper antes de llegar a los iconos
   («…trabajando en el / servidor aunque…»). */
#capaMenu .caja > p[data-t="menu.intro"] { margin-top: 10px; padding-right: 126px; min-height: 74px; }
.boton-campana.encendida { border-color: var(--acento); }
.boton-campana.encendida svg { stroke: var(--acento); }
.boton-campana.apagada::after {
  content: '';
  position: absolute;
  left: 6px; right: 6px; top: 50%;
  border-top: 2px solid var(--tenue);
  transform: rotate(-35deg);
}

/* Parpadeo de fin de orden: un velo naranja muy suave sobre toda la pantalla,
   5 destellos de un segundo. No captura toques. */
body.fin-parpadeo::after {
  content: '';
  position: fixed;
  inset: 0;
  background: var(--acento);
  opacity: 0;
  pointer-events: none;
  z-index: 90;
  animation: parpadeo-fin 1s ease-in-out 5;
}
@keyframes parpadeo-fin { 50% { opacity: 0.28; } }
@media (prefers-reduced-motion: reduce) {
  body.fin-parpadeo::after { animation: none; }
}

/* Cuenta atrás del borrado total (tecla ⌫ mantenida): en el centro de la
   pantalla, en rojo y parpadeando. No captura toques. */
#cuentaBorrado {
  position: fixed;
  top: 42%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: rgba(27, 25, 23, 0.88);
  border: 1px solid var(--error);
  border-radius: 10px;
  padding: 10px 16px;
  color: var(--error);
  font-weight: 700;
  font-size: 15px;
  letter-spacing: 1px;
  z-index: 95;
  pointer-events: none;
  animation: parpadeo-estado 0.5s ease-in-out infinite;
}

/* Aparatos conectados: bajo el diagrama del circuito, a la izquierda y en el
   verde de los iconos. ● = conectado ahora; ○ = última conexión (48 h). */
.aparatos-circuito { margin: 2px 0 10px 6px; text-align: left; }
.aparatos-circuito .titulo-aparatos {
  color: var(--ok);
  font-size: 11px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  opacity: 0.8;
  margin-bottom: 2px;
}
.fila-aparato { color: var(--ok); font-size: 11.5px; line-height: 1.6; opacity: 0.7; }
.fila-aparato.ahora { opacity: 1; font-weight: 600; }
#capaMenu .caja > p { margin-bottom: 6px; font-size: 11.5px; line-height: 1.35; flex: 0 0 auto; }
#capaMenu .rejilla {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  align-content: start;
  margin-bottom: 0;
  gap: 5px;
  grid-auto-rows: auto;
  /* Al soltar el dedo, el scroll para en una pantalla entera de botones y no
     a media fila. Los puntos de parada los marca marcarZonasAjustes() en el
     primer boton de cada zona, midiendo cuantas filas caben de verdad. */
  scroll-snap-type: y mandatory;
  scroll-padding-top: 0;
}
#capaMenu .rejilla button.inicio-zona { scroll-snap-align: start; }
/* Cada botón crece con su texto (título + descripción apilados en columna):
   las descripciones largas de dos líneas quedan SIEMPRE dentro del borde.
   El overflow hidden es el cierre de seguridad: nada puede salirse.
   Compacto a propósito: con once filas de botones, cada píxel de alto
   cuenta para que la última fila no quede cortada por el borde. */
#capaMenu .rejilla button {
  /* El doble de alto que antes (a gusto de Pedro, 26/08/2026): ahora la
     rejilla tiene scroll propio, asi que no hay que apretar para que quepan
     las once filas. */
  min-height: 76px;
  height: auto;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  padding: 8px 10px;
  font-size: 12.5px;
  line-height: 1.3;
}
#capaMenu .rejilla button small { font-size: 10.5px; margin-top: 3px; }
#capaMenu .rejilla button.contorno,
#capaMenu .rejilla button.acento,
#capaMenu .rejilla button.panico { align-items: center; }
#capaMenu .rejilla button.contorno { padding-top: 6px; padding-bottom: 6px; }
/* Zona inferior fija del menú: no hace scroll con el resto. «Volver a la
   terminal» va compacto para dejarle el alto al resto del cuadro. */
#capaMenu .pie-menu {
  flex: 0 0 auto;
  overflow: visible;
  margin-top: 6px;
}
#capaMenu .pie-menu button.contorno {
  min-height: 36px;
  padding-top: 6px;
  padding-bottom: 6px;
}
#capaMenu .pie-menu button.panico { padding-top: 8px; padding-bottom: 8px; }

/* Salud a pantalla completa: sin scroll de más y con sitio para los gráficos.
   Empieza tres líneas más abajo, como el cuadro Más (mínimo 126px), y por
   abajo se estira casi hasta el borde (aprovecha el hueco del gesto). */
#capaSalud { align-items: stretch; padding: max(calc(env(safe-area-inset-top) + 70px), 126px) 10px max(6px, calc(env(safe-area-inset-bottom) - 12px)); }
#capaSalud .caja { max-width: 720px; width: 100%; display: flex; flex-direction: column; }
#capaSalud .lista-ordenes { flex: 1 1 auto; max-height: none; }

/* Gráficos de la pantalla de Salud */
.medida {
  display: flex;
  align-items: center;
  gap: 8px;
  /* Aire a los lados (unos tres espacios): el nombre no pega al borde
     izquierdo ni el porcentaje/la línea al derecho. */
  padding: 8px 30px;
  border-bottom: 1px solid var(--borde);
  font-size: 12.5px;
}
.medida-nombre { flex: 0 0 82px; color: var(--tenue); }
.medida-barra {
  flex: 1 1 auto;
  min-width: 40px;
  height: 8px;
  background: var(--fondo-2);
  border-radius: 999px;
  overflow: hidden;
}
.medida-relleno { display: block; height: 100%; border-radius: 999px; background: var(--tenue); }
.medida-relleno.bien { background: var(--ok); }
.medida-relleno.mal { background: var(--error); }
.medida-valor { flex: 0 0 44px; text-align: right; color: var(--texto); }
.chispa-linea { flex: 0 0 84px; height: 24px; }
.chispa-linea polyline { fill: none; stroke: var(--acento); stroke-width: 2; }

/* Gráficas de las últimas 24 horas en Salud: una por medida, a lo ancho,
   con el área bajo la línea rellena en naranja tenue. */
.grafica-dia { margin: 4px 0 10px; }
/* Raya de separación entre Procesador, Memoria y Disco: las tres gráficas se
   pintan iguales y sin línea no se sabía dónde acaba una y empieza la otra
   (pedido por Pedro, 23/08/2026). La primera no la lleva. */
.grafica-dia + .grafica-dia {
  border-top: 1px solid var(--borde);
  padding-top: 10px;
  margin-top: 12px;
}
.grafica-dia .cabecera-grafica {
  display: flex;
  justify-content: space-between;
  padding: 0 20px;
  font-size: 11.5px;
  /* El nombre del recurso, en el color del texto: es el rótulo que dice a qué
     corresponde la gráfica de debajo, no un dato secundario. */
  color: var(--texto);
  margin-bottom: 3px;
}
.grafica-dia .cabecera-grafica span:first-child {
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-size: 10.5px;
}
.grafica-dia .cabecera-grafica b { color: var(--texto); font-weight: 600; }
.grafica-dia svg { width: 100%; height: 44px; display: block; }
.grafica-dia path.area { fill: rgba(217, 119, 87, 0.14); stroke: none; }
.grafica-dia path.linea { fill: none; stroke: var(--acento); stroke-width: 1.6; }

/* Cuadro naranja para nombrar pestañas. Mismo lenguaje visual que el eco del
   teclado (borde de acento, fondo de panel, arriba del todo) porque Pedro lo
   pidió «como el del teclado». Va arriba a propósito: el teclado del iPhone
   ocupa la mitad inferior y taparía el campo. */
.cuadro-nombre {
  position: fixed;
  top: calc(env(safe-area-inset-top) + 46px);
  left: 12px;
  right: 12px;
  z-index: 45;
  background: var(--panel);
  border: 2px solid var(--acento);
  border-radius: 12px;
  padding: 13px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
}
.cuadro-nombre label {
  display: block;
  font-size: 12px;
  color: var(--tenue);
  margin-bottom: 7px;
}
.cuadro-nombre input {
  width: 100%;
  background: var(--fondo);
  border: 1px solid var(--borde-claro);
  border-radius: 8px;
  padding: 11px 12px;
  color: var(--texto);
  font-family: var(--mono);
  font-size: 16px; /* 16px o iOS hace zoom al enfocar el campo */
  margin-bottom: 10px;
}
.cuadro-nombre .rejilla { margin-bottom: 0; }

/* El campo de «Claude Code en remoto», con el mismo aspecto que el de nombrar
   pestañas. Los 16px no son estética: por debajo, iOS hace zoom al enfocarlo
   y la pantalla se descoloca. */
#remTarea {
  width: 100%;
  background: var(--fondo);
  border: 1px solid var(--borde-claro);
  border-radius: 8px;
  padding: 11px 12px;
  color: var(--texto);
  font-family: var(--mono);
  font-size: 16px;
  margin-bottom: 10px;
}
/* Cuatro líneas más abajo (pedido por Pedro, 26/08/2026): el cuadro nacía
   bajo la barra superior y la cabecera salía cortada; el scroll de dentro
   ya estaba, pero sin sitio arriba no llegaba a verse entero. */
#capaRemoto { padding-top: max(calc(env(safe-area-inset-top) + 118px), 152px); } /* +4 líneas más (v1.64.4) */
#capaRemoto .caja { max-height: 100%; overflow-y: auto; -webkit-overflow-scrolling: touch; }

/* Pantalla Servidor (v1.61.1). Los títulos de grupo —Servicios, Registros y
   errores, Copias de seguridad…— iban pegados a los botones del grupo de
   arriba y parecían suyos. Ahora cada uno abre con una raya y respira por
   arriba, así se ve dónde acaba un grupo y empieza el siguiente. */
.grupo-servidor {
  margin: 22px 0 8px;
  padding-top: 12px;
  border-top: 1px solid var(--borde);
  color: var(--tenue);
  font-size: 11.5px;
  line-height: 1.35;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.grupo-servidor.primero { margin-top: 18px; }
.grupo-servidor b { color: var(--texto); font-weight: 700; }

/* El título de la pantalla, en mayúsculas: es el rótulo de la sala, no una
   frase. text-transform y no el texto en mayúsculas a mano, que si no habría
   que repetirlo en los cinco idiomas. */
#capaServidor .caja h2 { text-transform: uppercase; letter-spacing: 0.06em; }

/* Un cuadro que NO está bien se puede tocar para saber qué hacer. Se nota que
   se puede: borde de acento y la flecha. Los que están bien, ni se tocan ni
   lo aparentan. */
.tarjeta-repo.tocable { cursor: pointer; border-color: var(--borde-claro); }
.tarjeta-repo.tocable:active { border-color: var(--acento); }
.tarjeta-repo.tocable .nombre-repo::after {
  content: ' ›';
  color: var(--acento);
  font-weight: 700;
}

/* La explicación de un cuadro con fallo. Enmarcada para que se vea que habla
   de lo que acabas de tocar y no de la pantalla entera. */
#srvArreglo {
  margin: 10px 0 4px;
  padding: 10px 12px;
  border: 1px solid var(--acento);
  border-radius: 8px;
  background: var(--fondo-2);
}
#srvArreglo .titulo-arreglo { font-size: 12.5px; font-weight: 700; margin-bottom: 6px; }
#srvArreglo ul { margin: 4px 0 8px; padding-left: 18px; }
#srvArreglo li { margin-bottom: 3px; }
#srvArreglo p { margin: 8px 0 2px; }

/* Pestañas de la terminal (ventanas de tmux). La fila solo aparece cuando
   hay más de una; la activa lleva el acento y una × para cerrarla.
   Mantenerla pulsada la despega para cambiarla de sitio. */
.pestana.arrastrando {
  z-index: 3;
  opacity: 0.92;
  transform-origin: center;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.5);
  border-color: var(--acento);
}
/* Mientras se arrastra, la fila no debe desplazarse ni seleccionar texto:
   si no, el dedo mueve la pestaña y el carrusel a la vez. */
.pestanas.reordenando {
  overflow-x: hidden;
  user-select: none;
  touch-action: none;
}
.nombre-pestana { pointer-events: none; }

/* Cada enlace de la semana es pulsable: al tocarlo se copia. La dirección se
   parte por donde haga falta, que hay URLs largísimas y no debe desbordar. */
.enlace-semana { cursor: pointer; }
.enlace-semana .titulo-hito {
  color: var(--acento);
  word-break: break-all;
  line-height: 1.4;
}
.enlace-semana:active { background: var(--fondo-2); }

/* Modo eliminar de Mis botones: el «Borrar» de cada fila siempre estuvo ahí,
   pero discreto. Con el modo activo pasa a rojo y se ve de lejos. */
.lista-ordenes.modo-borrar .fila-macro .icono-boton {
  border-color: var(--error);
  color: var(--error);
  font-weight: 600;
}

/* Botones visibles: una línea por tecla, con su casilla. */
.fila-visible {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 4px;
  border-bottom: 1px solid var(--borde);
  font-size: 13px;
}
.fila-visible:last-child { border-bottom: none; }
.fila-visible input {
  width: 20px;
  height: 20px;
  accent-color: var(--acento);
  flex: none;
}
/* Aviso de terminal de root abierta (v1.60.0). Es la guarda 2 del diseño: que
   nunca esté abierta sin que se vea. Rojo de verdad, no el --error suave de
   los mensajes corrientes — esto tiene que incomodar un poco. El mismo par
   display:none / .visible que las pestañas, porque .oculto está declarado
   arriba del todo y aquí perdería por orden. */
.aviso-root {
  flex: 0 0 auto;
  display: none;
  flex-direction: column;     /* texto arriba, botones debajo: franja baja */
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 3px calc(8px + env(safe-area-inset-right)) 4px calc(8px + env(safe-area-inset-left));
  background: #8f1d0f;
  color: #fff3ee;
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 700;
  line-height: 1.2;
  border-bottom: 1px solid #c2603f;
  animation: latido-root 2s ease-in-out infinite;
}
.aviso-root.visible { display: flex; }
.aviso-root-botones { display: flex; gap: 8px; justify-content: center; }
.aviso-root button {
  flex: 0 0 auto;
  background: rgba(255, 255, 255, 0.16);
  color: #fff3ee;
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: 7px;
  padding: 2px 8px;
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 700;
  line-height: 1.3;
}
@keyframes latido-root {
  0%, 100% { background: #8f1d0f; }
  50% { background: #b32c18; }
}
/* Último minuto: late más rápido y más fuerte (y ha pitado al entrar en él). */
.aviso-root.urgente { animation: latido-root-fuerte 0.5s ease-in-out infinite; }
@keyframes latido-root-fuerte {
  0%, 100% { background: #7a1408; }
  50% { background: #e8452a; }
}
@media (prefers-reduced-motion: reduce) {
  .aviso-root, .aviso-root.urgente { animation: none; }
}

.pestanas {
  flex: 0 0 auto;
  display: none;
  gap: 6px;
  padding: 5px 8px 3px;
  overflow-x: auto;
  background: var(--fondo);
  border-bottom: 1px solid var(--borde);
  -webkit-overflow-scrolling: touch;
}
.pestanas.visible { display: flex; }
.pestanas button {
  flex: 0 0 auto;
  border: 1px solid var(--borde-claro);
  border-radius: 8px 8px 3px 3px;
  background: var(--fondo-2);
  color: var(--tenue);
  font-family: var(--mono);
  font-size: 12px;
  padding: 5px 10px;
  cursor: pointer;
  white-space: nowrap;
}
.pestanas button.activa {
  color: var(--acento);
  border-color: var(--acento-fuerte);
  background: var(--panel);
}
.pestanas button.mas-pestana { color: var(--acento); font-weight: 700; }
/* La × de cerrar necesita ser un objetivo de dedo de verdad: con la anterior,
   de tamaño de texto, el toque caía en la pestaña y cambiaba de ventana en vez
   de cerrarla (Pedro, 24/08/2026). Ahora es un recuadro de 26px con su borde. */
.pestanas button .cerrar-pestana {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  margin: -4px -6px -4px 8px;
  border: 1px solid var(--borde-claro);
  border-radius: 6px;
  background: var(--fondo);
  color: var(--tenue);
  font-size: 15px;
  line-height: 1;
  vertical-align: middle;
}
.pestanas button.activa .cerrar-pestana { color: var(--acento); border-color: var(--acento-fuerte); }
.pestanas button .cerrar-pestana:active { background: var(--error); color: var(--texto); }

/* Buscador dentro de «leer todo»: va justo encima de los botones. */
.buscar-en-texto {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 8px 0 10px;
}
.buscar-en-texto input {
  flex: 1;
  min-width: 0;
  background: var(--fondo);
  border: 1px solid var(--borde-claro);
  border-radius: 8px;
  padding: 9px 10px;
  color: var(--texto);
  font-family: var(--mono);
  font-size: 16px; /* 16px o iOS hace zoom al enfocar */
}
.buscar-en-texto button {
  flex: 0 0 auto;
  width: 38px;
  padding: 9px 0;
  font-size: 16px;
}
.contador-busqueda {
  flex: 0 0 auto;
  min-width: 44px;
  text-align: center;
  font-size: 11.5px;
  color: var(--tenue);
}
/* La aparición en la que estás, más marcada que las demás. */
#textoLeer mark { background: rgba(217, 119, 87, 0.30); color: var(--texto); }
#textoLeer mark.actual { background: var(--acento); color: #1b1917; }

/* Resultados del buscador de conversaciones: fecha y hora arriba, y el
   extracto con la palabra encontrada resaltada en naranja. */
.resultado-busqueda {
  border: 1px solid var(--borde);
  border-radius: 8px;
  background: var(--fondo);
  padding: 8px 10px;
  margin-bottom: 8px;
}
.resultado-busqueda .cabecera-resultado {
  font-size: 11.5px;
  color: var(--tenue);
  margin-bottom: 4px;
}
.resultado-busqueda .cabecera-resultado b { color: var(--acento); font-weight: 600; }
.resultado-busqueda pre {
  margin: 0;
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--texto);
  white-space: pre-wrap;
  word-break: break-word;
}
.resultado-busqueda mark {
  background: rgba(217, 119, 87, 0.35);
  color: var(--texto);
  border-radius: 3px;
  padding: 0 1px;
}
.fila-buscador { display: flex; gap: 8px; margin-bottom: 10px; }
.fila-buscador input { flex: 1 1 auto; min-width: 0; }

/* Diff antes de fusionar: verde lo que entra, rojo lo que sale, y las
   cabeceras de fichero y de tramo en su propio color. */
.diff pre {
  margin: 0;
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-all;
}
.diff .l-mas { color: var(--ok); }
.diff .l-menos { color: var(--error); }
.diff .l-arroba { color: #d9a55f; }
.diff .l-fichero { color: var(--acento); font-weight: 700; }

/* Diario de trabajo: línea temporal con puntos naranjas. */
.dia-diario {
  color: var(--acento);
  font-weight: 700;
  font-size: 12.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 12px 0 6px;
}
.hito {
  position: relative;
  padding: 2px 0 10px 18px;
  border-left: 1px solid var(--borde-claro);
  margin-left: 5px;
}
.hito::before {
  content: '';
  position: absolute;
  left: -4.5px;
  top: 6px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--acento);
}
.hito.apagado::before { background: var(--tenue); }
.hito .hora-hito { color: var(--tenue); font-size: 11.5px; }
.hito .texto-hito { font-size: 13px; line-height: 1.45; }
.hito .texto-hito b { color: var(--texto); }
.hito .texto-hito code {
  color: var(--acento);
  background: var(--fondo);
  border-radius: 4px;
  padding: 0 4px;
  font-size: 11.5px;
}

/* Sesiones vivas en Seguridad */
.sesion-viva {
  display: flex;
  align-items: center;
  gap: 10px;
  border: 1px solid var(--borde);
  border-radius: 8px;
  padding: 8px 10px;
  margin-bottom: 6px;
}
.sesion-viva .punto-salud { flex: 0 0 auto; }
.sesion-viva small { color: var(--tenue); }
.sesion-viva .propia { color: var(--ok); font-size: 11px; margin-left: auto; }

/* Editor de «Mis botones» */
.fila-macro {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 6px 8px;
  border: 1px solid var(--borde);
  border-radius: 8px;
  padding: 8px;
  margin-bottom: 8px;
}
.fila-macro .nombre-macro { color: var(--acento); font-weight: 700; font-size: 13px; }
.fila-macro .texto-macro {
  grid-column: 1 / -1;
  color: var(--tenue);
  font-family: var(--mono);
  font-size: 11.5px;
  white-space: pre-wrap;
  word-break: break-word;
}
.form-macro { display: grid; gap: 8px; margin-top: 10px; }
.form-macro label.marcar { display: flex; align-items: center; gap: 8px; color: var(--tenue); font-size: 12.5px; }

/* Diagrama animado del circuito en Salud: iconos de iPhone, servidor, Claude
   y GitHub unidos por líneas de puntos que avanzan cuando fluye información.
   Verde = conectado · ámbar = pendiente de subir · rojo = sin conexión
   (en rojo la línea se queda parada). */
.diagrama-salud {
  display: block;
  width: 100%;
  max-width: 430px;
  margin: 12px auto 8px;
  /* La proporción explícita obliga a Safari de iOS a darle el alto que le
     corresponde: sin esto, a veces encajona el SVG en 150px y el dibujo
     sale encogido (en Chrome no pasaba y por eso costó cazarlo). */
  height: auto;
  /* Versión apaisada del circuito: 780×430. La de la portada es 780×600, más
     alta, y en Salud se comía las gráficas y la lista de revisiones. */
  aspect-ratio: 780 / 382;
  /* Tocarlo actualiza los datos del circuito al momento */
  cursor: pointer;
}
.diagrama-salud .icono-nodo {
  fill: none;
  stroke: var(--tenue);
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.diagrama-salud .icono-nodo.bien { stroke: var(--ok); }
.diagrama-salud .icono-nodo.pendiente { stroke: #d9a55f; }
.diagrama-salud .icono-nodo.mal { stroke: var(--error); }
.diagrama-salud .relleno-nodo { fill: var(--tenue); }
.diagrama-salud .relleno-nodo.bien { fill: var(--ok); }
.diagrama-salud .relleno-nodo.pendiente { fill: #d9a55f; }
.diagrama-salud .relleno-nodo.mal { fill: var(--error); }
.diagrama-salud text {
  /* 26 sobre un lienzo de 780. Estaba en 9.5, que era lo justo para el dibujo
     viejo de 340 de ancho; con el lienzo nuevo se quedaba ilegible. */
  fill: #cfc9be;
  font-size: 26px;
  font-weight: 500;
  letter-spacing: 0.6px;
  font-family: var(--mono);
  text-anchor: middle;
}
/* «Servidor» en mayúsculas, también cuando lo traduce el diccionario. El
   generador ya lo escribe en mayúsculas para el español; esto cubre el resto. */
.diagrama-salud .rotulo-servidor { text-transform: uppercase; }
.diagrama-salud .flujo {
  fill: none;
  stroke-width: 1.6;
  stroke-dasharray: 5 5;
  animation: flujo-avanza 0.9s linear infinite;
}
/* Los iconos también respiran: la imagen entera se ve viva */
.diagrama-salud .icono-nodo,
.diagrama-salud .relleno-nodo { animation: latido-suave 2.2s ease-in-out infinite; }
/* Zonas de toque del circuito: invisibles, pero capturan el dedo. Los iconos
   son trazos de 1,6px y con el dedo no se acierta ni de casualidad. */
.zonas-nodo rect {
  fill: transparent;
  cursor: pointer;
  pointer-events: all;
}
.zonas-nodo rect:active { fill: rgba(217, 119, 87, 0.16); }
.zonas-nodo rect.trabajando {
  fill: rgba(217, 119, 87, 0.22);
  animation: latido-suave 1.1s ease-in-out infinite;
}
/* Aspecto del circuito nuevo (tarjetas con aura y brillo, trama de puntos y
   líneas que corren). Estas reglas venían dentro del propio SVG, en un
   <style>, pero la CSP del servidor es style-src 'self' y bloquea los estilos
   incrustados: el dibujo salía sin colores. Por eso viven aquí. */
.diagrama-salud .carta {
  fill: rgba(255, 255, 255, 0.03);
  stroke: var(--tenue);
  stroke-opacity: 0.42;
  stroke-width: 1.5;
}
.diagrama-salud .carta.bien { stroke: var(--ok); }
.diagrama-salud .carta.pendiente { stroke: #d9a55f; }
.diagrama-salud .carta.mal { stroke: var(--error); }
.diagrama-salud .brillo {
  fill: none;
  stroke: rgba(255, 255, 255, 0.13);
  stroke-width: 1.2;
}
.diagrama-salud .aura { fill: var(--tenue); opacity: 0.16; }
.diagrama-salud .aura.bien { fill: var(--ok); }
.diagrama-salud .aura.pendiente { fill: #d9a55f; }
.diagrama-salud .aura.mal { fill: var(--error); }
.diagrama-salud .pulso { animation: latir-punto 3s ease-in-out infinite; }
@keyframes latir-punto { 0%, 100% { opacity: 0.45; } 50% { opacity: 1; } }

.diagrama-salud .punta { fill: var(--tenue); }
.diagrama-salud .punta.bien { fill: var(--ok); }
.diagrama-salud .punta.pendiente { fill: #d9a55f; }
.diagrama-salud .punta.mal { fill: var(--error); }
.diagrama-salud .flujo.bien { stroke: var(--ok); }
.diagrama-salud .flujo.pendiente { stroke: #d9a55f; animation-duration: 1.8s; }
.diagrama-salud .flujo.mal { stroke: var(--error); animation: none; opacity: 0.7; }
@keyframes flujo-avanza {
  to { stroke-dashoffset: -20; }
}

/* Ventana de "seleccionar": el texto de la terminal como texto normal de página */
.caja-texto { max-width: 640px; }
.texto-terminal {
  margin: 0 0 12px;
  padding: 10px;
  background: var(--fondo);
  border: 1px solid var(--borde);
  border-radius: 8px;
  color: var(--texto);
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.45;
  /* Antes eran 46dvh porque solo cabía la pantalla de tmux; ahora aquí entra
     todo lo hablado en el día y merece la pena verlo a pantalla más grande. */
  max-height: 58dvh;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-all;
  -webkit-user-select: text;
  user-select: text;
}

/* Pantalla apaisada: barras compactas para dejar sitio a la terminal */
@media (orientation: landscape) and (max-height: 520px) {
  .barra-superior { padding-top: calc(env(safe-area-inset-top) + 3px); padding-bottom: 3px; }
  /* En horizontal también con hueco arriba (tres líneas): el título y el
     texto no se cortan tampoco con el móvil tumbado. */
  #capaMenu, #capaSalud { padding-top: max(calc(env(safe-area-inset-top) + 60px), 64px); }
  .teclas { padding-top: 4px; }
  .teclas.fila-1 { padding-bottom: 3px; }
  .teclas button { height: 31px; min-width: 38px; font-size: 12px; }
  #teclas2 button { height: calc(29px * var(--escala-teclas, 1)); font-size: calc(11.5px * var(--escala-teclas, 1)); }
  .teclas:last-of-type { padding-bottom: calc(4px + env(safe-area-inset-bottom)); }
  .migas { padding-top: 5px; padding-bottom: 5px; }
}

.capa {
  position: fixed;
  inset: 0;
  background: rgba(27, 25, 23, 0.92);
  display: none;
  align-items: flex-end;
  justify-content: center;
  padding: 18px;
  padding-bottom: calc(18px + env(safe-area-inset-bottom));
  z-index: 20;
}
.capa.visible { display: flex; }

/* El cuadro del botón Menú, centrado en vertical (a gusto de Pedro, 23/08/2026).
   Las demás capas siguen pegadas abajo, al alcance del pulgar: solo cambia esta. */
#capaNav { align-items: center; }

/* La caja de «¿seguimos donde ibas?» crece con las tarjetas (PC, claude.ai,
   conversaciones) y se salía por arriba, tapada por el reloj y la muesca.
   Se le deja un techo de unas 6 líneas (a gusto de Pedro, 25/08/2026) y
   scroll propio: se ve entera, salgan las tarjetas que salgan. */
#capaSeguir { padding-top: max(calc(env(safe-area-inset-top) + 64px), 108px); }
#capaSeguir .caja { max-height: 100%; overflow-y: auto; }
/* Primeros pasos: ocho pasos con su remedio, el cuadro se salía por arriba y
   no había forma de leer los primeros. Cinco líneas más abajo y con scroll
   propio (pedido por Pedro, 25/08/2026). */
/* Pantalla Servidor, Ayuda de Ubuntu y Permisos de Claude: mismo criterio que
   Primeros pasos — cinco lineas mas abajo para que la cabecera no tape el
   titulo, y scroll propio del cuadro, que la lista de acciones es larga
   (pedido por Pedro, 26/08/2026). */
#capaServidor, #capaAyudaUbuntu, #capaModoClaude { padding-top: max(calc(env(safe-area-inset-top) + 54px), 90px); }
#capaServidor .caja, #capaAyudaUbuntu .caja, #capaModoClaude .caja { max-height: 100%; overflow-y: auto; -webkit-overflow-scrolling: touch; }
#capaPrimeros { padding-top: max(calc(env(safe-area-inset-top) + 54px), 90px); }
#capaPrimeros .caja { max-height: 100%; overflow-y: auto; -webkit-overflow-scrolling: touch; }
/* Seguridad y accesos: la lista de movimientos más alta y con scroll de dedo
   (pedido por Pedro, 25/08/2026); el cuadro entero también acotado, por si
   la pantalla es baja. */
#capaSeguridad { padding-top: max(calc(env(safe-area-inset-top) + 40px), 64px); }
#capaSeguridad .caja { max-height: 100%; overflow-y: auto; -webkit-overflow-scrolling: touch; display: flex; flex-direction: column; }
#capaSeguridad .lista-ordenes { max-height: none; flex: 1 1 auto; min-height: 40dvh; -webkit-overflow-scrolling: touch; }
/* Histórico de avisos (tecla «Histórico»): mismo trato que Seguridad. */
#capaHistorico { padding-top: max(calc(env(safe-area-inset-top) + 40px), 64px); }
#capaHistorico .caja { max-height: 100%; overflow-y: auto; -webkit-overflow-scrolling: touch; display: flex; flex-direction: column; }
#capaHistorico .lista-ordenes { max-height: none; flex: 1 1 auto; min-height: 40dvh; -webkit-overflow-scrolling: touch; }
/* Artifact: el listado de informes anteriores crece sin freno y sacaba el
   cuadro por arriba. Cuadro acotado y listado con scroll propio (pedido por
   Pedro, 26/08/2026). */
#capaArtifact { padding-top: max(calc(env(safe-area-inset-top) + 40px), 64px); }
#capaArtifact .caja { max-height: 100%; overflow-y: auto; -webkit-overflow-scrolling: touch; display: flex; flex-direction: column; }
#capaArtifact #artHistorico { flex: 1 1 auto; min-height: 24dvh; overflow-y: auto; -webkit-overflow-scrolling: touch; margin-bottom: 12px; border: 1px solid var(--borde); border-radius: 8px; padding: 6px; }

/* Buscar lleva campo de texto: al enfocarlo, el teclado del iPhone ocupa la
   mitad inferior y tapaba el cuadro entero, que nace pegado abajo. Arriba del
   todo (pedido por Pedro, 24/08/2026). Mismo motivo en Mis botones, que
   también escribe. */
/* Mis botones vuelve a abrirse como Órdenes (a gusto de Pedro, 24/08/2026).
   Lo había subido arriba del todo por el teclado del iPhone, pero así se veía
   cortado; el cuadro es alto y llega de sobra por encima del teclado. */

/* Botón «Menú» de la barra: más grande, pegado al borde derecho y con el mismo
   latido naranja que la tecla «teclado». */
.barra-superior #botonMenu {
  margin-left: auto;
  margin-right: -2px;
  padding: 9px 15px;
  font-size: 14px;
  border-color: var(--acento-fuerte);
  background-image: linear-gradient(160deg, rgba(217, 119, 87, 0) 45%, rgba(217, 119, 87, 0.10) 100%);
  animation: latido-teclado 3.4s ease-in-out infinite;
}
.barra-superior #botonMenu:active { background-image: none; }

/* Tabla de una hoja de cálculo: se desplaza a lo ancho dentro de su cuadro,
   y la primera fila se queda fija al subir y bajar. */
.tabla-hoja {
  max-height: 58dvh;
  overflow: auto;
  border: 1px solid var(--borde);
  border-radius: 8px;
  margin-bottom: 10px;
}
.tabla-hoja table { border-collapse: collapse; font-size: 12px; white-space: nowrap; }
.tabla-hoja th,
.tabla-hoja td {
  border: 1px solid var(--borde);
  padding: 5px 8px;
  text-align: left;
  max-width: 240px;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tabla-hoja th {
  position: sticky;
  top: 0;
  background: var(--panel);
  color: var(--acento);
  font-weight: 600;
}
.tabla-hoja td { color: var(--texto); }
.tabla-hoja tr:nth-child(even) td { background: var(--fondo-2); }
/* Buscar iba tan arriba que la cabecera del cuadro quedaba cortada por la
   barra superior. Baja unas cinco líneas y sigue muy por encima del teclado
   (Pedro, 24/08/2026). */
#capaBuscar {
  align-items: flex-start;
  padding-top: calc(env(safe-area-inset-top) + 120px);
}

/* Diario de trabajo: selector de periodo y detalle de cada commit. */
.periodo-diario {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 10px;
  font-size: 12px;
  color: var(--tenue);
}
.periodo-diario select {
  flex: 1;
  background: var(--fondo);
  color: var(--texto);
  border: 1px solid var(--borde);
  border-radius: 8px;
  padding: 8px 10px;
  font-family: var(--mono);
  font-size: 13px;
}
.resumen-diario { margin: 0 0 8px; }
.titulo-hito { margin: 2px 0 0; color: var(--texto); }
.cuerpo-hito {
  margin: 4px 0 2px;
  padding-left: 8px;
  border-left: 2px solid var(--borde);
  color: var(--tenue);
  font-size: 12px;
  line-height: 1.45;
  white-space: normal;
}

.capa .caja {
  background: var(--panel);
  border: 1px solid var(--borde);
  border-radius: 14px;
  padding: 18px;
  max-width: 420px;
  width: 100%;
}

.capa h2 { font-size: 14px; margin: 0 0 4px; }
.capa p { margin: 0 0 15px; color: var(--tenue); font-size: 13px; line-height: 1.5; }

.rejilla {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-bottom: 8px;
}
.rejilla button {
  border-radius: 9px;
  padding: 13px 10px;
  font-size: 13.5px;
  font-family: var(--mono);
  cursor: pointer;
  border: 1px solid var(--borde-claro);
  background: var(--fondo-2);
  color: var(--texto);
  text-align: left;
}
.rejilla button:active { border-color: var(--acento); }
.rejilla button.ancho { grid-column: 1 / -1; }

/* «Volver a la terminal»: fondo negro, borde naranja y doble de alto */
.rejilla button.contorno {
  background: var(--fondo);
  border: 2px solid var(--acento);
  color: var(--texto);
  font-weight: 650;
  text-align: center;
  padding-top: 22px;
  padding-bottom: 22px;
}
.rejilla button.contorno:active { background: var(--fondo-2); }
.rejilla button.acento { background: var(--acento); color: #20130d; border-color: var(--acento); font-weight: 600; text-align: center; }
.rejilla button small { display: block; color: var(--tenue); font-size: 11px; margin-top: 3px; }
.rejilla button.acento small { color: rgba(32, 19, 13, 0.7); }

/* Botones .acento y .contorno SUELTOS (fuera de una rejilla): mismas reglas.
   Sin esto, un «Volver a la terminal» fuera de .rejilla se quedaba con el
   estilo del navegador — blanco y desentonando (pasó en «¿seguimos?»). */
button.acento, button.contorno {
  border-radius: 9px;
  padding: 13px 10px;
  font-size: 13.5px;
  font-family: var(--mono);
  cursor: pointer;
}
button.acento { background: var(--acento); color: #20130d; border: 1px solid var(--acento); font-weight: 600; text-align: center; }
button.contorno { background: var(--fondo); border: 2px solid var(--acento); color: var(--texto); font-weight: 650; text-align: center; }
button.ancho { width: 100%; }

/* «Abrir terminal de root», del mismo tamaño que el «Volver a la terminal» de
   abajo (a gusto de Pedro, 26/08/2026): las medidas de button.acento, pero en
   ámbar — que es lo que es, ni una acción normal ni la salida. */
button.boton-root {
  border-radius: 9px;
  padding: 13px 10px;
  font-size: 13.5px;
  font-family: var(--mono);
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  border: 1px solid #d9a55f;
  background: rgba(217, 165, 95, 0.14);
  color: #d9a55f;
  margin-bottom: 10px;
}
button.boton-root:active { background: rgba(217, 165, 95, 0.28); }
/* Cabecera de Servidor: título a la izquierda y el botón de root, en corto,
   arriba a la derecha (v1.65.1). */
.cabecera-servidor { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.cabecera-servidor-texto { flex: 1 1 auto; min-width: 0; }
.cabecera-servidor h2 { margin: 0; }
#capaServidor .cabecera-servidor p.apunte { margin: 3px 0 0; }
button.boton-root-arriba { margin: 0; padding: 9px 12px; font-size: 12.5px; flex: 0 0 auto; white-space: nowrap; }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* --------------------------------------------------------- listas (proyectos y ficheros) */

.lista {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 14px 14px calc(14px + env(safe-area-inset-bottom));
  -webkit-overflow-scrolling: touch;
}

.bloque {
  background: var(--panel);
  border: 1px solid var(--borde);
  border-radius: 12px;
  padding: 14px;
  margin-bottom: 12px;
}

.fila-titulo {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 9px;
}
.fila-titulo h2 { font-size: 13.5px; margin: 0; flex: 1; }

.apunte { color: var(--tenue); font-size: 12.5px; line-height: 1.5; margin: 0 0 10px; }
.apunte.pequeno { font-size: 11.5px; }
.apunte.bien { color: var(--ok); }
.apunte.mal { color: var(--error); }
.apunte.pendiente { color: #d9a55f; }

/* Estado del circuito de trabajo: botón semáforo y diagrama iPhone→GitHub→PC.
   Verde: al día. Ámbar parpadeando: falta algo. Rojo parpadeando: hay un fallo. */
.icono-boton.estado-bien { border-color: var(--ok); color: var(--ok); }
.icono-boton.estado-pendiente { border-color: #d9a55f; color: #d9a55f; animation: parpadeo-estado 1.1s ease-in-out infinite; }
.icono-boton.estado-mal { border-color: var(--error); color: var(--error); animation: parpadeo-estado 0.7s ease-in-out infinite; }
@keyframes parpadeo-estado { 50% { opacity: 0.35; } }
@media (prefers-reduced-motion: reduce) {
  .icono-boton.estado-pendiente, .icono-boton.estado-mal,
  #capaMenu #btnSalud.estado-mal { animation: none; }
}
.cadena { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin: 4px 0 14px; }
.nodo {
  border: 1.5px solid var(--tenue);
  border-radius: 8px;
  padding: 7px 11px;
  font-size: 12.5px;
  color: var(--texto);
  background: var(--fondo-2);
}
.flecha { font-size: 15px; color: var(--tenue); }
.nodo.bien { border-color: var(--ok); }
.nodo.pendiente { border-color: #d9a55f; }
.nodo.mal { border-color: var(--error); }
.flecha.bien { color: var(--ok); }
.flecha.pendiente { color: #d9a55f; }
.flecha.mal { color: var(--error); }

.fila-controles { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* Barra de carga naranja del cuadro de conexión con GitHub */
.carga-github {
  height: 10px;
  border: 1px solid var(--acento);
  border-radius: 999px;
  background: var(--fondo-2);
  overflow: hidden;
  margin: 8px 0 4px;
}
.carga-github.oculta { display: none; }
.carga-github-relleno {
  display: block;
  height: 100%;
  width: 0;
  background: var(--acento);
  border-radius: 999px;
  transition: width 0.25s ease;
}

.entrada {
  flex: 1;
  min-width: 140px;
  background: var(--fondo-2);
  border: 1px solid var(--borde-claro);
  border-radius: 8px;
  color: var(--texto);
  font-family: var(--mono);
  font-size: 16px;
  padding: 10px 12px;
  outline: none;
}
.entrada:focus { border-color: var(--acento); }

.selector {
  background: var(--fondo-2);
  border: 1px solid var(--borde-claro);
  border-radius: 8px;
  color: var(--texto);
  font-family: var(--mono);
  font-size: 13px;
  padding: 9px 10px;
}
.selector.ancho { flex: 1; min-width: 0; max-width: 100%; }

.icono-boton.acento { background: var(--acento); color: #20130d; border-color: var(--acento); font-weight: 600; }

.clave {
  width: 100%;
  background: var(--fondo-2);
  border: 1px solid var(--borde-claro);
  border-radius: 8px;
  color: var(--tenue);
  font-family: var(--mono);
  font-size: 11px;
  padding: 10px;
  resize: none;
  margin-bottom: 8px;
  word-break: break-all;
}

.interruptor { position: relative; display: inline-block; width: 46px; height: 26px; flex: 0 0 auto; }
.interruptor input { opacity: 0; width: 0; height: 0; }
.interruptor span {
  position: absolute;
  inset: 0;
  background: var(--borde-claro);
  border-radius: 999px;
  transition: background 0.18s ease;
}
.interruptor span::before {
  content: '';
  position: absolute;
  width: 20px;
  height: 20px;
  left: 3px;
  top: 3px;
  background: var(--texto);
  border-radius: 50%;
  transition: transform 0.18s ease;
}
.interruptor input:checked + span { background: var(--acento); }
.interruptor input:checked + span::before { transform: translateX(20px); }

.tarjeta-repo {
  border: 1px solid var(--borde);
  border-radius: 10px;
  padding: 12px;
  margin-bottom: 9px;
  background: var(--fondo-2);
}
.nombre-repo { font-size: 14px; font-weight: 600; margin-bottom: 7px; }

/* Cuadro «Cambios en GitHub» (pantalla GitHub): lista con scroll propio. */
.lista-cambios {
  max-height: 46dvh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--borde);
  border-radius: 8px;
  background: var(--fondo);
  padding: 4px 10px;
}
.lista-cambios .resumen-cambios { margin: 6px 0 4px; }
.fila-cambio { padding: 8px 0; border-bottom: 1px solid var(--borde); font-size: 12.5px; line-height: 1.4; }
.fila-cambio:last-child { border-bottom: 0; }
.fila-cambio .cambio-nombre b { color: var(--texto); overflow-wrap: anywhere; }
.fila-cambio .cambio-nombre .etiqueta { margin-left: 4px; }
.fila-cambio .cambio-donde { color: var(--tenue); font-family: var(--mono); font-size: 11.5px; overflow-wrap: anywhere; }
.fila-cambio .cambio-quien { color: var(--tenue); font-size: 11.5px; }
.fila-cambio .cambio-quien code { color: var(--tenue); }
.fila-cambio.accion-A .etiqueta { border-color: var(--ok); color: var(--ok); }
.fila-cambio.accion-D .etiqueta { border-color: var(--error); color: var(--error); }

.etiquetas { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.etiqueta {
  font-size: 11px;
  padding: 3px 8px;
  border-radius: 999px;
  border: 1px solid var(--borde-claro);
  color: var(--tenue);
}
.etiqueta.atencion { color: var(--acento); border-color: var(--acento-fuerte); }
.etiqueta.bien { color: var(--ok); border-color: rgba(127, 168, 127, 0.5); }
.etiqueta.mal { color: var(--error); border-color: rgba(210, 105, 79, 0.5); }

/* --------------------------------------------------------- explorador */

/* La ruta de carpetas ocupa las líneas que hagan falta (2, 3, 4…): dentro de
   una subcarpeta de una subcarpeta se ve SIEMPRE el camino entero, sin tener
   que arrastrar de lado. */
.migas {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 2px 4px;
  padding: 9px 14px;
  background: var(--fondo-2);
  border-bottom: 1px solid var(--borde);
  flex: 0 0 auto;
}
.migas button { word-break: break-all; text-align: left; }
.migas button {
  background: transparent;
  border: none;
  color: var(--acento);
  font-family: var(--mono);
  font-size: 12.5px;
  padding: 2px 2px;
  cursor: pointer;
}
.migas span { color: var(--tenue); font-size: 12.5px; }

.fila-fichero {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 10px;
  border-bottom: 1px solid var(--borde);
  cursor: pointer;
}
.fila-fichero:active { background: var(--panel); }
.marca-tipo { color: var(--acento); width: 12px; flex: 0 0 auto; }
.nombre-fichero {
  flex: 1;
  min-width: 0;
  font-size: 13.5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.datos-fichero { color: var(--tenue); font-size: 11.5px; flex: 0 0 auto; }

/* Modo lectura (v1.66.5): la conversación entera en el sitio de la terminal */
.lectura-vivo {
  flex: 1 1 auto;
  min-height: 0;
  max-height: none;
  margin: 0;
  border: 0;
  border-radius: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 13px;
  line-height: 1.45;
  padding: 8px 10px 8px 12px;
  -webkit-user-select: text;
  user-select: text;
}
#terminal.oculto { display: none !important; }

/* ---- «Claude pide permiso» (v1.67.1, publico/autorizar.js) ----
   Los estilos van aqui y no dentro del JS: la CSP de la app no deja hojas de
   estilo en linea, y sin esto el cuadro salia como texto suelto al final de la
   pagina (captura de Pedro, 02/09/2026). Encima de todo y centrado. */
#capaAutorizar {
  position: fixed;
  inset: 0;
  z-index: 97;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px;
  background: rgba(27, 25, 23, 0.94);
}
#capaAutorizar[hidden] { display: none; }
#capaAutorizar .caja-aut {
  width: min(440px, 100%);
  max-height: calc(100vh - 36px);
  overflow-y: auto;
  background: #242220;
  border: 1px solid var(--acento);
  border-radius: 14px;
  padding: 18px 18px 16px;
  color: var(--texto, #f0eee6);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.6);
}
#capaAutorizar h2 { margin: 0 0 4px; font-size: 17px; color: var(--acento); }
#capaAutorizar .aut-quien { font-size: 12px; opacity: 0.7; margin: 0 0 12px; }
#capaAutorizar .aut-accion { font-size: 18px; font-weight: 700; margin: 0 0 6px; line-height: 1.3; }
#capaAutorizar .aut-motivo { font-size: 14px; line-height: 1.45; margin: 0 0 14px; white-space: pre-wrap; }
#capaAutorizar .aut-fila { display: flex; gap: 10px; }
#capaAutorizar .aut-fila button {
  flex: 1;
  border: 0;
  border-radius: 10px;
  padding: 14px 10px;
  font-size: 16px;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
}
#capaAutorizar .aut-si { background: var(--acento); color: #1b1917; }
#capaAutorizar .aut-no, #capaAutorizar .aut-cerrar { background: #3a3633; color: #f0eee6; }
#capaAutorizar .aut-fila button:disabled { opacity: 0.5; }
#capaAutorizar .aut-estado {
  font-size: 13.5px;
  line-height: 1.45;
  margin: 10px 0 0;
  white-space: pre-wrap;
  border-left: 3px solid #6b6663;
  padding-left: 10px;
}
#capaAutorizar .aut-estado.bien { border-color: var(--ok, #7bc47f); }
#capaAutorizar .aut-estado.mal { border-color: var(--error, #e0605e); }
#capaAutorizar .aut-mas { font-size: 12px; opacity: 0.7; margin: 10px 0 0; }

/* ---------------------------------------------------- el boton RESET
   Reinicia el servidor entero. Va suelto abajo a la derecha, en rojo y sin
   parecerse a ningun otro boton, porque es la unica accion de la app que corta
   el servicio. El z-index lo deja por encima de la terminal pero POR DEBAJO de
   las capas (que van a 95 y 97): mientras hay un dialogo abierto no debe verse.
   El hueco de abajo respeta la barra del iPhone. */
.boton-reset {
  position: fixed;
  right: 14px;
  /* Encima de las dos filas de teclas, nunca tapandolas: la altura real la mide
     el JS y la deja en --reset-abajo (CSSOM, permitido por la CSP). El valor de
     reserva sirve mientras no se haya medido. */
  bottom: var(--reset-abajo, calc(14px + env(safe-area-inset-bottom)));
  z-index: 60;
  padding: 9px 15px;
  border: 1px solid #7f2a1c;
  border-radius: 10px;
  background: #b3341f;
  color: #fff;
  font: 700 0.78rem/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: 0.09em;
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.4);
  opacity: 0.72;
  transition: opacity 0.15s ease, transform 0.1s ease;
  -webkit-tap-highlight-color: transparent;
}
.boton-reset:hover,
.boton-reset:focus-visible { opacity: 1; }
.boton-reset:active { transform: scale(0.95); }
/* Mientras se esta reiniciando no se puede volver a pulsar */
.boton-reset[disabled] { opacity: 0.35; cursor: default; }
/* Con un dialogo abierto estorba. Va por hermano posterior porque el boton
   esta en el HTML DESPUES de todas las capas; `body.capa-abierta` no existe en
   esta app —me lo invente— y la regla no habria hecho nada. */
.capa.visible ~ .boton-reset { display: none; }

/* v1.74 — escribir y dictar: letra de 17 px (con menos de 16 el iPhone hace
   zoom al enfocar) y alto grande para dictar párrafos. */
.caja-escribir { width: 100%; min-height: 38dvh; font-size: 17px; line-height: 1.45; resize: vertical; box-sizing: border-box; margin: 6px 0 10px; }
/* La pregunta de una pestaña, tal como se ve en la terminal. */
.pantalla-pregunta { max-height: 46dvh; overflow: auto; white-space: pre-wrap; word-break: break-word; font-size: 12.5px; line-height: 1.35; background: var(--fondo-hundido, rgba(0,0,0,0.25)); border-radius: 10px; padding: 10px; margin: 8px 0 12px; }
/* CLAUDE CODE OFICIAL: el primero de Ajustes, con el borde del acento. */
#capaMenu .rejilla button.boton-oficial { border-color: var(--acento); }
#capaMenu .rejilla button.boton-oficial span { color: var(--acento); font-weight: 700; letter-spacing: 0.04em; }
/* v1.75 — la foto de la web ocupa el ancho de la caja y se desplaza con ella. */
.imagen-captura { width: 100%; height: auto; border-radius: 10px; border: 1px solid var(--borde, rgba(255,255,255,0.15)); margin: 6px 0 12px; }
