/* Hoja única de la aplicación.
 *
 * Dos reglas que sostienen todo lo demás:
 *
 * 1. **Ningún color hexadecimal fuera de `:root`.** No es estética: es lo que hace que añadir
 *    modo oscuro más adelante cueste una lista de variables y no una revisión de cada regla.
 *    Hoy no hay modo oscuro y no se inventa uno; se deja la puerta abierta sin pagarla.
 * 2. **Cada color de texto o de contorno lleva su ratio de contraste anotado**, calculado
 *    contra el fondo sobre el que se usa de verdad. Un contraste que nadie mide es un
 *    contraste que nadie cumple.
 */

:root {
  --fondo: #f4f6fb;
  --panel: #ffffff;

  --texto: #0f172a; /* 16,7:1 sobre --panel */
  --texto-suave: #4b5563; /* 7,6:1 sobre --panel */

  /* Contorno **decorativo**: separadores, bordes de tarjeta. No transmite información, así
   * que no le aplica el mínimo de 3:1. */
  --borde: #d5dae6; /* 1,4:1 sobre --panel — sólo decorativo */

  /* Contorno de los **controles**: campos, desplegables, botones. Aquí sí manda WCAG 2.2
   * SC 1.4.11, que pide 3:1, y el `--borde` de arriba daba 1,4:1: los campos de todo el
   * proyecto lo incumplían. Se separan en dos variables en vez de subir `--borde` porque
   * oscurecer los separadores de las tablas las convierte en una rejilla. */
  --borde-control: #6b7280; /* 4,8:1 sobre --panel */

  --acento: #1d4ed8; /* 7,0:1 sobre --panel */
  --acento-texto: #ffffff; /* 7,0:1 sobre --acento */
  --acento-oscuro: #1e40af;

  --ok: #14532d; /* 9,4:1 sobre --ok-fondo */
  --ok-fondo: #dcfce7;
  --warn: #7c2d12; /* 8,7:1 sobre --warn-fondo */
  --warn-fondo: #fef3c7;
  --error: #7f1d1d; /* 9,6:1 sobre --error-fondo */
  --error-fondo: #fee2e2;
  --info: #1e3a8a; /* 9,8:1 sobre --info-fondo */
  --info-fondo: #dbeafe;

  /* Estado sin carga emocional: cancelado, archivado, «no procede». Deliberadamente apagado:
   * pintar «Cancelado» en rojo hace pensar en un fallo cuando fue una decisión de alguien. */
  --neutro: #374151; /* 10,3:1 sobre --neutro-fondo */
  --neutro-fondo: #e5e7eb;

  --radio: 10px;
  --espacio: 1rem;

  /* Única sombra del proyecto, y sólo para lo que flota sobre el resto: diálogos y menús. Las
   * tarjetas se separan del fondo con `--borde`, que es más barato de pintar y no compite. */
  --sombra-flotante: 0 10px 30px rgb(15 23 42 / 18%);

  /* Área táctil mínima. 44 px es lo que pide la guía de Apple y lo que necesita un dedo con
   * guantes de trabajo en una cubierta. */
  --tactil: 44px;

  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  color-scheme: light;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--fondo);
  color: var(--texto);
  /* La zona segura del iPad y de los móviles con muesca. Sin esto el contenido queda bajo la
   * barra de inicio en horizontal. */
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom)
    env(safe-area-inset-left);
}

/* --- Accesibilidad transversal ------------------------------------------------------- */

/* Un solo anillo de foco para toda la aplicación, y **visible**. `:focus-visible` y no
 * `:focus`: así el ratón no lo dibuja al hacer clic, pero el teclado siempre lo ve. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 3px solid var(--acento);
  outline-offset: 2px;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.salto-al-contenido {
  position: absolute;
  left: -999px;
  top: 0;
  z-index: 10;
  background: var(--panel);
  color: var(--texto);
  padding: 0.75rem 1rem;
  border-radius: 0 0 var(--radio) 0;
}

.salto-al-contenido:focus {
  left: 0;
}

/* --- Armazón ------------------------------------------------------------------------- */

.cabecera {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem var(--espacio);
  background: var(--panel);
  border-bottom: 1px solid var(--borde);
}

/* El logo de la cabecera (31-ago-2026).
 *
 * `height` fija y `width: auto` es lo que conserva la proporción: dar los dos en píxeles la
 * deformaría en cuanto alguien tocara uno. El archivo mide 452x160 y se sirve a 28 px de alto,
 * así que en pantallas de densidad doble y triple sigue nítido sin pedir una segunda imagen.
 *
 * `object-fit: contain` no hace falta con `width: auto` —la caja ya la decide la imagen— pero
 * se declara igualmente: si un día alguien le pone un ancho fijo desde otra regla, la imagen
 * se encogerá dentro en vez de estirarse.
 *
 * `flex-shrink: 0` porque la cabecera es flexible y a 360 px el logo era lo primero que se
 * comprimía; una marca aplastada es peor que una marca que empuja la navegación a otra línea,
 * y `flex-wrap` ya está puesto para que caiga sin desbordar. */
.cabecera__logo {
  height: 28px;
  width: auto;
  object-fit: contain;
  flex-shrink: 0;
}

.cabecera__marca {
  font-weight: 600;
}

.cabecera__nav {
  display: flex;
  gap: 1rem;
}

/* Los enlaces de la navegación medían ~19 px de alto: el texto y nada más. El contrato pide
 * 44 px de área táctil y ahí no se cumplía. Se le da altura al enlace, no a la barra, porque
 * lo que el dedo tiene que acertar es el enlace. */
.cabecera__nav a {
  display: inline-flex;
  align-items: center;
  min-height: var(--tactil);
  padding: 0 0.25rem;
}

.cabecera__salir {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-left: auto;
}

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

.contenido {
  padding: var(--espacio);
  max-width: 68rem;
  margin: 0 auto;
}

/* El foco que recibe `<main>` desde el salto al contenido no debe pintar un recuadro alrededor
 * de media página: el desplazamiento ya dice al usuario dónde está. */
.contenido:focus {
  outline: none;
}

.avisos {
  position: fixed;
  left: 0;
  right: 0;
  bottom: env(safe-area-inset-bottom);
  display: grid;
  gap: 0.5rem;
  padding: 0 var(--espacio) var(--espacio);
  pointer-events: none;
}

.avisos > * {
  pointer-events: auto;
}

/* --- Avisos --------------------------------------------------------------------------- */

.aviso {
  margin: 0 0 var(--espacio);
  padding: 0.75rem 1rem;
  border-radius: var(--radio);
  border: 1px solid transparent;
}

.aviso--ok {
  background: var(--ok-fondo);
  color: var(--ok);
}
.aviso--aviso {
  background: var(--warn-fondo);
  color: var(--warn);
}
.aviso--error {
  background: var(--error-fondo);
  color: var(--error);
}
.aviso--info {
  background: var(--info-fondo);
  color: var(--info);
}
.aviso--neutro {
  background: var(--neutro-fondo);
  color: var(--neutro);
}

/* --- Controles ------------------------------------------------------------------------ */

.campo {
  display: grid;
  gap: 0.35rem;
  margin-bottom: var(--espacio);
}

.campo label {
  font-weight: 600;
}

.campo__ayuda {
  margin: 0;
  color: var(--texto-suave);
  font-size: 0.9rem;
}

input,
select,
textarea {
  font: inherit;
  color: var(--texto);
  background: var(--panel);
  border: 1px solid var(--borde-control);
  border-radius: var(--radio);
  padding: 0.6rem 0.75rem;
  min-height: var(--tactil);
  width: 100%;
}

input[aria-invalid="true"],
select[aria-invalid="true"],
textarea[aria-invalid="true"] {
  border-color: var(--error);
  /* Nunca **sólo** color: quien no distingue el rojo necesita el mensaje, que lo pone
   * `validacion.js` enlazado con `aria-describedby`. El borde grueso es la segunda señal. */
  border-width: 2px;
}

.boton {
  font: inherit;
  min-height: var(--tactil);
  padding: 0.6rem 1.1rem;
  border-radius: var(--radio);
  border: 1px solid var(--borde-control);
  background: var(--panel);
  color: var(--texto);
  cursor: pointer;
}

.boton--principal {
  background: var(--acento);
  border-color: var(--acento);
  color: var(--acento-texto);
  font-weight: 600;
}

.boton--principal:hover {
  background: var(--acento-oscuro);
  border-color: var(--acento-oscuro);
}

.boton--discreto {
  background: transparent;
}

.boton[disabled] {
  opacity: 0.6;
  cursor: not-allowed;
}

/* --- Contraseña ----------------------------------------------------------------------- */

.campo__contrasena {
  position: relative;
}

.campo__contrasena input {
  /* Sitio para el ojo, sin que el texto pase por debajo. */
  padding-right: calc(var(--tactil) + 0.5rem);
}

/* Edge dibuja su propio ojo. Con el nuestro al lado quedaban **dos** controles para lo mismo:
 * fue un defecto real del 7-ago-2026. Se esconde el suyo, no el nuestro, porque el nativo no
 * existe en Chrome para Android, no se alcanza con el tabulador y no anuncia su estado. */
.campo__contrasena input::-ms-reveal,
.campo__contrasena input::-ms-clear {
  display: none;
}

.ojo {
  position: absolute;
  right: 0;
  top: 0;
  width: var(--tactil);
  height: var(--tactil);
  border: 0;
  background: transparent;
  cursor: pointer;
  /* El icono se pinta con `mask` desde el CSS para no meter SVG en línea: la política de
   * contenido lo permitiría, pero el HTML se llena de ruido en cada campo. */
  background-color: var(--texto-suave);
  mask: var(--ojo-cerrado) center / 22px 22px no-repeat;
  -webkit-mask: var(--ojo-cerrado) center / 22px 22px no-repeat;
}

.ojo[aria-pressed="true"] {
  mask-image: var(--ojo-abierto);
  -webkit-mask-image: var(--ojo-abierto);
}

:root {
  --ojo-cerrado: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E");
  --ojo-abierto: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3Cpath d='m3 3 18 18'/%3E%3C/svg%3E");
}

/* --- Página de acceso ------------------------------------------------------------------ */

.acceso {
  max-width: 26rem;
  margin: 2rem auto;
  background: var(--panel);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: 1.5rem;
}

/* En el acceso el logo manda más que el título: es donde alguien comprueba que ha llegado a
 * la aplicación de su empresa. `max-width: 100%` para que a 360 px se reduzca en vez de
 * desbordar la tarjeta, que tiene 26rem de ancho máximo y 1,5rem de relleno a cada lado. */
.acceso__logo {
  display: block;
  height: 56px;
  width: auto;
  max-width: 100%;
  object-fit: contain;
  margin: 0 auto 1.25rem;
}

.acceso__titulo {
  margin-top: 0;
}

.acceso__demo {
  margin-top: 1.5rem;
  padding-top: 1rem;
  border-top: 1px solid var(--borde);
  color: var(--texto-suave);
  font-size: 0.9rem;
}

.acceso__demo h2 {
  font-size: 1rem;
  margin: 0 0 0.5rem;
}

.acceso__demo ul {
  margin: 0;
  padding-left: 1.2rem;
}

/* --- Los cuatro tamaños ----------------------------------------------------------------
 *
 * El proyecto tenía **un solo** punto de corte, en 900 px. El iPad en vertical mide 834 y caía
 * por debajo, así que recibía el diseño de teléfono entero: el panel de oficina en una columna
 * y botones de 800 px de ancho. Tres cortes en vez de uno, y ninguno cae entre 768 y 834:
 *
 *   < 640    teléfono
 *   640-1023 teléfono grande y tableta en vertical  ← aquí entra el iPad (834)
 *   1024+    tableta en horizontal
 *   1280+    escritorio
 */

@media (min-width: 640px) {
  .contenido {
    padding: 1.5rem;
  }
}

@media (min-width: 768px) {
  /* Dos columnas de campos desde 768 y no desde 640: con las etiquetas de este formulario
   * —«Fabricante del inversor», «Potencia nominal»— dos columnas a 640 px parten las palabras. */
  .campos--dos {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0 1.5rem;
  }
}

@media (min-width: 1024px) {
  .contenido {
    padding: 2rem;
  }
}

@media (min-width: 1280px) {
  .contenido {
    max-width: 76rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* --- Zona de peligro y confirmación (26-ago-2026; global desde el 31-ago) ---------------------------------------------
 *
 * La zona de peligro se separa del resto con contorno propio **y** por su posición: es lo
 * último del detalle, después de la auditoría, para que nadie llegue aquí por inercia
 * mientras corrige un dato.
 */
.peligro {
  margin-top: 2rem;
  padding: var(--espacio);
  border: 1px solid var(--error);
  border-radius: var(--radio);
  background: var(--error-fondo);
}

.peligro h2,
.peligro h3 {
  margin-top: 0;
  color: var(--error);
}

.boton--peligro {
  background: var(--error);
  border-color: var(--error);
  color: var(--panel);
  /* 44 px: es una acción con consecuencias y no puede ser el control más pequeño de la
   * página. Que sea fácil de acertar no la hace más fácil de disparar sin querer — para eso
   * está la confirmación con motivo obligatorio. */
  min-height: var(--tactil);
}

.boton--peligro:hover {
  /* No hay un token más oscuro para el error, y no se añade uno sólo para esto: el cambio de
   * opacidad ya distingue el estado sin introducir un color nuevo fuera de `:root`. */
  opacity: 0.9;
}

/* El `<summary>` estilizado como botón. `list-style: none` + `::-webkit-details-marker`
 * porque el triangulito por omisión lo pinta cada navegador a su manera y aquí sobra: el
 * control ya se lee como botón. */
.peligro__confirmar > summary {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  list-style: none;
}

.peligro__confirmar > summary::-webkit-details-marker {
  display: none;
}

.confirmar {
  margin-top: var(--espacio);
  padding: var(--espacio);
  background: var(--panel);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

.confirmar h3,
.confirmar h4 {
  margin-top: 0;
}

.confirmar__acciones {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: var(--espacio);
}

.confirmar__acciones .boton {
  min-height: var(--tactil);
}

/* El diálogo que crea `pagina-oficina.js` moviendo dentro el formulario de arriba. Cuelga del
 * `<body>`, así que ningún antepasado puede recortarlo. */
.confirmar-dialogo {
  width: min(94vw, 34rem);
  padding: 0;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra-flotante);
  background: var(--panel);
  color: var(--texto);
}

.confirmar-dialogo::backdrop {
  background: rgb(15 23 42 / 55%);
}

.confirmar-dialogo .confirmar {
  margin: 0;
  border: 0;
}


/* El alcance de un borrado, en números y antes de confirmar. Lista y no párrafo: son cuatro
 * cantidades independientes y leerlas seguidas en prosa obliga a contarlas con el dedo. */
.peligro__alcance {
  margin: 0.5rem 0;
  padding-left: 1.2rem;
}

.peligro__alcance li {
  margin: 0.15rem 0;
}

