@charset "UTF-8";
/* =============================================================================
   Portal de facturación — hoja de estilo única
   -----------------------------------------------------------------------------
   Cliente:    FRENAT (Asesores energía/instalaciones) · ERP CORETEL
   Requisitos: un solo fichero, sin preprocesador, sin build, sin JavaScript,
               sin peticiones externas (CSP estricta), sólo modo claro.
   Tipografía: pila del sistema. No se carga ninguna fuente.

   ÍNDICE
     01. Tokens (variables)
     02. Reset y base
     03. Estructura (.site, .site-header, .site-main, .site-footer)
     04. Marca
     05. Navegación
     06. Tarjetas (.card)
     07. Cifras destacadas (.stat)
     08. Tablas de datos (.data-table)  ← lo más delicado, ver 08.b (móvil)
     09. Formularios, filtros y botones
     10. Avisos y estado vacío
     11. Login
     12. Pie y sedes
     13. Utilidades
     14. Foco visible (accesibilidad por teclado)
     15. Responsive (móvil y tableta)
     16. Movimiento reducido
     17. Impresión

   CONVENIOS
     - Los nombres de clase están cerrados: los usan las plantillas PHP.
       No renombrar ni inventar nuevos sin tocar también views/.
     - Todo color de texto cumple WCAG AA (>= 4.5:1) sobre su fondo.
       El verde claro del portal de 2007 (#90b557) NO llega a 4.5:1 sobre
       blanco: los tonos 300 y 400 se reservan para fondos, bordes y acentos.
       Para texto se usa --color-brand-600 (4,67:1) o más oscuro.
     - Los cortes responsive se declaran como `@media screen and (...)` para
       que la impresión (sección 17) nunca herede el modo tarjeta del móvil.
   ============================================================================= */


/* =============================================================================
   01. TOKENS
   ========================================================================== */

:root {
  /* --- Tipografía ------------------------------------------------------- */
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
               "Helvetica Neue", Arial, "Noto Sans", sans-serif;

  /* --- Color de marca ---------------------------------------------------
     Estos nueve tonos son EL tema. app.css no escribe ni un color a mano en
     ninguna regla, así que cambiar el tema desde el panel es reescribir esta
     lista en un <style> y nada más: ni un fichero que tocar.

     Los de aquí son el verde de FRENAT, muestreado del logotipo, no
     inventado: 600 es su verde exacto y 300 el claro del marco. Sustituyen
     al #90b557 de 2007, que sobre blanco se quedaba en 3,2:1.
     300/400 → fondos y acentos. 600 → primer tono que pasa AA (4,67:1).
     700 → texto y botones (6,28:1).
     Los demás temas están en app/Tema.php, y tests/temas.php comprueba que
     todos cumplen esos mínimos.                                            */
  --color-brand-50:  #f4f9ef;
  --color-brand-100: #e7f2dc;
  --color-brand-200: #cfe6ba;
  --color-brand-300: #a8d08d;   /* ← verde claro EXACTO del logotipo */
  --color-brand-400: #86b968;
  --color-brand-500: #6a9c4b;
  --color-brand-600: #528034;   /* ← VERDE DE MARCA, exacto del logotipo (4.67:1 sobre blanco) */
  --color-brand-700: #446a2b;   /* texto sobre blanco, 6.28:1 */
  --color-brand-800: #365522;

  /* --- Color de apoyo (enlaces y acciones secundarias) -------------------
     El segundo color del tema. Aquí, el azul del portal original.          */
  --color-accent-50:  #eef5fc;
  --color-accent-100: #d9e8f7;
  --color-accent-200: #b9d3ee;
  --color-accent-600: #2b6dab;
  --color-accent-700: #1b5790;    /* ← azul de enlaces original */
  --color-accent-800: #15446f;
  --color-accent-900: #0f3252;

  /* --- Neutros (fríos, para casar con el fondo azulado del portal) ------- */
  --color-bg:            #f2f5f9;
  --color-bg-top:        #e4ecf4;   /* evolución del #e5ecf3 de 2007 */
  --color-surface:       #ffffff;
  --color-surface-2:     #f6f8fb;
  --color-surface-3:     #eef2f7;
  --color-border:        #dfe6ee;
  --color-border-strong: #c8d4e0;
  --color-ink:           #17212e;   /* titulares y cifras */
  --color-text:          #2c3a47;   /* cuerpo (11.6:1) */
  --color-muted:         #566573;   /* secundario (6.0:1) */
  --color-footer:        #1e2a35;

  /* --- Estado ------------------------------------------------------------ */
  --color-danger:        #a32218;
  --color-danger-bg:     #fdf2f0;
  --color-danger-border: #f1cdc7;

  --color-focus: #2b6dab;

  /* --- Espaciado --------------------------------------------------------- */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;

  /* --- Radios ------------------------------------------------------------ */
  --radius-sm:   6px;
  --radius-md:   10px;
  --radius-lg:   14px;
  --radius-xl:   20px;
  --radius-pill: 999px;

  /* --- Sombras (muy suaves: es un portal de datos, no una landing) ------- */
  --shadow-sm: 0 1px 2px rgba(23, 33, 46, .06);
  --shadow-md: 0 1px 2px rgba(23, 33, 46, .05),
               0 8px 20px -12px rgba(23, 33, 46, .28);
  --shadow-lg: 0 2px 4px rgba(23, 33, 46, .05),
               0 24px 48px -24px rgba(23, 33, 46, .38);

  /* --- Medidas ----------------------------------------------------------- */
  --width-page: 1120px;
  --gutter: clamp(1rem, 4vw, 2rem);
  --control-h: 2.75rem;          /* 44px: mínimo táctil recomendado */

  /* --- Transiciones ------------------------------------------------------ */
  --t-fast: .15s ease;
}


/* -----------------------------------------------------------------------------
   Cortes de línea de seguridad

   Los datos vienen de un ERP y traen referencias largas sin espacios (códigos
   de equipo, CUPS, números de contrato). Un solo token de esos fija un ancho
   mínimo que la página no puede bajar, y por debajo de ~360 px eso rompía la
   maqueta entera: el contenido se salía por la derecha.

   `anywhere` (y no `break-word`) es lo que hace falta, porque es el único que
   además reduce el tamaño mínimo intrínseco del elemento.
   -------------------------------------------------------------------------- */
h1, h2, h3, h4,
p, li, dd, dt,
td, th, caption,
.stat-label, .stat-value,
.field-label,
.office-address, .office-city,
.brand-title {
  overflow-wrap: anywhere;
}

/* Botón a todo el ancho. Lo usa el formulario de acceso. */
.btn--block {
  width: 100%;
  justify-content: center;
}

/* -----------------------------------------------------------------------------
   Enlace de salto

   Primer elemento enfocable de la página: permite a quien navega con teclado
   saltarse la cabecera y el menú. Invisible hasta que recibe el foco.
   -------------------------------------------------------------------------- */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: .625rem 1rem;
  background: var(--color-brand-700);
  color: #fff;
  font-weight: 600;
  text-decoration: none;
  border-radius: 0 0 var(--radius-sm) 0;
}

.skip-link:focus-visible,
.skip-link:focus {
  left: 0;
}

/* El logotipo lleva el claim incrustado en la propia imagen; por debajo de
   ~44px la línea "FUSIÓN · RECURSOS · NATURALES" deja de leerse. */
.brand-logo {
  height: 2.75rem;
  width: auto;
}

.login-card .brand-logo { height: 4rem; }

/* -----------------------------------------------------------------------------
   Icono genérico

   Un <svg> con viewBox y sin width/height se estira hasta llenar su
   contenedor. Sin esta regla, el marcador de dirección del pie salía a
   200 px de alto.
   -------------------------------------------------------------------------- */
.icon {
  width: 1.15em;
  height: 1.15em;
  flex: 0 0 auto;
  vertical-align: -.18em;
}

/* El sprite de iconos va incrustado una vez en el <body>: presente en el árbol
   del documento para que <use href="#id"> lo encuentre, pero sin ocupar sitio.
   Va como clase y no como style="..." porque la CSP del portal bloquea también
   los atributos de estilo en línea. */
.sprite-oculto {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/* =============================================================================
   02. RESET Y BASE
   ========================================================================== */

*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: 1.55;
  color: var(--color-text);
  background-color: var(--color-bg);
  background-image: linear-gradient(180deg, var(--color-bg-top) 0, rgba(228, 236, 244, 0) 460px);
  background-repeat: no-repeat;
  -webkit-font-smoothing: antialiased;
}

img,
svg { vertical-align: middle; }

img { max-width: 100%; height: auto; }

h1, h2, h3, h4 {
  margin: 0 0 var(--space-3);
  color: var(--color-ink);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -.015em;
  text-wrap: balance;
}

h1 { font-size: clamp(1.5rem, 1.15rem + 1.4vw, 2rem); }
h2 { font-size: clamp(1.25rem, 1.1rem + .6vw, 1.5rem); }
h3 { font-size: 1.0625rem; }

p  { margin: 0 0 var(--space-4); }
p:last-child { margin-bottom: 0; }

a {
  color: var(--color-accent-700);
  text-decoration-thickness: 1px;
  text-underline-offset: .15em;
}
a:hover { color: var(--color-accent-800); }

hr {
  height: 1px;
  margin: var(--space-5) 0;
  border: 0;
  background: var(--color-border);
}

/* Las cifras siempre en cifras de ancho fijo: los importes se leen en columna. */
b, strong { font-weight: 700; }

::selection {
  background: var(--color-brand-200);
  color: var(--color-ink);
}


/* =============================================================================
   03. ESTRUCTURA
   ========================================================================== */

.site {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
}

/* La cabecera y el pie son de ancho completo, pero su contenido se alinea con
   el de .site-main. El `max()` centra un bloque de --width-page sin necesidad
   de un div contenedor extra en las plantillas. */
.site-header {
  position: relative;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-3);
  padding-inline: max(var(--gutter), calc((100% - var(--width-page)) / 2));
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  box-shadow: 0 1px 2px rgba(23, 33, 46, .04);
}

/* Filo superior verde → azul. Es el único adorno de la página y de un vistazo
   dice «esto es nuevo» sin recurrir a animaciones. */
.site-header::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  background: linear-gradient(90deg,
              var(--color-brand-400) 0%,
              var(--color-brand-600) 42%,
              var(--color-accent-700) 100%);
}

.site-main {
  flex: 1 1 auto;
  display: grid;
  align-content: start;
  gap: clamp(1rem, 2.4vw, 1.5rem);
  width: 100%;
  max-width: var(--width-page);
  margin-inline: auto;
  padding: clamp(1.25rem, 3vw, 2rem) var(--gutter) var(--space-7);
}

.site-main > h1,
.site-main > h2 { margin-bottom: 0; }

.site-footer {
  position: relative;
  margin-top: auto;
  padding-block: clamp(2rem, 5vw, 2.75rem);
  padding-inline: max(var(--gutter), calc((100% - var(--width-page)) / 2));
  color: #d8e1ea;
  background: var(--color-footer);
  font-size: .9375rem;
}

.site-footer::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  background: linear-gradient(90deg,
              var(--color-brand-500) 0%,
              var(--color-brand-400) 45%,
              var(--color-accent-600) 100%);
}


/* =============================================================================
   04. MARCA
   ========================================================================== */

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
  color: inherit;
  text-decoration: none;
  border-radius: var(--radius-md);
}

/* El logotipo de FRENAT es un bloque apaisado (~3,1:1) que incluye el claim
   «Asesores energía/instalaciones». Por debajo de 40 px de alto ese claim deja
   de leerse, de ahí los 44 px de escritorio. */
.brand-logo {
  display: block;
  flex: none;
  width: auto;
  height: 2.75rem;
}

.brand-title {
  padding-left: var(--space-3);
  border-left: 1px solid var(--color-border);
  color: var(--color-ink);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -.01em;
  white-space: nowrap;
}


/* =============================================================================
   05. NAVEGACIÓN
   -----------------------------------------------------------------------------
   Cinco entradas: Inicio · Detalle · Facturas · Datos de cliente · Salir.
   «Salir» es SIEMPRE la última: se distingue con .nav-item:last-child, así que
   si algún día se reordena el menú hay que revisar estas reglas.
   ========================================================================== */

.nav { min-width: 0; }

.nav-list {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

.nav-item { display: flex; }

.nav-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: .5rem .75rem;
  border-radius: var(--radius-md);
  color: var(--color-text);
  font-size: .9375rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color var(--t-fast), color var(--t-fast),
              box-shadow var(--t-fast);
  -webkit-tap-highlight-color: transparent;
}

.nav-link:hover {
  background: var(--color-accent-50);
  color: var(--color-accent-800);
}

.nav-link.is-active {
  background: var(--color-brand-100);
  color: var(--color-brand-700);
  box-shadow: inset 0 0 0 1px var(--color-brand-200);
}

.nav-link.is-active:hover {
  background: var(--color-brand-100);
  color: var(--color-brand-700);
}

.nav-icon {
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
  color: currentColor;
}

.nav-link.is-active .nav-icon { color: var(--color-brand-600); }

.nav-label { display: inline-block; }

/* Salir: separado del resto por una línea y en gris, no compite con la
   navegación real. Al pasar por encima se tiñe de rojo para confirmar que es
   una acción de salida. */
.nav-item:last-child {
  margin-inline-start: var(--space-2);
  padding-inline-start: var(--space-2);
  border-inline-start: 1px solid var(--color-border);
}

.nav-item:last-child .nav-link { color: var(--color-muted); }

.nav-item:last-child .nav-link:hover {
  background: var(--color-danger-bg);
  color: var(--color-danger);
}


/* =============================================================================
   06. TARJETAS
   ========================================================================== */

.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--color-border);
  border-radius: calc(var(--radius-lg) - 1px) calc(var(--radius-lg) - 1px) 0 0;
  background: linear-gradient(180deg, #fff, var(--color-surface-2));
}

.card-title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  color: var(--color-ink);
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: -.01em;
}

.card-title svg {
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
  color: var(--color-brand-600);
}

/* El cuerpo es una pila: los hijos directos se separan solos con `gap`, así
   las plantillas no necesitan clases de espaciado. */
.card-body {
  min-width: 0;
  display: grid;
  align-content: start;
  gap: var(--space-4);
  padding: var(--space-5);
}

.card-body > p { margin-bottom: 0; }
.card-body > h3 { margin-bottom: 0; }
.card-body > hr { margin: var(--space-1) 0; }


/* =============================================================================
   07. CIFRAS DESTACADAS
   -----------------------------------------------------------------------------
   Un .card-body que contenga .stat se convierte solo en una rejilla de fichas.
   Si el navegador no soporta :has(), las fichas simplemente se apilan: sigue
   siendo legible.
   ========================================================================== */

.card-body:has(> .stat) {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
}

.stat {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-4) var(--space-5);
  background: var(--color-surface-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

.stat-label {
  color: var(--color-muted);
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
}

.stat-value {
  color: var(--color-ink);
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -.015em;
  font-variant-numeric: tabular-nums;
}

/* El saldo pendiente de facturar: lo primero que mira el usuario. */
.stat-value--big {
  font-size: clamp(2.25rem, 1.5rem + 3.2vw, 3.25rem);
  letter-spacing: -.03em;
  line-height: 1.05;
}

/* La ficha del saldo ocupa toda la fila: es la cifra que el usuario busca
   nada más entrar, y así la cifra grande nunca se desborda de su columna. */
.stat:has(.stat-value--big) {
  grid-column: 1 / -1;
  background: linear-gradient(135deg, var(--color-brand-50), #fff 65%);
  border-color: var(--color-brand-200);
}


/* =============================================================================
   08.a TABLAS DE DATOS — ESCRITORIO
   ========================================================================== */

.table-wrap {
  /* min-width:0 es imprescindible: como hijo de un grid/flex, por defecto vale
     `auto` y el contenedor crece hasta el ancho de la tabla en vez de hacer
     scroll. Sin esto, entre 700 y ~1000 px la tabla empujaba la página entera
     y aparecía scroll horizontal en el documento. */
  min-width: 0;
  /* max-width evita que el contenedor se estire hasta el ancho intrínseco de
     la tabla. Sin esto, en la franja justo por encima del corte responsive
     (Chrome evalúa las media queries contando la barra de scroll, así que hay
     ~15 px en los que se aplican las reglas de escritorio con menos espacio
     del que anuncian) la tabla empujaba el documento entero en vez de hacer
     scroll dentro de su caja. */
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: .9375rem;
}

.data-table caption {
  caption-side: top;
  padding: var(--space-3) var(--space-4);
  color: var(--color-muted);
  font-size: .875rem;
  text-align: left;
}

.data-table th,
.data-table td {
  padding: .6875rem .875rem;
  text-align: left;
  vertical-align: top;
}

.data-table thead th {
  background: var(--color-surface-3);
  border-bottom: 1px solid var(--color-border-strong);
  color: var(--color-ink);
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .055em;
  text-transform: uppercase;
  white-space: nowrap;
}

.data-table tbody td { color: var(--color-text); }

/* Tabla clave/valor (pantalla «Datos de cliente»): el nombre del campo va en
   <th scope="row"> y el valor en <td>. */
.data-table tbody th[scope="row"] {
  width: 1%;
  color: var(--color-muted);
  font-weight: 600;
  white-space: nowrap;
}

.data-table tbody tr + tr td { border-top: 1px solid #eef2f6; }

/* Filas alternas muy sutiles: guían el ojo sin ensuciar. */
.data-table tbody tr:nth-child(even) { background: #f8fafc; }

@media (hover: hover) {
  .data-table tbody tr:hover { background: var(--color-accent-50); }
}

.data-table tfoot td {
  background: var(--color-surface-2);
  border-top: 2px solid var(--color-border-strong);
  color: var(--color-ink);
  font-weight: 700;
}

/* Celdas auxiliares */
.data-table .num,
.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

.data-table .nowrap,
.nowrap { white-space: nowrap; }

/* Botón de descarga dentro de una celda */
.data-table td .btn { margin: -.25rem 0; }


/* =============================================================================
   09. FORMULARIOS, FILTROS Y BOTONES
   ========================================================================== */

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3) var(--space-4);
  padding: var(--space-4);
  background: var(--color-surface-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

.filter-bar > .btn { margin-inline-start: auto; }

.field {
  display: flex;
  flex-direction: column;
  gap: .375rem;
  flex: 1 1 10rem;
  min-width: 0;
  max-width: 15rem;
}

.field-label {
  color: var(--color-muted);
  font-size: .8125rem;
  font-weight: 600;
}

.input,
.select {
  width: 100%;
  min-height: var(--control-h);
  padding: .5rem .75rem;
  font-family: inherit;
  font-size: 1rem;              /* 16px: evita el zoom automático de iOS */
  line-height: 1.4;
  color: var(--color-ink);
  background-color: #fff;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  transition: border-color var(--t-fast);
}

.input:hover,
.select:hover { border-color: #aabccd; }

.input:focus,
.select:focus { border-color: var(--color-accent-600); }

.input::placeholder { color: #92a2b1; }

.input:disabled,
.select:disabled {
  background: var(--color-surface-3);
  color: var(--color-muted);
  cursor: not-allowed;
}

/* El <select> conserva su flecha nativa a propósito: dibujarla exigiría una
   imagen data: URI, que la CSP del portal puede bloquear. */
.select { padding-right: .5rem; }

/* --- <input type="date"> nativo -----------------------------------------
   Safari/iOS le aplica un relieve propio y centra el valor; esto lo alinea
   con el resto de campos. */
input[type="date"].input,
input[type="time"].input {
  -webkit-appearance: none;
  appearance: none;
}

input[type="date"].input::-webkit-date-and-time-value {
  margin: 0;
  text-align: left;
}

input[type="date"].input::-webkit-datetime-edit { padding: 0; }

input[type="date"].input::-webkit-calendar-picker-indicator {
  padding: .25rem;
  border-radius: var(--radius-sm);
  opacity: .55;
  cursor: pointer;
  transition: opacity var(--t-fast), background-color var(--t-fast);
}

input[type="date"].input::-webkit-calendar-picker-indicator:hover {
  background: var(--color-accent-50);
  opacity: 1;
}

/* --- Botones ------------------------------------------------------------ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--control-h);
  padding: .5rem 1.125rem;
  font-family: inherit;
  font-size: .9375rem;
  font-weight: 600;
  line-height: 1.2;
  color: var(--color-ink);
  text-decoration: none;
  white-space: nowrap;
  background: #fff;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: background-color var(--t-fast), border-color var(--t-fast),
              color var(--t-fast), transform .08s ease;
  -webkit-tap-highlight-color: transparent;
}

.btn svg {
  flex: none;
  width: 1.125rem;
  height: 1.125rem;
}

.btn:hover { border-color: #aabccd; }
.btn:active { transform: translateY(1px); }

.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: .55;
  cursor: not-allowed;
  transform: none;
}

/* Primario en el verde del logotipo. El degradado va de 600 a 700, así que en
   su punto más claro el texto blanco sigue a 4,67:1 (AA). Si alguien aclara
   estos tonos, deja de cumplir: comprobarlo antes de tocarlos. */
.btn--primary {
  color: #fff;
  background-color: var(--color-brand-700);
  background-image: linear-gradient(180deg,
                    var(--color-brand-600), var(--color-brand-700));
  border-color: var(--color-brand-800);
}

.btn--primary:hover {
  background-image: linear-gradient(180deg,
                    var(--color-brand-700), var(--color-brand-800));
  border-color: #2c451b;
}

.btn--ghost {
  color: var(--color-accent-700);
  background: transparent;
  border-color: var(--color-border-strong);
  box-shadow: none;
}

.btn--ghost:hover {
  background: var(--color-accent-50);
  border-color: var(--color-accent-200);
  color: var(--color-accent-800);
}

/* Sólo icono. Requiere aria-label o .visually-hidden dentro. */
.btn--icon {
  width: var(--control-h);
  min-width: var(--control-h);
  padding: 0;
}

.btn--icon svg { width: 1.25rem; height: 1.25rem; }


/* =============================================================================
   10. AVISOS Y ESTADO VACÍO
   ========================================================================== */

.alert {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4);
  color: var(--color-text);
  background: var(--color-surface-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font-size: .9375rem;
  line-height: 1.5;
}

.alert svg {
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
  margin-top: .125em;
}

.alert p { margin: 0; }
.alert p + p { margin-top: var(--space-2); }

.alert--error {
  color: var(--color-danger);
  background: var(--color-danger-bg);
  border-color: var(--color-danger-border);
}

.alert--info {
  color: var(--color-accent-800);
  background: var(--color-accent-50);
  border-color: var(--color-accent-200);
}

.alert--info a { color: var(--color-accent-800); }

/* Imagen que viene dentro de un aviso del ERP.
   El ERP la mandaba con style="height:240px" incrustado, así que son
   imágenes de tamaño natural, no banners: se respeta su tamaño y sólo se
   reduce si no cabe. fit-content evita que una imagen pequeña se estire
   —y se emborrone— hasta el ancho de la tarjeta. */
.aviso-imagen {
  display: block;
  width: fit-content;
  max-width: 100%;
  margin-top: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.aviso-imagen:first-child { margin-top: 0; }

.aviso-imagen img {
  display: block;
  max-width: 100%;
  height: auto;
}

.aviso-imagen:hover,
.aviso-imagen:focus-visible { border-color: var(--color-brand-500); }

/* Estado vacío: es información, no un error. Sin rojo, sin iconos de alarma. */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  padding: clamp(2rem, 6vw, 3.25rem) var(--space-4);
  text-align: center;
  color: var(--color-muted);
  background: var(--color-surface-2);
  border: 1px dashed var(--color-border-strong);
  border-radius: var(--radius-lg);
}

.empty-state svg {
  width: 2rem;
  height: 2rem;
  margin-bottom: var(--space-1);
  color: var(--color-brand-500);
}

.empty-state strong {
  display: block;
  color: var(--color-ink);
  font-size: 1.0625rem;
  font-weight: 700;
}

.empty-state p {
  max-width: 42ch;
  margin: 0;
  font-size: .9375rem;
}


/* =============================================================================
   11. LOGIN
   ========================================================================== */

.login-shell {
  display: grid;
  place-items: center;
  /* Nada de 100vh: este bloque vive dentro de .site-main, y .site ya mide
     100vh. Sumar otra pantalla completa empujaba el pie —con los teléfonos
     de las oficinas— fuera de la vista, y dejaba un hueco vacío enorme
     encima de la tarjeta. */
  min-height: 24rem;
  padding: clamp(2rem, 7vh, 4.5rem) var(--space-4);
  background-color: var(--color-bg);
  background-image:
    radial-gradient(900px 520px at 18% -12%, rgba(144, 181, 87, .22), transparent 62%),
    radial-gradient(820px 520px at 92% 6%,  rgba(27, 87, 144, .16), transparent 62%);
  background-repeat: no-repeat;
}

.login-card {
  position: relative;
  overflow: hidden;
  width: 100%;
  max-width: 25rem;
  padding: clamp(1.5rem, 4vw, 2.25rem);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
}

.login-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 4px;
  background: linear-gradient(90deg,
              var(--color-brand-400) 0%,
              var(--color-brand-600) 42%,
              var(--color-accent-700) 100%);
}

.login-card .brand {
  justify-content: center;
  width: 100%;
  margin-bottom: var(--space-5);
}

/* En el acceso el logotipo es el protagonista y hay sitio de sobra: a 44 px
   la línea «FUSIÓN · RECURSOS · NATURALES» no se lee. */
.login-card .brand-logo { height: 4rem; }

.login-card h1 {
  font-size: 1.375rem;
  text-align: center;
}

.login-card > p {
  margin-bottom: var(--space-5);
  color: var(--color-muted);
  font-size: .9375rem;
  text-align: center;
}

.login-card form {
  display: grid;
  gap: var(--space-4);
}

.login-card .field {
  flex: 1 1 auto;
  max-width: none;
}

.login-card .btn { width: 100%; }

.login-card .alert { margin-bottom: var(--space-4); }


/* =============================================================================
   12. PIE Y SEDES
   -----------------------------------------------------------------------------
   Hasta 2025 las sedes y los teléfonos eran píxeles dentro de un JPEG. Ahora
   son texto seleccionable y enlaces tel: que llaman al tocarlos.
   ========================================================================== */

.offices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
  gap: var(--space-5);
}

.office {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
}

.office-city {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  color: var(--color-brand-300);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: .02em;
}

.office-city svg {
  flex: none;
  width: 1.125rem;
  height: 1.125rem;
}

.office-phone {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 2.5rem;
  padding: .4375rem .875rem;
  color: #fff;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: .01em;
  text-decoration: none;
  background: rgba(255, 255, 255, .08);
  border: 1px solid rgba(255, 255, 255, .2);
  border-radius: var(--radius-pill);
  transition: background-color var(--t-fast), border-color var(--t-fast);
}

.office-phone svg {
  flex: none;
  width: 1rem;
  height: 1rem;
  color: var(--color-brand-300);
}

.office-phone:hover {
  color: #fff;
  background: rgba(255, 255, 255, .16);
  border-color: rgba(255, 255, 255, .34);
}

.office-address {
  max-width: 36ch;
  margin: 0;
  color: #b8c4cf;
  font-size: .875rem;
  line-height: 1.55;
}

.colophon {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-2) var(--space-4);
  margin-top: var(--space-6);
  padding-top: var(--space-4);
  border-top: 1px solid rgba(255, 255, 255, .12);
  color: #8fa0af;
  font-size: .8125rem;
}

.colophon p { margin: 0; }
.colophon a { color: #c8d4de; }
.colophon a:hover { color: #fff; }


/* =============================================================================
   13. UTILIDADES
   ========================================================================== */

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

.muted { color: var(--color-muted); }

.text-right { text-align: right; }


/* =============================================================================
   14. FOCO VISIBLE
   -----------------------------------------------------------------------------
   Un único sistema de foco para todo. No se elimina nunca el outline sin
   sustituirlo.
   ========================================================================== */

:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
}

.nav-link:focus-visible,
.btn:focus-visible,
.brand:focus-visible { border-radius: var(--radius-md); }

/* Sobre el pie oscuro el azul no se ve: se usa el verde claro. */
.site-footer :focus-visible { outline-color: var(--color-brand-300); }

/* Sólo para navegadores sin :focus-visible; se descarta en cuanto existe. */
:focus:not(:focus-visible) { outline: none; }


/* =============================================================================
   15. RESPONSIVE
   -----------------------------------------------------------------------------
   Todo `screen and` a propósito: la impresión no debe heredar el modo tarjeta.
   ========================================================================== */

/* --- 15.a Escritorio: cabecera pegajosa --------------------------------- */
@media screen and (min-width: 701px) {
  .site-header {
    position: sticky;
    top: 0;
  }
}

/* --- 15.a-bis Franja incómoda (tableta en vertical) ---------------------
   Entre 701 y 900 px la tabla de detalle tiene ya sus siete columnas pero
   poco sitio: se aprieta la tipografía y el relleno para que quepa entera y
   no haya que arrastrarla en horizontal. Por debajo de 701 pasa a tarjetas.
   Si aun así no cabe, .table-wrap sigue teniendo scroll horizontal.        */
@media screen and (min-width: 701px) and (max-width: 900px) {
  .data-table { font-size: .875rem; }

  .data-table th,
  .data-table td { padding: .5rem .5rem; }

  .data-table thead th {
    font-size: .6875rem;
    letter-spacing: .03em;
  }

  .card-header,
  .card-body { padding: var(--space-4); }
}

/* --- 15.b-bis Tableta ---------------------------------------------------
   Entre 701 y 1023 px la cabecera de una sola fila no cabe: la marca más
   cinco destinos con etiqueta miden ~1250 px, y el sobrante empujaba la
   página entera provocando scroll horizontal del documento.
   Se reutiliza la cabecera apilada, que ya está resuelta más abajo.
   ---------------------------------------------------------------------- */
@media screen and (min-width: 701px) and (max-width: 1023px) {
  .site-header {
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-2);
  }

  .nav { width: 100%; }

  .nav-list {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    gap: 0;
  }

  .nav-link {
    flex-direction: column;
    gap: .25rem;
    width: 100%;
    padding: .5rem .25rem .625rem;
    font-size: .75rem;
    line-height: 1.15;
    text-align: center;
    white-space: normal;
  }

  .nav-item:last-child {
    margin-inline-start: 0;
    padding-inline-start: 0;
    border-inline-start: 0;
  }
}

/* --- 15.b Móvil y tableta estrecha -------------------------------------- */
@media screen and (max-width: 700px) {

  /* Cabecera en dos filas: marca arriba, menú debajo.
     El `top` negativo vale exactamente lo que mide la fila de la marca
     (10px de padding + 36px de logotipo + 8px de hueco = 54px = 3.375rem), de
     modo que al bajar la página el logotipo se va y la barra de menú se
     queda pegada arriba. Sin JavaScript.
     Si se cambia el alto del logotipo o el padding, hay que recalcular. */
  .site-header {
    position: sticky;
    top: -3.375rem;
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-2);
    padding: .625rem var(--space-4) 0;
  }

  .brand { min-width: 0; }

  .brand-logo { height: 2.25rem; }

  /* Una sola línea siempre: si la marca creciera, el cálculo del `top` de
     arriba dejaría de cuadrar. */
  .brand-title {
    overflow: hidden;
    min-width: 0;
    font-size: .875rem;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .nav {
    margin-inline: calc(var(--space-4) * -1);
    padding-inline: var(--space-1);
    background: var(--color-surface);
    border-top: 1px solid var(--color-border);
  }

  /* Cinco columnas iguales: icono arriba, etiqueta debajo. Entra sin scroll
     incluso en 320px y cada destino es un objetivo táctil holgado. */
  .nav-list {
    display: grid;
    /* Columnas iguales sean cuantas sean las entradas: el menú lo decide
       config.php y otro cliente puede tener más de cinco. Antes estaba
       fijado a repeat(5, 1fr). */
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    gap: 0;
  }

  .nav-link {
    flex-direction: column;
    gap: .25rem;
    width: 100%;
    padding: .5rem .125rem .625rem;
    border-radius: var(--radius-sm);
    font-size: .6875rem;
    font-weight: 600;
    line-height: 1.15;
    text-align: center;
    white-space: normal;
    hyphens: auto;
  }

  .nav-icon { width: 1.375rem; height: 1.375rem; }

  .nav-link.is-active {
    background: transparent;
    box-shadow: inset 0 -3px 0 var(--color-brand-500);
    color: var(--color-brand-700);
  }

  .nav-item:last-child {
    margin-inline-start: 0;
    padding-inline-start: 0;
    border-inline-start: 0;
  }

  .card-header,
  .card-body { padding: var(--space-4); }

  .filter-bar { padding: var(--space-3); }

  .field {
    flex: 1 1 100%;
    max-width: none;
  }

  .filter-bar > .btn {
    width: 100%;
    margin-inline-start: 0;
  }

  /* --- 15.c TABLAS EN MODO TARJETA ------------------------------------
     Cada <tr> se convierte en una ficha y cada <td> muestra su etiqueta
     mediante el atributo data-label que ponen las plantillas:
         <td data-label="Fecha">04/08/2026</td>
     Sin data-label la celda se ve igual pero sin rótulo.                  */

  .table-wrap {
    overflow: visible;
    background: none;
    border: 0;
    border-radius: 0;
  }

  .data-table,
  .data-table tbody,
  .data-table tfoot,
  .data-table tr,
  .data-table th,
  .data-table td { display: block; }

  .data-table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .data-table caption {
    display: block;
    padding: 0 0 var(--space-3);
  }

  .data-table tr,
  .data-table tbody tr:nth-child(even) {
    margin-bottom: var(--space-3);
    padding: .25rem .875rem;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
  }

  .data-table tr:last-child { margin-bottom: 0; }

  .data-table tbody tr:hover { background: var(--color-surface); }

  .data-table td,
  .data-table tbody tr + tr td {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-4);
    padding: .5rem 0;
    text-align: right;
    border-top: 1px solid #f0f3f7;
  }

  .data-table td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    color: var(--color-muted);
    font-size: .8125rem;
    font-weight: 600;
    text-align: left;
  }

  .data-table td:empty::after { content: "—"; }

  /* Primera celda como título de la ficha, última (el importe) destacada. */
  .data-table tbody tr td:first-child,
  .data-table tbody tr + tr td:first-child {
    padding-top: .75rem;
    border-top: 0;
    color: var(--color-ink);
    font-weight: 700;
  }

  .data-table tbody tr td:last-child {
    padding-bottom: .75rem;
    color: var(--color-ink);
    font-size: 1.0625rem;
    font-weight: 700;
  }

  /* Tabla clave/valor en modo tarjeta: el campo arriba, el valor debajo. */
  .data-table tbody th[scope="row"] {
    width: auto;
    padding: .75rem 0 0;
    color: var(--color-muted);
    font-size: .8125rem;
    font-weight: 600;
    text-align: left;
    white-space: normal;
  }

  .data-table tbody th[scope="row"] + td {
    justify-content: flex-start;
    padding-top: .0625rem;
    border-top: 0;
    font-size: 1rem;
    font-weight: 600;
    text-align: left;
  }

  /* Pie de tabla: la ficha entera se tiñe. La celda con colspan sobra aquí,
     porque su texto ya lo aporta el data-label de la celda del importe. */
  .data-table tfoot tr {
    background: var(--color-brand-50);
    border-color: var(--color-brand-200);
  }

  .data-table tfoot td {
    background: none;
    border-top: 0;
  }

  .data-table tfoot td[colspan] { display: none; }

  .site-footer { font-size: .9375rem; }

  .colophon { justify-content: flex-start; }
}

/* --- 15.d Pantallas muy estrechas --------------------------------------- */
@media screen and (max-width: 380px) {
  .nav-label { font-size: .625rem; }

  .card-header,
  .card-body { padding: var(--space-3); }

  .stat { padding: var(--space-3) var(--space-4); }
}


/* =============================================================================
   16. MOVIMIENTO REDUCIDO
   ========================================================================== */

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

  .btn:active { transform: none; }
}


/* =============================================================================
   17. IMPRESIÓN
   -----------------------------------------------------------------------------
   Los clientes imprimen el detalle de consumos. Negro sobre blanco, sin
   fondos, sin navegación y con la cabecera de la tabla repetida en cada hoja.
   ========================================================================== */

@page { margin: 14mm; }

@media print {

  html,
  body {
    background: #fff !important;
    color: #000 !important;
    font-size: 10.5pt;
  }

  .site-header,
  .nav,
  .site-footer,
  .filter-bar,
  .btn,
  .empty-state svg { display: none !important; }

  .site-main {
    display: block;
    max-width: none;
    padding: 0;
  }

  .card {
    margin: 0 0 8mm;
    border: 1px solid #999;
    border-radius: 0;
    box-shadow: none;
    break-inside: avoid;
  }

  .card-header {
    padding: 0 0 2mm;
    background: none;
    border-bottom: 1px solid #000;
    border-radius: 0;
  }

  .card-title,
  .card-title svg { color: #000; }

  .card-body { padding: 3mm 0 0; }

  .stat,
  .stat:has(.stat-value--big),
  .empty-state {
    background: none !important;
    border: 0;
    padding: 0 0 3mm;
  }

  /* Todo el texto en negro: los grises secundarios y el azul de los enlaces
     salen lavados en una impresora doméstica. */
  .muted,
  .stat-label,
  .card-title,
  .card-title svg,
  .alert svg,
  .alert--info,
  .alert--info a,
  .alert--error,
  .field-label,
  .data-table caption,
  .data-table tbody th[scope="row"] { color: #000 !important; }

  .stat-value,
  .stat-value--big,
  .stat-label { color: #000; }

  .stat-value--big { font-size: 20pt; }

  .table-wrap {
    overflow: visible;
    background: none;
    border: 0;
    border-radius: 0;
  }

  .data-table { font-size: 9pt; }

  /* Repite la cabecera de la tabla en cada página impresa. */
  .data-table thead { display: table-header-group; }

  .data-table thead th {
    background: none !important;
    color: #000;
    border-bottom: 1.2pt solid #000;
  }

  .data-table tbody tr,
  .data-table tbody tr:nth-child(even) {
    background: none !important;
    break-inside: avoid;
  }

  .data-table td {
    border-top: 0;
    border-bottom: .5pt solid #bbb;
    padding: 3pt 5pt;
  }

  .data-table tfoot td {
    background: none !important;
    border-top: 1.2pt solid #000;
    color: #000;
  }

  .alert {
    background: none;
    border: 1pt solid #000;
    color: #000;
  }

  a {
    color: #000;
    text-decoration: none;
  }
}


/* =============================================================================
   18. PANEL DE ADMINISTRACIÓN

   Reutiliza el sistema del portal —tarjetas, campos, botones— a propósito:
   así el panel hereda el tema elegido y se ve el cambio de color aplicado
   sobre la propia herramienta que lo cambia. Aquí sólo van las piezas que el
   portal público no necesita.
   ========================================================================== */

/* Ancho de lectura.
   Una tarjeta de 1120 px con un párrafo dentro obliga a barrer la cabeza de
   lado a lado para leer una línea. En el portal las tablas necesitan ese
   ancho; aquí no hay tablas, hay formularios, y un formulario ancho no se
   rellena mejor: se rellena peor. */
.panel-cuerpo { max-width: 44rem; }

/* .field nace acotado a 15 rem porque su sitio original es la barra de
   filtros, donde conviven cuatro campos en una fila. En un formulario de
   configuracion eso deja cajas de juguete: aqui ocupa el ancho de lectura. */
.panel-cuerpo .field {
  max-width: none;
  margin-bottom: var(--space-4);
}

.panel-cuerpo .input,
.panel-cuerpo .select { max-width: 30rem; }
.panel-cuerpo .input[type="number"] { max-width: 10rem; }
.panel-cuerpo .input[type="file"] { padding: .45rem .5rem; }

/* Explicacion bajo un campo. Nunca existio en el portal publico porque alli
   los campos se explican solos; aqui hay ajustes que necesitan una linea. */
.field-hint {
  margin: 0;
  font-size: .8125rem;
  line-height: 1.5;
  color: var(--color-muted);
}

.field-hint code {
  padding: .05rem .3rem;
  font-size: .95em;
  background: var(--color-surface-3);
  border-radius: 3px;
}

.panel-intro {
  margin: 0 0 var(--space-5);
  color: var(--color-muted);
  font-size: .9375rem;
}

.panel-intro + .panel-intro { margin-top: calc(var(--space-5) * -1 + var(--space-2)); }

.panel-sep {
  height: 1px;
  margin: var(--space-6) 0;
  border: 0;
  background: var(--color-border);
}

.panel-subtitulo {
  margin: 0 0 var(--space-2);
  font-size: 1rem;
  font-weight: 700;
  color: var(--color-ink);
}

/* --- Selector de temas ---------------------------------------------------- */
.temas {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13.5rem, 1fr));
  gap: var(--space-3);
  margin: 0 0 var(--space-5);
  padding: 0;
  list-style: none;
}

.tema {
  display: block;
  position: relative;
  padding: var(--space-4);
  padding-right: var(--space-6);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  cursor: pointer;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}

.tema:hover {
  border-color: var(--color-border-strong);
  box-shadow: var(--shadow-sm);
}

/* La casilla se esconde y el borde de la tarjeta hace de marca de selección:
   el radio de serie es diminuto al lado de una tarjeta de 14 rem. Sigue
   estando en el árbol, así que el teclado y el lector de pantalla la
   encuentran igual. */
.tema input {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  margin: 0;
  accent-color: var(--color-brand-600);
}

.tema:has(input:checked) {
  border-color: var(--color-brand-600);
  box-shadow: 0 0 0 1px var(--color-brand-600);
}

.tema:has(input:focus-visible) {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
}

.tema-muestra {
  display: flex;
  gap: 3px;
  margin-bottom: var(--space-3);
}

.tema-tono {
  display: block;
  flex: 1 1 0;
  height: 2.25rem;
  border-radius: var(--radius-sm);
}

.tema-nombre {
  display: block;
  font-weight: 700;
  color: var(--color-ink);
  margin-bottom: var(--space-1);
}

.tema-desc {
  display: block;
  font-size: .8125rem;
  line-height: 1.45;
  color: var(--color-muted);
}

/* --- Sedes ---------------------------------------------------------------- */
.sede {
  margin: 0 0 var(--space-4);
  padding: var(--space-4) var(--space-5) var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface-2);
}

.sede legend {
  padding: 0 var(--space-2);
  margin-left: calc(var(--space-2) * -1);
  font-weight: 700;
  color: var(--color-brand-700);
  font-size: .75rem;
  text-transform: uppercase;
  letter-spacing: .06em;
}

.sede--nueva {
  background: transparent;
  border-style: dashed;
}

/* --- Casillas -------------------------------------------------------------
   Cada opción es una fila completa y pinchable. En la versión 1 se quedaron
   en línea unas detrás de otras y era imposible saber qué texto pertenecía a
   qué casilla. */
.checks {
  display: grid;
  gap: var(--space-2);
  margin: 0 0 var(--space-5);
}

.check {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: start;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  cursor: pointer;
  transition: background var(--t-fast), border-color var(--t-fast);
}

.check:hover { background: var(--color-surface-2); }
.check:has(input:checked) { border-color: var(--color-brand-300); background: var(--color-brand-50); }
.check:has(input:disabled) { cursor: default; opacity: .8; }
.check:has(input:focus-visible) { outline: 3px solid var(--color-focus); outline-offset: 2px; }

.check input {
  margin: .2rem 0 0;
  accent-color: var(--color-brand-600);
}

.check strong { display: block; color: var(--color-ink); font-weight: 600; }
.check small  { display: block; color: var(--color-muted); font-size: .8125rem; line-height: 1.45; }

/* --- Logotipo actual ------------------------------------------------------ */
.logo-actual {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 7rem;
  margin: 0 0 var(--space-3);
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  /* Damero: deja ver si el PNG tiene fondo transparente o un blanco pegado. */
  background-color: var(--color-surface);
  background-image:
    linear-gradient(45deg, var(--color-surface-3) 25%, transparent 25%),
    linear-gradient(-45deg, var(--color-surface-3) 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, var(--color-surface-3) 75%),
    linear-gradient(-45deg, transparent 75%, var(--color-surface-3) 75%);
  background-size: 16px 16px;
  background-position: 0 0, 0 8px, 8px -8px, -8px 0;
}

.logo-actual img { max-height: 5rem; width: auto; }

/* --- Bloque para copiar (el .htaccess) ------------------------------------ */
.bloque-copiar {
  margin: 0;
  padding: var(--space-4);
  overflow-x: auto;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .78rem;
  line-height: 1.5;
  color: #e6ebe2;
  background: var(--color-footer);
  border-radius: var(--radius-md);
  white-space: pre;
  -webkit-user-select: all;
  user-select: all;
}

/* --- Estado del servidor -------------------------------------------------- */
.revision { display: grid; gap: var(--space-1); margin: 0 0 var(--space-4); }

.revision-fila {
  display: grid;
  grid-template-columns: 1.5rem 11rem 1fr;
  gap: var(--space-3);
  align-items: start;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
}

.revision-fila:nth-child(odd) { background: var(--color-surface-2); }
.revision-que { font-weight: 600; color: var(--color-ink); }
.revision-detalle { color: var(--color-muted); font-size: .875rem; overflow-wrap: anywhere; }
.revision-si { color: var(--color-brand-600); font-weight: 700; }
.revision-no { color: var(--color-danger); font-weight: 700; }

/* --- Varios --------------------------------------------------------------- */
.acciones { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.acciones form { margin: 0; }

.panel-salir { margin-top: var(--space-6); }

.interruptor {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-2);
}

.interruptor-estado { font-weight: 600; color: var(--color-ink); }
.interruptor-estado.on  { color: var(--color-brand-700); }
.interruptor-estado.off { color: var(--color-muted); }

.alert--ok {
  color: var(--color-brand-800);
  background: var(--color-brand-50);
  border: 1px solid var(--color-brand-200);
}

@media screen and (max-width: 40rem) {
  .revision-fila { grid-template-columns: 1.5rem 1fr; }
  .revision-detalle { grid-column: 2; }
}


/* =============================================================================
   19. RESUMEN DEL PERIODO Y GRÁFICOS (detalle)

   El ERP devuelve una lista plana de líneas y ningún total. Esto es lo que
   convierte esa lista en algo que se puede leer de un vistazo.
   ========================================================================== */

.resumen {
  margin-bottom: var(--space-5);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface-2);
  overflow: hidden;
}

/* Fila principal: cuántas líneas a la izquierda, las sumas a la derecha. */
.resumen-total {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2) var(--space-4);
  margin: 0;
  padding: var(--space-4) var(--space-5);
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
}

.resumen-etiqueta { color: var(--color-muted); font-size: .9375rem; }
.resumen-etiqueta strong { color: var(--color-ink); }

.resumen-cifras {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-4);
}

.resumen-cifras b {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--color-ink);
  font-variant-numeric: tabular-nums;
}

.resumen-importe { color: var(--color-brand-700); }

/* Desglose por concepto. Rejilla, no tabla: son cuatro datos por fila y en
   el movil se apilan sin que haya que reinventar la maqueta. */
.resumen-lista { margin: 0; padding: 0; list-style: none; }

.resumen-grupo {
  display: grid;
  grid-template-columns: minmax(8rem, 1.4fr) auto minmax(6rem, 1fr) auto;
  align-items: baseline;
  gap: var(--space-2) var(--space-4);
  padding: var(--space-3) var(--space-5);
  border-bottom: 1px solid var(--color-border);
}

.resumen-grupo:last-child { border-bottom: 0; }

.resumen-concepto { font-weight: 600; color: var(--color-ink); }
.resumen-filas    { color: var(--color-muted); font-size: .8125rem; white-space: nowrap; }

.resumen-medidas {
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.resumen-euros {
  font-weight: 600;
  color: var(--color-brand-700);
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

/* -----------------------------------------------------------------------------
   El gráfico

   UNO y grande. La primera versión pintaba tres en una rejilla de tres
   columnas: a 1120 px de ancho eso deja cada gráfico en 340 px, y con las
   etiquetas del eje de doce meses no se leía ninguno.
   -------------------------------------------------------------------------- */
.grafico {
  margin-bottom: var(--space-5);
  padding: var(--space-4) var(--space-5) var(--space-5);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
}

.grafico-mandos {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.grafico .frch-figura { min-width: 0; }

/* Pestañas. Son enlaces, no botones: cada una es una dirección de verdad que
   se puede compartir o guardar en un marcador, y funcionan sin JavaScript. */
.pestanyas {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  padding: 3px;
  background: var(--color-surface-3);
  border-radius: var(--radius-pill);
}

.pestanya {
  padding: .4rem .9rem;
  font-size: .875rem;
  font-weight: 600;
  color: var(--color-muted);
  text-decoration: none;
  border-radius: var(--radius-pill);
  white-space: nowrap;
  transition: background var(--t-fast), color var(--t-fast);
}

.pestanya:hover { color: var(--color-ink); background: rgba(255, 255, 255, .6); }

.pestanya.is-active {
  color: var(--color-brand-800);
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
}

.pestanyas--periodo .pestanya.is-active { color: var(--color-accent-800); }

@media screen and (max-width: 40rem) {
  .resumen-grupo {
    grid-template-columns: 1fr auto;
    row-gap: var(--space-1);
  }

  .resumen-concepto { grid-column: 1; }
  .resumen-euros    { grid-column: 2; grid-row: 1; }
  .resumen-filas    { grid-column: 1; }
  .resumen-medidas  { grid-column: 2; text-align: right; }
}

/* -----------------------------------------------------------------------------
   Atajos de periodo

   Escribir dos fechas a mano para ver "el año pasado" es trabajo que puede
   hacer el portal. Son enlaces, así que cada periodo tiene su dirección.
   -------------------------------------------------------------------------- */
.atajos {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: calc(var(--space-4) * -1 + var(--space-1)) 0 var(--space-5);
}

.atajos-titulo {
  color: var(--color-muted);
  font-size: .8125rem;
  font-weight: 600;
}

.atajo {
  padding: .3rem .75rem;
  font-size: .8125rem;
  font-weight: 600;
  color: var(--color-accent-700);
  text-decoration: none;
  background: var(--color-surface-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  white-space: nowrap;
  transition: background var(--t-fast), border-color var(--t-fast);
}

.atajo:hover { background: var(--color-accent-50); border-color: var(--color-accent-200); }

.atajo.is-active {
  color: #fff;
  background: var(--color-brand-600);
  border-color: var(--color-brand-600);
}

/* -----------------------------------------------------------------------------
   Fila de totales de la tabla
   -------------------------------------------------------------------------- */
.fila-total {
  border-top: 2px solid var(--color-border-strong);
  background: var(--color-surface-2);
}

.fila-total th,
.fila-total td {
  padding-top: var(--space-3);
  padding-bottom: var(--space-3);
  font-weight: 700;
  color: var(--color-ink);
  font-variant-numeric: tabular-nums;
}

.fila-total th { text-align: left; color: var(--color-muted); font-size: .8125rem;
                 text-transform: uppercase; letter-spacing: .05em; }

.total-medida { display: block; }
.total-medida + .total-medida { margin-top: .15rem; }

/* La lectura es un acumulado del contador: sumarla no daría ningún dato. */
.total-nosuma { color: var(--color-muted); font-weight: 400; cursor: help; }

@media screen and (max-width: 48rem) {
  /* En modo tarjeta, la fila de totales se convierte en su propia tarjeta. */
  .fila-total { display: block; border-radius: var(--radius-md); }
  .fila-total th { display: block; }
  .fila-total td:empty { display: none; }
}

/* -----------------------------------------------------------------------------
   20. PIEZAS NUEVAS DEL PIE Y DEL ACCESO
   -------------------------------------------------------------------------- */

/* Correo y horario de una sede. Mismo tratamiento que el teléfono: el correo
   es pulsable y abre el gestor de correo; el horario es sólo informativo. */
.office-mail {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
  color: var(--color-brand-300);
  text-decoration: none;
  overflow-wrap: anywhere;
}

.office-mail:hover { color: #fff; text-decoration: underline; }

.office-hours {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  margin: 0 0 var(--space-2);
  color: rgba(255, 255, 255, .62);
  font-size: .875rem;
}

/* Línea final: colofón a un lado, avisos legales al otro. */
.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.footer-legal {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}

.footer-legal a {
  color: rgba(255, 255, 255, .62);
  font-size: .8125rem;
  text-decoration: none;
}

.footer-legal a:hover { color: #fff; text-decoration: underline; }

/* -----------------------------------------------------------------------------
   Ayuda del acceso

   El portal no tiene recuperación de contraseña —las credenciales viven en el
   ERP—, así que la única salida es llamar. Antes eso no se decía en ninguna
   parte y quien la olvidaba se quedaba sin saber qué hacer.
   -------------------------------------------------------------------------- */
.login-ayuda {
  margin-top: var(--space-5);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-border);
}

.login-ayuda-titulo {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-2);
  font-weight: 700;
  color: var(--color-ink);
}

.login-ayuda-texto {
  margin: 0 0 var(--space-3);
  font-size: .875rem;
  color: var(--color-muted);
}

.login-ayuda-vias {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
}

.login-ayuda-vias a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: .45rem .85rem;
  font-size: .875rem;
  font-weight: 600;
  color: var(--color-accent-700);
  text-decoration: none;
  background: var(--color-surface-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  overflow-wrap: anywhere;
}

.login-ayuda-vias a:hover {
  background: var(--color-accent-50);
  border-color: var(--color-accent-200);
}

/* -----------------------------------------------------------------------------
   De quién es la cuenta

   El acceso es un código de cliente, no un nombre. Con varias sociedades o
   comunidades a nombre de la misma persona, no ver de quién son los datos
   significa mirar unos consumos creyendo que son otros.
   -------------------------------------------------------------------------- */
.card-quien {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  padding: .3rem .8rem;
  font-size: .875rem;
  font-weight: 600;
  color: var(--color-brand-800);
  background: var(--color-brand-50);
  border: 1px solid var(--color-brand-200);
  border-radius: var(--radius-pill);
  overflow-wrap: anywhere;
}

/* Área de texto del panel, para los teléfonos uno por línea. */
.panel-cuerpo textarea.input {
  min-height: 5rem;
  max-width: 30rem;
  font-family: inherit;
  resize: vertical;
}

/* -----------------------------------------------------------------------------
   Barrido de registros del ERP

   Una tabla ancha con muchas columnas: lo que importa es distinguir de un
   vistazo el hueco («no viene ese campo») del vacío («viene, pero en blanco»),
   que es justo la diferencia que resuelve un "no sé de qué son estos datos".
   -------------------------------------------------------------------------- */
.barrido-vacio { color: var(--color-muted); }

.barrido-nota {
  display: block;
  margin-top: .15rem;
  color: var(--color-muted);
  font-size: .75rem;
}

/* -----------------------------------------------------------------------------
   Sección del menú en el panel: la casilla y sus dos rótulos

   Los rótulos van sangrados bajo su casilla para que se lea como lo que es —
   ajustes de esa sección— y no como cuatro campos sueltos en una lista.
   -------------------------------------------------------------------------- */
.seccion-menu {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  overflow: hidden;
}

.seccion-menu .check {
  border: 0;
  border-radius: 0;
  margin: 0;
}

.seccion-menu:has(input[name="menu[]"]:checked) { border-color: var(--color-brand-300); }

.rotulos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: var(--space-3);
  padding: 0 var(--space-4) var(--space-4) 2.6rem;
}

.rotulos .field { margin-bottom: 0; }
.rotulos .input { max-width: none; }
