/*!
Theme Name: MEDINNOVA
Theme URI: https://medinnova.example
Author: MEDINNOVA
Description: Tema propio de MEDINNOVA. Portada inmersiva de capitulos a pantalla completa (§41-49 del brief) y contenido institucional editable con Gutenberg. Los datos de la experiencia viven en el plugin medinnova-core.
Version: 0.2.14
Requires at least: 6.5
Tested up to: 7.0
Requires PHP: 8.0
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: medinnova
*/

/*
  Estilos portados del prototipo de ritmo (prototype/index.html), que sirvio
  para validar §41-49 antes de escribir el tema. Se conservan los comentarios
  que explican POR QUE cada regla es como es: casi todos documentan un fallo
  real que costo encontrar.
*/

:root{
  --blue:#006397;          /* §19.2 Azul MEDINNOVA */
  --night:#0f2f53;         /* §19.2 Azul noche #16243C*/
  --dark:#031325;         /* §19.2 Azul noche #16243C*/
  --limestone:#F5F2EA;
  --sand:#D8CDBB;
  --stone:#A7ADB0;
  --ui:'Helvetica Neue',Arial,sans-serif;
  --mono:ui-monospace,'SF Mono',Consolas,monospace;
}
*{box-sizing:border-box}
/* Reserva el hueco de la barra de scroll desde el primer pintado. La
   precarga bloquea el scroll y al soltarlo la barra aparece: sin esto, el
   viewport se estrecharia de golpe y desplazaria todo lo centrado. */
html{scroll-behavior:auto;scrollbar-gutter:stable}
body{
  margin:0;background:var(--night);color:var(--limestone);
  font-family:var(--ui);-webkit-font-smoothing:antialiased;
  overflow-x:hidden;            /* §29: jamas scroll horizontal involuntario */
}
html.lock{overflow:hidden}

/* ---------- lienzo WebGL (v3) ----------
   Fijo y detras de todo: el scroll nativo mueve el documento por encima
   mientras el shader pinta la foto que corresponde a la camara. */
.glcv{position:fixed;inset:0;z-index:0;width:100%;height:100%;background:var(--night)}
html:not(.gl-on) .glcv{display:none}
/* vineta unica sobre el canvas: en v3 sustituye a los .scrim por capitulo */
.j-vig{position:fixed;inset:0;z-index:2;pointer-events:none;opacity:0;
  background:radial-gradient(120% 90% at 50% 60%, transparent 34%, rgba(22,36,60,.5) 100%)}
html.gl-on .j-vig{opacity:1}
html.gl-on .scrim,html.gl-on .plate{display:none}
html.gl-on .stage-pin{background:transparent}

/* ---------- loader de marca ----------
   Existe por una razon funcional: la primera textura debe estar decodificada
   antes de abrir la escena (nunca un pop de imagen a medio cargar, §44). */
.loader{position:fixed;inset:0;z-index:60;background:var(--night);
  display:grid;place-items:center;transition:opacity .5s ease,visibility .5s}
.loader.off{opacity:0;visibility:hidden}
/* logo real en la precarga; tamano forzado por CSS, el PNG no se toca */
.l-logo{display:block;width:clamp(200px,26vw,320px);height:auto;margin:0 auto;
  opacity:0;transform:translateY(14px);
  transition:opacity .8s ease,transform .8s cubic-bezier(.16,1,.3,1)}
.loader.go .l-logo{opacity:1;transform:none}
.l-bar{width:min(300px,50vw);height:1px;background:rgba(245,242,234,.16);
  margin:24px auto 0;overflow:hidden}
.l-bar i{display:block;height:100%;background:var(--blue);
  transform:scaleX(0);transform-origin:left;transition:transform .4s ease}

/* ---------- cabecera discreta (§46) ----------
   Franja de ~50px de azul noche sobre toda la cabecera (logo incluido): opaca
   arriba y al 75% abajo, para que se funda con la escena en vez de cortarla.
   Con ella el texto va SIEMPRE en blanco, sin depender de mix-blend. */
.hdr{
  position:fixed;inset:0 0 auto 0;z-index:50;height:50px;
  display:flex;align-items:center;
  padding:0 clamp(16px,3vw,40px);
  color:#fff;pointer-events:none;
  background:linear-gradient(rgb(22 35 59),rgba(22,35,59,.75));
}
/* tamano forzado por CSS a proposito: el PNG original no se toca todavia */
.hdr .brand-logo{display:block;height:35px;width:auto}
.hdr nav{position:absolute;left:50%;transform:translateX(-50%)}
/* El hueco entre opciones baja de 10-26px a 0-8px porque ahora separa tambien
   el relleno de la pildora, 24px por pareja: sumados a los de antes, la fila
   crecia lo justo para alcanzar al logotipo en pantallas de ~800px. */
.hdr nav ul{list-style:none;margin:0;padding:0;display:flex;gap:clamp(0px,.6vw,8px);font-size:11px;letter-spacing:.12em;text-transform:uppercase}
.hdr a{color:#fff;text-decoration:none;opacity:.85;pointer-events:auto;transition:opacity .3s}
.hdr a:hover{opacity:1}
/* Pildora de la opcion en curso (§46). El relleno lo llevan TODOS los enlaces
   y no solo el marcado: si apareciera solo bajo la pildora, los rotulos se
   correrian de sitio al cambiar de pagina. `display:block` es lo que hace que
   ese relleno vertical cuente —sobre un enlace en linea se pinta por fuera sin
   mover nada— y de paso agranda el area de clic a la pildora entera.
   El radio en 999px es la manera exacta de pedir "la mitad de la altura": el
   navegador lo recorta a la mitad del lado corto, asi que los extremos siguen
   siendo semicirculos aunque cambie la tipografia o el zoom del navegador. */
.hdr nav a{display:block;padding:6px 12px;border-radius:999px;
  transition:opacity .3s,background-color .3s}
.hdr nav .current-menu-item>a,
.hdr nav .current-menu-ancestor>a,
.hdr nav .current_page_item>a{background:var(--dark);opacity:1}
/* El menu va centrado en la ventana, no en el hueco que deja el logotipo, asi
   que por debajo de ~1200px los dos se disputan la fila. Con la pildora son
   24px mas por opcion, 168 en total, y a 1024px la primera opcion se metia
   debajo del logotipo. Se aprieta la caja de la pildora y se baja un punto el
   cuerpo; el espaciado entre letras se queda como esta, que es lo que da a la
   barra su aire de marca. Medido en el navegador: a 1024px quedan 13px de
   holgura hasta el logotipo, y 47 a 1100px. */
@media(max-width:1200px){
  .hdr nav ul{font-size:10px}
  .hdr nav a{padding:6px 8px}
}
@media(max-width:720px){.hdr nav{display:none}}

/* ---------- menu movil (§46) ----------
   Menu tradicional: un boton abre un panel a pantalla completa con los
   mismos enlaces. No se replican los microelementos de desktop. */
.burger{display:none;position:absolute;right:clamp(16px,3vw,40px);
  width:40px;height:40px;align-items:center;justify-content:center;
  background:none;border:0;padding:0;margin:0;cursor:pointer;
  pointer-events:auto;color:#fff}
.burger:focus-visible{outline:1px solid #fff;outline-offset:2px}
.burger i{display:block;width:20px;height:1px;background:currentColor;position:relative}
.burger i::before,.burger i::after{content:'';position:absolute;left:0;
  width:20px;height:1px;background:currentColor;transition:transform .3s}
.burger i::before{top:-6px}
.burger i::after{top:6px}
html.mnav-on .burger i{background:transparent}
html.mnav-on .burger i::before{transform:translateY(6px) rotate(45deg)}
html.mnav-on .burger i::after{transform:translateY(-6px) rotate(-45deg)}
html.mnav-on{overflow:hidden}
/* El margen lateral descuenta el relleno de la pildora (abajo) para que los
   rotulos sigan cayendo donde caian: lo que se mete hacia dentro el enlace se
   le quita al panel. */
.mnav{position:fixed;inset:0;z-index:45;background:var(--night);
  display:grid;align-content:center;padding:0 calc(8vw - 14px);
  opacity:0;visibility:hidden;transition:opacity .35s ease,visibility .35s}
html.mnav-on .mnav{opacity:1;visibility:visible}
/* `display:block` no es cosmetico: el enlace es inline dentro de su <li>, y
   sobre un inline el relleno vertical no separa filas —se sale por arriba y
   por abajo sin mover nada—. Con 12px puestos, el paso real entre opciones era
   el interlineado y nada mas. De paso, el area tocable pasa a ser la fila
   entera y no solo las letras.

   El aire va en vh y no en pixeles fijos: el panel ocupa la pantalla entera,
   asi que el sitio disponible lo marca su altura. Son 20px por lado en un
   movil corriente y 14 en uno de 568, que es lo que habia escrito antes. */
.mnav a{color:var(--limestone);text-decoration:none;display:block;
  padding:clamp(14px,2.4vh,22px) 14px;
  font-size:clamp(22px,7vw,34px);font-weight:700;letter-spacing:-.01em}
/* La misma pildora que en la barra de arriba, aqui a cuerpo de titular.
   `width:fit-content` la ajusta al rotulo: sin eso el enlace es un bloque de
   fila entera y la marca saldria como una banda de lado a lado del panel.
   Solo se encoge el enlace marcado; los demas conservan la fila entera como
   area tocable, que es lo que explica el comentario de arriba. */
.mnav .current-menu-item>a,
.mnav .current-menu-ancestor>a,
.mnav .current_page_item>a{background:var(--dark);border-radius:999px;width:fit-content}
@media(max-width:720px){.burger{display:flex}}
@media(min-width:721px){.mnav{display:none}}

/* indicador de capitulo, discreto y lateral (§46) */
.chapno{
  position:fixed;left:clamp(16px,3vw,40px);bottom:clamp(16px,3vw,34px);z-index:50;
  font-family:var(--mono);font-size:11px;letter-spacing:.16em;
  mix-blend-mode:difference;color:#fff;
}
.chapno b{font-weight:400}

/* ---------- rail lateral de capitulos (§46: indicador lateral, no barra llamativa) ----------
   Todo en blanco puro al 50%: letras, lineas y numeros. Sin mix-blend, que
   invertia el color contra la foto y dejaba de leerse como blanco. El
   capitulo activo se distingue por la longitud de su marca, no por el brillo. */
.rail{position:fixed;right:clamp(14px,2vw,30px);top:50%;transform:translateY(-50%);
  z-index:9;display:grid;gap:16px;color:#fff;opacity:.5;transition:opacity .5s}
.rail.gone{opacity:0;pointer-events:none}
.rail button{all:unset;cursor:pointer;display:flex;align-items:center;gap:10px;
  justify-content:flex-end;color:inherit;
  font-family:var(--mono);font-size:10px;letter-spacing:.18em;text-transform:uppercase}
.rail button:focus-visible{outline:1px solid #fff;outline-offset:4px}
.rail .nm{opacity:0;transform:translateX(6px);transition:opacity .3s,transform .3s}
.rail i{width:18px;height:1px;background:currentColor;transition:width .3s}
.rail button:hover .nm,.rail button.on .nm{opacity:1;transform:none}
.rail button.on i{width:34px}
@media(max-width:720px){.rail{display:none}}   /* §46 movil: simplificar */

/* invitacion a seguir bajando: se retira con el gesto y vuelve en cada
   capitulo, cuando la escena lleva un cuarto de segundo parada (scroll.js).
   Sin mix-blend-mode: invertia el color contra la fotografia y dejaba de ser
   blanco, que es justo lo que se pide aqui. La sombra hace que la flecha se
   lea igual sobre un cielo claro que sobre agua oscura. */
/* 200px por encima del margen inferior habitual, que es donde se pidio. Se
   conserva la base responsive para que en pantallas estrechas no se pegue al
   borde. */
.cue{position:fixed;bottom:calc(clamp(16px,3vw,30px) + 200px);left:50%;
  transform:translateX(-50%);
  z-index:9;color:#FFFFFF;opacity:0;transition:opacity .6s;pointer-events:none}
.cue.show{opacity:1}
.cue svg{display:block;width:60px;height:auto;
  filter:drop-shadow(0 1px 6px rgba(10,20,35,.55));
  animation:bob 1.9s ease-in-out infinite}
/* En pantalla estrecha, 60px son casi un sexto del ancho y la flecha compite
   con la tipografia del capitulo en vez de acompanarla. */
@media(max-width:720px){.cue svg{width:38px}}
/* solo se mueve, no se atenua: asi el blanco es siempre #FFFFFF */
@keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(7px)}}

/* ---------- ESCENARIO UNICO (§44) ----------
   v2 apilaba las escenas en un sticky y las escalaba con transform.
   En v3 la FOTO vive en el canvas; este contenedor conserva el recorrido de
   scroll (alto n × 220vh fijado por JS) y las capas DOM de cada capitulo:
   tipografia, subtitulo, red SVG y primer plano organico. */
.wp-block-button__link {
    background-color: var(--dark);
    margin-bottom: 20px;
}
.wp-block-button.is-style-outline--1 .wp-block-button__link{
    border: none;
    background-color: rgba(58,191,240,1.00);
    color: var(--dark);
}
.stage{position:relative;z-index:3}
.stage-pin{
  position:sticky;top:0;height:100svh;overflow:hidden;
  background:var(--night);                      /* nunca un flash blanco (§44) */
}
.chapter{position:absolute;inset:0;will-change:transform,opacity}
.scene{
  position:absolute;inset:0;overflow:hidden;
  display:grid;place-items:center;
  transform-origin:50% 50%;
}
.plate{position:absolute;inset:-8%;width:116%;height:116%;object-fit:cover;will-change:transform}
.scrim{position:absolute;inset:0;background:
  radial-gradient(120% 90% at 50% 60%, transparent 30%, rgba(22,36,60,.55) 100%)}

/* capa de red: el mismo SVG dibujado a mano en todos los capitulos, espejado
   y reencuadrado en cada uno por el JS, con su propio parallax (§32). */
.net-layer{position:absolute;inset:0;color:#fff;opacity:.8;will-change:transform}
.net-layer svg{width:100%;height:100%;display:block}
.net-layer .r{stroke-dasharray:1;stroke-dashoffset:1}   /* lo traza el JS */
.net-nodes{opacity:0}
/* Grosor configurable (el asset trae 1.35 y 7). Se hace aqui y no en el SVG
   para no tocar el arte final. El halo conserva su proporcion original. */
.net-layer .net-line{stroke-width:var(--net-stroke,.68)}
.net-layer .net-glow{stroke-width:calc(var(--net-stroke,.68) * 5.15)}

/* capa organica de primer plano.
   Va en el marcado ANTES de .type, asi que por orden de pintado quedaba
   DEBAJO de la tipografia (que ademas lleva z-index:5): la posidonia se veia
   recortada por la palabra en vez de pasarle por delante, y el efecto de
   profundidad —lo unico que justifica esta capa— no llegaba a producirse.
   Con z-index:6 pasa por delante del texto, que es lo que promete el editor.
   El salto no se escapa del capitulo: .chapter tiene will-change:transform y
   crea su propio contexto de apilado, asi que el HUD y la flecha (z-index:9,
   fuera del capitulo) siguen por encima. */
.fg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
    z-index:6;pointer-events:none;will-change:transform}

/* ---------- tipografia de capitulo (§41.C) ---------- */
/* Capa absoluta a pantalla completa del tamano de la escena. */
.type{position:absolute;inset:0;z-index:5;text-align:center}
/* Grupo tipografico: palabra + subtitulo viajan JUNTOS, como en la
   referencia, donde ambos viven en el mismo plano y crecen a la vez.
   Centrado DETERMINISTA: el grupo precompuesto mide miles de px y ningun
   centrado de grid/text-align sobrevive a ese desborde (los tracks auto se
   dimensionan por max-content y se alinean al inicio; los scroll containers
   aplican "safe alignment"). Absoluto en 50%/50% + translate(-50%,-50%)
   DENTRO del transform, compuesto antes del scale: exacto siempre. */
.tgroup{--wmax:1;position:absolute;left:50%;top:50%;
  transform:translate(-50%,-50%);white-space:nowrap;will-change:transform}
/* La palabra se compone GRANDE y se escala HACIA ABAJO.
   Con will-change:transform el navegador promueve el elemento a su propia capa
   y lo rasteriza UNA VEZ al tamano inicial; a partir de ahi la GPU estira ese
   mapa de bits, y a 7x se ven los pixeles. (Se nota que es eso porque al tocar
   cualquier cosa en el inspector se fuerza un re-rasterizado y se ve nitida.)
   Componiendo al tamano maximo y escalando de 0.14 a 1, la textura siempre se
   muestra a su resolucion nativa o por debajo, y nunca se pixela.
   --wmax lo lee el JS para saber desde donde arrancar. */
/* El tamano de reposo se limita ADEMAS por el numero de caracteres: con
   clamp() sola, MEDINNOVA (9 letras) medía 490px en un viewport de 390 y la
   palabra arrancaba ya cortada, cuando §44 pide que en la presentacion el
   titulo se lea entero. El 0.85 es el ancho medio real por caracter en esta
   fuente (medido en el navegador) e incluye la ampliacion de reposo que
   aplica el JS. Las palabras cortas no se ven afectadas: para ellas manda
   el clamp. --chars lo fija el JS; el valor por defecto evita un calc
   invalido en el primer frame. */
.word{
  --chars:8;
  --w-rest:min(clamp(64px,15vw,220px), calc(90vw / (var(--chars) * 0.85)));
  margin:0;line-height:.82;letter-spacing:-.02em;
  font-size:var(--w-rest);
  /* La inclinacion puede vivir aqui porque el parallax del raton se escribe en
     la propiedad `translate`, no en `transform`: son independientes y el
     navegador las compone, asi que el bucle de animacion no la pisa. */
  font-weight:900;
  transform:skewX(-5deg);
  /* sombra suave: sin ella el blanco sobre caliza clara es ilegible.
     Detalle observado en la referencia NORD. */
  text-shadow:0 2px 40px rgba(10,20,35,.55),0 1px 3px rgba(10,20,35,.35);
}
/* el tamano compuesto ya incluye la ampliacion maxima */
.word.prescaled{font-size:calc(var(--w-rest) * var(--wmax))}
/* El subtitulo vive DENTRO del grupo y se compone tambien a escala --wmax:
   crece y se desvanece con la palabra, como en la referencia.
   width:max-content lo mantiene en UNA linea; solo salta cuando de verdad no
   cabe, porque --sub-max es el ancho util de pantalla convertido a la escala
   interna del grupo (lo calcula el JS). Un 34ch fijo lo partia en dos aunque
   sobrara sitio, y un max-width en vw no vale: dentro del grupo preescalado
   las unidades de viewport no se escalan y romperian la geometria. */
.sub{
  /* El valor de reserva es enorme a proposito. El JS calcula el ancho util
     exacto (ronda 230-295vw dentro del grupo preescalado), pero lo hace tras
     el primer pintado: con un tope pequeno aqui, el subtitulo se dibujaria en
     dos lineas y saltaria a una al llegar el JS. Partiendo de "no partas",
     no hay nada que recolocar. */
  margin:.55em auto 0;width:max-content;max-width:var(--sub-max,250vw);
  white-space:normal;text-wrap:balance;   /* si tiene que partir, dos lineas parejas */
  font-size:calc(clamp(16px,2.1vw,28px) * var(--wmax));
  font-weight:400;letter-spacing:.01em;opacity:.92;text-align:center;
  text-shadow:0 1px 18px rgba(10,20,35,.75);
  /* Misma inclinacion que la palabra, para que el grupo se lea como una pieza.
     Cabe aqui por lo mismo: el parallax del raton va en `translate`. */
  transform:skewX(-5deg);
}

/* ---------- zona editorial (§43): se abandona el escalado ---------- */
.editorial{position:relative;z-index:4;background:var(--night);
  padding:clamp(70px,12vh,150px) clamp(20px,6vw,90px)}
.editorial .inner{max-width:1100px;margin:0 auto}
/* Un unico tamano para todos los h2 del sitio: titulos de seccion del
   contenido, titulares del listado de actualidad y titulares de tarjeta. Las
   palabras de capitulo de la portada llevan .word y viven fuera de .editorial,
   asi que conservan su escala display.

   Sin max-width: el limite de 20ch venia de cuando estos titulares median
   54px, y a 2rem parte en seis lineas cualquier titular largo —los del listado
   de actualidad y los ejes de /areas—. La medida la marca ya .inner: a 32px,
   1100px son unos 60 caracteres, en linea con los 62ch de los parrafos.

   El :not() sigue haciendo falta aunque el tamano coincida: esta regla (0,1,1)
   le gana a .card__title (0,1,0), y sin el las tarjetas heredarian tambien el
   line-height y el margen de los titulos de seccion. */
.editorial h2:not(.card__title){
  font-size:2rem;line-height:1.12;font-weight:700;
  letter-spacing:-.015em;margin:0 0 .7em;
}
@media(max-width:720px){
  .editorial h2:not(.card__title){font-size:1.7rem}
}
.editorial p{font-size:clamp(15px,1.5vw,19px);line-height:1.65;max-width:62ch;opacity:.86;margin:0 0 1.1em}
.rule{height:1px;background:linear-gradient(90deg,var(--blue),transparent);margin:44px 0}
/* revelado editorial sin GSAP (§45): IntersectionObserver anade .on */
.reveal{opacity:0;transform:translateY(22px);
  transition:opacity .9s cubic-bezier(.22,.61,.36,1),transform .9s cubic-bezier(.22,.61,.36,1)}
.reveal.on{opacity:1;transform:none}

/* ---------- §20 · §24: motion reducido ----------
   El :not(.force-motion) permite forzar el movimiento con ?motion=on para poder
   revisar el prototipo en una maquina que tenga las animaciones del sistema
   desactivadas. En produccion no existe esa clase y la regla manda siempre. */
@media (prefers-reduced-motion: reduce){
  html:not(.force-motion) .loader,html:not(.force-motion) .glcv,
  html:not(.force-motion) .j-vig,html:not(.force-motion) .rail,
  html:not(.force-motion) .cue{display:none}
  html:not(.force-motion) .stage{height:auto!important}
  html:not(.force-motion) .stage-pin{position:static;height:auto;overflow:visible}
  html:not(.force-motion) .chapter{position:relative;inset:auto;opacity:1!important}
  html:not(.force-motion) .scene{position:relative;height:82svh}
  /* .word y .sub quedan fuera: aqui el motor ni siquiera llega a ejecutarse,
     asi que no hay transform que cancelar, y anularlo borraria la inclinacion
     de la palabra, que es parte del diseno y no una animacion. */
  html:not(.force-motion) :is(.plate,.fg,.net-layer,.type,.tgroup){transform:none!important;will-change:auto}
  html:not(.force-motion) :is(.word,.sub){translate:none!important;will-change:auto}
  html:not(.force-motion) :is(.type,.tgroup){position:static}
  /* Se neutraliza el multiplicador del preescalado. Aqui la tipografia no se
     amplia, asi que componerla a tamano gigante no aporta nada, y dejarlo
     puesto agrandaba el subtitulo (que tambien lo usa) hasta descompensar la
     escena. Con --wmax en 1, palabra y subtitulo recuperan su proporcion y la
     palabra conserva su tamano ajustado al ancho de pantalla. */
  html:not(.force-motion) .tgroup{--wmax:1!important}
  html:not(.force-motion) .sub{position:static;transform:none;margin:.9em auto 0;width:auto;max-width:34ch}
  /* la red se muestra ya trazada: sin JS animando, nadie fija estos valores */
  html:not(.force-motion) .net-layer .r{stroke-dasharray:none;stroke-dashoffset:0}
  html:not(.force-motion) .net-nodes{opacity:1}
  html:not(.force-motion) .reveal{opacity:1;transform:none;transition:none}
}
/* ==========================================================================
   Anadidos propios del tema (no existian en el prototipo)
   ========================================================================== */

/* Salto al contenido: obligatorio para teclado y lectores de pantalla (§24).
   Fuera de pantalla hasta que recibe el foco. */
.skip{position:absolute;left:-9999px;top:0;z-index:100;
  background:var(--night);color:var(--limestone);padding:12px 18px;
  font-size:14px;text-decoration:none}
.skip:focus{left:12px;top:12px}

/* Menu movil: los enlaces los envuelve WordPress en una lista */
.mnav ul{list-style:none;margin:0;padding:0;display:grid}

/* Logo: WordPress envuelve el suyo en .custom-logo-link */
.hdr .custom-logo-link{display:block;line-height:0;pointer-events:auto}
.hdr .custom-logo{display:block;height:35px;width:auto}
.hdr .brand-logo-link{display:block;line-height:0;pointer-events:auto}

/* Contenido institucional editado con Gutenberg (§43). El editor produce
   titulares, parrafos, listas y separadores; se les da el mismo ritmo que
   tenia el prototipo sin imponerles maquetacion. */
.editorial h1,.editorial h3{font-size:clamp(24px,3.4vw,44px);line-height:1.15;
  font-weight:700;letter-spacing:-.015em;margin:1.6em 0 .6em;max-width:22ch}
.editorial h1:first-child,.editorial h2:first-child{margin-top:0}
.editorial a{color:var(--limestone);text-underline-offset:.2em}
.editorial a:hover{color:#fff}
.editorial ul,.editorial ol{max-width:62ch;line-height:1.65;opacity:.86;
  margin:0 0 1.1em;padding-left:1.2em}
.editorial li{margin:0 0 .4em}
.editorial img{max-width:100%;height:auto}
.editorial hr,.editorial .wp-block-separator{border:0;height:1px;
  background:linear-gradient(90deg,var(--blue),transparent);margin:44px 0}
.editorial blockquote{border-left:2px solid var(--blue);margin:2em 0;
  padding-left:1.2em;font-size:clamp(18px,2.2vw,26px);line-height:1.4}

/* Vistas que no son la portada: la cabecera fija taparia el comienzo.
   Con margin y no con padding a proposito: un padding-top aqui gana en
   especificidad al de .editorial y le dejaba el titulo pegado a la franja. */
body:not(.has-experience) main{margin-top:50px}
.page-title{font-size:clamp(26px,4vw,48px);line-height:1.12;margin:0 0 1em}
.entry{margin:0 0 3em}
.entry-title{font-size:clamp(20px,2.6vw,32px);line-height:1.2;margin:0 0 .5em}
.entry-title a{color:inherit;text-decoration:none}
.entry-title a:hover{text-decoration:underline}

/* Los titulares del listado son enlaces a la entrada, no titulos de seccion:
   van un escalon por debajo del h2 editorial y con una medida mas larga que su
   tope de 20ch, que en la columna de 1100px partia cada titular en seis lineas.
   El selector lleva el elemento a proposito: `.editorial h2:not(.card__title)`
   puntua (0,2,1) porque el argumento del :not() tambien cuenta, de modo que un
   `.editorial .entry-title` a secas perdia. Por lo mismo `.editorial
   .entry-meta` (0,2,0) le gana a `.editorial p` (0,1,1). */
.editorial h2.entry-title{font-size:1.5rem;max-width:46ch}
.editorial .entry-meta{font-size:13px;letter-spacing:.06em;text-transform:uppercase;
  opacity:.55;margin:0 0 .7em}
.entry-meta a{color:inherit;text-decoration:none}
.entry-meta a:hover{color:var(--limestone);text-decoration:underline}
.entry-meta__sep{margin:0 .5em}

/* Entrada del listado con portada: la miniatura a la izquierda y el texto a la
   derecha. La columna de lectura mide 62ch y la del listado 1100px, asi que sin
   la imagen sobraba un tercio de ancho vacio a la derecha de cada entrada.
   La rejilla solo se monta con `.entry--media`, que pone index.php: una entrada
   sin portada no debe reservar la columna. */
.entry--media{display:grid;grid-template-columns:300px 1fr;gap:clamp(20px,2.4vw,34px);
  align-items:start}
.entry__media{display:block;overflow:hidden;border-radius:6px;aspect-ratio:16/10}
.entry__media img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .6s cubic-bezier(.22,.61,.36,1)}
.entry__media:hover img{transform:scale(1.04)}
/* El titular ya no compite con el ancho del parrafo: dentro de la columna
   estrecha, 46ch nunca se alcanzan y el tope sobra. */
.entry--media .entry-title{max-width:none}
.entry__body>*:first-child{margin-top:0}
@media(max-width:720px){
  .editorial h2.entry-title{font-size:1.3rem}
  /* En movil la miniatura pasa arriba: 300px de columna dejarian el texto en
     una tira de dos palabras. */
  .entry--media{grid-template-columns:1fr;gap:14px}
}

/* Pie */
.site-footer{position:relative;z-index:4;background:var(--night);
  border-top:1px solid rgba(245,242,234,.12);
  padding:clamp(40px,7vh,80px) clamp(20px,6vw,90px)}
/* align-items:center y no el stretch por defecto: el logo mide 30px y las dos
   lineas de texto ~19px, y sin esto cada bloque se apoya en el borde de arriba
   de su caja y la fila queda descuadrada. */
.site-footer .inner{max-width:1100px;margin:0 auto;
  display:flex;flex-wrap:wrap;align-items:center;
  gap:12px 40px;justify-content:space-between;
  font-size:13px;opacity:.7}
.site-footer p{margin:0}
/* El logo hereda el opacity:.7 de .inner, el mismo que tenia la palabra.
   width:auto para que los atributos width/height del img no lo deformen. */
.f-brand{display:block;height:30px;width:auto;flex:0 0 auto}
.f-legal-nav{display:flex;flex-wrap:wrap;gap:6px 24px;
  margin:0;padding:0;list-style:none}
.f-legal-nav a{color:inherit;text-decoration:none}
.f-legal-nav a:hover{text-decoration:underline}

/* Foco visible en todo el sitio: el navegador lo quita en cuanto se toca
   outline en algun sitio, y sin el la navegacion por teclado se pierde. */
a:focus-visible,button:focus-visible{outline:2px solid var(--blue);
  outline-offset:3px}

/* La pantalla de carga usa una clase en vez del estilo en linea del
   prototipo: WordPress puede servir con Content-Security-Policy estricta. */
.loader-in{text-align:center}

/* ==========================================================================
   Proyectos y ecosistema
   ========================================================================== */

.archive-head{margin:0 0 clamp(30px,5vh,60px)}
.archive-intro{max-width:62ch;line-height:1.65;opacity:.86}

/* Rejilla de tarjetas. auto-fill y minmax en vez de columnas fijas: con dos
   proyectos no deja huecos y con quince no se apelmaza. */
.cards{display:grid;gap:clamp(20px,3vw,38px);
  grid-template-columns:repeat(auto-fill,minmax(min(300px,100%),1fr))}
.card{margin:0}
.card__link{display:block;color:inherit;text-decoration:none}
.card__media{overflow:hidden;border-radius:6px;margin:0 0 14px;aspect-ratio:16/10}
.card__media img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .6s cubic-bezier(.22,.61,.36,1)}
.card__link:hover .card__media img{transform:scale(1.04)}
.card__eyebrow{display:block;font-family:var(--mono);font-size:10px;
  letter-spacing:.2em;text-transform:uppercase;color:var(--stone);margin:0 0 6px}
/* Los nombres de entidad traen palabras que no caben en una columna de la
   rejilla («Mediterranean», «Ayuntamiento»): sin esto se salen por encima de la
   tarjeta vecina.
   Sin guionado: `hyphens:auto` estaba partiendo palabras corrientes ahora que
   el titular mide 2rem —«en el li-toral», «en entor-nos portuarios»— y eso se
   lee como una errata, no como tipografia. `break-word` en vez de `anywhere`
   por lo mismo: parte solo la palabra que no cabe ella sola en la linea, que
   es el caso que habia que cubrir, y nunca las que si caben. */
.card__title{font-size:2rem;line-height:1.25;margin:0 0 .4em;
  font-weight:700;letter-spacing:-.01em;overflow-wrap:break-word}
.card__link:hover .card__title{text-decoration:underline;text-underline-offset:.18em}
@media(max-width:720px){
  .card__title{font-size:1.7rem}
}
.card__text{font-size:15px;line-height:1.6;opacity:.8;margin:0;max-width:46ch}

/* Paginador de los listados (ecosistema, proyectos y actualidad). WordPress
   pinta `.page-numbers` sin estilo ninguno, asi que heredaba los enlaces
   subrayados de la zona editorial: las cifras quedaban pegadas entre si y con
   el mismo peso que un enlace de texto corriente.
   Cada numero es una casilla de 42px, que es el area de pulsacion minima comoda
   en movil, y la pagina actual va en azul de marca. Un relleno claro pesaria
   mas que las propias tarjetas que tiene encima. */
.pagination{margin:clamp(40px,6vh,80px) 0 0;padding-top:clamp(22px,3vh,36px);
  border-top:1px solid rgba(245,242,234,.14)}
.pagination .nav-links{display:flex;flex-wrap:wrap;align-items:center;
  justify-content:center;gap:4px}
.pagination .page-numbers{display:inline-flex;align-items:center;
  justify-content:center;min-width:42px;height:42px;padding:0 14px;
  border-radius:4px;font-size:15px;line-height:1;color:var(--stone);
  text-decoration:none;transition:background-color .18s ease,color .18s ease}
.pagination a.page-numbers:hover{background:rgba(245,242,234,.1);
  color:var(--limestone)}
.pagination .page-numbers.current{background:var(--blue);color:#fff;
  font-weight:700}
/* Los dos extremos son palabras, no cifras: se apartan del grupo de numeros
   para que se lean como acciones y no como una pagina mas. */
.pagination .prev{margin-right:10px}
.pagination .next{margin-left:10px}
/* El salto de paginas no es pulsable: ni casilla ni area de 42px. */
.pagination .page-numbers.dots{min-width:0;padding:0 6px;
  color:rgba(245,242,234,.4)}
@media(max-width:520px){
  .pagination .page-numbers{min-width:38px;height:38px;padding:0 10px;
    font-size:14px}
  .pagination .prev{margin-right:4px}
  .pagination .next{margin-left:4px}
}

/* Detalle */
.single-hero{margin:0 0 clamp(30px,5vh,60px)}
.single-hero img{width:100%;height:clamp(240px,45vh,520px);object-fit:cover;display:block}
.single-head{margin:0 0 clamp(24px,4vh,44px)}
.eyebrow{font-family:var(--mono);font-size:11px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--stone);margin:0 0 .8em}
.eyebrow a{color:inherit;text-decoration:none}
.eyebrow a:hover{color:var(--limestone)}
.single-lede{font-size:clamp(17px,2vw,22px);line-height:1.5;max-width:50ch;opacity:.9}
.single-logo{max-width:220px;margin:0 0 24px}
.single-logo img{width:100%;height:auto;display:block}
.single-back{margin-top:clamp(40px,6vh,80px);font-size:14px}
.single-back a{color:var(--stone);text-decoration:none}
.single-back a:hover{color:var(--limestone)}

/* Ficha de datos (bloque del plugin). Rejilla de dos columnas que se apila en
   movil; el termino manda su ancho al valor con subgrid para que todas las
   filas queden alineadas aunque las etiquetas midan distinto. */
.medinnova-ficha{margin:clamp(30px,5vh,60px) 0;
  border-top:1px solid rgba(245,242,234,.16)}
.medinnova-ficha__titulo{font-size:clamp(18px,2vw,24px);margin:1.4em 0 .8em;
  font-weight:700;letter-spacing:-.01em}
.medinnova-ficha__lista{margin:0;display:grid;gap:0}
.medinnova-ficha__fila{display:grid;grid-template-columns:minmax(140px,22%) 1fr;
  gap:8px 24px;padding:16px 0;border-bottom:1px solid rgba(245,242,234,.12)}
.medinnova-ficha__fila dt{font-family:var(--mono);font-size:11px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--stone);margin:2px 0 0}
.medinnova-ficha__fila dd{margin:0;font-size:16px;line-height:1.55}
.medinnova-ficha__fila dd a{color:var(--limestone);text-underline-offset:.18em}
.medinnova-ficha__nota{display:block;font-size:14px;opacity:.7;margin-top:4px}
@media(max-width:640px){
  .medinnova-ficha__fila{grid-template-columns:1fr;gap:4px}
}

/* El editor pinta la ficha sobre fondo claro; sin esto las etiquetas en color
   piedra sobre blanco quedan por debajo del contraste minimo (§24). */
.editor-styles-wrapper .medinnova-ficha__fila dt,
.editor-styles-wrapper .medinnova-ficha__fila dd{color:inherit}
