/*
 * layout.css — Contenedores, grids y estructura de página
 * Depende de base.css
 */

/* Contenedor principal */
.ipg-container {
    width: var(--ipg-container-width);
    margin-inline: auto;
    padding-inline: var(--ipg-container-px);
}

/* Contenedor estrecho para artículos */
.ipg-container--content {
    max-width: var(--ipg-container-content);
    margin-inline: auto;
    padding-inline: var(--ipg-container-px);
}

/* ── Ancho de los bloques del editor dentro de .entry-content ────────────
   Este tema es clásico (page.php, front-page.php, etc.), no un tema de
   bloques FSE. Gutenberg SÍ constriñe automáticamente cada bloque suelto
   en el editor (usa contentSize/wideSize de theme.json), pero esa
   constricción NO se replica sola en el frontend de un tema clásico —
   por eso lo editado no coincidía con lo publicado (bloques que se veían
   angostos en el editor se estiraban al ancho completo al publicar) y
   las opciones de alineación "Ancho" / "Pantalla completa" del bloque no
   hacían nada visual. Estas reglas replican en el frontend lo mismo que
   el editor ya muestra.

   IMPORTANTE: no hay que excluir los bloques con clase "wp-container-*".
   Esa clase la agrega Gutenberg a CUALQUIER Grupo que declare un layout
   interno (por ejemplo, para centrar su propio contenido a 500px) —
   pase o no pase ese mismo Grupo a estar marcado como "Ancho"/"Full".
   Son dos cosas distintas: cómo se acomoda el contenido DENTRO del
   grupo (eso ya lo resuelve Gutenberg con esa clase) vs. qué tan ancho
   es el grupo COMO BLOQUE de la página (eso lo resuelve esta regla). Si
   se excluye por tener "wp-container-*", un grupo sin alineación "Ancho"
   pero con layout interno propio (como el banner de contacto) se queda
   sin ningún tope de ancho y se estira sin control. */
.entry-content > :where(:not(.alignwide):not(.alignfull)) {
    max-width: var(--ipg-container-content);
    margin-left: auto;
    margin-right: auto;
}
.entry-content > .alignwide {
    max-width: var(--ipg-container-max);
    margin-left: auto;
    margin-right: auto;
}
/* "Ancho completo" no llega al cristal: se para en --ipg-marco, el mismo
   marco del banner. Asi todas las secciones a sangre —el hero, los banners
   CTA, las franjas de color— comparten el mismo borde izquierdo y derecho, y
   el lienzo gris se ve como un marco continuo en vez de aparecer solo
   alrededor del banner.

   La cuenta es la de siempre para salirse del contenedor (50% es la mitad
   del contenedor, 50vw la mitad de la pantalla), corrida por el marco. */
.entry-content > .alignfull {
    max-width: none;
    width: calc(100vw - var(--ipg-marco) * 2);
    margin-left: calc(50% - 50vw + var(--ipg-marco));
    margin-right: calc(50% - 50vw + var(--ipg-marco));
}

/* Grids */
.ipg-grid-3 {
    display: grid;
    /* auto-fit + mínimo 360px: cabe un máximo de 3 en el ancho del sitio;
       con menos de 3 se reparten sin dejar hueco vacío. */
    /* min() para que la pista nunca sea mas ancha que su contenedor. Un
       minmax(Npx, 1fr) pelado IMPONE ese minimo: si la pantalla da menos, la
       columna se sale y aparece scroll horizontal. Con min(Npx, 100%) el
       minimo cede cuando no cabe, y se acabo el desbordamiento sin depender
       de acertar un punto de corte. */
    grid-template-columns: repeat(auto-fit, minmax(min(360px, 100%), 1fr));
    gap: var(--ipg-space-6);
}
.ipg-grid-2 {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(380px, 100%), 1fr));
    gap: var(--ipg-space-6);
}

/* ── "Marco" de página ─────────────────────────────────────────────────────
   Solo envuelve <main>: el hero, los accesos destacados y las noticias
   quedan acotados y centrados como tarjetas flotantes sobre el canvas
   gris (--ipg-color-surface, ver body en base.css). Header y footer NO
   viven acá a propósito — son barras a todo el ancho de pantalla (ver
   más abajo), cada una centrando su propio contenido por dentro. */
.site-shell {
    max-width: calc(var(--ipg-container-max) + var(--ipg-shell-gutter) * 2);
    margin-inline: auto;
    padding: var(--ipg-shell-gutter);
    flex: 1;
    display: flex;
    flex-direction: column;

    /* Sin estas dos líneas el marco se ensancha hasta caber su contenido en
       vez de caber en la pantalla, y arrastra consigo TODA la página.

       El mecanismo: <body> es un contenedor flex en columna, así que este
       div es un ítem flex. Un ítem flex no se encoge por debajo del ancho
       mínimo de su contenido mientras su tamaño en ese eje sea automático —
       basta un título largo, una tarjeta ancha o una tabla adentro para que
       el marco se estire y el resto de la página se vaya con él. Medido en
       Acompañamiento Estudiantil a 390px: el marco quedaba de 740px, casi el
       doble de la pantalla, y todo el contenido salía cortado por la derecha.
       Se veía como si el sitio estuviera "corrido", no como un bloque suelto
       desbordándose, justamente porque el que se desbordaba era el marco.

       `width: 100%` lo ata al ancho disponible y `min-width: 0` le levanta
       ese piso automático a él y a sus hijos. En escritorio no cambia nada:
       el 100% lo sigue recortando el max-width de arriba, que es quien manda
       mientras la pantalla sea más ancha que el sitio. */
    width: 100%;
    min-width: 0;
}

/* Cabecera — barra blanca a todo el ancho de pantalla, con DOS franjas
   apiladas: la de utilidad (Alumnos, Docentes, Pago en Línea) siempre
   arriba en su propia línea, separada por un borde, y la principal
   (marca + menú) abajo. Quedan "separadas y unidas al mismo tiempo":
   visualmente son dos filas distintas, pero comparten fondo y sombra
   como una sola barra. Al no competir por espacio en la misma línea, el
   ancho del contenido ya no decide si algo "cae" a una segunda fila — el
   resultado es igual en cualquier página, sin importar cuál ítem del
   menú esté activo. Cada franja centra su contenido con .ipg-container
   (mismo ancho responsive que el resto del sitio) en vez de estirarlo de
   punta a punta, que se vería raro en monitores muy anchos. */
.site-header {
    position: sticky;
    top: 0;
    z-index: var(--ipg-z-sticky);
    background-color: var(--ipg-header-bg);
    color: var(--ipg-header-text);
    box-shadow: var(--ipg-shadow-md);
    transition: box-shadow var(--ipg-transition-fast);
}
/* Se agrega al hacer scroll (ver assets/js/main.js) — un poco más de
   elevación para distinguirla del contenido que pasa debajo. */
.site-header.is-scrolled {
    box-shadow: var(--ipg-shadow-lg);
}
.site-header__utility-row {
    border-bottom: 1px solid var(--ipg-color-border);
}
.site-header__utility-row__inner {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--ipg-space-5);
    padding-block: var(--ipg-space-2);
    /* 13px: un punto más que el xs (12px), que se leía muy chico, pero
       siempre por debajo del menú principal (14px, o 16px desde 1240px)
       para que la franja de utilidad siga siendo secundaria. No hay paso
       de la escala entre 12 y 14, por eso va el valor directo. */
    font-size: 0.8125rem;
}
/* Logo pegado a la izquierda y menú pegado a la derecha: space-between
   reparte el espacio sobrante entre los dos, en vez de dejarlos juntos al
   inicio de la fila. El gap queda como separación mínima para cuando el
   menú crece y ya no sobra espacio. */
.site-header__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--ipg-space-8);
    min-height: var(--ipg-header-height);
}
.utility-menu {
    display: flex;
    list-style: none;
    align-items: center;
    gap: var(--ipg-space-4);
    margin: 0;
    padding: 0;
}
.utility-menu a {
    display: inline-flex;
    align-items: center;
    gap: var(--ipg-space-1);
    color: var(--ipg-color-text-muted);
    text-decoration: none;
}
.utility-menu a:hover { color: var(--ipg-color-text); }
.site-header__cta { white-space: nowrap; }

/* Nombre del sitio (fallback si no hay logo personalizado) */
.site-name {
    font-size: var(--ipg-text-xl);
    font-weight: var(--ipg-weight-bold);
    color: var(--ipg-color-text);
    text-decoration: none;
}
.site-name:hover { color: var(--ipg-color-primary); }

/* Menú principal */
.nav-primary__list {
    display: flex;
    list-style: none;
    align-items: center;
    gap: var(--ipg-space-2);
    margin: 0;
    padding: 0;
}
.nav-primary__list a {
    display: inline-block;
    color: var(--ipg-color-text-muted);
    text-decoration: none;
    font-weight: var(--ipg-weight-medium);
    /* 16px y no 14: al lado del logo (85px de alto, con el nombre de la
       institución en tres líneas) los ítems a 14px se veían chicos. */
    font-size: var(--ipg-text-base);
    padding: var(--ipg-space-2) var(--ipg-space-4);
    border-radius: var(--ipg-radius-full);
    transition: background-color var(--ipg-transition-fast), color var(--ipg-transition-fast);
}
/* A 16px el menú mide ~740px y solo cabe en una línea junto al logo desde
   1240px de pantalla. Por debajo vuelve a 14px, que es lo que tenía antes:
   así el cambio no adelanta el punto donde los ítems se parten en dos
   líneas y el logo se encoge. */
@media (max-width: 1239px) {
    .nav-primary__list a { font-size: var(--ipg-text-sm); }
}
.nav-primary__list a:hover {
    color: var(--ipg-color-text);
    background-color: var(--ipg-color-surface);
}

/* Resaltado tipo "píldora" blanca — se aplica a la página activa (INICIO
   cuando estás en portada) y a cualquier ítem de menú al que le agregues
   la clase "menu-highlight" desde Apariencia → Menús → Opciones de
   pantalla → activar "Clases CSS". Sobre el header ya blanco, la píldora
   activa se distingue por su propia sombra y el texto en negrita, no por
   un color de fondo distinto. */
/* La seccion PADRE tambien se remarca. WordPress ya pone estas clases en el
   item de nivel superior cuando se esta viendo una pagina hija suya —lo hace
   solo, no hay que configurar nada—, pero el tema solo miraba
   .current-menu-item, o sea el item exacto. Como las paginas hijas viven en
   el desplegable y no en la barra, el resultado era que al entrar en
   "Vida Estudiantil > Acompanamiento" no quedaba nada marcado arriba y se
   perdia la referencia de donde se estaba.

   Se cubren las cuatro variantes que usa WordPress: las de menu
   (-ancestor / -parent, para paginas que SI estan en el menu) y las de
   pagina (_ancestor / _parent, que ademas alcanzan a una pagina hija que no
   se haya agregado al menu). */
.nav-primary__list .current-menu-item > a,
.nav-primary__list .current-menu-ancestor > a,
.nav-primary__list .current-menu-parent > a,
.nav-primary__list .current_page_ancestor > a,
.nav-primary__list .current_page_parent > a,
.nav-primary__list li.menu-highlight > a {
    background-color: var(--ipg-color-background);
    color: var(--ipg-color-text);
    font-weight: var(--ipg-weight-bold);
    box-shadow: var(--ipg-shadow-sm);
}
.nav-primary__list li.menu-highlight > a:hover { background-color: var(--ipg-color-background); }
.utility-menu li.menu-highlight > a {
    color: var(--ipg-color-primary);
    font-weight: var(--ipg-weight-semibold);
}

/* Píldoras de color para destacar un ítem por sobre el resto del menú —
   pensadas para las acciones que queremos que el estudiante encuentre
   primero (Admisión, por ejemplo).

   Se aplican igual que "menu-highlight": Apariencia → Menús → Opciones de
   pantalla → activar "Clases CSS", y escribir la clase en el ítem:
     menu-highlight-primary  → píldora azul institucional
     menu-highlight-accent   → píldora naranja

   Usar solo una por menú: si todo está destacado, nada lo está. */
.nav-primary__list li.menu-highlight-primary > a,
.utility-menu li.menu-highlight-primary > a {
    background-color: var(--ipg-color-primary);
    color: var(--ipg-color-text-inverted);
    font-weight: var(--ipg-weight-bold);
}
.nav-primary__list li.menu-highlight-primary > a:hover,
.utility-menu li.menu-highlight-primary > a:hover {
    background-color: var(--ipg-color-primary-dark);
    color: var(--ipg-color-text-inverted);
}
.nav-primary__list li.menu-highlight-accent > a,
.utility-menu li.menu-highlight-accent > a {
    background-color: var(--ipg-color-accent);
    /* Marino, no blanco: ver la nota en base.css sobre .btn--accent. */
    color: var(--ipg-color-primary);
    font-weight: var(--ipg-weight-bold);
}
.nav-primary__list li.menu-highlight-accent > a:hover,
.utility-menu li.menu-highlight-accent > a:hover {
    background-color: var(--ipg-color-accent-dark);
    color: var(--ipg-color-text-inverted);
}
/* El menú de utilidad no tiene padding propio en sus enlaces, así que sin
   esto la píldora quedaría pegada al texto. */
.utility-menu li.menu-highlight-primary > a,
.utility-menu li.menu-highlight-accent > a {
    padding: var(--ipg-space-1) var(--ipg-space-3);
    border-radius: var(--ipg-radius-full);
}

/* Submenú desplegable (ej. "Instituto") — accesible por hover y por teclado
   vía :focus-within, sin necesidad de JS ni de un walker personalizado. */
.nav-primary__list .sub-menu {
    list-style: none;
    margin: 0;
    padding: var(--ipg-space-2) 0;
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 220px;
    background-color: var(--ipg-color-background);
    border: 1px solid var(--ipg-color-border);
    box-shadow: var(--ipg-shadow-md);
    border-radius: var(--ipg-radius);
    z-index: var(--ipg-z-dropdown);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-4px);
    transition: opacity var(--ipg-transition-fast), transform var(--ipg-transition-fast), visibility var(--ipg-transition-fast);
}
.nav-primary__list .menu-item-has-children {
    position: relative;
}
.nav-primary__list .menu-item-has-children:hover > .sub-menu,
.nav-primary__list .menu-item-has-children:focus-within > .sub-menu {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}
.nav-primary__list .menu-item-has-children > a::after {
    content: '';
    display: inline-block;
    width: 6px;
    height: 6px;
    margin-left: var(--ipg-space-2);
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(45deg) translateY(-2px);
}
.nav-primary__list .sub-menu a {
    display: block;
    padding: var(--ipg-space-2) var(--ipg-space-4);
    border-radius: 0;
    white-space: nowrap;
}
.nav-primary__list .sub-menu a:hover { background-color: var(--ipg-color-surface); color: var(--ipg-color-text); }

/* Y dentro del desplegable, la pagina exacta en la que se esta. Va aqui y no
   arriba porque la regla de .sub-menu a pesa lo mismo y aparece despues, asi
   que ganaba y dejaba el item actual sin marcar.

   La marca es distinta a la de la barra —negrita y celeste, sin pildora— a
   proposito: una pildora dentro de un desplegable se lee como un boton, y
   ademas conviene que el item exacto y su seccion padre no se marquen igual. */
.nav-primary__list .sub-menu .current-menu-item > a,
.nav-primary__list .sub-menu .current_page_item > a {
    color: var(--ipg-color-primary);
    font-weight: var(--ipg-weight-bold);
    box-shadow: inset 3px 0 0 var(--ipg-color-accent);
}

/* Submenú de la barra de utilidad (ej. "Alumnos" → Plataforma Virtual,
   Portal alumnos en línea).

   Mismo lenguaje visual que el desplegable del menú principal, con dos
   diferencias que vienen de dónde vive: se alinea a la DERECHA (la franja
   de utilidad está pegada al borde derecho; abriendo hacia la izquierda se
   saldría de pantalla) y hereda el tamaño chico de la franja.

   Se abre de tres maneras, y las tres tienen que estar: hover (mouse),
   :focus-within (teclado) y la clase .is-open que pone el botón de flecha
   desde main.js (táctil — en un teléfono no hay hover, y el enlace padre
   navega en vez de abrir). */
.utility-menu .menu-item-has-children {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--ipg-space-1);
}
.utility-menu .sub-menu {
    list-style: none;
    margin: 0;
    padding: var(--ipg-space-2) 0;
    position: absolute;
    top: 100%;
    right: 0;
    left: auto;
    min-width: 200px;
    background-color: var(--ipg-color-background);
    border: 1px solid var(--ipg-color-border);
    box-shadow: var(--ipg-shadow-md);
    border-radius: var(--ipg-radius);
    z-index: var(--ipg-z-dropdown);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-4px);
    transition: opacity var(--ipg-transition-fast), transform var(--ipg-transition-fast), visibility var(--ipg-transition-fast);
}
.utility-menu .menu-item-has-children:hover > .sub-menu,
.utility-menu .menu-item-has-children:focus-within > .sub-menu,
.utility-menu .menu-item-has-children.is-open > .sub-menu {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}
.utility-menu .sub-menu a {
    display: block;
    padding: var(--ipg-space-2) var(--ipg-space-4);
    white-space: nowrap;
}
.utility-menu .sub-menu a:hover {
    background-color: var(--ipg-color-surface);
    color: var(--ipg-color-text);
}
.utility-menu .sub-menu .current-menu-item > a,
.utility-menu .sub-menu .current_page_item > a {
    color: var(--ipg-color-primary);
    font-weight: var(--ipg-weight-bold);
    box-shadow: inset 3px 0 0 var(--ipg-color-accent);
}

/* Flecha del desplegable. Es un <button> de verdad (lo inserta main.js), no
   un ::after decorativo como en el menú principal: acá el ítem padre suele
   ser un enlace con destino propio, así que hace falta un control aparte
   para abrir sin perder el enlace — y un botón es lo único que funciona
   igual con dedo, mouse y teclado. */
.utility-menu__toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Área táctil mínima cómoda sin agrandar la franja: el padding negativo
       vertical la extiende por fuera de la caja. */
    padding: var(--ipg-space-2) var(--ipg-space-1);
    margin-block: calc(var(--ipg-space-2) * -1);
    background: none;
    border: none;
    cursor: pointer;
    color: var(--ipg-color-text-muted);
    line-height: 0;
}
.utility-menu__toggle:hover { color: var(--ipg-color-text); }
.utility-menu__toggle::before {
    content: '';
    display: block;
    width: 6px;
    height: 6px;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(45deg) translate(-2px, -2px);
    transition: transform var(--ipg-transition-fast);
}
.utility-menu .menu-item-has-children.is-open > .utility-menu__toggle::before {
    transform: rotate(-135deg) translate(-2px, -2px);
}
/* Sin JS la flecha no existe, así que el ítem padre queda sin ninguna señal
   de que esconde algo. Este ::after la repone y desaparece en cuanto main.js
   marca el menú como mejorado. */
.utility-menu .menu-item-has-children:not(.has-toggle) > a::after {
    content: '';
    display: inline-block;
    width: 5px;
    height: 5px;
    margin-left: var(--ipg-space-1);
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(45deg) translateY(-2px);
}

/* Botón hamburguesa — solo visible en móvil */
.nav-toggle {
    display: none;
    background: none;
    border: none;
    cursor: pointer;
    padding: var(--ipg-space-2);
    color: var(--ipg-color-text);
}
.hamburger-icon,
.hamburger-icon::before,
.hamburger-icon::after {
    display: block;
    width: 24px;
    height: 2px;
    background-color: currentColor;
    transition: transform var(--ipg-transition-fast);
}
.hamburger-icon { position: relative; }
.hamburger-icon::before,
.hamburger-icon::after {
    content: '';
    position: absolute;
    left: 0;
}
.hamburger-icon::before { top: -7px; }
.hamburger-icon::after  { top:  7px; }

/* Main — en Inicio, cada sección hija (hero, accesos+cifras, noticias) es
   su propio bloque flotante sobre el canvas gris; el gap entre ellas se
   resuelve acá en vez de con paddings sueltos en cada una. */
.site-main {
    min-height: 60vh;
    padding-top: var(--ipg-space-6);
    padding-bottom: var(--ipg-space-12);
    display: flex;
    flex-direction: column;
    gap: var(--ipg-space-6);
    /* Mismo motivo que en .site-shell: es un ítem flex y además contenedor
       flex, o sea que el piso automático de ancho se hereda hacia abajo por
       toda la cadena. Cortarlo una vez acá evita tener que repetirlo en cada
       componente que viva dentro de <main>. */
    min-width: 0;
}
/* En Inicio el hero ya trae su propio aire arriba (.hero-carousel);
   se quita este padding-top para que no se sumen los dos espacios. */
body.home .site-main { padding-top: 0; padding-bottom: 0; }

/* Lo mismo en las páginas interiores, arriba y abajo: la primera y la última
   sección tienen que quedar pegadas al menú y al footer. Sin esto quedaban
   dos franjas de canvas gris —44px arriba, 68px abajo— que se leían como un
   error de alineación, porque casi todas esas secciones traen fondo propio
   (degradado o color) y el gris de al lado las delata.

   En los dos casos son espacios sumados y hay que anular cada uno por su
   lado: el padding de .site-main (24px arriba, 48px abajo), que se quita, y
   el aire del marco .site-shell (20px), que no es de <main> sino de su
   envoltorio — por eso se compensa con un margen negativo en el bloque de
   la punta, exactamente el mismo recurso que usa .hero-carousel en Inicio.

   Se aplica al primer y último bloque sin mirar cuáles son, y es seguro:
   toda página abre con un hero (page.php lo documenta como requisito, sin
   él la página se queda sin H1) y todas cierran con un grupo de primer
   nivel, que el CSS del Personalizador ya deja con 60px de padding propio.
   Es decir, pegar el bloque al borde no deja texto contra el footer. */
.site-main.page-content { padding-top: 0; padding-bottom: 0; }
.page-content .entry-content > :first-child {
    margin-top: calc(var(--ipg-shell-gutter) * -1);
}
.page-content .entry-content > :last-child {
    margin-bottom: calc(var(--ipg-shell-gutter) * -1);
}

/* Secciones */
.ipg-section { padding-block: var(--ipg-space-16); }
.ipg-section--surface { background-color: var(--ipg-color-surface); }
.section-title {
    font-size: var(--ipg-text-3xl);
    margin-bottom: var(--ipg-space-8);
}

/* Footer — barra oscura a todo el ancho de pantalla, igual que el header;
   su contenido queda centrado adentro vía .ipg-container (ver
   footer-widgets__inner / footer-bottom__inner más abajo). */
.site-footer {
    background-color: var(--ipg-color-primary-dark);
    color: var(--ipg-color-text-inverted);
}
.footer-widgets { padding-block: var(--ipg-space-12); }
/* La marca manda más ancho que las columnas de texto: con tres columnas
   iguales (el repeat(auto-fit, minmax(200px, 1fr)) de antes) el logo con su
   sello de acreditación quedaba apretado y las listas, sueltas a lo ancho.
   align-items: start alinea las tres por arriba; sin eso cada columna se
   centraba a su propio alto y los títulos no coincidían entre sí. */
.footer-widgets__inner {
    display: grid;
    /* La primera columna va mas ancha porque suele llevar el logo y la
       direccion; las otras tres son listas de enlaces y se reparten igual.
       minmax(0, …) y no fr a secas: un fr no baja del ancho de su palabra
       más larga, y el correo de contacto empujaba el footer ~60px fuera de
       pantalla entre 770 y 880px. */
    grid-template-columns: minmax(0, 1.6fr) repeat(3, minmax(0, 1fr));
    gap: var(--ipg-space-10);
    align-items: start;
}

/* Los ítems de una columna van uno bajo otro y pegados: cada uno es su
   propio widget, así que sin esto el espaciado entre "Admisión 2026" y
   "Malla Curricular" depende de los márgenes que traiga cada bloque y sale
   irregular. Acá se ponen a cero y la separación la da un único gap. */
.footer-widget-area {
    display: flex;
    flex-direction: column;
    gap: var(--ipg-space-2);
}
.footer-widget { margin: 0; }
.footer-widget p { margin: 0; }
.footer-widget-area p,
.footer-widget-area li {
    font-size: var(--ipg-text-sm);
    line-height: var(--ipg-leading-normal);
    color: rgba(255,255,255,0.75);
}
.footer-widget-area a {
    overflow-wrap: anywhere; /* Correos largos: parten antes que desbordar. */
    color: rgba(255,255,255,0.75);
    text-decoration: none;
    transition: color var(--ipg-transition-fast);
}
.footer-widget-area a:hover { color: #fff; }
/* La imagen de marca no hereda el ancho de columna completo: se le deja un
   tope para que el sello no se estire más que en la maqueta. */
.footer-widget-area figure { margin: 0; }
.footer-widget-area img { max-width: 320px; height: auto; }
/* Entre tablet y escritorio las cuatro columnas no caben: la marca sube a
   lo ancho y las tres listas quedan debajo, con aire para el correo.
   Bajo 768px manda la regla de dos columnas del bloque responsive. */
@media (min-width: 769px) and (max-width: 1023px) {
    .footer-widgets__inner { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .footer-widget-area:first-child { grid-column: 1 / -1; }
}
.footer-bottom {
    border-top: 1px solid rgba(255,255,255,0.15);
    padding-block: var(--ipg-space-4);
    font-size: var(--ipg-text-sm);
}
.footer-bottom__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--ipg-space-4);
}
.footer-menu {
    display: flex;
    list-style: none;
    gap: var(--ipg-space-4);
    margin: 0;
    padding: 0;
}
.footer-menu a {
    color: rgba(255,255,255,0.75);
    font-size: var(--ipg-text-sm);
    text-decoration: none;
}
.footer-menu a:hover { color: #fff; }
/* Rótulo de columna ("Enlaces rápidos", "Contacto", "Síguenos").
   Es un <h3>, así que sin esto hereda los 24px en negrita de base.css y
   compite con el contenido en vez de encabezarlo — era el motivo de que
   "Síguenos" se viera desproporcionado frente al resto del pie. Chico, en
   mayúsculas y con la letra espaciada: pesa como título sin gritar. */
.footer-widget__title {
    color: var(--ipg-color-text-inverted);
    font-size: var(--ipg-text-xs);
    font-weight: var(--ipg-weight-bold);
    text-transform: uppercase;
    letter-spacing: var(--ipg-tracking-wider);
    margin: 0 0 var(--ipg-space-1);
}
/* Un respiro extra solo antes de los iconos sociales, que cierran la
   columna después del bloque de contacto. */
.footer-social__title { margin-top: var(--ipg-space-4); }
.footer-social {
    display: flex;
    list-style: none;
    gap: var(--ipg-space-3);
    margin: 0;
    padding: 0;
}
.footer-social a {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: var(--ipg-radius-full);
    background-color: rgba(255,255,255,0.1);
    color: rgba(255,255,255,0.85);
    transition: background-color var(--ipg-transition-fast), color var(--ipg-transition-fast);
}
.footer-social a:hover {
    background-color: var(--ipg-color-accent);
    /* El icono social al pasar el cursor: sobre celeste, marino. */
    color: var(--ipg-color-primary);
}
.screen-reader-text {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Responsive */
/* Hamburguesa hasta 1199px, no solo en móvil.

   Entre 769 y ~1160px el menú horizontal no cabe junto al logo: tres
   ítems se partían en dos líneas y el logo se encogía (a 800px quedaba de
   148px de ancho). Desde 1200px el menú cabe completo a 14px, y desde
   1240px a 16px (ver .nav-primary__list a). Si se agregan ítems al menú y
   vuelven a partirse, este es el número que hay que subir.

   La franja de utilidad (Pago en Línea, Estudiantes, Docentes) no cambia:
   sigue con su ajuste propio en el bloque de 768px de más abajo. */
@media (max-width: 1199px) {
    .nav-toggle { display: block; }

    .nav-primary__list {
        display: none;
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        margin-top: var(--ipg-space-2);
        flex-direction: column;
        align-items: stretch;
        background-color: var(--ipg-color-background);
        border: 1px solid var(--ipg-color-border);
        border-radius: var(--ipg-radius);
        box-shadow: var(--ipg-shadow-md);
        padding: var(--ipg-space-2);
        gap: 0;

        /* El menú se desplaza por dentro en vez de crecer fuera de pantalla.

           Cuelga del header, que es sticky: si crece más que la pantalla, la
           parte de abajo queda debajo del borde inferior y hacer scroll en la
           página no la trae — la página se mueve, el header (y el menú que le
           cuelga) no. Con muchos ítems y submenús abiertos, los últimos eran
           literalmente inalcanzables.

           El tope se calcula desde el alto real del header, que lo mide y
           publica assets/js/main.js en --ipg-header-h. El respaldo de 9rem es
           para el instante antes de que corra el JS.

           100dvh y no 100vh: en móvil la barra de direcciones aparece y
           desaparece, y vh se queda con la pantalla "larga" — el menú quedaría
           unos 60px más alto que el espacio realmente visible. dvh sigue el
           alto disponible en cada momento. Se deja vh antes como respaldo
           para navegadores sin dvh. */
        max-height: calc(100vh  - var(--ipg-header-h, 9rem) - var(--ipg-space-6));
        max-height: calc(100dvh - var(--ipg-header-h, 9rem) - var(--ipg-space-6));
        overflow-y: auto;
        /* Al llegar al final del menú, el gesto no se "contagia" a la página
           de atrás: se detiene en el menú, que es lo que la persona cree que
           está desplazando. */
        overscroll-behavior: contain;
        -webkit-overflow-scrolling: touch;
    }
    .nav-primary__list.is-open { display: flex; }

    /* La llamada a la acción abre el menú, no lo cierra.

       "Admisión" está al final del menú en Apariencia → Menús, y en desktop
       ese es su lugar: es el último ítem de la barra, destacado como botón,
       donde se espera encontrar una CTA. Pero al apilarse en móvil "el
       último" pasa a significar "hay que desplazarse hasta abajo para
       verlo" — justo lo contrario de lo que se quiere con el acceso a
       admisión.

       Se resuelve con `order` y no cambiando el menú en el admin, para no
       arrastrar el cambio al desktop, donde el orden actual es el correcto.
       Se apunta a la clase de resaltado y no a "Admisión" por su nombre: si
       mañana la CTA es otra, sigue funcionando sin tocar esto. */
    .nav-primary__list > li.menu-highlight-primary,
    .nav-primary__list > li.menu-highlight-accent {
        order: -1;
    }
    .nav-primary__list a {
        border-radius: var(--ipg-radius-sm);
        padding: var(--ipg-space-3) var(--ipg-space-4);
    }

    /* En móvil el submenú va siempre visible y apilado dentro del menú
       abierto (no depende de hover, que no existe en pantallas táctiles). */
    .nav-primary__list .sub-menu {
        position: static;
        opacity: 1;
        visibility: visible;
        transform: none;
        box-shadow: none;
        border: none;
        background-color: var(--ipg-color-surface);
        padding-left: var(--ipg-space-4);
    }

    /* Entre tablet y escritorio el panel no se estira de borde a borde: a
       1100px una lista apilada de pantalla completa se ve vacía. Se alinea
       bajo la hamburguesa, al borde derecho de .ipg-container (92% de
       ancho centrado → 4% de margen + su padding). */
    @media (min-width: 769px) {
        .nav-primary__list {
            left: auto;
            right: calc(4% + var(--ipg-container-px));
            width: 22rem;
        }
    }
}

@media (max-width: 768px) {
    .site-header__utility-row__inner { padding-block: var(--ipg-space-2); }
    .site-header__inner { gap: var(--ipg-space-4); }

    /* Accesos rápidos (Alumnos, Docentes) + botón: ya tienen su propia
       franja fija arriba (.site-header__utility-row); acá solo se
       envuelven si tampoco caben todos en una línea a este ancho. */
    .site-header__utility-row__inner {
        gap: var(--ipg-space-3);
        flex-wrap: wrap;
    }
    .utility-menu { flex-wrap: wrap; gap: var(--ipg-space-3); }

    /* El desplegable de utilidad NO se vuelve estático/apilado como el del
       menú principal: acá la franja está siempre visible (no vive dentro de
       la hamburguesa), así que apilar los hijos empujaría el logo hacia
       abajo en cada carga. Sigue siendo un panel flotante, pero acá se
       ancla al HEADER en vez de al ítem que lo abre.

       El motivo: en pantalla angosta la fila de utilidad se envuelve y el
       ítem padre puede quedar en cualquier parte. Colgando el panel del
       ítem, se sale de pantalla apenas el padre queda cerca de un borde
       (medido: a 376px de ancho se cortaba 30px por la izquierda). Se
       quita el position: relative del padre para que el absolute suba
       hasta .site-header —que es sticky, o sea bloque contenedor— y ahí
       se fija de borde a borde. Así el ancho lo decide la pantalla y no
       la posición donde cayó el ítem. */
    .utility-menu .menu-item-has-children {
        position: static;
    }
    .utility-menu .sub-menu {
        left: var(--ipg-space-4);
        right: var(--ipg-space-4);
        min-width: 0;
    }
}
/* ── Hero — carrusel ──────────────────────────────────────────────────────
   Estructura: .hero-carousel > .hero-carousel__viewport > .hero-carousel__track
   > .hero-slide (uno visible a la vez, sin JS = fallback al primer slide).
   El comportamiento de avanzar/retroceder vive en assets/js/main.js.

   Es una tarjeta blanca más (mismo lenguaje visual que el header y el
   footer), no una sección a todo lo ancho — por eso .hero-slide ya no
   necesita su propio max-width/padding-inline: el "container" ahora es
   el padding de la tarjeta. */
/* El hero se pega al header y ocupa el ancho completo de la pantalla.
   Vive dentro de .site-main (que a su vez vive en el marco .site-shell,
   con 20px de aire alrededor), así que tiene que "escaparse" de ese marco:
   100vw de ancho, márgenes laterales negativos para volver al borde de la
   pantalla, y un margen superior negativo que anula el aire del marco para
   que no quede franja gris entre el menú y el banner.
   Ya no es una tarjeta: sin borde redondeado ni sombra, para que se lea
   como continuación de la barra blanca del header. */
.hero-carousel {
    position: relative;
    background-color: var(--ipg-color-background);
    overflow: hidden;
    width: 100vw;
    max-width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    margin-top: calc(var(--ipg-shell-gutter) * -1);
}
.hero-carousel__viewport {
    overflow: hidden;
}
/* Todos los slides ocupan la MISMA celda de grid, uno encima de otro. Es lo
   que permite el fundido: para cruzar de una imagen a la siguiente las dos
   tienen que coexistir en pantalla un instante. Antes iban en flujo normal
   y solo se veía una porque las demás estaban en display:none, que es un
   corte seco e intransicionable.
   La celda toma el alto del slide más alto, así que el carrusel sigue sin
   "saltar" al avanzar. */
.hero-carousel__track {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-areas: "slide";
}
/* Mismo alto para todos los slides: el carrusel no "salta" al avanzar. */
.hero-slide {
    grid-area: slide;
    position: relative;
    min-height: var(--ipg-hero-height);
    display: grid;
    grid-template-columns: 1fr;
    align-items: center;
    gap: var(--ipg-space-10);
}

/* Sin JavaScript el atributo hidden del marcado sigue mandando y se ve solo
   el primer slide, como antes. Esta regla es ese respaldo. */
.hero-slide[hidden] { display: none; }

/* ── Fundido entre slides ─────────────────────────────────────────────────
   Solo se activa cuando el JS tomó el control (.hero-carousel--js, que el
   propio JS agrega al iniciar). Si el JS no corre, nada de esto aplica y
   manda el [hidden] de arriba.

   visibility, no solo opacity: un slide en opacity:0 sigue recibiendo clics
   y sigue en el orden de tabulación, así que los botones de los slides
   ocultos serían alcanzables con Tab. visibility:hidden los saca de ambos.
   Va sin duración pero con retardo igual al fundido, para que el slide no
   desaparezca de golpe apenas empieza a desvanecerse.

   El cruce es simultáneo (entra uno mientras sale el otro) a propósito: es
   el comportamiento que se auto-corrige si alguien pulsa las flechas varias
   veces seguidas, sin temporizadores en JS que sincronizar. */
.hero-carousel--js .hero-slide {
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--ipg-hero-fade) ease-in-out,
                visibility 0s linear var(--ipg-hero-fade);
}
.hero-carousel--js .hero-slide.is-active {
    opacity: 1;
    visibility: visible;
    z-index: 1;
    transition: opacity var(--ipg-hero-fade) ease-in-out,
                visibility 0s linear 0s;
}

/* Slide con texto: el fondo llega de borde a borde, pero el contenido se
   centra al mismo ancho que el menú (.ipg-container) — de ahí la coherencia
   entre header y banner. */
.hero-slide--text {
    width: var(--ipg-container-width);
    margin-inline: auto;
    grid-template-columns: 1fr 1fr;
    padding-block: var(--ipg-space-10);
}
/* Dentro del slide con texto la imagen se estira al alto del hero, sin
   imponer un mínimo propio que lo agrandaría. */
.hero-slide--text .hero-slide__media {
    min-height: 0;
}

/* Slide "solo imagen": ocupa exactamente la MISMA caja que el slide con
   texto —mismo ancho de contenedor, mismo aire arriba y abajo— y la foto
   lleva las mismas esquinas redondeadas y la misma sombra que cualquier
   otra imagen del hero. La única diferencia es que acá la foto ocupa el
   ancho entero en vez de una de las dos columnas.

   Antes iba de borde a borde, sin radio ni sombra. Eso era además el motivo
   de todo el trato especial de .hero-carousel--image-slide: controles
   superpuestos sobre la foto con una franja oscura, para que se leyeran
   encima de la imagen. Al unificar la caja ese trato dejó de tener sentido
   y se eliminó — los controles son ahora los mismos en los dos tipos de
   slide.

   El alto lo pone la propia imagen, no --ipg-hero-height. Estos slides son
   banners con el texto y el botón dibujados dentro, y meterlos en una caja
   de alto fijo con object-fit: cover los agrandaba y les cortaba los
   bordes (en el teléfono, casi todo). Ahora se ven enteros, con su
   proporción. El costo: si el carrusel mezcla un banner con un slide de
   texto, la celda compartida toma el alto del más alto. Con banners de la
   misma medida no se nota. */
.hero-slide--image-only {
    width: var(--ipg-container-width);
    margin-inline: auto;
    padding-block: var(--ipg-space-10);
    gap: 0;
    min-height: 0;
}
.hero-slide--image-only .hero-slide__media {
    min-height: 0;
    align-self: start;
}
.hero-slide--image-only .hero-slide__media img {
    position: static;
    display: block;
    height: auto;
}
/* Banner con enlace: todo el banner es clicable. Al pasar el mouse se
   aclara apenas, para que se note que se puede hacer clic. El foco del
   teclado va por dentro del borde, porque .hero-slide__media recorta
   (overflow: hidden) cualquier contorno dibujado por fuera. */
.hero-slide__link {
    display: block;
    transition: filter var(--ipg-transition);
}
.hero-slide__link:hover { filter: brightness(1.05); }
.hero-slide__link:focus-visible {
    outline: 3px solid var(--ipg-color-primary);
    outline-offset: -3px;
}

.hero-slide__content { max-width: 520px; }
.hero-slide__eyebrow {
    display: inline-flex;
    align-items: center;
    gap: var(--ipg-space-2);
    background-color: var(--ipg-color-info-bg);
    color: var(--ipg-color-primary);
    font-size: var(--ipg-text-xs);
    font-weight: var(--ipg-weight-semibold);
    letter-spacing: var(--ipg-tracking-wide);
    text-transform: uppercase;
    padding: var(--ipg-space-1) var(--ipg-space-3);
    border-radius: var(--ipg-radius-full);
    margin-bottom: var(--ipg-space-4);
}
.hero-slide__eyebrow::before {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background-color: currentColor;
    flex-shrink: 0;
}
.hero-slide__title {
    font-size: clamp(1.75rem, 4.5vw, 3rem);
    font-weight: var(--ipg-weight-bold);
    line-height: var(--ipg-leading-tight);
    margin-bottom: var(--ipg-space-4);
    display: flex;
    flex-direction: column;
}
.hero-slide__title-line { color: var(--ipg-color-text); }
/* La palabra destacada va en celeste, no en --ipg-color-primary. Con el
   marino como color institucional, primary (#0E1E4D) quedó a un paso del
   color de texto (#111729) —1.11:1— y el "destacado" no destacaba nada.
   El celeste sí se despega (7.66:1 del texto).
   Ojo al maquetar: sobre fondo blanco el celeste da 2.33:1, por debajo del
   mínimo WCAG. Acá se acepta porque es una palabra suelta dentro de un
   titular grande, con el resto de la frase en el color de texto normal: lo
   que se lee no depende de ella. No replicar el recurso en texto corrido. */
.hero-slide__title-highlight { color: var(--ipg-color-primary-light); }
.hero-slide__description {
    font-size: var(--ipg-text-lg);
    line-height: var(--ipg-leading-normal);
    color: var(--ipg-color-text-muted);
    margin-bottom: var(--ipg-space-8);
}
.hero-slide__actions { display: flex; gap: var(--ipg-space-4); flex-wrap: wrap; }

.hero-slide__media {
    position: relative;
    /* min-height (no height fija): la caja de la imagen se estira para
       igualar el alto de la columna de texto cuando esta es más alta
       (align-self: stretch), en vez de quedar centrada con espacio vacío
       arriba/abajo — el contenedor "depende de su contenido". El
       min-height es el piso: nunca queda más bajo que esto. */
    align-self: stretch;
    min-height: 480px;
    overflow: hidden;
    border-radius: var(--ipg-radius-lg);
    box-shadow: var(--ipg-shadow-md);
}
.hero-slide__media img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Sello institucional flotante sobre la imagen del primer slide */
.hero-badge {
    position: absolute;
    left: var(--ipg-space-6);
    bottom: var(--ipg-space-6);
    display: flex;
    align-items: center;
    gap: var(--ipg-space-3);
    background-color: var(--ipg-color-background);
    border-radius: var(--ipg-radius);
    box-shadow: var(--ipg-shadow-md);
    padding: var(--ipg-space-3) var(--ipg-space-4);
}
.hero-badge__icon { font-size: var(--ipg-text-xl); }
.hero-badge__text { display: flex; flex-direction: column; font-size: var(--ipg-text-xs); }
.hero-badge__label { color: var(--ipg-color-text-subtle); }
.hero-badge__value { font-weight: var(--ipg-weight-semibold); color: var(--ipg-color-text); }

/* Controles del carrusel — siempre superpuestos abajo al centro, en los dos
   tipos de slide. Antes iban debajo del slide con texto y superpuestos solo
   en el de imagen; al unificar el alto conviene también unificar su
   posición, si no los puntos se mueven de lugar al cambiar de slide. */
.hero-carousel__controls {
    position: absolute;
    inset-inline: 0;
    bottom: var(--ipg-space-5);
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--ipg-space-6);
}
.hero-carousel__arrow {
    /* Oculta las flechas de anterior/siguiente. Solo quedan los puntos.
       El carrusel sigue funcionando igual: las flechas del teclado, el
       autoplay y la pausa al pasar el mouse o el foco (assets/js/main.js)
       no dependen de que estos botones se vean.
       El botón de pausa ya no existe: se retiró del marcado. */
    display: none;
    background: none;
    border: 1px solid var(--ipg-color-border);
    border-radius: 50%;
    width: 36px;
    height: 36px;
    font-size: var(--ipg-text-xl);
    line-height: 1;
    cursor: pointer;
    color: var(--ipg-color-text);
    transition: background-color var(--ipg-transition-fast);
}
.hero-carousel__arrow:hover { background-color: var(--ipg-color-surface-2); }
.hero-carousel__dots { display: flex; gap: var(--ipg-space-2); }
.hero-carousel__dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    border: none;
    background-color: var(--ipg-color-border);
    cursor: pointer;
    padding: 0;
}
.hero-carousel__dot[aria-selected="true"] { background-color: var(--ipg-color-primary); }

/* Acá vivía el trato especial de .hero-carousel--image-slide: quitaba el
   padding del carrusel, pegaba los controles al borde inferior de la foto
   con una franja oscura degradada y subía el sello institucional para que
   no se taparan entre sí. Todo eso existía porque el slide "solo imagen"
   iba de borde a borde. Ahora ocupa la misma caja que el slide con texto
   (ver .hero-slide--image-only más arriba), así que los controles no tienen
   por qué comportarse distinto según el slide visible. La clase quedó sin
   uso y se retiró también de front-page.php y de assets/js/main.js.

   De paso: dos de esas reglas ya no hacían nada. `.hero-carousel--image-slide
   { padding: 0 }` apuntaba a un padding que .hero-carousel solo tiene dentro
   de las media queries, y `.hero-slide--image-only { margin: 0 }` a un margen
   que .hero-slide nunca declaró. */

/* ── Hero de portada: un peldaño más grande que en el resto del sitio ─────
   Todo va colgado de body.home a propósito. Hoy .hero-carousel solo existe
   en front-page.php, así que el efecto sería el mismo sin el prefijo — pero
   el hero está pensado para poder reutilizarse como patrón en otras páginas,
   y sin esta marca este agrandado se les pegaría también. El cambio es "solo
   en Inicio" por decisión, no por accidente de dónde vive el markup hoy.

   Tres cosas, todas relativas a los valores normales del tema (no números
   sueltos): la caja del hero se ensancha, la foto se queda con algo más de
   la mitad de esa caja, y la tipografía sube un escalón. */
body.home {
    /* 68vh → 72vh, con los topes movidos en la misma proporción. */
    --ipg-hero-height: clamp(540px, 72vh, 740px);
}
/* 92% / 1440px es el ancho del resto del sitio (--ipg-container-width). Acá
   el hero se sale de esa reja: 2% de aire por lado en vez de 4%. El tope de
   1800px es el que manda recién en monitores muy anchos. */
body.home .hero-slide--text,
body.home .hero-slide--image-only {
    width: min(96%, 1800px);
}
/* Slide con texto: las dos columnas eran 1fr 1fr. La foto pasa a llevarse
   ~53% de la caja en vez del 50% exacto. Es poco a propósito: más que esto
   y la columna de texto empieza a partir el titular en renglones cortos. */
body.home .hero-slide--text {
    grid-template-columns: 1fr 1.15fr;
}
/* Sin tope de ancho: el texto llena su columna en vez de cortarse a 520px y
   dejar aire muerto a la derecha. El largo de renglón lo termina fijando la
   columna, que es poco más de la mitad de la caja —a 1512px de monitor da
   ~680px, todavía en rango cómodo de lectura. */
body.home .hero-slide__content { max-width: none; }
body.home .hero-slide__title { font-size: clamp(2rem, 5vw, 3.5rem); }
body.home .hero-slide__description { font-size: var(--ipg-text-xl); }

/* ── Accesos destacados + cifras ──────────────────────────────────────────── */
/* Grid "bento" de 21 columnas — el mínimo común múltiplo de las dos
   proporciones que aparecen en la maqueta (2:1 arriba, 2:5 abajo), así
   una sola grilla puede darle a cada fila su propia proporción exacta sin
   necesitar dos grids independientes:
     fila 1 → Carreras 14/21 (66,7%)  + Campus Virtual 7/21  (33,3%)
     fila 2 → Financiamiento 6/21 (28,6%) + Caja de cifras 15/21 (71,4%)
   Asume el contenido actual (3 tarjetas de acceso + caja de cifras, ver
   front-page.php). Si en el futuro se cargan más de 3 tarjetas desde ACF,
   las adicionales caen a ancho completo en su propia fila en vez de
   romper el acomodo — se degrada, no se rompe. */
.home-highlights__grid {
    display: grid;
    grid-template-columns: repeat(21, 1fr);
    gap: var(--ipg-space-6);
}
/* Se cuenta con :nth-child y NO con :nth-of-type. La diferencia importa acá:
   :nth-of-type cuenta por etiqueta, y una tarjeta sin enlace se renderiza
   como <div> en vez de <a> (ver front-page.php). Con etiquetas mezcladas,
   el <div> de la primera tarjeta y el <a> de la segunda son ambos "el
   primero de su tipo", caen las dos en la misma celda y una tapa a la otra.
   :nth-child cuenta la posición en la grilla, que es lo que acá se quiere
   decir, y es indiferente a con qué etiqueta se pinte cada tarjeta. */
.home-highlights__grid .highlight-card:nth-child(1) { grid-column: 1 / 15; grid-row: 1; }
.home-highlights__grid .highlight-card:nth-child(2) { grid-column: 15 / 22; grid-row: 1; }
.home-highlights__grid .highlight-card:nth-child(3) { grid-column: 1 / 7;  grid-row: 2; }
.home-highlights__grid .stats-box                    { grid-column: 7 / 22; grid-row: 2; }
.home-highlights__grid .highlight-card:nth-child(n+4) { grid-column: 1 / -1; }

/* Caja de cifras — tarjeta blanca (no azul): título e íconos en gris,
   cifras en azul institucional, misma familia visual que el resto de
   tarjetas blancas de la página. */
.stats-box {
    background-color: var(--ipg-color-background);
    border-radius: var(--ipg-radius-lg);
    box-shadow: var(--ipg-shadow-sm);
    padding: var(--ipg-space-6);
    display: flex;
    flex-direction: column;
}
.stats-box__title {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--ipg-space-2);
    font-size: var(--ipg-text-xs);
    font-weight: var(--ipg-weight-semibold);
    letter-spacing: var(--ipg-tracking-wider);
    text-transform: uppercase;
    color: var(--ipg-color-text-subtle);
    margin-bottom: var(--ipg-space-5);
}
/* Punto de estado — presente en la maqueta junto al título de la caja de
   cifras, decorativo (no representa una conexión en vivo real). */
.stats-box__title::after {
    content: '';
    flex-shrink: 0;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background-color: var(--ipg-color-status-dot);
}
.stats-box__inner {
    flex: 1;
    display: flex;
    align-items: center;
}
.stats-grid {
    width: 100%;
    display: grid;
    /* auto-fit: las cifras se reparten a lo largo de una sola línea (hasta
       ~8, según el ancho disponible); si se agrega una más de las que
       caben, esa salta a la siguiente línea en vez de amontonarse. */
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: var(--ipg-space-6);
}
.stat-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--ipg-space-1);
    padding-inline-start: var(--ipg-space-4);
    border-inline-start: 1px solid var(--ipg-color-border);
}
.stat-item:first-child { border-inline-start: none; padding-inline-start: 0; }
/* Icono de la cifra (opcional, se elige en el panel — ver inc/stat-icons.php).
   El SVG viene con stroke: currentColor, así que basta con darle color acá y
   el trazo lo hereda. width/height en el <svg> para que no dependa del
   viewBox si algún icono nuevo lo trae distinto. */
.stat-item__icon {
    display: block;
    color: var(--ipg-color-primary);
    margin-bottom: var(--ipg-space-1);
}
.stat-item__icon svg {
    display: block;
    width: 32px;
    height: 32px;
}
.stat-item__number {
    font-size: var(--ipg-text-5xl);
    font-weight: var(--ipg-weight-bold);
    /* Azul marino, no el azul institucional: el icono de arriba ya lleva ese
       azul, y con los dos del mismo color la cifra —que es lo que importa—
       competía con su propio icono. En marino el número pesa y el icono lo
       acompaña. Contraste sobre el blanco de la caja: 16:1 (AAA). */
    color: var(--ipg-color-navy);
    line-height: 1.05;
}
.stat-item__label {
    font-size: var(--ipg-text-xs);
    font-weight: var(--ipg-weight-semibold);
    letter-spacing: var(--ipg-tracking-wide);
    text-transform: uppercase;
    color: var(--ipg-color-text-subtle);
}

/* ── Encabezado sección Noticias ─────────────────────────────────────────── */
.news-section__header {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--ipg-space-4);
    margin-bottom: var(--ipg-space-8);
}
/* Mismo caso que el destacado del hero: ver .hero-slide__title-highlight. */
.section-title__highlight { color: var(--ipg-color-primary-light); }
.news-section__subtitle { color: var(--ipg-color-text-muted); margin: 0; }
.news-section__more {
    display: inline-flex;
    align-items: center;
    gap: var(--ipg-space-2);
    color: var(--ipg-color-primary);
    font-weight: var(--ipg-weight-semibold);
    text-decoration: none;
    white-space: nowrap;
}
.news-section__more:hover { text-decoration: underline; }

/* ── Espaciado entre secciones de Inicio (desktop) ────────────────────────
   El gap entre bloques ya lo pone .site-main (flex + gap); acá solo se
   define el "aire" interno de cada sección: nada arriba (lo da el gap),
   y el respiro grande antes de Noticias / footer abajo. */
/* El aire de abajo de cada seccion de la portada. Sumado a los 24px de gap
   de .site-main es la costura entre bloque y bloque: 16 + 24 = 40px. Era el
   doble (40px, costuras de 64px) y se veia suelto — sobre todo en el corte
   entre lo hecho a codigo y lo que se agrega desde el editor.

   Es el unico numero que hay que mover para apretar o soltar toda la
   portada de una vez; su contraparte de movil esta en el bloque de 768px. */
.home-highlights.ipg-section { padding-block: 0 var(--ipg-space-4); }
.news-section.ipg-section { padding-block: 0 var(--ipg-space-4); }

/* Zona editable de Inicio (el contenido que se agrega desde el editor,
   despues de las secciones que vienen por codigo).

   Esta zona traia aire propio TAMBIEN por arriba (40px, en un style inline
   en front-page.php), asi que contra la caja de cifras sumaba tres cosas y
   quedaba un hueco de canvas gris del doble que el resto, justo en la
   costura entre lo hecho a codigo y lo agregado desde WordPress.

   Ahora sigue el mismo patron que sus dos vecinas: 0 arriba, y por abajo el
   mismo valor que ellas (ver la nota de arriba).

   Los margenes del primer y ultimo bloque se anulan a proposito. Sin eso el
   hueco cambiaria segun QUE se agregue —un grupo con fondo no trae margen,
   pero un titulo o un parrafo si—, y la idea es que cualquier cosa que se
   cree quede a la misma distancia. */
.home-entry-content { padding-block: 0 var(--ipg-space-4); }
.home-entry-content > :first-child { margin-top: 0; }
.home-entry-content > :last-child { margin-bottom: 0; }

/* ── Responsive tablet (≤ 768px) ────────────────────────────────────────── */
@media (max-width: 768px) {
    .site-shell { padding: var(--ipg-space-3); }
    .site-main { gap: var(--ipg-space-4); }

    /* Hero carrusel */
    .hero-carousel { padding: var(--ipg-space-6); }
    .hero-slide--text {
        grid-template-columns: 1fr;
        text-align: center;
    }
    .hero-slide__content { max-width: 100%; margin-inline: auto; }
    /* Repetidas con el prefijo body.home porque el agrandado del hero de
       Inicio (ver "Hero de portada" más arriba) usa ese prefijo y por lo
       tanto pesa más que las dos reglas de acá: sin esto, en Inicio el
       banner se quedaba en dos columnas también en el teléfono, con la
       foto reducida a ~120px de ancho. El agrandado es un efecto de
       escritorio; en móvil el hero se apila igual que siempre. */
    body.home .hero-slide--text { grid-template-columns: 1fr; }
    body.home .hero-slide__content { max-width: 100%; }
    .hero-slide__actions { justify-content: center; }
    .hero-slide__actions .btn {
        width: 100%;
        justify-content: center;
    }
    .hero-badge { left: var(--ipg-space-4); bottom: var(--ipg-space-4); }
    .hero-slide__media { min-height: 340px; }

    /* ── Alto del banner en móvil ─────────────────────────────────────────
       --ipg-hero-height (540–740px) está pensado para un monitor apaisado.
       En un teléfono vertical se traduce en un banner de ~645px sobre una
       pantalla de 844: tres cuartos del alto útil ocupados por el
       encabezado, antes de que empiece el contenido.

       Y el efecto sobre la foto era el contrario al esperado: en el slide
       con texto, el texto se lleva su fila del grid y a la imagen le queda
       lo que sobra. Con el alto forzado, ese sobrante la dejaba aplastada
       en una franja de 99px —una foto de 1440×600 mostrada a 344×99— dentro
       de un banner gigante. Se veía desproporcionado justamente porque lo
       era: mucho aire y una imagen minúscula.

       Se baja el piso a poco más de media pantalla y se deja que la foto
       del slide con texto conserve su proporción real en vez de estirarse
       a la fila. Medido a 390×844: el banner pasa de 645px a ~500px y la
       foto de 99px a ~143px. El slide de solo imagen no cambia de trato,
       solo hereda el alto nuevo. */
    .hero-carousel { --ipg-hero-height: clamp(360px, 52vh, 480px); }
    .hero-slide { gap: var(--ipg-space-6); }

    /* El aire de arriba y abajo del slide (40px + 40px) es aire de
       escritorio: en el teléfono son 80px de nada dentro de un banner que
       ya se está comiendo media pantalla, y encima duplicado con los 16px
       que el propio carrusel pone alrededor. */
    .hero-slide--text,
    .hero-slide--image-only { padding-block: var(--ipg-space-4); }

    /* La bajada del hero de Inicio va a 20px, que a ancho de teléfono son
       cuatro renglones y 150px de alto — más que el propio titular. A 17px
       entra en tres y sigue siendo cómoda de leer.
       Lleva el prefijo body.home porque la regla de escritorio también lo
       lleva y si no, no la alcanza en peso. */
    body.home .hero-slide__description { font-size: var(--ipg-text-md); }
    .hero-slide--text .hero-slide__media {
        align-self: start;
        /* 12/5 es exactamente la proporción del recorte 'ipg-hero' que
           genera el tema (1440×600, ver add_image_size en functions.php),
           así que la foto se ve completa y sin recorte extra.

           Va como aspect-ratio y no como height:auto porque la imagen está
           posicionada en absoluto dentro de esta caja: sin ella la caja no
           tiene alto propio y se colapsa a cero. */
        aspect-ratio: 12 / 5;
    }

    /* Accesos destacados + cifras — el bento de 2 filas se apila en una
       sola columna, en el mismo orden que trae el contenido. */
    .home-highlights__grid { grid-template-columns: 1fr; }
    .home-highlights__grid .highlight-card:nth-child(1),
    .home-highlights__grid .highlight-card:nth-child(2),
    .home-highlights__grid .highlight-card:nth-child(3),
    .home-highlights__grid .highlight-card:nth-child(n+4),
    .home-highlights__grid .stats-box {
        grid-column: 1 / -1;
        grid-row: auto;
    }

    /* Encabezado sección noticias */
    .news-section__header { flex-direction: column; align-items: flex-start; }

    /* Secciones */
    .site-main { padding-top: var(--ipg-space-4); padding-bottom: var(--ipg-space-6); }
    .ipg-section { padding-block: var(--ipg-space-10); }
    .home-highlights.ipg-section,
    .news-section.ipg-section,
    .home-entry-content { padding-block: 0 var(--ipg-space-2); }
    .section-title {
        font-size: var(--ipg-text-2xl);
        margin-bottom: var(--ipg-space-6);
    }

    /* Encabezado de archivo */
    .archive-title { font-size: var(--ipg-text-3xl); }

    /* Footer — las tres columnas no caben: la marca arriba a lo ancho y las
       dos de texto repartidas debajo. El grid deja de ser fijo. */
    .footer-widgets__inner {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: var(--ipg-space-8);
    }
    .footer-widget-area:first-child { grid-column: 1 / -1; }

    /* Footer inferior */
    .footer-bottom__inner {
        flex-direction: column;
        text-align: center;
    }
    .footer-menu { justify-content: center; }
}

/* ── Responsive móvil pequeño (≤ 480px) ─────────────────────────────────── */
@media (max-width: 480px) {
    .footer-widgets__inner { grid-template-columns: minmax(0, 1fr); }
    .ipg-container { padding-inline: var(--ipg-space-4); }
    .ipg-grid-2 { grid-template-columns: 1fr; }
    .site-shell { padding: var(--ipg-space-2); }
    .hero-carousel { padding: var(--ipg-space-4); }
    .hero-slide__media { min-height: 260px; }
    .stats-grid { grid-template-columns: 1fr; }
    .stat-item { border-inline-start: none; padding-inline-start: 0; }
    h1 { font-size: var(--ipg-text-3xl); }
    h2 { font-size: var(--ipg-text-2xl); }
}

/* ─────────────────────────────────────────────────────────────────────────
   Reglas rescatadas de Apariencia → Personalizar → CSS adicional
   ─────────────────────────────────────────────────────────────────────────
   Vivían solo en la base de datos (wp_posts, post_type 'custom_css'), fuera
   de git: nadie las veía al revisar el tema y se habrían perdido en cualquier
   reinstalación limpia. Son estructurales — no cosméticas — así que el sitio
   se ve distinto sin ellas. Se copian textualmente para no cambiar el
   resultado visual; lo que había que arreglar era dónde viven.

   Al mover esto, el CSS adicional del Personalizador quedó vacío a propósito.
   ───────────────────────────────────────────────────────────────────────── */

/* Fondo gris más oscuro para la sección Luis Galdames.
   DEUDA: redefine el preset "superficie" para TODO el sitio, no solo para esa
   sección. Lo correcto sería una clase propia en el grupo de esa sección, o
   alinear el valor en theme.json. Se deja igual para no mover el diseño. */
.has-superficie-background-color {
    background-color: #DCDCDC !important;
}

/* Cierra el hueco entre la barra de navegación y el hero de portada. */
.wp-block-cover:first-of-type {
    margin-top: 0 !important;
    padding-top: 0 !important;
}

/* Separación entre secciones.

   Solo a los grupos de PRIMER NIVEL del contenido (hijos directos de
   .entry-content), que son las secciones de la página.

   Antes esta regla decía ".wp-block-group" a secas y alcanzaba a todos los
   grupos, incluidos los anidados. Los patrones del tema anidan tres o
   cuatro niveles (sección → componente → columna → tarjeta), así que una
   tarjeta terminaba con 240px o más de relleno vertical. Por eso el tema
   tenía nueve bloques de CSS que anulaban esta regla componente por
   componente; al acotarla acá, ese CSS defensivo ya no hace falta. */
.entry-content > .wp-block-group {
    padding-top: 60px !important;
    padding-bottom: 60px !important;
}
