* {
  box-sizing: border-box;
  margin: 0;
}

:root {
  --fondo: #1b1c1e;
  --superficie: #212225;
  --texto: #e8eaec;
  --texto-suave: #8d9297;
  --primario: #a5ff2e;
  --error: #f09595;
  --fuego: #ff8c3a;
  --logo: #a5ff2e;
  --sombra-oscura: rgba(0, 0, 0, 0.55);
  --sombra-clara: rgba(255, 255, 255, 0.05);
}

body {
  font-family: "Josefin Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  background: var(--fondo);
  color: var(--texto);
  min-height: 100vh;
}

header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  /* Con viewport-fit=cover el contenido llega a los bordes; se respeta el área
     segura de arriba (notch) y los lados. */
  padding: calc(18px + env(safe-area-inset-top)) calc(22px + env(safe-area-inset-right)) 18px calc(22px + env(safe-area-inset-left));
  background: transparent;
  max-width: 640px;
  margin: 0 auto;
}

header h1 {
  font-family: "Fredoka", sans-serif;
  font-size: 22px;
  font-weight: 600;
  letter-spacing: 0;
  line-height: 1.1;
  color: var(--logo);
}

.logo {
  color: var(--texto);
}

.marca {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.marca:active {
  opacity: 0.6;
}

.logo {
  width: 40px;
  height: 40px;
  flex-shrink: 0;
}

.subtitulo-marca {
  display: block;
  font-size: 12px;
  color: var(--texto-suave);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 40vw;
}

#info-usuario {
  font-size: 13px;
  color: var(--texto-suave);
  min-width: 0;
  flex-shrink: 1;
  text-align: right;
}

#nombre-usuario {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 42vw;
  display: inline-block;
  vertical-align: bottom;
}

main {
  max-width: 640px;
  margin: 0 auto;
  /* Sin zona muerta grande: el dimmer ahora es horizontal y no pelea con el
     gesto de inicio de iOS. Solo se respeta el área segura del home bar. */
  padding: 16px 16px calc(24px + env(safe-area-inset-bottom));
}

.centrado {
  text-align: center;
  color: var(--texto-suave);
  padding: 32px 0;
}

.tarjeta {
  background: var(--superficie);
  border: none;
  border-radius: 22px;
  padding: 26px 22px;
  margin-bottom: 16px;
  box-shadow: 9px 9px 20px var(--sombra-oscura), -9px -9px 20px var(--sombra-clara);
}

.aviso h2 {
  font-size: 17px;
  margin-bottom: 8px;
}

.aviso p {
  color: var(--texto-suave);
  line-height: 1.6;
  margin-bottom: 12px;
}

code {
  background: var(--fondo);
  border-radius: 6px;
  padding: 1px 6px;
  font-size: 13px;
  box-shadow: inset 2px 2px 5px var(--sombra-oscura), inset -2px -2px 5px var(--sombra-clara);
}

#form-login {
  max-width: 380px;
  margin: 6vh auto 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* Con la lista de invitados visible, separar la de dispositivos: pegadas se
   leen como un solo grupo de casillas. */
#pase-invitados-lista:not(.oculto) + #pase-dispositivos {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
}

/* Cómo entra cada vecino (Google / clave), en la lista de gestión. */
.como-entra {
  margin-left: 8px;
  padding: 2px 7px;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.06);
  color: var(--texto-suave);
  font-size: 11px;
  font-style: normal;
  white-space: nowrap;
}

/* Punto de conexión de cada dispositivo en la lista de gestión. */
.punto-con {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  margin-right: 8px;
  vertical-align: middle;
  flex: 0 0 auto;
}

.punto-con.con-ok { background: var(--primario); }
.punto-con.con-mal { background: var(--error); }

/* Apila los botones: aquí conviven "Continuar" y el opcional de Google. */
#form-email {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.cabecera-login {
  text-align: center;
  margin-bottom: 14px;
}

#form-login h2 {
  font-family: "Fredoka", sans-serif;
  font-size: 34px;
  font-weight: 600;
  letter-spacing: 0;
  margin: 12px 0 2px;
  color: var(--logo);
}

.logo-login {
  width: 68px;
  height: 68px;
  color: var(--texto);
  /* El ícono es un squircle sobre negro puro: al recortarlo cuadrado quedaban
     las esquinas negras marcadas contra la tarjeta (más clara). Se redondean
     para que se funda con el fondo. */
  border-radius: 23%;
}

.subtitulo-login {
  font-size: 13px;
  color: var(--texto-suave);
}

/* Aviso del evento al invitado (pantallas del flujo de pase). */
.pase-evento-info {
  text-align: center;
  color: var(--texto-suave);
  font-size: 14px;
  margin: -4px 0 14px;
}
.pase-evento-info strong {
  color: var(--primario);
  font-weight: 600;
}


#form-login input::placeholder,
#form-registro input::placeholder,
#form-email input::placeholder {
  color: var(--texto-suave);
}

.campo-clave {
  position: relative;
}

.campo-clave input {
  padding-right: 50px;
}

.btn-ver-clave {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 8px;
  width: 50px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  color: var(--texto-suave);
  -webkit-tap-highlight-color: transparent;
}

.btn-ver-clave.viendo {
  color: var(--primario);
}

.enlace-clave {
  background: transparent;
  color: var(--texto-suave);
  font-size: 13px;
  padding: 6px;
  text-align: center;
  -webkit-tap-highlight-color: transparent;
}

.enlace-clave:active {
  color: var(--primario);
}

#form-login input,
#form-registro input,
#form-email input,
#form-perfil input,
#form-perfil select,
#form-clave input,
#form-skin input,
#form-skin select,
#form-skin textarea,
.campo input,
.campo select,
.campo textarea {
  padding: 13px 14px;
  border: none;
  border-radius: 12px;
  background: var(--fondo);
  color: var(--texto);
  font-size: 16px;
  margin-bottom: 8px;
  box-shadow: inset 4px 4px 9px var(--sombra-oscura), inset -4px -4px 9px var(--sombra-clara);
  outline: none;
  width: 100%;
  -webkit-appearance: none;
  appearance: none;
}

#form-login input:focus,
#form-registro input:focus,
#form-email input:focus,
#form-perfil input:focus,
#form-perfil select:focus,
#form-clave input:focus,
#form-skin input:focus,
#form-skin select:focus,
#form-skin textarea:focus,
.campo input:focus,
.campo select:focus {
  box-shadow: inset 4px 4px 9px var(--sombra-oscura), inset -4px -4px 9px var(--sombra-clara), 0 0 0 1.5px var(--primario);
}

#form-perfil input::placeholder,
#form-clave input::placeholder {
  color: var(--texto-suave);
}

/* ---- Mi perfil ---- */
#info-usuario {
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
#info-usuario:active #nombre-usuario {
  color: var(--primario);
}

#form-perfil, #form-clave {
  display: flex;
  flex-direction: column;
}
.perfil-seccion h3 {
  font-size: 15px;
  font-weight: 600;
  color: var(--texto);
  margin-bottom: 12px;
}

/* Botón que despliega una sección (p. ej. cambiar clave), con chevron. */
.btn-desplegar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  background: transparent;
  color: var(--texto);
  font-size: 15px;
  font-weight: 600;
  padding: 2px 0;
  -webkit-tap-highlight-color: transparent;
}
.btn-desplegar::after {
  content: '';
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--texto-suave);
  border-bottom: 2px solid var(--texto-suave);
  transform: rotate(-45deg);
  transition: transform 0.2s ease;
}
.btn-desplegar[aria-expanded="true"]::after {
  transform: rotate(45deg);
}
.form-desplegable {
  margin-top: 14px;
}

.campo-perfil {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12.5px;
  color: var(--texto-suave);
  margin-bottom: 6px;
}
#perfil-email:disabled {
  opacity: 0.6;
}

.perfil-seccion {
  margin: 10px 0 6px;
}
/* Inmuebles del perfil: solo lectura (los asigna el admin). Lista vertical
   limpia: nombre + tipo por ítem. */
.lista-inmuebles {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 4px;
  /* 14px = mismo sangrado que el texto dentro de los inputs, para que los
     inmuebles alineen con los valores (Eduardo, Jimenez…), no con los labels. */
  padding: 0 0 0 14px;
  list-style: none;
}
.inmueble-ro {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.inmueble-ro strong {
  color: var(--texto);
  font-size: 14px;
  font-weight: 600;
}

.campo input:disabled {
  opacity: 0.5;
}

button {
  font-size: 16px;
  border: none;
  cursor: pointer;
  color: var(--texto);
  background: var(--superficie);
}

button:disabled {
  opacity: 0.55;
  cursor: wait;
}

.btn-primario {
  border-radius: 14px;
  padding: 14px 18px;
  min-height: 50px;
  font-weight: 600;
  color: var(--primario);
  box-shadow: 6px 6px 14px var(--sombra-oscura), -6px -6px 14px var(--sombra-clara);
}

.btn-primario:not(:disabled):active {
  box-shadow: inset 5px 5px 10px var(--sombra-oscura), inset -5px -5px 10px var(--sombra-clara);
}

.btn-secundario {
  border-radius: 12px;
  padding: 8px 16px;
  min-height: 38px;
  font-size: 14px;
  color: var(--texto-suave);
  box-shadow: 4px 4px 10px var(--sombra-oscura), -4px -4px 10px var(--sombra-clara);
}

.btn-secundario:not(:disabled):active {
  box-shadow: inset 4px 4px 8px var(--sombra-oscura), inset -4px -4px 8px var(--sombra-clara);
}

/* Botón solo-icono (p. ej. refrescar): cuadrado, sin texto. */
.btn-icono {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 8px;
  line-height: 0;
}

.mensaje-error {
  color: var(--error);
  font-size: 14px;
}

.mensaje-ok {
  color: var(--primario);
  font-size: 14px;
}

.izq {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

.btn-menu {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  flex-shrink: 0;
  border-radius: 12px;
  color: var(--texto);
  background: var(--superficie);
  box-shadow: 4px 4px 10px var(--sombra-oscura), -4px -4px 10px var(--sombra-clara);
  -webkit-tap-highlight-color: transparent;
}

.btn-menu:active {
  box-shadow: inset 4px 4px 8px var(--sombra-oscura), inset -4px -4px 8px var(--sombra-clara);
}

.backdrop {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: rgba(0, 0, 0, 0.55);
}

.menu-lateral {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: 250px;
  max-width: 80vw;
  z-index: 50;
  background: var(--fondo);
  padding: calc(34px + env(safe-area-inset-top)) 16px calc(22px + env(safe-area-inset-bottom)) calc(16px + env(safe-area-inset-left));
  display: flex;
  flex-direction: column;
  gap: 10px;
  transform: translateX(-105%);
  transition: transform 0.28s ease;
}

.menu-lateral.abierto {
  transform: translateX(0);
  box-shadow: 12px 0 28px var(--sombra-oscura);
}

.item-menu {
  text-align: left;
  border-radius: 14px;
  padding: 14px 18px;
  font-size: 15px;
  font-weight: 600;
  color: var(--texto-suave);
  background: var(--superficie);
  box-shadow: 5px 5px 12px var(--sombra-oscura), -5px -5px 12px var(--sombra-clara);
  -webkit-tap-highlight-color: transparent;
}

.item-menu.activa {
  color: var(--primario);
  box-shadow: inset 4px 4px 9px var(--sombra-oscura), inset -4px -4px 9px var(--sombra-clara);
}

.item-salir {
  color: var(--error);
}

.dps-detectados {
  margin-top: 8px;
  font-size: 12px;
  color: var(--texto-suave);
  line-height: 1.55;
  word-break: break-word;
}

.titulo-grupo {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--texto-suave);
  text-align: center;
  margin: 34px 4px 22px;
}

/* Acceso del invitado: una fila por dispositivo con su tiempo restante. */
/* Encabezado por pase en la tarjeta de invitado: evento + quién invitó. */
.acceso-cab {
  padding: 4px 2px 6px;
}
.acceso-cab:not(:first-child) {
  margin-top: 10px;
  padding-top: 14px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.acceso-cab strong {
  display: block;
  color: var(--primario);
  font-size: 16px;
  font-weight: 600;
}
.acceso-invitador {
  display: block;
  color: var(--texto-suave);
  font-size: 13px;
  margin-top: 2px;
}

.acceso-fila {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 11px 2px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.acceso-fila:last-child {
  border-bottom: none;
}

.acceso-nombre {
  font-size: 15px;
  font-weight: 500;
  color: var(--texto);
}

.acceso-reloj {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--primario);
  white-space: nowrap;
}

.acceso-reloj svg {
  width: 15px;
  height: 15px;
  flex: 0 0 auto;
}

.acceso-reloj.urgente {
  color: var(--fuego);
}

.acceso-reloj.vencido {
  color: var(--error);
}

/* Perilla giratoria (dimmer) */
.perilla {
  position: relative;
  width: 132px;
  height: 132px;
  /* pan-x deja que el swipe horizontal deslice el carrusel; el resto del gesto
     (vertical/rotatorio) y los toques operan el dial. */
  touch-action: pan-x;
  -webkit-tap-highlight-color: transparent;
  cursor: grab;
}

.perilla:active {
  cursor: grabbing;
}

.perilla-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.perilla-track {
  fill: none;
  stroke: #2c2e33;
  stroke-width: 11;
  stroke-linecap: round;
}

.perilla-nivel {
  fill: none;
  stroke: var(--primario);
  stroke-width: 11;
  stroke-linecap: round;
  filter: drop-shadow(0 0 5px rgba(165, 255, 46, 0.5));
}

.perilla:not(.encendido) .perilla-nivel {
  opacity: 0;
}

.perilla-centro {
  position: absolute;
  inset: 22px;
  border-radius: 50%;
  background: var(--superficie);
  box-shadow: 7px 7px 16px var(--sombra-oscura), -7px -7px 16px var(--sombra-clara);
  display: flex;
  align-items: center;
  justify-content: center;
}

.perilla-indicador {
  position: absolute;
  inset: 0;
  transform-origin: 50% 50%;
  transform: rotate(-135deg);
  pointer-events: none;
}

.perilla-indicador::before {
  content: "";
  position: absolute;
  top: 9px;
  left: 50%;
  width: 7px;
  height: 7px;
  margin-left: -3.5px;
  border-radius: 50%;
  background: var(--texto-suave);
}

.perilla.encendido .perilla-indicador::before {
  background: var(--primario);
  box-shadow: 0 0 6px rgba(165, 255, 46, 0.7);
}

.perilla-valor {
  font-size: 23px;
  font-weight: 600;
  color: var(--texto-suave);
}

.perilla.encendido .perilla-valor {
  color: var(--primario);
}

.perilla-accion {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--texto-suave);
}

.perilla.encendido .perilla-accion {
  color: var(--primario);
}

.perilla-enviando {
  animation: pulso-envio 0.9s ease-in-out infinite;
}

/* Termostato: perilla de temperatura + actual + modos. */
.termostato {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.termo-objetivo {
  font-size: 24px;
  font-weight: 600;
  color: var(--primario);
}

/* Temperatura actual al lado del nombre del termostato. */
.termo-temp {
  color: var(--texto-suave);
  font-weight: 400;
}

.termo-modos {
  display: flex;
  gap: 8px;
}

.termo-modo {
  border: none;
  border-radius: 10px;
  padding: 7px 14px;
  font-size: 13px;
  font-weight: 500;
  color: var(--texto-suave);
  background: var(--fondo);
  box-shadow: inset 2px 2px 5px var(--sombra-oscura), inset -2px -2px 5px var(--sombra-clara);
  cursor: pointer;
}

.termo-modo[data-modo="off"].activa {
  color: var(--texto);
  box-shadow: inset 2px 2px 5px var(--sombra-oscura), inset -2px -2px 5px var(--sombra-clara), inset 0 0 0 1.5px var(--texto-suave);
}

.termo-modo[data-modo="heat"].activa {
  color: var(--fuego);
  box-shadow: inset 2px 2px 5px var(--sombra-oscura), inset -2px -2px 5px var(--sombra-clara), inset 0 0 0 1.5px var(--fuego);
}

.termo-modo[data-modo="cool"].activa {
  color: #5ec8ff;
  box-shadow: inset 2px 2px 5px var(--sombra-oscura), inset -2px -2px 5px var(--sombra-clara), inset 0 0 0 1.5px #5ec8ff;
}

/* El arco, el número y el indicador se tiñen según el modo activo. */
.perilla-termo.modo-heat .perilla-nivel { stroke: var(--fuego); filter: drop-shadow(0 0 5px rgba(255, 140, 58, 0.5)); }
.perilla-termo.modo-heat .termo-objetivo { color: var(--fuego); }
.perilla-termo.modo-heat .perilla-indicador::before { background: var(--fuego); box-shadow: 0 0 6px rgba(255, 140, 58, 0.7); }

.perilla-termo.modo-cool .perilla-nivel { stroke: #5ec8ff; filter: drop-shadow(0 0 5px rgba(94, 200, 255, 0.5)); }
.perilla-termo.modo-cool .termo-objetivo { color: #5ec8ff; }
.perilla-termo.modo-cool .perilla-indicador::before { background: #5ec8ff; box-shadow: 0 0 6px rgba(94, 200, 255, 0.7); }

.perilla-termo.modo-off .perilla-nivel { stroke: var(--texto-suave); filter: none; opacity: 0.45; }
.perilla-termo.modo-off .termo-objetivo { color: var(--texto-suave); }
.perilla-termo.modo-off .perilla-indicador::before { background: var(--texto-suave); box-shadow: none; }

.grupo-controles {
  display: flex;
  flex-wrap: wrap;
  gap: 30px 34px;
  justify-content: center;
  align-items: flex-start;
}

/* Carrusel horizontal por categoría: el control centrado queda en foco. */
.grupo-controles.carrusel {
  flex-wrap: nowrap;
  gap: 0;
  justify-content: flex-start;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  padding: 8px max(10px, calc(50% - 112px));
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.grupo-controles.carrusel::-webkit-scrollbar {
  display: none;
}

.grupo-controles.carrusel > .control {
  flex: 0 0 224px;
  scroll-snap-align: center;
  transform-origin: center center;
  transform: scale(0.66);
  opacity: 0.4;
  will-change: transform, opacity;
}

.control {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}

.etiqueta-control {
  font-size: 14px;
  color: var(--texto-suave);
  text-align: center;
  max-width: 150px;
}

/* Dimmer a lo ancho con slider horizontal (fuera del carrusel). */
.control-dimmer {
  display: flex;
  flex-direction: column;
  gap: 12px;
  background: var(--superficie);
  border-radius: 18px;
  padding: 16px 18px;
  margin: 0 auto 14px;
  max-width: 380px;
  box-shadow: 6px 6px 14px var(--sombra-oscura), -6px -6px 14px var(--sombra-clara);
}

.dimmer-cab {
  display: flex;
  align-items: center;
  gap: 10px;
}

.dimmer-icono {
  display: flex;
  padding: 2px;
  background: transparent;
  border: none;
  color: var(--texto-suave);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color 0.2s;
}

.dimmer-icono svg {
  width: 26px;
  height: 26px;
}

.dimmer-nombre {
  flex: 1;
  font-size: 15px;
  color: var(--texto);
}

.dimmer-valor {
  font-size: 14px;
  color: var(--texto-suave);
  font-variant-numeric: tabular-nums;
}

.control-dimmer.encendido .dimmer-icono,
.control-dimmer.encendido .dimmer-valor {
  color: var(--primario);
}

.dimmer-pista {
  position: relative;
  height: 44px;
  border-radius: 14px;
  background: var(--fondo);
  overflow: hidden;
  cursor: pointer;
  touch-action: pan-y;
  -webkit-tap-highlight-color: transparent;
  box-shadow: inset 4px 4px 9px var(--sombra-oscura), inset -4px -4px 9px var(--sombra-clara);
}

.dimmer-fill {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 0;
  border-radius: 14px;
  background: var(--primario);
}

/* Control "Jet Switch": tapa de seguridad roja + palanca, sobre módulo negro.
   Los recortes de imagen (background-size/position) están calculados para un
   switch de 210px de ancho; no cambiar sin recalcular. */
.control-jet {
  gap: 10px;
}

.jet-titulo {
  font-size: 12px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--texto-suave);
}

/* --jet-s = factor de escala del switch. Los recortes de imagen están
   calculados para 210px de ancho; con calc() todo escala junto, así basta
   cambiar este número para agrandarlo o achicarlo. */
.jet-switch {
  --jet-s: 0.75;
  position: relative;
  width: calc(210px * var(--jet-s));
  height: calc(400px * var(--jet-s));
  background: #0a0a0b;
  border-radius: calc(46px * var(--jet-s));
  overflow: hidden;
  cursor: grab;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  box-shadow: 6px 6px 16px var(--sombra-oscura), -6px -6px 16px var(--sombra-clara);
}

.jet-capa {
  position: absolute;
  inset: 0;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  transition: opacity 0.13s ease;
}

/* Cada estado viene ya recortado a la caja del switch, así que se estira y
   listo. Antes cada capa cargaba el render completo (hasta 1,1 MB) y el
   recorte lo hacía background-position: 2,9 MB para un control de 157px. */
.jet-cerrado { background-image: url('jet-cerrado.webp?v=1'); }
.jet-armado { background-image: url('jet-armado.webp?v=1'); opacity: 0; }
.jet-abierto { background-image: url('jet-abierto.webp?v=1'); opacity: 0; }

/* Bomba de búnker sobre "ENGAGE" en la tapa roja (solo subtipo búnker). */
.jet-bunker {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -100%);
  color: #fff;
  line-height: 0;
}

.jet-bunker svg {
  width: calc(64px * var(--jet-s));
  height: calc(64px * var(--jet-s));
  stroke: #fff;
  stroke-width: 3.4;
}

/* Cuerpo de la bomba relleno de blanco para que lea sólida como "ENGAGE",
   no un aro gris. */
.jet-bunker svg circle {
  fill: #fff;
}

.boton-circular {
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #a9afb5;
  background: var(--superficie);
  box-shadow: 9px 9px 18px var(--sombra-oscura), -9px -9px 18px var(--sombra-clara);
  transition: color 0.25s, box-shadow 0.15s;
  -webkit-tap-highlight-color: transparent;
}

.boton-circular:not(:disabled):active {
  box-shadow: inset 7px 7px 14px var(--sombra-oscura), inset -7px -7px 14px var(--sombra-clara);
}

.boton-circular.con-nombre {
  flex-direction: column;
  gap: 8px;
}

.nombre-boton {
  font-size: 13px;
  color: var(--texto-suave);
  text-align: center;
  line-height: 1.15;
  max-width: 82%;
  padding: 0 4px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.boton-circular.medio.con-nombre {
  gap: 5px;
}

.boton-circular.medio.con-nombre .nombre-boton {
  font-size: 10.5px;
}

.anillo {
  position: relative;
  border-radius: 50%;
  padding: 26px;
  background: var(--superficie);
  box-shadow: inset 7px 7px 16px var(--sombra-oscura), inset -7px -7px 16px var(--sombra-clara);
}

.boton-circular.grande {
  width: 168px;
  height: 168px;
}

/* Botón con imagen de logo (p. ej. escudo de Argentina) en vez de icono SVG:
   la imagen llena el círculo del botón y el nombre va encima, abajo, con el
   mismo gris y fuente que el resto de botones (sin negrita). */
.boton-imagen {
  position: relative;
  overflow: hidden;
  padding: 0;
}

.boton-logo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  border-radius: 50%;
  display: block;
  pointer-events: none;
  z-index: 0;
}

/* Aspecto Argentina "camiseta": dos caras que se cruzan. Frente = escudo AFA
   (por defecto); al presionar se revela la cara de atrás (estampita de Messi)
   nítida por un momento y vuelve. La cara de atrás se encuadra hacia la cara. */
.boton-camiseta .boton-logo {
  transition: opacity 0.18s ease;
}
.boton-camiseta .cara-atras {
  object-position: 50% 8%;
  opacity: 0;
}
.boton-camiseta.mostrar-atras .cara-frente {
  opacity: 0;
}
.boton-camiseta.mostrar-atras .cara-atras {
  opacity: 1;
}

/* Aspecto Bordado: el parche gira en sentido horario mientras el botón está
   activo (enviando / éxito). En reposo, quieto. Como el parche está centrado y
   el botón recorta al círculo, gira en su sitio sin mostrar el negro. */
.boton-bordado.enviando .boton-logo,
.boton-bordado.exito .boton-logo {
  animation: girar-bordado 2.5s linear infinite;
}
@keyframes girar-bordado {
  to { transform: rotate(360deg); }
}
/* Aspecto Hal: el ojo cobra vida al activarse. Un resplandor rojo palpita
   alrededor del botón y el propio ojo se enciende más fuerte (brightness),
   como el HAL de la película. En reposo, apagado y quieto. */
.boton-hal .boton-logo {
  transition: filter 0.4s ease;
}
/* Aro tenue en el canto: el lente de HAL es negro sobre fondo casi negro, así
   que sin él el borde se pierde y el botón se lee más chico que los otros
   aspectos. Va como pseudo-elemento para no pelear con el box-shadow animado
   del latido. */
.boton-hal::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.2);
  pointer-events: none;
  z-index: 1;
}
.boton-hal.enviando,
.boton-hal.exito {
  animation: latir-hal 1.5s ease-in-out infinite;
}
.boton-hal.enviando .boton-logo,
.boton-hal.exito .boton-logo {
  animation: brillo-hal 1.5s ease-in-out infinite;
}
@keyframes latir-hal {
  0%, 100% {
    box-shadow: 9px 9px 20px var(--sombra-oscura), -9px -9px 20px var(--sombra-clara),
                0 0 14px 2px rgba(255, 40, 0, 0.45);
  }
  50% {
    box-shadow: 9px 9px 20px var(--sombra-oscura), -9px -9px 20px var(--sombra-clara),
                0 0 34px 9px rgba(255, 45, 5, 0.9);
  }
}
@keyframes brillo-hal {
  0%, 100% { filter: brightness(1); }
  50% { filter: brightness(1.55) saturate(1.15); }
}

/* Animaciones de los skins de galería. Las de Bordado y Hal están atadas a
   ellos (una gira un parche, la otra palpita en rojo de HAL); estas son
   genéricas, para que publicar un skin nuevo no exija CSS nuevo. */
.skin-gira.enviando .boton-logo,
.skin-gira.exito .boton-logo {
  animation: girar-bordado 2.5s linear infinite;
}
.skin-late.enviando,
.skin-late.exito {
  animation: latir-skin 1.5s ease-in-out infinite;
}
.skin-late.enviando .boton-logo,
.skin-late.exito .boton-logo {
  animation: brillo-hal 1.5s ease-in-out infinite;
}
@keyframes latir-skin {
  0%, 100% {
    box-shadow: 9px 9px 20px var(--sombra-oscura), -9px -9px 20px var(--sombra-clara),
                0 0 14px 2px rgba(165, 255, 46, 0.4);
  }
  50% {
    box-shadow: 9px 9px 20px var(--sombra-oscura), -9px -9px 20px var(--sombra-clara),
                0 0 32px 8px rgba(165, 255, 46, 0.85);
  }
}

/* Nombre abajo DENTRO del anillo (sobre la franja oscura, no sobre la foto)
   para los botones con imagen (Argentina, Bordado). Una sola línea; el largo
   se limita en el campo de nombre del editor. Se desvanece mientras el botón
   está activo. La sombra lo hace legible por si roza el borde de la foto. */
.nombre-anillo {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 5px;
  text-align: center;
  font-size: 14px;
  font-weight: 600;
  color: var(--texto-suave);
  white-space: nowrap;
  z-index: 2;
  pointer-events: none;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
  transition: opacity 0.25s ease;
}
.boton-circular.enviando ~ .nombre-anillo,
.boton-circular.exito ~ .nombre-anillo {
  opacity: 0;
}

.boton-imagen .nombre-boton {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 18px;
  /* El .nombre-boton base trae max-width: 82%, que con left/right absolutos
     empuja la caja a la izquierda y descentra el texto. Lo anulamos para que
     ocupe todo el ancho y quede centrado. */
  max-width: none;
  z-index: 1;
  /* Sombra sutil para despegar el gris del escudo, sin cambiar color ni peso. */
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}

.boton-circular.grande svg {
  width: 108px;
  height: auto;
}

.boton-circular.grande svg.icono-candado {
  width: auto;
  height: 66px;
}

.boton-circular.grande.cuadrado svg {
  width: 82px;
  height: 82px;
}

.boton-circular.medio {
  width: 92px;
  height: 92px;
}

.boton-circular.chico {
  width: 72px;
  height: 72px;
}

.fila-cortina {
  display: flex;
  gap: 18px;
}

.boton-circular.activo {
  color: var(--primario);
  box-shadow: inset 6px 6px 13px var(--sombra-oscura), inset -6px -6px 13px var(--sombra-clara),
              inset 0 0 0 2px rgba(165, 255, 46, 0.55);
}

.boton-circular.activo svg {
  filter: drop-shadow(0 0 9px rgba(165, 255, 46, 0.8));
}

.boton-circular.exito {
  color: var(--primario);
}

/* Ascensor: el icono se mantiene neutro; solo la flecha de subir se
   enciende (se rellena de verde) cuando el botón está enviando o activo. */
.icono-ascensor {
  color: var(--texto-suave);
}

.boton-circular.enviando .flecha-subir,
.boton-circular.exito .flecha-subir,
.boton-circular.activo .flecha-subir {
  stroke: var(--primario);
  fill: var(--primario);
}

/* Búnker: la bomba se mantiene neutra; la mecha se enciende (verde con
   brillo) al pulsar/activar, como si prendiera. */
.icono-bunker {
  color: var(--texto-suave);
}

.boton-circular.enviando .mecha {
  stroke: var(--fuego);
  filter: drop-shadow(0 0 3px rgba(255, 140, 58, 0.95));
}

/* Al encenderse (éxito/activo) la mecha titila 3 veces, como una chispa. */
.boton-circular.exito .mecha,
.boton-circular.activo .mecha {
  animation: titilar-mecha 0.35s ease-in-out 3 both;
}

@keyframes titilar-mecha {
  0%, 100% { stroke: var(--fuego); opacity: 1; filter: drop-shadow(0 0 4px rgba(255, 140, 58, 0.95)); }
  50%      { stroke: var(--texto-suave); opacity: 0.2; filter: none; }
}

/* Portón: el garaje y el carro se mantienen neutros. Al abrir (éxito) una
   sola luz recorre las persianas de abajo hacia arriba, apagándose cada una
   al encender la siguiente, como si la puerta se estuviera abriendo. */
.icono-porton {
  color: var(--texto-suave);
}

.icono-porton .persianas line {
  transition: stroke 0.3s ease;
}

/* Al abrir (éxito): una sola luz recorre las persianas de abajo hacia arriba
   — cada persiana se apaga justo cuando enciende la siguiente. */
.boton-circular.exito .icono-porton .persianas line {
  animation-duration: 1.6s;
  animation-timing-function: ease-in-out;
  animation-fill-mode: both;
  /* Se repite mientras el botón esté activo: el portón tarda ~15s en abrir y
     con un número fijo de vueltas la animación se apagaba mucho antes. */
  animation-iteration-count: infinite;
}
.boton-circular.exito .icono-porton .persianas line:nth-of-type(4) { animation-name: porton-persiana-4; }
.boton-circular.exito .icono-porton .persianas line:nth-of-type(3) { animation-name: porton-persiana-3; }
.boton-circular.exito .icono-porton .persianas line:nth-of-type(2) { animation-name: porton-persiana-2; }
.boton-circular.exito .icono-porton .persianas line:nth-of-type(1) { animation-name: porton-persiana-1; }

@keyframes porton-persiana-4 { /* abajo: 1ª en encender */
  0%   { stroke: var(--texto-suave); filter: none; }
  6%   { stroke: var(--primario); filter: drop-shadow(0 0 2.5px rgba(165, 255, 46, 0.9)); }
  22%  { stroke: var(--primario); filter: drop-shadow(0 0 2.5px rgba(165, 255, 46, 0.9)); }
  28%  { stroke: var(--texto-suave); filter: none; }
  100% { stroke: var(--texto-suave); filter: none; }
}
@keyframes porton-persiana-3 {
  0%, 22% { stroke: var(--texto-suave); filter: none; }
  28%     { stroke: var(--primario); filter: drop-shadow(0 0 2.5px rgba(165, 255, 46, 0.9)); }
  47%     { stroke: var(--primario); filter: drop-shadow(0 0 2.5px rgba(165, 255, 46, 0.9)); }
  53%     { stroke: var(--texto-suave); filter: none; }
  100%    { stroke: var(--texto-suave); filter: none; }
}
@keyframes porton-persiana-2 {
  0%, 47% { stroke: var(--texto-suave); filter: none; }
  53%     { stroke: var(--primario); filter: drop-shadow(0 0 2.5px rgba(165, 255, 46, 0.9)); }
  72%     { stroke: var(--primario); filter: drop-shadow(0 0 2.5px rgba(165, 255, 46, 0.9)); }
  78%     { stroke: var(--texto-suave); filter: none; }
  100%    { stroke: var(--texto-suave); filter: none; }
}
@keyframes porton-persiana-1 { /* arriba: última en encender, luego se apaga */
  0%, 72% { stroke: var(--texto-suave); filter: none; }
  78%     { stroke: var(--primario); filter: drop-shadow(0 0 2.5px rgba(165, 255, 46, 0.9)); }
  94%     { stroke: var(--primario); filter: drop-shadow(0 0 2.5px rgba(165, 255, 46, 0.9)); }
  100%    { stroke: var(--texto-suave); filter: none; }
}

.boton-circular.enviando {
  animation: pulso-envio 0.9s ease-in-out infinite;
}

@keyframes pulso-envio {
  50% { opacity: 0.45; }
}

/* ===== Skins del botón (estilo elegible tipo "vestuario") =====
   El default (neumórfico) es el base sin clase. Cada skin reestiliza
   .boton-circular cuando lleva la clase piel-X (una por dispositivo); los mismos
   para las muestras del selector (.skin-muestra.piel-X). Los iconos usan
   currentColor, así que se themean con `color`. El pulido fino de estados
   (éxito/activo por skin) va después. */
.boton-circular[class*="piel-"]:not(:disabled):active {
  transform: scale(0.96);
}

/* Muestra (swatch) del selector de skin: mini botón circular. */
.skin-muestra {
  width: 58px;
  height: 58px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #a9afb5;
  background: var(--superficie);
  box-shadow: 5px 5px 12px var(--sombra-oscura), -5px -5px 12px var(--sombra-clara);
}
.skin-muestra svg { width: 26px; height: 26px; }
.skin-muestra { overflow: hidden; }
.skin-muestra img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
  display: block;
}

/* Neón */
.boton-circular.piel-neon,
.skin-muestra.piel-neon {
  color: var(--primario);
  background: #0c0c0f;
  box-shadow: 0 0 0 2px var(--primario), 0 0 20px rgba(165, 255, 46, 0.5), inset 0 0 16px rgba(165, 255, 46, 0.12);
}
.boton-circular.piel-neon svg,
.skin-muestra.piel-neon svg { filter: drop-shadow(0 0 6px rgba(165, 255, 46, 0.85)); }

/* Acero */
.boton-circular.piel-acero,
.skin-muestra.piel-acero {
  color: #dfe3e8;
  background: linear-gradient(145deg, #4a4e54, #23262b);
  box-shadow: 6px 6px 14px rgba(0, 0, 0, 0.55), -4px -4px 10px rgba(255, 255, 255, 0.07), inset 0 2px 3px rgba(255, 255, 255, 0.22), inset 0 -3px 6px rgba(0, 0, 0, 0.45);
}

/* Cristal */
.boton-circular.piel-cristal,
.skin-muestra.piel-cristal {
  color: #eef2f5;
  background: rgba(255, 255, 255, 0.07);
  box-shadow: inset 0 1px 8px rgba(255, 255, 255, 0.16), inset 0 0 0 1px rgba(255, 255, 255, 0.22), 0 6px 16px rgba(0, 0, 0, 0.38);
}

/* Pop (verde sólido) */
.boton-circular.piel-pop,
.skin-muestra.piel-pop {
  color: #14210a;
  background: var(--primario);
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.4), inset 0 -4px 8px rgba(0, 0, 0, 0.16), inset 0 3px 6px rgba(255, 255, 255, 0.3);
}

/* ===== Las mismas pieles, vestidas sobre PERILLA (cortina y termostato) =====
   Aquí se viste el aro (track), el nivel y el centro; el valor y el indicador
   siguen a la piel para que el dial se lea como una pieza. */
.perilla.piel-neon .perilla-track { stroke: #16181c; }
.perilla.piel-neon .perilla-nivel { filter: drop-shadow(0 0 8px rgba(165, 255, 46, 0.95)); }
.perilla.piel-neon .perilla-centro {
  background: #0c0c0f;
  box-shadow: 0 0 0 2px var(--primario), 0 0 18px rgba(165, 255, 46, 0.45), inset 0 0 14px rgba(165, 255, 46, 0.12);
}

.perilla.piel-acero .perilla-track { stroke: #43474d; }
.perilla.piel-acero .perilla-nivel { stroke: #dfe3e8; filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.5)); }
.perilla.piel-acero .perilla-centro {
  background: linear-gradient(145deg, #4a4e54, #23262b);
  box-shadow: 6px 6px 14px rgba(0, 0, 0, 0.55), -4px -4px 10px rgba(255, 255, 255, 0.07), inset 0 2px 3px rgba(255, 255, 255, 0.22), inset 0 -3px 6px rgba(0, 0, 0, 0.45);
}
.perilla.piel-acero .perilla-valor,
.perilla.piel-acero .perilla-accion { color: #dfe3e8; }
.perilla.piel-acero .perilla-indicador::before { background: #dfe3e8; box-shadow: none; }

.perilla.piel-cristal .perilla-track { stroke: rgba(255, 255, 255, 0.12); }
.perilla.piel-cristal .perilla-nivel { stroke: #eef2f5; filter: none; }
.perilla.piel-cristal .perilla-centro {
  background: rgba(255, 255, 255, 0.07);
  box-shadow: inset 0 1px 8px rgba(255, 255, 255, 0.16), inset 0 0 0 1px rgba(255, 255, 255, 0.22), 0 6px 16px rgba(0, 0, 0, 0.38);
}
.perilla.piel-cristal .perilla-valor,
.perilla.piel-cristal .perilla-accion { color: #eef2f5; }
.perilla.piel-cristal .perilla-indicador::before { background: #eef2f5; box-shadow: none; }

.perilla.piel-pop .perilla-track { stroke: #2a2d31; }
.perilla.piel-pop .perilla-nivel { filter: none; stroke-width: 13; }
.perilla.piel-pop .perilla-centro {
  background: var(--primario);
  box-shadow: 0 8px 16px rgba(0, 0, 0, 0.4), inset 0 -4px 8px rgba(0, 0, 0, 0.16), inset 0 3px 6px rgba(255, 255, 255, 0.3);
}
.perilla.piel-pop .perilla-valor,
.perilla.piel-pop .perilla-accion { color: #14210a; }
.perilla.piel-pop.encendido .perilla-valor,
.perilla.piel-pop.encendido .perilla-accion { color: #14210a; }

/* ===== Aspecto RUEDA: rodillo moleteado con detente y arco de luces =====
   Reemplaza el control (no es una piel). El color sigue al dispositivo:
   cortina en verde, termostato en azul frío, dimmer en ámbar cálido (~2500K,
   la luz de un incandescente). */
.control-rueda {
  --rueda-luz: var(--primario);
  --rueda-halo: rgba(165, 255, 46, 0.9);
}
.control-rueda.frio {
  --rueda-luz: #5ec8ff;
  --rueda-halo: rgba(94, 200, 255, 0.9);
}
.control-rueda.calido {
  --rueda-luz: #ffbe6b;
  --rueda-halo: rgba(255, 190, 107, 0.95);
}

.rueda-ctrl {
  position: relative;
  width: 150px;
  height: 150px;
  /* pan-x deja el swipe horizontal al carrusel; lo vertical es de la rueda. */
  touch-action: pan-x;
  /* Encierra los repintados de las luces: que encender una no invalide la
     tarjeta ni la fila del carrusel. */
  contain: layout paint;
  -webkit-tap-highlight-color: transparent;
  cursor: grab;
}
.rueda-ctrl:active { cursor: grabbing; }

.rueda-arco { position: absolute; inset: 0; pointer-events: none; }
.rueda-led {
  position: absolute;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #2c2e33;
  transform: translate(-50%, -50%);
  /* Sin transición: interpolar el box-shadow de 13 luces obliga a repintar el
     halo en cada frame, y mientras se arrastra la rueda eso es justo lo que la
     hace temblar. Un detente enciende de golpe, además, que es lo correcto. */
}
.rueda-led.on {
  background: var(--rueda-luz);
  box-shadow: 0 0 8px var(--rueda-halo);
}

/* El rodillo va en su cavidad: la foto trae bisel, collares metálicos y
   sombras, y solo se anima la ventana del moleteado. Un único bitmap. */
.rueda-marco {
  position: absolute;
  left: 6px;
  top: 17px;
  width: 116px;
  height: 116px;
  border-radius: 24px;
  background: url("rueda-marco.jpg?v=1") center/100% 100% no-repeat;
}
/* Ventana entre los dos collares, medida sobre la foto. */
.rueda-moleteado-caja {
  position: absolute;
  left: 25.4%;
  right: 25.2%;
  top: 10.4%;
  bottom: 10.4%;
  overflow: hidden;
}
/* Franja alta que se desplaza con transform (compositor, sin repintar). La
   textura repite cada 155px, así que el giro se toma módulo 155. */
.rueda-moleteado {
  position: absolute;
  left: 0;
  right: 0;
  top: -155px;
  height: 465px;
  background: url("rueda-textura2.jpg?v=1") center top/100% 155px repeat-y;
  will-change: transform;
}
/* Curvatura del cilindro: la superficie se apaga al alejarse hacia los cantos.
   Va dentro de la ventana para no ensuciar el bisel. */
.rueda-brillo {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(0, 0, 0, 0.88) 0%,
    rgba(0, 0, 0, 0.35) 10%,
    rgba(255, 255, 255, 0.06) 45%,
    rgba(255, 255, 255, 0.04) 55%,
    rgba(0, 0, 0, 0.35) 90%,
    rgba(0, 0, 0, 0.88) 100%);
}

.rueda-valor {
  font-size: 22px;
  font-weight: 600;
  color: var(--rueda-luz);
  font-variant-numeric: tabular-nums;
  /* Ancho fijo: si el número cambia de ancho (9 → 10 → 100) rehace el layout
     de la tarjeta en pleno arrastre. */
  min-width: 3.4em;
  text-align: center;
}
.control-rueda.rueda-enviando { animation: pulso-envio 0.9s ease-in-out infinite; }

/* Tocar el rodillo (sin girarlo) apaga/enciende, y en la cortina pausa. Sin
   iconos: lo dicen las luces y el número. Apagado = todo oscuro; en pausa las
   luces laten, como algo detenido a medio camino. */
.control-rueda.rueda-apagado .rueda-valor { color: var(--texto-suave); }
.control-rueda.rueda-apagado .rueda-marco { filter: brightness(0.72); }
@keyframes rueda-latido {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.2; }
}
.control-rueda.rueda-pausa .rueda-led.on { animation: rueda-latido 1.3s ease-in-out infinite; }
.control-rueda.rueda-pausa .rueda-valor { animation: rueda-latido 1.3s ease-in-out infinite; }

/* ===== Piel COBRE: perilla de audio (foto) con corona de LEDs ámbar =====
   La foto va sobre .perilla-indicador, que es justo lo que el JS rota con el
   valor: así el knob gira de verdad y su línea marca la posición, sin tocar el
   JS. El punto indicador de siempre sobra (la foto ya trae la línea).
   El arco se enmascara con un gradiente cónico para que track y nivel se lean
   como una corona de LEDs: 20 puntos repartidos en los 270° del recorrido. */
.perilla.piel-cobre .perilla-centro {
  background: #0b0b0c;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.65);
  overflow: hidden;
}
.perilla.piel-cobre .perilla-indicador {
  background: url("perilla-cobre.jpg?v=1") center/cover no-repeat;
  border-radius: 50%;
}
.perilla.piel-cobre .perilla-indicador::before { display: none; }

.perilla.piel-cobre .perilla-svg {
  -webkit-mask: repeating-conic-gradient(from -135deg at 50% 50%, #000 0 4deg, transparent 4deg 13.5deg);
  mask: repeating-conic-gradient(from -135deg at 50% 50%, #000 0 4deg, transparent 4deg 13.5deg);
}
.perilla.piel-cobre .perilla-track { stroke: #4a3a28; stroke-width: 7; }
.perilla.piel-cobre .perilla-nivel {
  stroke: #ffb545;
  stroke-width: 7;
  filter: drop-shadow(0 0 6px rgba(255, 170, 60, 0.95));
}
/* El valor va sobre el cobre: oscuro, con un realce claro para que se lea.
   Necesita position+z-index porque el indicador (que ahora lleva la foto) está
   posicionado y, sin esto, se pintaría encima del número. */
.perilla.piel-cobre .perilla-valor,
.perilla.piel-cobre .perilla-accion,
.perilla.piel-cobre .termo-objetivo {
  position: relative;
  z-index: 1;
  color: #2b1a0c;
  text-shadow: 0 1px 2px rgba(255, 225, 190, 0.7);
}

/* Cobre en el slider del dimmer: mismo material, sin knob. */
.control-dimmer.piel-cobre { background: #101012; box-shadow: 0 6px 16px rgba(0, 0, 0, 0.55); }
.control-dimmer.piel-cobre .dimmer-pista { background: #0b0b0c; box-shadow: inset 0 0 0 1px rgba(255, 170, 60, 0.22); }
.control-dimmer.piel-cobre .dimmer-fill {
  background: linear-gradient(180deg, #d9a071, #a86a3c);
  box-shadow: 0 0 14px rgba(255, 170, 60, 0.5);
}
.control-dimmer.piel-cobre.encendido .dimmer-icono,
.control-dimmer.piel-cobre.encendido .dimmer-valor { color: #ffb545; }

/* ===== Las mismas pieles, vestidas sobre el SLIDER del dimmer ===== */
.control-dimmer.piel-neon { background: #0c0c0f; box-shadow: 0 0 0 1.5px rgba(165, 255, 46, 0.5), 0 0 18px rgba(165, 255, 46, 0.15); }
.control-dimmer.piel-neon .dimmer-pista { background: #08080a; box-shadow: inset 0 0 0 1.5px rgba(165, 255, 46, 0.35); }
.control-dimmer.piel-neon .dimmer-fill { box-shadow: 0 0 16px rgba(165, 255, 46, 0.85); }

.control-dimmer.piel-acero { background: linear-gradient(145deg, #4a4e54, #23262b); }
.control-dimmer.piel-acero .dimmer-pista { background: #1c1e21; }
.control-dimmer.piel-acero .dimmer-fill { background: linear-gradient(180deg, #eef1f4, #9aa1a9); }
.control-dimmer.piel-acero.encendido .dimmer-icono,
.control-dimmer.piel-acero.encendido .dimmer-valor { color: #dfe3e8; }

.control-dimmer.piel-cristal { background: rgba(255, 255, 255, 0.07); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.22), 0 6px 16px rgba(0, 0, 0, 0.38); }
.control-dimmer.piel-cristal .dimmer-pista { background: rgba(0, 0, 0, 0.28); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14); }
.control-dimmer.piel-cristal .dimmer-fill { background: rgba(255, 255, 255, 0.85); }
.control-dimmer.piel-cristal.encendido .dimmer-icono,
.control-dimmer.piel-cristal.encendido .dimmer-valor { color: #eef2f5; }

.control-dimmer.piel-pop { background: var(--primario); }
.control-dimmer.piel-pop .dimmer-nombre { color: #14210a; font-weight: 600; }
.control-dimmer.piel-pop .dimmer-icono,
.control-dimmer.piel-pop .dimmer-valor { color: #14210a; }
.control-dimmer.piel-pop.encendido .dimmer-icono,
.control-dimmer.piel-pop.encendido .dimmer-valor { color: #14210a; }
.control-dimmer.piel-pop .dimmer-pista { background: rgba(0, 0, 0, 0.22); box-shadow: none; }
.control-dimmer.piel-pop .dimmer-fill { background: #14210a; }

/* Vestuario: un bloque por dispositivo, cada uno con su galería de aspectos. */
.vest-ayuda {
  font-size: 13px;
  color: var(--texto-suave);
  margin: -6px 0 16px;
}

/* Dropdown del dispositivo que se está vistiendo. */
.vest-select {
  width: 100%;
  padding: 12px 14px;
  border: none;
  border-radius: 12px;
  background: var(--fondo);
  color: var(--texto);
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
  margin-bottom: 18px;
  box-shadow: inset 4px 4px 9px var(--sombra-oscura), inset -4px -4px 9px var(--sombra-clara);
  outline: none;
  -webkit-appearance: none;
  appearance: none;
  /* Con appearance:none se pierde la flecha nativa: se dibuja una. */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238d9297' stroke-width='2.4' stroke-linecap='round'><polyline points='6 9 12 15 18 9'/></svg>");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 18px;
  padding-right: 38px;
}

/* Demo: el control de verdad, para verlo y tocarlo antes de decidir. */
.vest-demo {
  display: flex;
  justify-content: center;
  padding: 4px 0 18px;
}

/* Carrusel de opciones: la centrada es la elegida (coverflow como el de los
   dispositivos). El padding lateral deja que la primera y la última se
   centren. */
.vest-opciones {
  display: flex;
  gap: 0;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  padding: 6px calc(50% - 46px);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 18%, #000 82%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 18%, #000 82%, transparent);
}
.vest-opciones::-webkit-scrollbar { display: none; }

.vest-opciones .skin-op {
  flex: 0 0 92px;
  scroll-snap-align: center;
  transition: transform 0.12s ease, opacity 0.12s ease;
}
/* La centrada se marca en verde; el carrusel ya le da escala y opacidad. */
.vest-opciones .skin-op.enfoque .skin-muestra {
  outline: 2px solid var(--primario);
  outline-offset: 3px;
}
.vest-opciones .skin-op.enfoque .skin-nom { color: var(--primario); }

.vest-nota {
  margin: 18px 0 0;
  padding-top: 14px;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
}

/* Muestra de Cobre en el dimmer: ahí el control es un slider, no una perilla,
   así que la miniatura es el material y no el knob (que no aparecería). */
.muestra-cobre {
  background: linear-gradient(160deg, #d9a071, #8a5730) !important;
  box-shadow: 0 0 12px rgba(255, 170, 60, 0.35) !important;
}

/* Muestra del Jet Switch: su tapa roja, que no es una foto. */
.muestra-jet {
  width: 26px;
  height: 30px;
  border-radius: 6px;
  background: linear-gradient(160deg, #e2483a, #a3241a);
  box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.35);
}

/* Selector de skin en el perfil. */
.skin-galeria {
  display: flex;
  gap: 16px;
  overflow-x: auto;
  padding: 4px 2px 6px;
  scrollbar-width: none;
}
.skin-galeria::-webkit-scrollbar { display: none; }
.skin-op {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  border: none;
  background: none;
  cursor: pointer;
  padding: 4px;
  border-radius: 14px;
}
.skin-op .skin-nom {
  font-size: 12px;
  color: var(--texto-suave);
  font-weight: 600;
}
.skin-op.activa .skin-muestra {
  outline: 2px solid var(--primario);
  outline-offset: 3px;
}
.skin-op.activa .skin-nom { color: var(--primario); }

.encabezado-admin {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 44px 4px 14px;
}

.encabezado-admin h2,
#pase-generador h2 {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--texto-suave);
}
#pase-generador h2 {
  margin-bottom: 12px;
}

#lista-registros {
  list-style: none;
  padding: 0;
}

#lista-registros li {
  background: var(--fondo);
  border-radius: 12px;
  padding: 11px 15px;
  margin-bottom: 9px;
  font-size: 13px;
  color: var(--texto-suave);
  box-shadow: inset 3px 3px 7px var(--sombra-oscura), inset -3px -3px 7px var(--sombra-clara);
}

#lista-registros li.registro-error {
  color: var(--error);
}

#toast {
  position: fixed;
  left: 50%;
  bottom: calc(26px + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  padding: 13px 22px;
  border-radius: 16px;
  font-size: 15px;
  max-width: 90vw;
  background: var(--superficie);
  box-shadow: 8px 8px 18px var(--sombra-oscura), -8px -8px 18px var(--sombra-clara);
}

#toast.toast-ok {
  color: var(--primario);
}

#toast.toast-error {
  color: var(--error);
}

.lista-gestion {
  list-style: none;
  padding: 0;
}

.lista-gestion li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: var(--fondo);
  border-radius: 12px;
  padding: 10px 10px 10px 15px;
  margin-bottom: 9px;
  font-size: 14px;
  color: var(--texto);
  box-shadow: inset 3px 3px 7px var(--sombra-oscura), inset -3px -3px 7px var(--sombra-clara);
}

.lista-gestion li.inactivo span:first-child {
  opacity: 0.45;
  text-decoration: line-through;
}

/* Encabezado de grupo por proveedor en la lista de gestión. */
.lista-gestion li.grupo-gestion {
  display: block;
  background: none;
  box-shadow: none;
  padding: 16px 4px 4px;
  margin-bottom: 0;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--texto-suave);
}

.lista-gestion li.grupo-gestion:first-child {
  padding-top: 2px;
}

.titulo-editor {
  font-size: 16px;
  font-weight: 600;
  margin-bottom: 16px;
}

.campo {
  display: block;
  font-size: 13px;
  color: var(--texto-suave);
  margin-bottom: 4px;
}

.campo > span {
  display: block;
  margin-bottom: 5px;
}

/* Un campo sin etiqueta no debe dejar el hueco de la etiqueta. */
.campo > span:empty {
  display: none;
}

/* Selección múltiple (inmuebles, dispositivos): lista vertical con scroll. */
.casillas {
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap;
  gap: 2px;
  margin: 6px 0 12px;
  max-height: 220px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.casilla {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: var(--texto);
  background: var(--fondo);
  border-radius: 10px;
  padding: 9px 13px;
  box-shadow: inset 3px 3px 6px var(--sombra-oscura), inset -3px -3px 6px var(--sombra-clara);
  cursor: pointer;
}

/* El checkbox no debe heredar el estilo de input de texto de `.campo input`
   (fondo + sombra + appearance:none lo convertían en un círculo gris). */
.casilla input {
  accent-color: var(--primario);
  width: 17px;
  height: 17px;
  flex: 0 0 auto;
  padding: 0;
  margin: 0;
  border-radius: 4px;
  background: none;
  box-shadow: none;
  -webkit-appearance: auto;
  appearance: auto;
}

.casilla.marcada {
  color: var(--primario);
  box-shadow: inset 3px 3px 6px var(--sombra-oscura), inset -3px -3px 6px var(--sombra-clara), inset 0 0 0 1.5px var(--primario);
}

/* Dentro de las listas: solo check + texto (sin recuadro ni borde, que se
   confundía con un botón). Los checkbox sueltos (Cuenta activa) no cambian. */
.casillas .casilla {
  display: flex;
  gap: 11px;
  padding: 8px 6px;
  border-radius: 8px;
  background: transparent;
  box-shadow: none;
  font-size: 15px;
}
.casillas .casilla.marcada {
  color: var(--primario);
  background: transparent;
  box-shadow: none;
}

.barra-editor {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 14px;
}

.barra-editor .btn-primario {
  flex: 1;
  min-width: 130px;
}

.btn-peligro {
  border-radius: 12px;
  padding: 8px 16px;
  min-height: 38px;
  font-size: 14px;
  color: var(--error);
  background: var(--superficie);
  box-shadow: 4px 4px 10px var(--sombra-oscura), -4px -4px 10px var(--sombra-clara);
}

.btn-peligro:not(:disabled):active {
  box-shadow: inset 4px 4px 8px var(--sombra-oscura), inset -4px -4px 8px var(--sombra-clara);
}

.oculto {
  display: none !important;
}

/* ---- Pases (acceso compartido por enlace) ---- */
.ayuda-pase {
  color: var(--texto-suave);
  font-size: 14px;
  line-height: 1.45;
  margin: 0 0 14px;
}

.pase-disp {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 16px;
}

.pase-casilla {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 4px;
  border-radius: 8px;
  background: transparent;
  color: var(--texto);
  cursor: pointer;
}

/* El checkbox real queda oculto (accesible) y el label lo alterna; el toggle
   visual es una pieza aparte (.pase-tgl) — en iOS Safari desliza más confiable
   que un pseudo-elemento sobre el <input>. Toggle a la izquierda, nombre a la
   derecha, sin icono. */
.pase-casilla input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.pase-tgl {
  flex: 0 0 auto;
  width: 44px;
  height: 25px;
  border-radius: 999px;
  position: relative;
  background: var(--superficie);
  box-shadow: inset 2px 2px 5px var(--sombra-oscura), inset -2px -2px 5px var(--sombra-clara);
  transition: background 0.15s ease;
}

.pase-tgl::before {
  content: '';
  position: absolute;
  top: 3px;
  left: 3px;
  width: 19px;
  height: 19px;
  border-radius: 50%;
  background: var(--texto-suave);
  transition: left 0.15s ease, background 0.15s ease;
}

input:checked ~ .pase-tgl {
  background: var(--primario);
}

input:checked ~ .pase-tgl::before {
  left: 22px;
  background: #14210a;
}

.pase-nom {
  font-size: 16px;
  font-weight: 600;
  color: var(--texto);
}

/* Grupos desplegables por tipo (Puertas, Ascensores…) en Compartir acceso. */
.pase-grupo {
  border-radius: 12px;
  background: var(--superficie);
  box-shadow: 3px 3px 8px var(--sombra-oscura), -3px -3px 8px var(--sombra-clara);
  overflow: hidden;
}

.pase-grupo-cab {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 13px 14px;
  cursor: pointer;
  list-style: none;
  font-size: 15px;
  font-weight: 600;
  color: var(--texto);
  -webkit-user-select: none;
  user-select: none;
}
.pase-grupo-cab::-webkit-details-marker { display: none; }

.pase-grupo-flecha {
  flex: 0 0 auto;
  color: var(--texto-suave);
  transition: transform 0.18s ease;
}
.pase-grupo[open] .pase-grupo-flecha {
  transform: rotate(90deg);
}

.pase-grupo-tit {
  flex: 1;
}

.pase-grupo-conteo {
  min-width: 22px;
  height: 22px;
  padding: 0 7px;
  border-radius: 999px;
  background: var(--primario);
  color: #14210a;
  font-size: 13px;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.pase-grupo-conteo[hidden] { display: none; }

.pase-grupo-cuerpo {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 0 12px 8px;
}

.pase-duracion {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 14px;
}

.chip-dur {
  flex: 1 1 30%;
  padding: 10px 12px;
  border: none;
  border-radius: 12px;
  background: var(--superficie);
  color: var(--texto-suave);
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 3px 3px 7px var(--sombra-oscura), -3px -3px 7px var(--sombra-clara);
}

.chip-dur.activa {
  color: var(--primario);
  box-shadow: inset 3px 3px 6px var(--sombra-oscura), inset -3px -3px 6px var(--sombra-clara), inset 0 0 0 1.5px var(--primario);
}

/* Rueda de duración: una sola fila con scroll horizontal y snap. Se ve un
   valor faded a cada lado (3 visibles) y el del centro es el elegido. Los
   ítems miden 1/3 del ancho y el padding lateral es de 1/3 para que el primero
   y el último puedan centrarse. */
.dur-rueda-wrap {
  flex: 1 1 100%;
  position: relative;
  border-radius: 12px;
  background: var(--superficie);
  box-shadow: inset 3px 3px 7px var(--sombra-oscura), inset -3px -3px 7px var(--sombra-clara);
  overflow: hidden;
}

/* Ventana central que enmarca el valor elegido. */
.dur-rueda-wrap::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 30%;
  height: 40px;
  transform: translate(-50%, -50%);
  border-radius: 9px;
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.06);
  pointer-events: none;
  z-index: 2;
}

.dur-rueda-wrap.activa::before {
  box-shadow: inset 0 0 0 1.5px var(--primario);
}

.dur-rueda {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  padding: 9px 0;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 34%, #000 66%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 34%, #000 66%, transparent);
}

.dur-rueda::-webkit-scrollbar {
  display: none;
}

/* Espaciadores de 1/3 al inicio y al final: permiten centrar el primer y el
   último valor. Van sin padding en la rueda para que el 33.33% de cada ítem
   se mida sobre el ancho completo (si no, el padding % encoge el basis %). */
.dur-esp {
  flex: 0 0 33.3333%;
}

.dur-op {
  flex: 0 0 33.3333%;
  scroll-snap-align: center;
  border: none;
  background: none;
  color: var(--texto-suave);
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  padding: 6px 0;
  cursor: pointer;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  transition: color 0.12s ease, font-size 0.12s ease;
}

.dur-op.centro {
  color: var(--texto);
  font-size: 16px;
}

.dur-rueda-wrap.activa .dur-op.centro {
  color: var(--primario);
}

/* Toggle admin "Míos / Todos" en Mis pases. */
.pase-scope {
  display: flex;
  gap: 8px;
  margin: 0 0 12px;
}
.chip-scope {
  padding: 6px 16px;
  border: none;
  border-radius: 10px;
  background: var(--superficie);
  color: var(--texto-suave);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 3px 3px 7px var(--sombra-oscura), -3px -3px 7px var(--sombra-clara);
  -webkit-tap-highlight-color: transparent;
}
.chip-scope.activa {
  color: var(--primario);
  box-shadow: inset 3px 3px 6px var(--sombra-oscura), inset -3px -3px 6px var(--sombra-clara), inset 0 0 0 1.5px var(--primario);
}

/* Tipo de enlace: Simple / Multiuso, con una "i" que despliega la ayuda. */
.pase-multi {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 16px;
}

/* Sin el margen inferior que .pase-scope trae por defecto: sumaba alto al
   bloque de chips y align-items:center dejaba la "i" corrida hacia abajo. */
.pase-multi .pase-scope {
  margin: 0;
}

.btn-info {
  flex: 0 0 auto;
  /* Flex para centrar la "i" ópticamente dentro del círculo: con line-height
     sola la itálica queda descuadrada. */
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  width: 13px;
  height: 13px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--superficie);
  color: var(--texto-suave);
  font-family: Georgia, "Times New Roman", serif;
  font-style: italic;
  font-size: 9px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  box-shadow: 1px 1px 3px var(--sombra-oscura), -1px -1px 3px var(--sombra-clara);
  -webkit-tap-highlight-color: transparent;
}

/* El círculo es pequeño a propósito, pero el área que se toca se extiende
   con un pseudo-elemento invisible para que siga siendo cómoda en el móvil. */
.btn-info::after {
  content: '';
  position: absolute;
  inset: -9px;
}

.btn-info[aria-expanded="true"] {
  color: var(--primario);
  box-shadow: inset 2px 2px 5px var(--sombra-oscura), inset -2px -2px 5px var(--sombra-clara);
}

.pase-ayuda {
  margin: -6px 0 16px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--texto-suave);
}

.pase-ayuda strong {
  color: var(--texto);
  font-weight: 600;
}

.pase-resultado {
  margin-top: 18px;
}

.pase-ok {
  color: var(--primario);
  font-size: 14px;
  margin: 0 0 10px;
}

.pase-url {
  width: 100%;
  padding: 11px 12px;
  border: none;
  border-radius: 10px;
  background: var(--fondo);
  color: var(--texto);
  font-size: 13px;
  box-shadow: inset 2px 2px 5px var(--sombra-oscura), inset -2px -2px 5px var(--sombra-clara);
  margin-bottom: 10px;
}

.pase-acciones {
  display: flex;
  gap: 10px;
}

.pase-acciones .btn-secundario {
  flex: 1;
}

.pase-info {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.pase-info strong {
  color: var(--texto);
  font-size: 15px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pase-meta {
  color: var(--texto-suave);
  font-size: 12.5px;
}

/* Estado del vencimiento: activo (verde) / vencido (rojo). */
.vence-ok { color: var(--primario); font-weight: 500; }
.vence-mal { color: var(--error); font-weight: 500; }

/* Campo Evento del generador de pases + su etiqueta en "Mis pases". */
.pase-evento {
  width: 100%;
  padding: 12px 14px;
  margin: 10px 0;
  border: none;
  border-radius: 12px;
  background: var(--fondo);
  color: var(--texto);
  font-size: 15px;
  box-shadow: inset 4px 4px 9px var(--sombra-oscura), inset -4px -4px 9px var(--sombra-clara);
  outline: none;
  -webkit-appearance: none;
  appearance: none;
}
.pase-evento::placeholder { color: var(--texto-suave); }
.pase-evento:focus {
  box-shadow: inset 4px 4px 9px var(--sombra-oscura), inset -4px -4px 9px var(--sombra-clara), 0 0 0 1.5px var(--primario);
}
.pase-evento-lbl {
  color: var(--texto);
  font-size: 13px;
  font-weight: 500;
}

.pase-fila-acciones {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
}

/* El detalle de canjes se despliega en una fila completa debajo. */
.fila-pase { flex-wrap: wrap; }
.pase-detalle {
  flex-basis: 100%;
  width: 100%;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid rgba(141, 146, 151, 0.18);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.pase-detalle-item {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
}
.pase-detalle-item > span:first-child {
  color: var(--texto);
  font-size: 13px;
}

.pase-estado {
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 3px 8px;
  border-radius: 8px;
}

.estado-activo { color: var(--primario); background: rgba(165, 255, 46, 0.12); }
.estado-usado { color: var(--texto-suave); background: rgba(141, 146, 151, 0.16); }
.estado-vencido { color: var(--texto-suave); background: rgba(141, 146, 151, 0.16); }
.estado-revocado { color: var(--error); background: rgba(240, 149, 149, 0.14); }

.btn-mini {
  border: none;
  border-radius: 9px;
  padding: 7px 11px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  background: var(--superficie);
  color: var(--texto-suave);
  box-shadow: 2px 2px 5px var(--sombra-oscura), -2px -2px 5px var(--sombra-clara);
}

.btn-mini:not(:disabled):active {
  box-shadow: inset 2px 2px 5px var(--sombra-oscura), inset -2px -2px 5px var(--sombra-clara);
}

.btn-mini-peligro {
  color: var(--error);
}

.lista-gestion li.vacio {
  justify-content: center;
  color: var(--texto-suave);
  font-size: 14px;
  box-shadow: none;
  background: transparent;
}

/* ===== Crear un skin con IA (solo admin, dentro del Locker) ===== */
/* La previa usa el MISMO anillo y botón que la app de verdad, para que lo que
   ves antes de publicar sea exactamente lo que verá el vecino. */
.skin-previa {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.skin-previa-anillo {
  align-self: center;
  margin: 4px 0 8px;
}

.skin-previa .boton-circular.grande {
  width: 168px;
  height: 168px;
  cursor: default;
}

.skin-lista {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 14px;
}

.skin-fila {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 10px;
  border-radius: 14px;
  background: var(--fondo);
}

.skin-fila img {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  object-fit: cover;
  flex: 0 0 auto;
}

.skin-fila span {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 14px;
}

.btn-borrar-skin {
  background: none;
  border: none;
  color: var(--texto-suave);
  font-size: 13px;
  padding: 6px 8px;
  cursor: pointer;
}

.btn-borrar-skin:active { color: var(--error); }

/* El textarea hereda el estilo de los inputs, pero no su fuente ni su altura:
   sin esto sale en monospace del navegador y se puede estirar a lo ancho. */
#form-skin textarea,
.campo textarea {
  font-family: inherit;
  line-height: 1.4;
  resize: vertical;
  min-height: 62px;
}

/* Interruptor con foto de la galería (una luz, un relé). El aro verde de
   .activo es un box-shadow interior, y la imagen lo tapa: el encendido se lee
   en la propia foto (apagada se atenúa) más un aro dibujado encima. Se acota a
   .medio para no tocar los botones de pulso con foto (Bordado, Hal, Argentina),
   que nunca llevan .activo y quedarían apagados para siempre. */
.boton-circular.medio.boton-imagen .boton-logo {
  filter: brightness(0.4) saturate(0.5);
  transition: filter 0.25s ease;
}

.boton-circular.medio.boton-imagen.activo .boton-logo {
  filter: none;
}

.boton-circular.medio.boton-imagen.activo::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  box-shadow: inset 0 0 0 2px rgba(165, 255, 46, 0.85);
  pointer-events: none;
  z-index: 2;
}

/* Chips de "para qué tipos sirve este botón", al crear y al editar. */
.skin-tipos {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 2px;
}

.chip-tipo {
  border: none;
  border-radius: 999px;
  padding: 7px 13px;
  font-size: 12.5px;
  font-family: inherit;
  color: var(--texto-suave);
  background: var(--fondo);
  box-shadow: inset 2px 2px 5px var(--sombra-oscura), inset -2px -2px 5px var(--sombra-clara);
  cursor: pointer;
}

.chip-tipo.activa {
  color: var(--primario);
  box-shadow: inset 0 0 0 1.5px rgba(165, 255, 46, 0.6);
}

/* La fila del skin abre su editor al tocarla. */
.skin-item { border-radius: 14px; overflow: hidden; }
.skin-fila { cursor: pointer; }

.skin-editor {
  padding: 4px 10px 12px;
  background: var(--fondo);
  border-radius: 0 0 14px 14px;
  margin-top: -4px;
}

.skin-acciones {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 4px;
}

.skin-acciones .btn-secundario {
  flex: 1;
  margin: 0;
}

/* El nombre dentro de un interruptor con foto: el estilo base está pensado
   para el botón grande (168px) y en uno de 92 queda alto y se pierde sobre la
   imagen. Se baja y se le pone un velo degradado que lo despega del fondo. */
.boton-circular.medio.boton-imagen .nombre-boton {
  bottom: 9px;
}

.boton-circular.medio.boton-imagen::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 52%;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0));
  pointer-events: none;
  z-index: 1;
}

/* ===== Aspecto Ascensor: botón de llamada de acero =====
   La foto viene con el aro y la flecha YA encendidos, así que el reposo se
   consigue apagándolos con filter (queda como un difusor sin luz) y al pulsar
   se quita el filtro y el ámbar sale además ALREDEDOR del botón, como una
   llamada registrada. Un solo bitmap para los dos estados. */
.boton-ascensor {
  transition: box-shadow 0.35s ease;
}

.boton-ascensor .boton-logo {
  filter: saturate(0.12) brightness(0.68);
  transition: filter 0.35s ease;
}

.boton-ascensor.enviando .boton-logo,
.boton-ascensor.exito .boton-logo {
  filter: none;
}

.boton-ascensor.enviando,
.boton-ascensor.exito {
  box-shadow: 9px 9px 18px var(--sombra-oscura), -9px -9px 18px var(--sombra-clara),
              0 0 30px 7px rgba(255, 176, 62, 0.7);
}

/* La miniatura del Locker no usa .boton-logo sino .skin-muestra img, así que
   el reposo del ascensor hay que apagárselo también aquí. */
.skin-muestra.boton-ascensor img {
  filter: saturate(0.12) brightness(0.68);
}

/* ===== Aspecto Sabiem: placa de llamada de ascensor a la antigua =====
   Una placa vertical, no un botón redondo: control propio, como el Jet Switch.
   La foto trae los rótulos apagados; encenderlos son dos capas transparentes
   del MISMO tamaño que la placa (las letras ya vienen en su sitio), así no hay
   posiciones que calcular ni que se descuadren al cambiar el tamaño. */
.control-sabiem {
  gap: 10px;
}

.sabiem-placa {
  position: relative;
  width: 150px;
  height: 302px;      /* proporción de la placa original (605x1216) */
  border-radius: 7px;
  background: url("sabiem.webp?v=1") center/100% 100% no-repeat;
  box-shadow: 6px 6px 16px var(--sombra-oscura), -6px -6px 16px var(--sombra-clara);
}

.sabiem-luz {
  position: absolute;
  inset: 0;
  background-size: 100% 100%;
  background-repeat: no-repeat;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
}

/* Tres halos apilados: el fino define la letra, el medio la enciende y el
   ancho tiñe el vidrio verde alrededor, que es lo que hace que parezca luz de
   verdad y no letras pintadas de amarillo. */
.sabiem-luz.on {
  opacity: 1;
  filter: drop-shadow(0 0 3px rgba(255, 225, 140, 1))
          drop-shadow(0 0 9px rgba(255, 180, 40, 0.95))
          drop-shadow(0 0 22px rgba(255, 150, 20, 0.6));
}

.sabiem-ocupado { background-image: url("sabiem-ocupado.png?v=2"); }
.sabiem-llegando { background-image: url("sabiem-llegando.png?v=2"); }

/* Zona de toque sobre el botón negro de la foto (medido: centro 49.7% / 65.4%,
   diámetro 22% del ancho). Se deja algo más grande que el botón para que no
   haya que apuntar. */
.sabiem-boton {
  position: absolute;
  left: 49.7%;
  top: 65.4%;
  width: 34%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border: none;
  border-radius: 50%;
  background: none;
  padding: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.sabiem-boton:active {
  box-shadow: inset 0 0 12px rgba(0, 0, 0, 0.55);
}

/* Miniatura del Locker: la placa es vertical y el hueco es redondo, así que se
   muestra entera con `contain` en vez de recortarla. */
.muestra-sabiem {
  background: url("sabiem.webp?v=1") center/auto 100% no-repeat;
}

/* ===== Aspecto Bronce: botón de ascensor industrial =====
   Mismo patrón que el de acero, pero el filtro del reposo conserva algo de
   saturación: el bisel ES de bronce y desaturarlo del todo lo volvería gris,
   perdiendo justo lo que lo distingue. */
.boton-bronce {
  transition: box-shadow 0.35s ease;
}

.boton-bronce .boton-logo {
  filter: saturate(0.4) brightness(0.52);
  transition: filter 0.35s ease;
}

.boton-bronce.enviando .boton-logo,
.boton-bronce.exito .boton-logo {
  filter: none;
}

.boton-bronce.enviando,
.boton-bronce.exito {
  box-shadow: 9px 9px 18px var(--sombra-oscura), -9px -9px 18px var(--sombra-clara),
              0 0 30px 7px rgba(255, 176, 62, 0.7);
}

.skin-muestra.boton-bronce img {
  filter: saturate(0.4) brightness(0.52);
}

/* ===== Aspecto Lobby: pulsador de puerta de personas =====
   Mismo patrón que los de ascensor: la foto viene encendida y el reposo se
   consigue apagándola. Aquí se conserva algo de saturación porque el aro y el
   rótulo son ámbar sobre gunmetal y a saturación 0 se volvían plomo. */
.boton-lobby {
  transition: box-shadow 0.35s ease;
}

.boton-lobby .boton-logo {
  filter: saturate(0.28) brightness(0.5);
  transition: filter 0.35s ease;
}

.boton-lobby.enviando .boton-logo,
.boton-lobby.exito .boton-logo {
  filter: none;
}

.boton-lobby.enviando,
.boton-lobby.exito {
  box-shadow: 9px 9px 18px var(--sombra-oscura), -9px -9px 18px var(--sombra-clara),
              0 0 30px 7px rgba(255, 176, 62, 0.7);
}

.skin-muestra.boton-lobby img {
  filter: saturate(0.28) brightness(0.5);
}

/* Nota corta debajo de un campo replegado, para explicar cuándo hace falta. */
.campo-ayuda {
  font-size: 12.5px;
  color: var(--texto-suave);
  margin: 6px 0 0;
  line-height: 1.45;
}


/* Buscador de una lista de gestión. */
.buscador {
  width: 100%;
  padding: 11px 14px;
  margin: 0 0 6px;
  border: none;
  border-radius: 12px;
  background: var(--fondo);
  color: var(--texto);
  font-size: 15px;
  font-family: inherit;
  box-shadow: inset 4px 4px 9px var(--sombra-oscura), inset -4px -4px 9px var(--sombra-clara);
  outline: none;
  -webkit-appearance: none;
  appearance: none;
}

.buscador::placeholder { color: var(--texto-suave); }

/* ===== Aspecto Mando: el control remoto del portón =====
   La foto recortada ES el control. La zona de toque va sobre el botón crema
   (medido: 25.9% / 14.3%, 47.7% x 21.2%), no sobre todo el mando: es lo que se
   aprieta de verdad, y evita aperturas por rozar el cuerpo. */
.control-mando {
  gap: 10px;
}

.mando-cuerpo {
  position: relative;
  width: 170px;
  height: 247px;   /* proporción del recorte (386x560) */
  background: url("mando.webp?v=1") center/100% 100% no-repeat;
  filter: drop-shadow(4px 6px 10px rgba(0, 0, 0, 0.55));
}

.mando-boton {
  position: absolute;
  left: 25.9%;
  top: 14.3%;
  width: 47.7%;
  height: 21.2%;
  border: none;
  border-radius: 4px;
  background: none;
  padding: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: box-shadow 0.12s ease, transform 0.12s ease;
}

/* Al apretar, el botón se hunde y vuelve solo (`pulsado` se quita a los 1,1 s).
   NO se usan aquí las clases .enviando/.exito de `pulsar`: esas duran lo que
   tarda el portón en abrir, y un mando no se queda hundido 15 segundos. */
.mando-boton:active,
.mando-boton.pulsado {
  transform: translateY(2px) scale(0.94);
  box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.75);
}

/* Miniatura del Locker: el mando entero dentro del círculo. */
.muestra-mando {
  background: var(--superficie) url("mando.webp?v=1") center/auto 74% no-repeat;
}

/* Generar con IA o subir del carrete: las dos vías, del mismo tamaño. */
.skin-origen {
  display: flex;
  gap: 10px;
}

.skin-origen > * {
  flex: 1;
  margin: 0;
}

/* El input de archivo va DENTRO de la etiqueta y oculto ahí, no con .oculto
   (display:none): así el toque en la etiqueta abre el selector del teléfono de
   forma fiable en iOS. */
.btn-archivo {
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}

.btn-archivo input[type="file"] {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* La previa es recortable: la foto se posiciona y transforma a mano, así que se
   anulan el 100%/cover de .boton-logo. El contenedor circular la recorta. */
.skin-previa .boton-circular {
  cursor: grab;
  touch-action: none;   /* los gestos son nuestros, no del navegador */
}

.skin-previa .boton-circular:active { cursor: grabbing; }

.skin-previa .boton-logo {
  position: absolute;
  left: 50%;
  top: 50%;
  width: auto;
  height: auto;
  max-width: none;
  /* `fill`, no `none`: con `none` el bitmap se dibuja a tamaño natural y se
     ignora el width/height que le pone el JS, así que la previa no coincidía
     con lo que se publica. El recuadro ya lleva la proporción correcta. */
  object-fit: fill;
  border-radius: 0;
  transform-origin: center center;
}

/* Pista y deslizador del recorte. */
.recorte-pista {
  text-align: center;
  margin: 0 0 8px;
}

.zoom-recorte {
  width: 100%;
  margin: 0 0 10px;
  -webkit-appearance: none;
  appearance: none;
  background: none;
}

.zoom-recorte::-webkit-slider-runnable-track {
  height: 8px;
  border-radius: 999px;
  background: var(--fondo);
  box-shadow: inset 2px 2px 5px var(--sombra-oscura), inset -2px -2px 5px var(--sombra-clara);
}

.zoom-recorte::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 22px;
  height: 22px;
  margin-top: -7px;
  border-radius: 50%;
  background: var(--primario);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.55);
  cursor: grab;
}

.zoom-recorte::-moz-range-track {
  height: 8px;
  border-radius: 999px;
  background: var(--fondo);
}

.zoom-recorte::-moz-range-thumb {
  width: 22px;
  height: 22px;
  border: none;
  border-radius: 50%;
  background: var(--primario);
}

/* ===== Carrusel de dos en dos (grupos de más de dos controles) =====
   Cada ficha ocupa media pantalla y encaja al borde en vez de al centro, así
   siempre se ven DOS enteros y cada deslizada pasa al par siguiente. Sin
   coverflow: los dos van a tamaño completo. */
.grupo-controles.carrusel.doble {
  padding: 8px 0;
  gap: 0;
}

/* El hueco de cada ficha lo calcula el JS como una división ENTERA del ancho
   (--hueco-ficha), para que se vean controles completos y nunca "tres y un
   pedazo". Con 50% a secas, en un contenedor ancho se separaban dejando un
   agujero en medio. */
.grupo-controles.carrusel.doble > .control {
  flex: 0 0 var(--hueco-ficha, 50%);
  scroll-snap-align: start;
  transform: none;
  opacity: 1;
}

/* Los botones grandes se achican para que dos quepan enteros en la pantalla:
   220px (168 + 26 de aro a cada lado) no caben dos en un teléfono. */
.compacto .anillo {
  padding: 17px;
}

.compacto .boton-circular.grande {
  width: 122px;
  height: 122px;
}

.compacto .boton-circular.grande svg {
  width: 46px;
  height: 46px;
}

/* ===== Control espejado (columna derecha) =====
   En la columna derecha el pulgar tapa el costado derecho, justo donde está la
   columna de luces de la rueda. Se espeja el control entero: el rodillo es
   simétrico y las luces son círculos, así que lo único que cambia de verdad es
   de qué lado quedan. El gesto es vertical, así que no se invierte nada. */
.espejo .rueda-ctrl {
  transform: scaleX(-1);
}

/* Encabezado de grupo con algo caído: el naranja del fuego, que ya se usa para
   avisar sin ser una alarma roja. Va con la MISMA especificidad que
   `.lista-gestion li.grupo-gestion`, que si no le gana y no se ve. */
.lista-gestion li.grupo-gestion.grupo-alerta {
  color: var(--fuego);
}

/* Traer dispositivos de Tuya: botón y lista apilados dentro de su campo, con
   aire propio. Antes iban sueltos y se solapaban con el control de arriba.
   El margen de abajo iguala el de un input, para que el campo siguiente
   respire lo mismo que los demás. */
.tuya-lista {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 8px;
}

.tuya-lista > .btn-secundario,
.tuya-lista > select {
  margin: 0;
  width: 100%;
}

/* En medio de una columna de campos hundidos, el relieve del botón se lee
   como un halo. Aquí va hundido igual que ellos, y el texto se queda gris:
   en verde resaltaba más que el propio Guardar. */
.tuya-lista > .btn-secundario {
  box-shadow: inset 4px 4px 9px var(--sombra-oscura), inset -4px -4px 9px var(--sombra-clara);
}

.tuya-lista > .btn-secundario:not(:disabled):active {
  opacity: 0.6;
}

.tuya-lista > .dps-detectados:empty {
  display: none;
}

.tuya-lista > .dps-detectados {
  margin-top: 0;
}

/* Inmuebles en árbol: un edificio se pliega y sus apartamentos van dentro.
   La fila del padre imita a `.lista-gestion li` (que aquí no aplica, porque el
   li solo envuelve al <details>), y la flecha reaprovecha .pase-grupo-flecha:
   solo hace falta añadirle el giro, que allí está atado a .pase-grupo[open]. */
.lista-gestion li.inm-rama {
  display: block;
  padding: 0;
  background: none;
  box-shadow: none;
}

.inm-rama > details > summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 10px 10px 12px;
  border-radius: 12px;
  background: var(--fondo);
  box-shadow: inset 3px 3px 7px var(--sombra-oscura), inset -3px -3px 7px var(--sombra-clara);
  cursor: pointer;
  list-style: none;
  -webkit-user-select: none;
  user-select: none;
}
.inm-rama > details > summary::-webkit-details-marker { display: none; }

.lista-gestion li.inm-hoja {
  padding-left: 40px;   /* 12 del summary + 18 de la flecha + 10 del hueco */
}

.inm-rama > details > summary > span {
  flex: 1;
}

/* El conteo de lo que hay dentro, sin gritar. */
.inm-rama > details > summary em {
  font-style: normal;
  color: var(--texto-suave);
}

.inm-rama > details[open] .pase-grupo-flecha {
  transform: rotate(90deg);
}

/* Los hijos, sangrados y colgando de una línea, para que se lea de un vistazo
   qué está dentro de qué. */
.inm-rama > details > .lista-gestion {
  margin: 9px 0 0 14px;
  padding-left: 14px;
  border-left: 1px solid var(--sombra-oscura);
}

/* Alta de vecinos en lote: una fila por unidad. En móvil se apila (la unidad
   arriba, los tres campos debajo) y en pantalla ancha va todo en línea. */
.lote-vecinos {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 10px;
  max-height: 50vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.lote-fila {
  display: grid;
  grid-template-columns: 1fr;
  gap: 6px;
  align-items: center;
  padding: 10px 12px;
  border-radius: 12px;
  background: var(--fondo);
  box-shadow: inset 3px 3px 7px var(--sombra-oscura), inset -3px -3px 7px var(--sombra-clara);
}

.lote-unidad {
  font-size: 14px;
  font-weight: 600;
  color: var(--texto);
}

.lote-ocupado {
  font-size: 13px;
  color: var(--texto-suave);
}

/* Los inputs de la fila no son `.campo input`, así que se les da aquí el
   mismo aspecto hundido, un punto más bajo por ir tres seguidos. */
.lote-fila input {
  width: 100%;
  padding: 10px 12px;
  border: none;
  border-radius: 10px;
  background: var(--superficie);
  color: var(--texto);
  font-size: 16px;
  font-family: inherit;
  box-shadow: inset 3px 3px 6px var(--sombra-oscura), inset -3px -3px 6px var(--sombra-clara);
  outline: none;
  -webkit-appearance: none;
}

.lote-fila input:focus {
  box-shadow: inset 3px 3px 6px var(--sombra-oscura), inset -3px -3px 6px var(--sombra-clara), 0 0 0 1.5px var(--primario);
}

@media (min-width: 620px) {
  .lote-fila {
    grid-template-columns: 70px 1fr 1fr 1.4fr;
    gap: 8px;
  }
}
