/* ===========================================================================
   SISTEMA — el lenguaje visual de la web pública de Xestio.

   POR QUÉ EXISTE ESTE FICHERO
   ---------------------------
   El 18/09/2026 la web pública eran cuatro sistemas distintos:

     · la portada, con 494 líneas de CSS dentro del HTML;
     · contacto, con 396;
     · login, con 340;
     · casos de uso, con 219;
     · `paginas-publicas.css`, con sus tokens colgando de `.pp`;
     · `blog.css`, con los suyos propios (`--blog-*`).

   Unas 1.450 líneas metidas a mano en las plantillas y tres vocabularios que
   no se hablaban entre ellos. Cada página nueva se inventaba sus botones, sus
   radios, sus grises y su escala. Por eso al pasar de la portada al blog
   parecía otra empresa: no es que una fuera oscura y otra clara —eso convive
   perfectamente— es que no compartían NADA.

   Y el detalle que lo resume: `xestio-tokens.css` existe, está generado desde
   el manifiesto de marca v1.6... y solo lo usaba la portada.

   DE DÓNDE SALE
   -------------
   No está inventado. Es el sistema que ya había dentro de `index_xestio.html`,
   que era el único sitio donde estaba bien resuelto, sacado a donde puede
   usarlo todo el mundo. Los valores son los suyos, literales.

   CÓMO SE USA
   -----------
   Un sistema, DOS SUPERFICIES:

     · las páginas de marca —portada, contacto, login— van sobre superficie
       oscura, porque son escaparate y ahí la marca tiene que pesar;
     · las de lectura —blog, glosario, FAQ, legal— van sobre superficie clara,
       porque se leen largo y en oscuro cansan.

   Las dos usan los MISMOS tokens, los mismos botones, los mismos radios y la
   misma escala. Cambia la superficie, no el idioma.

   LA REGLA QUE NO SE SALTA
   ------------------------
   Si una regla pone el color del texto con un token, el fondo también sale de
   un token. Nunca uno fijo y otro no: es exactamente así como se rompió el
   modo oscuro de la intranet en septiembre de 2026 —fondo blanco a pelo, texto
   por token, y en oscuro no se leía nada—. Está anotado en la memoria del
   proyecto y aquí no se repite.
   =========================================================================== */

:root {
  /* ── Marca ─────────────────────────────────────────────────────────────
     Los cinco de `docs/marca/brand-manifest.json` v1.6. Se repiten aquí con
     nombre corto porque son los que se escriben a diario; `xestio-tokens.css`
     sigue siendo la fuente generada y no se toca a mano. */
  --petroleo: #0F3D3E;
  --turquesa: #14B8A6;
  --naranja:  #FF3B00;
  --crema:    #F2EFE7;
  --mint:     #E6FAF7;

  /* ── Superficies ───────────────────────────────────────────────────────
     `ground` es el fondo de la página; `surface` el papel donde va el
     contenido; `surface-soft` la variante para alternar secciones sin meter
     un borde; `band` la franja oscura de énfasis. */
  --ground:       var(--crema);
  --surface:      #FFFFFF;
  --surface-soft: var(--mint);
  --band:         var(--petroleo);

  /* ── Tinta ─────────────────────────────────────────────────────────────
     Tres niveles y no cinco: con más, nadie acierta cuál toca. */
  --ink:       #0F3D3E;
  --ink-soft:  #4C6B6C;
  --ink-faint: #7B9394;

  /* ── Filetes ───────────────────────────────────────────────────────── */
  --rule:      #DCD6C9;
  --rule-soft: #E9E4D9;

  /* ── Sobre la franja oscura ───────────────────────────────────────────
     La banda necesita su propia tinta y su propio filete: encima del petróleo
     no valen ni `--ink` ni `--rule`. */
  --on-band:      #FFFFFF;
  --on-band-soft: #A9C9C7;
  --band-rule:    #1D5254;
  --band-surface: #16494B;

  /* ── Acentos legibles ─────────────────────────────────────────────────
     El turquesa y el naranja de marca no tienen contraste suficiente para
     texto pequeño sobre claro. Estas son sus versiones para escribir. */
  --turquesa-deep: #0E8F82;
  --naranja-deep:  #C22D00;

  /* ── Acentos de sección ───────────────────────────────────────────────
     Las dos líneas editoriales del blog tienen color propio, y eso se queda:
     es lo que hace que un artículo de VeriFactu y uno de aula no se confundan.
     Lo que cambia es que ahora son tokens con valor claro y valor oscuro, en
     vez de dos colores sueltos que sobre fondo petróleo no se veían.

     Los valores están elegidos por CONTRASTE, no por gusto: van en el
     antetítulo, que es texto pequeño en negrita, y ahí hace falta 4,5:1. El
     terracota de marca (#C4562F) se queda en 4,3 sobre blanco, así que para
     escribir se usa uno un punto más oscuro. */
  --acento-verifactu:       #0E4D57;
  --acento-verifactu-suave: rgba(14, 77, 87, 0.09);
  --acento-aula:            #A8421F;
  --acento-aula-suave:      rgba(196, 86, 47, 0.10);

  /* ── Forma ─────────────────────────────────────────────────────────── */
  --radio-sm: 8px;
  --radio:    14px;
  --radio-lg: 22px;

  /* El ritmo vertical entre secciones. Una sola variable: si cada página
     elige su propio aire, el sitio deja de tener pulso. */
  --paso: clamp(56px, 7vw, 104px);

  --sombra:      0 1px 2px rgba(15,61,62,.05), 0 12px 32px -12px rgba(15,61,62,.18);
  --sombra-alta: 0 2px 4px rgba(15,61,62,.06), 0 28px 60px -24px rgba(15,61,62,.30);

  --fuente: Poppins, system-ui, "Segoe UI", Roboto, sans-serif;
}

/* ── Oscuro ───────────────────────────────────────────────────────────────
   Dos bloques y no uno, y el orden importa:

   1. quien tenga el sistema en oscuro lo ve en oscuro, SIN haber elegido nada
      —pero solo si no ha pedido claro a mano—;
   2. quien lo elige en la barra manda por encima de lo que diga el sistema.

   Es el contrato estándar y ya estaba bien resuelto en la portada. Aquí no se
   reinventa, se comparte. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ground:       #0A2829;
    --surface:      #103537;
    --surface-soft: #0E2F31;
    --band:         #061E1F;
    --ink:          #EBF6F4;
    --ink-soft:     #A7C6C4;
    --ink-faint:    #7FA5A3;
    --rule:         #1E5153;
    --rule-soft:    #17403F;
    --band-rule:    #14403F;
    --band-surface: #0C2A2B;
    --turquesa-deep: #2ED3BF;
    --naranja-deep:  #FF7A4D;
    /* Sobre petroleo, el acento tiene que aclararse o desaparece. */
    --acento-verifactu:       #5FD9C9;
    --acento-verifactu-suave: rgba(95, 217, 201, 0.12);
    --acento-aula:            #FF9468;
    --acento-aula-suave:      rgba(255, 148, 104, 0.13);
  }
}

:root[data-theme="dark"] {
  --ground:       #0A2829;
  --surface:      #103537;
  --surface-soft: #0E2F31;
  --band:         #061E1F;
  --ink:          #EBF6F4;
  --ink-soft:     #A7C6C4;
  --ink-faint:    #7FA5A3;
  --rule:         #1E5153;
  --rule-soft:    #17403F;
  --band-rule:    #14403F;
  --band-surface: #0C2A2B;
  --turquesa-deep: #2ED3BF;
  --naranja-deep:  #FF7A4D;
  /* Los mismos que arriba. Duplicar catorce líneas es feo, pero la alternativa
     es una tercera clase que los dos bloques hereden, y entonces el contrato
     —sistema primero, elección después— deja de leerse de un vistazo. Si se
     toca uno, se tocan los dos: lo vigila tests/test_sistema_publico.py. */
  --acento-verifactu:       #5FD9C9;
  --acento-verifactu-suave: rgba(95, 217, 201, 0.12);
  --acento-aula:            #FF9468;
  --acento-aula-suave:      rgba(255, 148, 104, 0.13);
}

/* ── Base ───────────────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

body.public-page {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--fuente);
  font-weight: 400;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
}

/* La caja de contenido. Una sola medida para todo el sitio: la portada usaba
   1140, las páginas SEO 1040 y el blog 1120, y esos 100 px de diferencia se
   notan al pasar de una a otra aunque nadie sepa decir por qué. */
.env {
  width: min(1140px, 100% - clamp(32px, 6vw, 80px));
  margin-inline: auto;
}

/* ── Escala tipográfica ────────────────────────────────────────────────────
   Tres tamaños con `clamp`, de la portada. El h1 llega a 4 rem porque ahí va
   un titular de seis palabras; el blog lo baja en su propia hoja, que es donde
   los titulares son largos. */
.public-page h1, .public-page h2, .public-page h3 {
  font-family: var(--fuente);
  font-weight: 600;
  text-wrap: balance;
  margin: 0;
}

.public-page h1 { font-size: clamp(2.15rem, 1.2rem + 3.7vw, 4.05rem); line-height: 1.04; }
.public-page h2 { font-size: clamp(1.6rem, 1.1rem + 1.9vw, 2.5rem); line-height: 1.12; }
.public-page h3 { font-size: 1.06rem; line-height: 1.34; letter-spacing: -0.012em; }

/* «Gestión que conecta»: el verbo de la marca, siempre en turquesa. */
.conecta { color: var(--turquesa-deep); }

/* El antetítulo de sección. */
.rotulo {
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* ── Iconos ─────────────────────────────────────────────────────────────── */

.ic    { width: 20px; height: 20px; flex: none; }
.ic-sm { width: 16px; height: 16px; }

/* ── Botones ──────────────────────────────────────────────────────────────
   Cuatro y no catorce. Sólido para la acción principal, línea para la
   secundaria, claro para encima de la franja oscura y fantasma para lo que
   acompaña sin competir. */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 13px 24px;
  border: 1px solid transparent;
  border-radius: 999px;
  font: 600 .95rem/1 var(--fuente);
  text-decoration: none;
  cursor: pointer;
  transition: background-color .18s ease, color .18s ease,
              border-color .18s ease, transform .18s ease, box-shadow .18s ease;
}

.btn svg { transition: transform .18s ease; }
.btn:hover svg { transform: translateX(3px); }

.btn-solido {
  background: var(--turquesa);
  color: var(--petroleo);
  box-shadow: 0 10px 24px -12px rgba(20,184,166,.9);
}

.btn-solido:hover { background: #12a695; transform: translateY(-1px); }

.btn-linea {
  background: transparent;
  color: var(--ink);
  border-color: var(--rule);
}

.btn-linea:hover { border-color: var(--ink); background: var(--surface); }

.btn-claro {
  background: var(--on-band);
  color: var(--petroleo);
}

.btn-claro:hover { transform: translateY(-1px); }

/* El botón de las superficies oscuras: su tinta base es `--on-band`, así que
   el turquesa del hover se lee. Lleva su fondo declarado —aunque sea
   `transparent`— para dejar dicho que sabe sobre qué va. */
.btn-fantasma {
  background: transparent;
  color: var(--on-band);
  border-color: var(--band-rule);
}

.btn-fantasma:hover {
  background: transparent;
  border-color: var(--turquesa);
  color: var(--turquesa);
}

/* ── Foco ─────────────────────────────────────────────────────────────────
   Visible de verdad y en todo el sitio. No se quita nunca: quien navega con
   teclado se queda sin saber dónde está. */
.public-page a:focus-visible,
.public-page button:focus-visible,
.public-page input:focus-visible,
.public-page textarea:focus-visible,
.public-page select:focus-visible,
.public-page summary:focus-visible {
  outline: 2.5px solid var(--turquesa);
  outline-offset: 3px;
  border-radius: 6px;
}

/* ── Secciones ────────────────────────────────────────────────────────────
   Alternar `sec-blanca` y `sec-mint` es lo que da ritmo sin meter filetes por
   todas partes. `banda` es el énfasis: una sola por página, o deja de serlo. */

.sec        { padding-block: var(--paso); }
.sec-blanca { background: var(--surface); }
.sec-mint   { background: var(--surface-soft); }

.sec-cab {
  max-width: 60ch;
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-bottom: clamp(34px, 4vw, 52px);
}

.sec-cab p { color: var(--ink-soft); font-size: 1.03rem; }

.banda {
  background: var(--band);
  color: var(--on-band);
  padding-block: var(--paso);
}

.banda .rotulo { color: var(--turquesa); }
.banda h2      { color: var(--on-band); }
.banda p       { color: var(--on-band-soft); }

.banda ul {
  list-style: none;
  margin: 22px 0 26px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.banda li {
  display: flex;
  gap: 13px;
  align-items: flex-start;
  font-size: .95rem;
  color: var(--on-band);
}

.banda li svg { color: var(--turquesa); margin-top: 1px; }

/* ── Tarjeta ──────────────────────────────────────────────────────────────
   La superficie elevada. Es lo que faltaba en el blog: el texto flotaba en
   medio de la pantalla sin nada que lo sostuviera. */

.tarjeta {
  background: var(--surface);
  border: 1px solid var(--rule-soft);
  border-radius: var(--radio-lg);
  box-shadow: var(--sombra);
  padding: clamp(1.5rem, 1rem + 2vw, 2.5rem);
}

/* ── Formularios ──────────────────────────────────────────────────────────
   Los campos se pintan según la superficie donde caen, no según la página:
   dentro de una `.banda` van oscuros y fuera, claros. Una sola definición
   para contacto, para el alta y para el pie de la portada. */

.campos {
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

.campo { display: flex; flex-direction: column; gap: 6px; }

.campo > span,
.campo > label {
  font-size: .82rem;
  font-weight: 500;
  color: var(--ink-soft);
}

.campo input,
.campo textarea,
.campo select {
  font-family: inherit;
  font-size: .95rem;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radio);
  padding: 11px 14px;
  width: 100%;
  transition: border-color .18s ease, box-shadow .18s ease;
}

.campo textarea { resize: vertical; min-height: 96px; }

.campo input:focus,
.campo textarea:focus,
.campo select:focus {
  outline: none;
  border-color: var(--turquesa);
  box-shadow: 0 0 0 3px rgba(20,184,166,.18);
}

.campo input::placeholder,
.campo textarea::placeholder { color: var(--ink-faint); }

/* Dentro de la franja oscura, el campo cambia de superficie. Esta es la regla
   que evita el fallo de siempre: fondo fijo y texto por token. */
.banda .campo > span,
.banda .campo > label { color: var(--on-band-soft); }

.banda .campo input,
.banda .campo textarea,
.banda .campo select {
  color: var(--on-band);
  background: var(--band-surface);
  border-color: var(--band-rule);
}

.banda .campo input::placeholder,
.banda .campo textarea::placeholder { color: var(--on-band-soft); }

/* El campo trampa del antispam: invisible para quien ve, presente para el
   robot que rellena todo lo que encuentra. `display:none` no vale, hay robots
   que lo detectan. */
.trampa {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ── La etiqueta de «nuevo» ───────────────────────────────────────────── */

.marca-nuevo {
  margin-left: auto;
  font-size: .67rem;
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--naranja-deep);
  border: 1px solid currentColor;
  padding: 2px 8px;
  border-radius: 999px;
}

/* ── Movimiento ───────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  .public-page *,
  .public-page *::before,
  .public-page *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ── La escena ────────────────────────────────────────────────────────────
   El fondo con atmósfera de las superficies de MARCA: portada, contacto,
   login, las bandas de llamada. Un plano oscuro liso se lee barato; lo que
   daba empaque a /contacto era esto, y ahora lo puede usar cualquier sección.

   NO va detrás de texto largo. Un artículo de mil palabras sobre una foto
   cansa, y para eso están las superficies de lectura.

   TRES CAPAS EN UN SOLO PSEUDOELEMENTO, de arriba abajo:

     1. grano fino, un SVG en línea —no es una peticion mas, va en la propia
        hoja— que rompe el degradado y evita el bandeado que se ve en
        pantallas de 8 bits;
     2. velo de petróleo, que es lo que garantiza el contraste del texto: la
        foto por debajo puede ser cualquiera y el texto sigue leyéndose;
     3. la foto.

   LA FOTO ESTÁ AUTOALOJADA, y no es un detalle. Hasta el 18/09/2026 /contacto
   la pedía a images.pexels.com en cada visita: 76 KB a un tercero que ve la IP
   de quien entra —con un aviso de cookies en la misma página—, una dependencia
   de que Pexels no la retire, y un tiempo de carga que no controlamos. Ahora
   es nuestra, en WebP y en tres anchos: 26, 44 y 61 KB. Licencia Pexels, que
   permite uso comercial sin atribución. */

.escena {
  position: relative;
  isolation: isolate;
  background-color: var(--band);
  color: var(--on-band);
  --escena-foto: url("/static/images/escenas/hojas-960.webp");
}

.escena::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23g)' opacity='.45'/%3E%3C/svg%3E"),
    linear-gradient(155deg, rgba(15, 61, 62, .95) 0%, rgba(15, 61, 62, .80) 55%, rgba(10, 40, 41, .92) 100%),
    var(--escena-foto);
  background-size: 180px 180px, cover, cover;
  background-position: center, center, center;
  background-repeat: repeat, no-repeat, no-repeat;
  /* El grano, muy por debajo de lo que se nota conscientemente: solo tiene que
     quitarle el plástico al degradado. */
  opacity: 1;
  mix-blend-mode: normal;
}

/* Cada ancho pide su fichero. Se cambia la variable y no el `background-image`
   entero: así el degradado y el grano se escriben UNA vez. */
@media (min-width: 961px)  { .escena { --escena-foto: url("/static/images/escenas/hojas-1440.webp"); } }
@media (min-width: 1441px) { .escena { --escena-foto: url("/static/images/escenas/hojas-1920.webp"); } }

/* Sin foto: degradado y grano. Para las secciones donde una imagen sobra pero
   el plano liso se queda corto. */
.escena-lisa { --escena-foto: none; }

/* La escena oscurece un punto más en tema oscuro: sobre una página ya oscura,
   el velo de contacto quedaba casi al mismo tono que el fondo y la banda
   dejaba de distinguirse. */
:root[data-theme="dark"] .escena::before,
:root:not([data-theme="light"]) .escena::before {
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23g)' opacity='.45'/%3E%3C/svg%3E"),
    linear-gradient(155deg, rgba(6, 30, 31, .95) 0%, rgba(10, 40, 41, .86) 55%, rgba(6, 30, 31, .95) 100%),
    var(--escena-foto);
  background-size: 180px 180px, cover, cover;
}

/* En una escena, lo que va encima es claro: el titular, el texto y los
   filetes. Si esto faltara, una seccion clara convertida en escena se
   quedaria con el texto oscuro sobre la foto, ilegible. Es la misma regla de
   siempre: fondo y texto salen juntos o no salen. */
.escena h1, .escena h2, .escena h3 { color: var(--on-band); }
.escena p                          { color: var(--on-band-soft); }
.escena .rotulo                    { color: var(--turquesa); }

/* ── Que la barra se quede pegada arriba ──────────────────────────────────
   `.pp-nav` es `position: sticky` desde siempre y NO se pegaba. La culpa no
   estaba en la barra: `publico.css` pone `overflow-x: hidden` en `html` y en
   `body`, y eso convierte al body en contenedor de scroll. Un `sticky` se pega
   al contenedor que scrollea, así que se quedaba pegado a algo que no se
   mueve: o sea, quieto arriba del documento y fuera de la pantalla en cuanto
   bajabas.

   `clip` hace lo mismo que `hidden` —recorta lo que se salga a los lados— pero
   NO crea contenedor de scroll, así que el sticky vuelve a funcionar. Es la
   razón por la que existe ese valor.

   Va aquí y no en `publico.css` porque esta hoja se carga solo en las páginas
   públicas y DESPUÉS de aquella: el arreglo llega donde tiene que llegar y no
   toca la intranet, que no lo necesita. */

html { overflow-x: clip; }
body.public-page { overflow-x: clip; }
