/*
Theme Name: Tema Cero
Theme URI: https://512.com.uy
Author: 512 Web Solutions
Author URI: https://512.com.uy
Description: Tema base del estudio 512 Web Solutions.
Version: 3.0.0-rc29
Requires at least: 6.5
Tested up to: 6.7
Requires PHP: 8.2
License: Propietario
Text Domain: tema
*/

/* =========================================================
   CASCADE LAYERS — orden explícito y predecible
   =========================================================
   Cada child theme y plugin sabe en qué layer va a vivir.
   Children pueden hacer `@layer plugins { ... }` y GANAR
   sin specifity-war ni `!important`.

   Order (lower → higher priority):
     reset       → normalize / box-sizing / element resets
     tokens      → CSS custom properties (--color-*, --fs-*, etc.)
     base        → element selectors (body, h1-h6, a, p)
     components  → .btn, .card, .site-header, .mold--*, etc.
     utilities   → .text-center, .hidden, animations, view-transitions
     plugins     → reservado para children y plugins #512

   Reglas FUERA de un @layer named viven en el "default layer"
   con prioridad más alta — usar SOLO para overrides puntuales.
   ========================================================= */
@layer reset, tokens, base, components, utilities, plugins;

/* =========================================================
   @layer reset — Box-sizing, element resets, defaults
   ========================================================= */
@layer reset {
    *, *::before, *::after { box-sizing: border-box; }
    html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; view-transition-name: root; }
    @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
    body { margin: 0; min-height: 100vh; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; }
    img, picture, svg, video { display: block; max-width: 100%; height: auto; }
    button { font: inherit; cursor: pointer; background: none; border: 0; color: inherit; }
    input, textarea, select { font: inherit; }
    a { color: inherit; text-decoration: none; }
    ul, ol { padding: 0; margin: 0; list-style: none; }
    h1, h2, h3, h4, h5, h6, p { margin: 0; }
}

/* =========================================================
   @layer tokens — Design tokens. Defaults; pisados por inc/dynamic-css.php
   ========================================================= */
/* Naming convention v1.2.0:
   --color-* | --font-* | --peso-* | --fs-* | --altura-* | --sp-*
   --shadow-* | --radio-* | --dur-* | --ease-* | --layout-* | --btn-*
   --focus-* */
@layer tokens {
    :root {
        /* Paleta canónica 512 v3.0 · Bone-Graphite-Terracota · quiet luxury Rolls-Royce
           Reemplaza la paleta azul vieja (#0052CC #7C3AED #10B981) por Titanium warm.
           Decisión Manual de Marca v2.0 + Estándar Premium 512 v2.1 + workshop 2026-05-02 */

        /* Neutrales warm · 6 escalones */
        --color-bone:     #FAFAF9; /* fondo base · más claro */
        --color-sand:     #F5F5F4; /* fondo secundario · cards */
        --color-stone:    #A8A29E; /* hairlines · borders sutiles */
        --color-smoke:    #57534E; /* secondary text · iconos */
        --color-graphite: #292524; /* body text · contraste fuerte */
        --color-obsidian: #0A0A0A; /* hero overlays · backgrounds dark */

        /* Acento único terracota · firma 512 (1-3% del UI) */
        --color-terracota:        #CC785C;
        --color-terracota-soft:   #E5A693; /* hover light */
        --color-terracota-strong: #A8634A; /* hover dark */

        /* Aliases semánticos · child puede repintar SIN tocar HTML */
        --color-bg:        var(--color-bone);
        --color-bg-soft:   var(--color-sand);
        --color-text:      var(--color-graphite);
        --color-text-soft: var(--color-smoke);
        --color-line:      color-mix(in oklab, var(--color-stone) 30%, transparent);
        --color-accent:    var(--color-terracota);
        --color-link:      var(--color-graphite);
        --color-link-hover: var(--color-terracota);

        /* Estados */
        --color-success:  #2D6A4F;
        --color-warning:  #C8915E;
        --color-error:    #B23A3A;
        --color-info:     #4A6B8A;

        /* === BACKWARDS-COMPAT v2.x · Aliases legacy ===
           Childs viejos (LeCorch v1, etc.) pueden seguir usando --color-primario.
           Apuntan a los slots canónicos v3.0. Mantener hasta v3.1. */
        --color-primario:    var(--color-graphite);
        --color-secundario:  var(--color-smoke);
        --color-acento:      var(--color-terracota);
        --color-fondo:       var(--color-bg);
        --color-fondo-suave: var(--color-bg-soft);
        --color-texto:       var(--color-text);
        --color-texto-suave: var(--color-text-soft);
        --color-borde:       var(--color-line);
        --color-exito:       var(--color-success);
        --color-aviso:       var(--color-warning);

        /* Tipografía canónica 512 v3.0 · Gilroy default (paga · WOFF2 local)
           Catálogo de 30 GoogleFonts disponible vía Customizer (ver inc/fonts.php) */
        --font-display:  'Gilroy', system-ui, -apple-system, sans-serif;
        --font-body:     'Gilroy', system-ui, -apple-system, sans-serif;
        --font-mono:     'JetBrains Mono', ui-monospace, monospace;

        /* Aliases legacy v2.x para compat childs viejos */
        --font-titulo:    var(--font-display);
        --font-subtitulo: var(--font-display);
        --font-cuerpo:    var(--font-body);

        --fw-light:    300;
        --fw-regular:  400;
        --fw-medium:   500;
        --fw-semibold: 600;
        --peso-titulo: var(--fw-semibold); /* legacy alias */
        --peso-cuerpo: var(--fw-regular);  /* legacy alias */

        --lh-display: 1.1;
        --lh-h2:      1.15;
        --lh-h3:      1.25;
        --lh-h4:      1.35;
        --lh-body:    1.6;
        --lh-tight:   1.4;
        --altura-linea-titulo: var(--lh-h2);  /* legacy */
        --altura-linea-cuerpo: var(--lh-body); /* legacy */

        /* Tamaños tipográficos — fluid clamps; dynamic-css los puede pisar */
        --escala-base: 16px;
        --fs-xs: 0.75rem;
        --fs-sm: 0.889rem;
        --fs-md: 1rem;
        --fs-lg: 1.333rem;
        --fs-xl: 1.777rem;
        --fs-2xl: 2.369rem;
        --fs-3xl: 3.157rem;
        --fs-5xl: 5.610rem;
        --fs-hero: clamp(2.5rem, 5vw + 1rem, 5.6rem);
        --fs-display: clamp(2rem, 4vw + 1rem, 4.2rem);
        --fs-h1: clamp(1.75rem, 3vw + 1rem, 3.15rem);
        --fs-h2: clamp(1.5rem, 2vw + 1rem, 2.37rem);
        --fs-h3: clamp(1.25rem, 1.5vw + 0.75rem, 1.78rem);
        --fs-h4: 1.333rem;
        --fs-body: 1rem;
        --fs-small: 0.889rem;
        --fs-lead: clamp(1.1rem, 0.5vw + 1rem, 1.33rem);

        /* Espaciado — escala 4-8-16-24-32-48-64 */
        --sp-xs: 0.25rem;
        --sp-sm: 0.5rem;
        --sp-md: 1rem;
        --sp-lg: 1.5rem;
        --sp-xl: 2rem;
        --sp-2xl: 3rem;
        --sp-3xl: 4rem;

        /* Bordes · DECISIÓN CANÓNICA · radius máximo 2px (quiet luxury · Estándar Premium principio 1)
           Aliases legacy apuntan a 0/2px para no romper childs viejos. */
        --radius-none:     0;
        --radius-hairline: 1px;
        --radius-sutil:    2px;
        --radio-sm:        var(--radius-sutil);  /* legacy */
        --radio-md:        var(--radius-sutil);  /* legacy */
        --radio-lg:        var(--radius-sutil);  /* legacy */
        --radio-pill:      var(--radius-sutil);  /* legacy · ya no es pill */

        /* Sombras · DECISIÓN CANÓNICA · cero shadows en superficies (quiet luxury)
           Solo permitido tooltip muy sutil. Aliases legacy = none. */
        --shadow-none:    none;
        --shadow-tooltip: 0 1px 3px rgba(0,0,0,0.08);
        --shadow-sm:      var(--shadow-none);  /* legacy */
        --shadow-md:      var(--shadow-none);  /* legacy */
        --shadow-lg:      var(--shadow-none);  /* legacy */
        --shadow-focus:   0 0 0 2px color-mix(in srgb, var(--color-accent) 60%, transparent);

        /* Z-index canónico */
        --z-base:     1;
        --z-sticky:   10;
        --z-overlay:  50;
        --z-whatsapp: 150;
        --z-modal:    100;
        --z-cookie:   200;
        --z-toast:    300;

        /* Botones · cero radius */
        --btn-radius: 0;
        --btn-px: 1.5rem;
        --btn-py: 0.75rem;
        --btn-weight: 600;

        /* Focus */
        --focus-color: var(--color-primario);
        --focus-width: 3px;
        --focus-offset: 2px;

        /* Animaciones · DECISIÓN CANÓNICA 2026-05-02 · UN solo easing
           Reemplaza los 12 easings de v2.x.
           Inspirado en Linear/Vercel/Apple "ease-out-expo" suavizado. */
        --ease-premium: cubic-bezier(0.16, 1, 0.3, 1);

        /* Aliases semánticos · TODOS apuntan al mismo --ease-premium */
        --ease-linear:      var(--ease-premium);
        --ease-out:         var(--ease-premium);
        --ease-in:          var(--ease-premium);
        --ease-in-out:      var(--ease-premium);
        --ease-decelerate:  var(--ease-premium);
        --ease-accelerate:  var(--ease-premium);
        --ease-emphasized:  var(--ease-premium);
        --ease-spring:      var(--ease-premium);
        --ease-spring-soft: var(--ease-premium);
        --ease-bounce:      var(--ease-premium);

        /* Duraciones canónicas (Estándar Premium 512 principio 6) */
        --dur-instant: 80ms;
        --dur-fast:    250ms; /* salidas, fade-out, cierre modal */
        --dur-hover:   320ms; /* cards, botones, links */
        --dur-base:    320ms; /* alias */
        --dur-medium:  460ms; /* underline grow estilo Bottega */
        --dur-slow:    600ms; /* entrada, fade-in al scroll, modales */
        --dur-slower:  600ms; /* alias */
        --dur-luxury:  1000ms; /* scale sutil hover en fotos */

        /* Stagger entre items */
        --stagger:     60ms;

        /* Layout */
        --layout-contenedor: 1200px;
        --layout-contenedor-estrecho: 800px;
        --layout-padding-lado: clamp(1rem, 3vw, 2rem);
        --layout-header-h: 72px;
    }

    /* Dark mode — pisa tokens cuando data-modo="oscuro" o media query y data-modo="auto" */
    [data-modo="oscuro"],
    html[data-modo="oscuro"] {
        --color-texto: #F3F4F6;
        --color-texto-suave: #9CA3AF;
        --color-fondo: #0F1117;
        --color-fondo-suave: #1A1D25;
        --color-borde: #2A2E38;
    }
    @media (prefers-color-scheme: dark) {
        html[data-modo="auto"] {
            --color-texto: #F3F4F6;
            --color-texto-suave: #9CA3AF;
            --color-fondo: #0F1117;
            --color-fondo-suave: #1A1D25;
            --color-borde: #2A2E38;
        }
    }

    /* Prefers-contrast: more — incrementar contraste cuando el usuario lo pide */
    @media (prefers-contrast: more) {
        :root {
            --color-borde: currentColor;
            --focus-width: 4px;
        }
    }
}

/* =========================================================
   @layer base — Element selectors. Bajo specifity para que
   children puedan overridear con clases de 1 nivel.
   ========================================================= */
@layer base {
    body {
        font-family: var(--font-cuerpo);
        font-size: var(--escala-base);
        font-weight: var(--peso-cuerpo);
        line-height: var(--altura-linea-cuerpo);
        color: var(--color-texto);
        background: var(--color-fondo);
        transition: background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);

        /* Tipografía premium — kerning, ligaduras y alternates contextuales.
           Compatible con todos los navegadores modernos. */
        font-feature-settings: "kern" 1, "liga" 1, "calt" 1;
        font-kerning: normal;
        text-rendering: optimizeLegibility;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
    }

    /* Headings — base typographic; spacing y max-width viven en .prose */
    h1, h2, h3, h4, h5, h6 {
        font-family: var(--font-titulo);
        font-weight: var(--peso-titulo);
        line-height: var(--altura-linea-titulo);
        letter-spacing: -0.02em;
        color: var(--color-texto);
        margin-block-end: var(--sp-md);

        /* text-wrap: balance — evita líneas huérfanas (1 palabra) y desbalance
           visual en titulares. Chrome 114+, Safari 17.5+, Firefox 121+. */
        text-wrap: balance;
    }
    h1 { font-size: var(--fs-h1); margin-block-end: var(--sp-lg); }
    h2 { font-size: var(--fs-h2); }
    h3 { font-size: var(--fs-h3); margin-block-end: var(--sp-sm); }
    h4, h5, h6 { font-size: var(--fs-lg); margin-block-end: var(--sp-sm); }

    /* Párrafos — sin max-width global. Si necesitás párrafos legibles, usar .prose.
       text-wrap: pretty — evita huérfanas en párrafos manteniendo justified.
       Chrome 117+, fallback graceful. */
    p {
        margin-block-end: var(--sp-md);
        text-wrap: pretty;
    }
    p:last-child { margin-block-end: 0; }

    a { color: var(--color-primario); }
    a:hover { text-decoration: underline; }

    strong, b { font-weight: 700; }

    /* Focus universal — Stripe pattern: outline + halo color-mix.
       Doble feedback visual (línea + glow) sin perder accesibilidad. */
    :focus { outline: none; }
    :focus-visible {
        outline: var(--focus-width) solid var(--focus-color);
        outline-offset: var(--focus-offset);
        border-radius: var(--radio-sm);
        box-shadow: 0 0 0 calc(var(--focus-width) + 2px)
            color-mix(in srgb, var(--focus-color) 22%, transparent);
        transition: box-shadow var(--dur-fast, 120ms) var(--ease-out, ease);
    }

    /* Animación suave entre cambios de modo claro/oscuro */
    @media (prefers-reduced-motion: no-preference) {
        [data-modo] { transition: background-color var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out); }
    }
}

/* =========================================================
   @layer utilities — utilities tipográficas + microinteractions
   Se cargan al final para ganar specifity sin !important.
   ========================================================= */
@layer utilities {

    /* Tabular-nums — para tablas de precios, números alineados verticalmente */
    .tabular-nums { font-variant-numeric: tabular-nums; }

    /* Text-wrap utilities — explícitas para casos puntuales */
    .text-balance { text-wrap: balance; }
    .text-pretty  { text-wrap: pretty; }
    .text-nowrap  { text-wrap: nowrap; white-space: nowrap; }

    /* Suavizar el scroll para anclas internas */
    @media (prefers-reduced-motion: no-preference) {
        :where(html) { scroll-behavior: smooth; }
    }
}

/* =========================================================
   @layer components — UI components (.btn, .card, .site-header, etc.)
   ========================================================= */
@layer components {

    /* Skip link y screen-reader utilities */
    .skip-link {
        position: absolute;
        top: -9999px;
        left: 0;
        background: var(--color-primario);
        color: #fff;
        padding: var(--sp-sm) var(--sp-lg);
        z-index: 9999;
        border-radius: 0 0 var(--radio-md) 0;
        font-weight: 600;
    }
    .skip-link:focus { top: 0; }

    .sr-only,
    .screen-reader-text {
        position: absolute !important;
        width: 1px; height: 1px;
        padding: 0; margin: -1px;
        overflow: hidden; clip: rect(0,0,0,0);
        white-space: nowrap; border: 0;
    }

    /* ----- Layout containers ----- */
    .contenedor {
        max-width: var(--layout-contenedor);
        margin-inline: auto;
        padding-inline: var(--layout-padding-lado);
    }
    .contenedor-estrecho {
        max-width: var(--layout-contenedor-estrecho);
        margin-inline: auto;
        padding-inline: var(--layout-padding-lado);
    }
    .seccion { padding-block: clamp(var(--sp-2xl), 10vw, var(--sp-3xl)); }
    .seccion + .seccion { border-top: 0; }

    .section { padding-block: clamp(var(--sp-2xl), 6vw, var(--sp-3xl)); }
    /* content-visibility — diferir render below-the-fold; reserva altura para evitar CLS */
    .section:not(.section-hero) {
        content-visibility: auto;
        contain-intrinsic-size: 800px;
    }

    /* ----- Prose (long-form content) — opt-in con clase ----- */
    /* Usar .prose en wrappers de contenido editorial (artículos, FAQ).
       NO se aplica globalmente a `p` para no atar children que quieren
       párrafos full-width. */
    .prose p { max-width: 65ch; }
    .prose p:not(:last-child) { margin-block-end: var(--sp-md); }

    /* ----- Botones ----- */
    .btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        gap: var(--sp-sm);
        padding: var(--btn-py) var(--btn-px);
        border-radius: var(--btn-radius);
        font-weight: var(--btn-weight);
        font-size: var(--fs-md);
        line-height: 1;
        min-height: 44px;
        text-decoration: none;
        transition: transform var(--dur-fast) var(--ease-out),
                    background var(--dur-fast) var(--ease-out),
                    color var(--dur-fast) var(--ease-out),
                    box-shadow var(--dur-fast) var(--ease-out);
    }
    .btn:hover { transform: translateY(-1px); text-decoration: none; }
    .btn:active { transform: translateY(0); }
    .btn:has(svg + span) { gap: var(--sp-sm); }

    .btn--primario {
        background: var(--color-primario);
        color: #fff;
        box-shadow: var(--shadow-sm);
    }
    .btn--primario:hover { filter: brightness(1.08); box-shadow: var(--shadow-md); color: #fff; }

    .btn--outline {
        background: transparent;
        color: var(--color-primario);
        border: 2px solid var(--color-primario);
    }
    .btn--outline:hover { background: var(--color-primario); color: #fff; }

    .btn--ghost {
        background: transparent;
        color: var(--color-texto);
    }
    .btn--ghost:hover { background: var(--color-fondo-suave); }

    /* prefers-contrast: more — botones con borde ineludible */
    @media (prefers-contrast: more) {
        .btn { border: 2px solid currentColor; }
    }

    /* ----- Botón disabled / loading ----- */
    .btn[disabled],
    .btn[aria-disabled="true"] {
        opacity: 0.55;
        pointer-events: none;
        cursor: not-allowed;
        transform: none !important;
    }

    /* Loading state — spinner SVG via ::after, sin necesidad de markup extra.
       Activado con [data-loading="true"] o [aria-busy="true"]. JS hookea
       en submit del form y persiste hasta que vuelva la respuesta. */
    .btn[data-loading="true"],
    .btn[aria-busy="true"] {
        position: relative;
        color: transparent !important;
        pointer-events: none;
        cursor: wait;
    }
    .btn[data-loading="true"] > *,
    .btn[aria-busy="true"] > * {
        opacity: 0;
    }
    .btn[data-loading="true"]::after,
    .btn[aria-busy="true"]::after {
        content: "";
        position: absolute;
        inset: 0;
        margin: auto;
        width: 1.2em;
        height: 1.2em;
        border-radius: 50%;
        border: 2px solid currentColor;
        border-top-color: transparent;
        border-right-color: transparent;
        color: #fff; /* coincide con texto del botón primario */
        animation: tema-spin 720ms linear infinite;
    }
    .btn--outline[data-loading="true"]::after,
    .btn--ghost[data-loading="true"]::after {
        color: var(--color-primario);
    }
    @keyframes tema-spin {
        to { transform: rotate(360deg); }
    }
    @media (prefers-reduced-motion: reduce) {
        .btn[data-loading="true"]::after,
        .btn[aria-busy="true"]::after {
            animation-duration: 1.6s;
        }
    }

    /* ----- Header ----- */
    .site-header {
        position: sticky;
        top: 0;
        z-index: 100;
        background: var(--color-fondo);
        border-bottom: 1px solid transparent;
        transition: background var(--dur-base) var(--ease-out),
                    border-color var(--dur-base) var(--ease-out),
                    box-shadow var(--dur-base) var(--ease-out);
        view-transition-name: site-header;
    }
    .site-header[data-scrolled="true"] {
        border-color: var(--color-borde);
        box-shadow: var(--shadow-sm);
    }
    ::view-transition-group(site-header) { animation: none; }

    .site-header__inner {
        display: flex;
        align-items: center;
        justify-content: space-between;
        min-height: var(--layout-header-h);
        gap: var(--sp-lg);
    }

    .site-brand {
        display: inline-flex;
        align-items: center;
        gap: var(--sp-sm);
        font-family: var(--font-titulo);
        font-weight: 700;
        font-size: var(--fs-lg);
        color: var(--color-texto);
        text-decoration: none;
    }
    /* FIX-11 — altura máxima del logo viene de --logo-max-h (Customizer). */
    .site-brand img,
    .site-header__branding img,
    .site-header__branding .custom-logo { max-height: var(--logo-max-h, 48px); width: auto; height: auto; }

    .primary-nav ul {
        display: flex;
        align-items: center;
        gap: var(--sp-xl);
    }
    .primary-nav a {
        color: var(--color-texto);
        font-weight: 500;
        padding: var(--sp-sm) 0;
        position: relative;
    }
    .primary-nav a:hover,
    .primary-nav .current-menu-item > a { color: var(--color-primario); text-decoration: none; }

    .header-cta {
        margin-left: var(--sp-lg);
    }

    /* Hamburger — WCAG 2.2 Target Size mínimo 44x44 (FIX-10) */
    .hamburger {
        display: none;
        width: 44px;
        height: 44px;
        min-width: 44px;
        min-height: 44px;
        align-items: center;
        justify-content: center;
        border-radius: var(--radio-md);
        flex-shrink: 0;
    }
    .hamburger__icon { display: inline-flex; align-items: center; justify-content: center; }
    .hamburger__bar {
        display: block;
        width: 24px;
        height: 2px;
        background: var(--color-texto);
        position: relative;
        transition: transform var(--dur-base) var(--ease-out);
    }
    .hamburger__bar::before,
    .hamburger__bar::after {
        content: '';
        position: absolute;
        left: 0; width: 24px; height: 2px;
        background: var(--color-texto);
        transition: transform var(--dur-base) var(--ease-out), top var(--dur-base) var(--ease-out);
    }
    .hamburger__bar::before { top: -8px; }
    .hamburger__bar::after { top: 8px; }
    .hamburger[aria-expanded="true"] .hamburger__bar { background: transparent; }
    .hamburger[aria-expanded="true"] .hamburger__bar::before { top: 0; transform: rotate(45deg); }
    .hamburger[aria-expanded="true"] .hamburger__bar::after { top: 0; transform: rotate(-45deg); }

    @media (max-width: 900px) {
        .primary-nav, .header-cta { display: none; }
        .hamburger { display: inline-flex; }
    }

    /* Mobile nav dialog */
    .mobile-nav {
        position: fixed;
        inset: 0;
        background: var(--color-fondo);
        z-index: 200;
        padding: var(--sp-2xl) var(--layout-padding-lado);
        overflow-y: auto;
        transform: translateX(100%);
        transition: transform var(--dur-base) var(--ease-out);
    }
    .mobile-nav[open] { transform: translateX(0); }
    .mobile-nav[hidden] { display: none; }
    .mobile-nav__close {
        position: absolute;
        top: var(--sp-md); right: var(--sp-md);
        width: 44px; height: 44px;
        border-radius: var(--radio-md);
        display: inline-flex; align-items: center; justify-content: center;
        font-size: 1.5rem;
    }
    .mobile-nav ul { display: flex; flex-direction: column; gap: var(--sp-md); margin-top: var(--sp-2xl); }
    .mobile-nav a { font-size: var(--fs-lg); font-weight: 600; color: var(--color-texto); }

    body.nav-open { overflow: hidden; }

    /* ============================================================
       FOOTER · Rolls-Royce style · v3.0.0-rc4
       Brand centrado arriba · hairline con marca circular en el medio ·
       grid de N columnas con headers en uppercase tracking · sociales
       como columna con texto (no íconos) · bottom row con copyright + nav.
       ============================================================ */
    .site-footer {
        background: var(--color-fondo);
        color: var(--color-texto);
        padding: var(--sp-3xl) 0 var(--sp-lg);
        margin-top: var(--sp-3xl);
        border-top: 1px solid var(--color-borde);
    }
    .site-footer__inner {
        display: flex;
        flex-direction: column;
    }

    /* Brand — logo + tagline arriba centrado */
    .site-footer__brand {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: var(--sp-xs, 6px);
        text-align: center;
        padding-bottom: var(--sp-lg);
    }
    .site-footer__site-title {
        font-family: var(--font-display, var(--font-body));
        font-weight: 700;
        font-size: clamp(40px, 4vw, 64px);
        letter-spacing: -0.01em;
        line-height: 1;
        color: var(--color-texto);
        margin: 0;
    }
    /* 4 escalas configurables vía filter `tema_footer_brand_size`
       ('sm' | 'md' | 'lg' | 'xl'). Default md. */
    .site-footer__brand--sm .site-footer__site-title { font-size: clamp(24px, 2.5vw, 36px); }
    .site-footer__brand--md .site-footer__site-title { font-size: clamp(40px, 4vw, 64px); }
    .site-footer__brand--lg .site-footer__site-title { font-size: clamp(56px, 5.5vw, 88px); }
    .site-footer__brand--xl .site-footer__site-title { font-size: clamp(72px, 7vw, 120px); }
    .site-footer__brand .custom-logo-link img,
    .site-footer__brand .custom-logo {
        max-height: clamp(44px, 4vw, 64px);
        width: auto;
    }
    .site-footer__brand--sm .custom-logo-link img,
    .site-footer__brand--sm .custom-logo { max-height: clamp(28px, 2.5vw, 40px); }
    .site-footer__brand--md .custom-logo-link img,
    .site-footer__brand--md .custom-logo { max-height: clamp(44px, 4vw, 64px); }
    .site-footer__brand--lg .custom-logo-link img,
    .site-footer__brand--lg .custom-logo { max-height: clamp(56px, 5vw, 88px); }
    .site-footer__brand--xl .custom-logo-link img,
    .site-footer__brand--xl .custom-logo { max-height: clamp(72px, 7vw, 120px); }
    .site-footer__tagline {
        font-family: var(--font-mono, ui-monospace, monospace);
        font-size: 11px;
        letter-spacing: 0.22em;
        text-transform: uppercase;
        color: var(--color-texto-suave);
        font-weight: 500;
        margin: 0;
    }

    /* Hairline horizontal con marca circular en el medio (R-R signature) */
    .site-footer__rule {
        position: relative;
        height: 1px;
        background: var(--color-borde);
        margin: var(--sp-lg) 0 var(--sp-2xl);
    }
    .site-footer__rule-mark {
        position: absolute;
        top: 50%;
        left: 50%;
        width: 10px;
        height: 10px;
        background: var(--color-fondo);
        border: 1px solid var(--color-borde);
        border-radius: 50%;
        transform: translate(-50%, -50%);
    }

    /* Grid de columnas */
    .site-footer__grid {
        display: grid;
        grid-template-columns: repeat(5, 1fr);
        gap: var(--sp-xl, var(--sp-lg));
        align-items: start;
        margin-bottom: var(--sp-2xl);
    }
    @media (max-width: 1100px) {
        .site-footer__grid { grid-template-columns: repeat(3, 1fr); gap: var(--sp-lg); }
    }
    @media (max-width: 700px) {
        .site-footer__grid { grid-template-columns: repeat(2, 1fr); gap: var(--sp-md); }
    }
    @media (max-width: 420px) {
        .site-footer__grid { grid-template-columns: 1fr; }
    }

    .site-footer__col-title,
    .site-footer h4,
    .site-footer h5 {
        font-family: var(--font-body);
        font-size: 14px;
        font-weight: 700;
        letter-spacing: 0.24em;
        text-transform: uppercase;
        color: var(--color-texto);
        margin: 0 0 var(--sp-md);
        padding: 0;
    }

    .site-footer__col-list {
        list-style: none;
        padding: 0;
        margin: 0;
    }
    .site-footer__col-list li {
        padding: 6px 0;
    }
    .site-footer__col-list a,
    .site-footer__col-static {
        font-family: var(--font-body);
        font-weight: 400;
        font-size: 16px;
        letter-spacing: 0.01em;
        line-height: 1.5;
        color: var(--color-texto-suave);
        text-transform: none;
        text-decoration: none;
        transition: color 320ms cubic-bezier(0.16, 1, 0.3, 1);
        display: inline-block;
        padding: 2px 0;
    }
    .site-footer__col-list a:hover {
        color: var(--color-texto);
    }

    /* Columna de redes sociales como TEXTO (no íconos) — variant BEM
       hereda de __col pero permite ajustes específicos a futuro. */
    .site-footer__col--socials .site-footer__col-list a {
        /* Mismo styling que items normales · variante explícita por claridad. */
    }
    .site-footer__socials-list {
        /* Hereda de __col-list. Existe la clase para poder customizar
           sin tocar otros __col-list si en el futuro hace falta. */
    }

    /* Hairline divisor antes del bottom */
    .site-footer__divider {
        border: 0;
        height: 1px;
        background: var(--color-borde);
        margin: var(--sp-lg) 0;
    }

    /* Bottom · copyright + cookies toggle + attribution */
    .site-footer__bottom {
        display: flex;
        flex-wrap: wrap;
        justify-content: space-between;
        align-items: center;
        gap: var(--sp-md);
        font-family: var(--font-body);
        font-size: 14px;
        letter-spacing: 0.18em;
        text-transform: uppercase;
        color: var(--color-texto-suave);
        font-weight: 500;
        padding-top: var(--sp-md);
    }
    @media (max-width: 700px) {
        .site-footer__bottom {
            flex-direction: column;
            gap: var(--sp-sm);
            text-align: center;
        }
    }
    .site-footer__copy { margin: 0; }
    .site-footer__nav .menu-footer {
        display: flex;
        gap: var(--sp-md);
        list-style: none;
        padding: 0;
        margin: 0;
    }
    .site-footer__nav a {
        color: var(--color-texto-suave);
        text-decoration: none;
        transition: color 320ms cubic-bezier(0.16, 1, 0.3, 1);
    }
    .site-footer__nav a:hover { color: var(--color-texto); }

    /* Botón "Configurar cookies" — reabre el banner del motor.
       Estilo botón-link minimal (mismo lenguaje que el resto del bottom). */
    .site-footer__cookies-toggle {
        background: transparent;
        border: 0;
        padding: 0;
        margin: 0;
        font-family: var(--font-body);
        font-size: 14px;
        font-weight: 500;
        letter-spacing: 0.18em;
        text-transform: uppercase;
        color: var(--color-texto-suave);
        cursor: pointer;
        transition: color 320ms cubic-bezier(0.16, 1, 0.3, 1);
    }
    .site-footer__cookies-toggle:hover,
    .site-footer__cookies-toggle:focus-visible {
        color: var(--color-texto);
        outline: none;
    }

    /* Atribución — "BY GERMÁN FALCIONI" / "BY 512 WEB SOLUTIONS" del bottom-row */
    .site-footer__copy { margin: 0; }
    .site-footer__attribution {
        margin-left: auto;
        color: var(--color-texto-suave);
    }
    .site-footer__attribution a {
        color: var(--color-accent, var(--color-terracota));
        font-weight: 600;
        letter-spacing: 0.18em;
        text-decoration: none;
        transition: opacity 320ms cubic-bezier(0.16, 1, 0.3, 1);
    }
    .site-footer__attribution a:hover { opacity: 0.7; }
    @media (max-width: 700px) {
        .site-footer__attribution { margin-left: 0; }
    }

    /* ============================================================
       LANG SWITCHER · ES | EN premium (motor v3.0.0-rc26+)
       Output canónico de tema_i18n_language_switcher() · usado por
       header del motor y por childs vía echo.

       ARQUITECTURA: las reglas respetan las mismas vars expuestas
       que .tema-idiomas__* en idiomas.php — el child setea UNA vez
       las vars y aplica a ambos switchers (legacy y nuevo).

       Vars expuestas (definir en .tema-header del child o en :root):
         --tema-idiomas-color           color de letras inactivas
         --tema-idiomas-hover-color     color al hover
         --tema-idiomas-active-color    color del item activo
         --tema-idiomas-sep-color       color del separador "|"
         --tema-idiomas-gap             gap entre items
         --tema-idiomas-font            font-family (default: --font-display)

       Cada var tiene fallback al comportamiento legacy → cualquier
       child viejo que NO setee las vars sigue rendereando idéntico.
       ============================================================ */
    .tema-lang-switcher {
        display: inline-flex;
        align-items: center;
    }
    .tema-lang-list {
        display: inline-flex;
        gap: var(--tema-idiomas-gap, 0);
        list-style: none;
        margin: 0;
        padding: 0;
        align-items: center;
    }
    .tema-lang-item {
        display: inline-flex;
        align-items: center;
    }
    /* Ocultar bandera SVG si el child la inyecta · queremos solo código tipográfico */
    .tema-lang-item.tema-lang-item svg { display: none; }

    /* Separador "|" entre items · margin controlable por el child.
       Default 3px (más apretado que los 6px legacy). */
    .tema-lang-item + .tema-lang-item::before {
        content: '|';
        display: inline-block;
        color: var(--tema-idiomas-sep-color, var(--tema-idiomas-color, var(--color-borde, currentColor)));
        opacity: 0.5;
        margin: 0 var(--tema-idiomas-sep-margin, 3px);
        font-weight: 400;
        line-height: 1;
        font-size: 12px;
    }

    /* Padding del link · controlable por el child.
       Default 2px lateral (antes era 4px legacy). */
    .tema-lang-item a {
        display: inline-flex;
        align-items: center;
        padding: 8px var(--tema-idiomas-link-padding-x, 2px);
        font-family: var(--tema-idiomas-font, var(--font-display, var(--font-body)));
        font-weight: 500;
        font-size: 12px;
        letter-spacing: 0.28em;
        text-transform: uppercase;
        color: var(--tema-idiomas-color, var(--color-texto-suave));
        text-decoration: none;
        line-height: 1;
        background: transparent;
        border-radius: 0;
        transition: color 320ms cubic-bezier(0.16, 1, 0.3, 1);
    }
    .tema-lang-item a:hover {
        color: var(--tema-idiomas-hover-color, var(--color-texto));
    }
    .tema-lang-item.is-active a {
        color: var(--tema-idiomas-active-color, var(--color-accent, var(--color-terracota)));
        cursor: default;
        pointer-events: none;
    }

    /* Legacy compatibility — clases viejas que pueden seguir usándose */
    .site-footer__socials {
        display: flex;
        flex-wrap: wrap;
        gap: var(--sp-sm);
        margin-top: var(--sp-md);
    }
    .site-footer__socials a {
        width: 40px; height: 40px;
        display: inline-flex;
        align-items: center; justify-content: center;
        border-radius: var(--radio-pill);
        background: var(--color-fondo);
        border: 1px solid var(--color-borde);
    }

    /* WhatsApp flotante */
    .wa-float {
        position: fixed;
        bottom: var(--sp-lg); right: var(--sp-lg);
        width: 56px; height: 56px;
        border-radius: var(--radio-pill);
        background: #25D366;
        color: #fff;
        display: inline-flex;
        align-items: center; justify-content: center;
        box-shadow: var(--shadow-lg);
        z-index: 90;
        transition: transform var(--dur-fast) var(--ease-out);
    }
    .wa-float:hover { transform: scale(1.08); color: #fff; }
    .wa-float svg { width: 28px; height: 28px; }

    /* ----- Sección Hero ----- */
    /* FIX-13 — `--hero-bg` y `--hero-tx` son extension points pensados para que un
       molde de hero específico los pise localmente (ej. .mold--hero-editorial define
       `--hero-bg: var(--color-fondo-suave)`). El fallback usa los tokens globales,
       así que no hay warning si nadie los setea. */
    .section-hero {
        position: relative;
        min-height: min(90vh, 820px);
        display: flex;
        align-items: center;
        background: var(--hero-bg, var(--color-fondo));
        color: var(--hero-tx, var(--color-texto));
        overflow: hidden;
        isolation: isolate;
    }
    .section-hero__inner {
        position: relative;
        z-index: 2;
        display: grid;
        gap: var(--sp-xl);
        max-width: 60ch;
        padding-block: var(--sp-3xl);
    }
    .section-hero__titulo { font-size: var(--fs-hero); line-height: 1.05; letter-spacing: -0.03em; margin: 0; text-wrap: balance; }
    .section-hero__subtitulo { font-size: var(--fs-lead); color: var(--color-texto-suave); text-wrap: pretty; }
    .section-hero__ctas { display: flex; flex-wrap: wrap; gap: var(--sp-md); }
    .section-hero__media {
        position: absolute; inset: 0;
        z-index: 1;
    }
    .section-hero__media img,
    .section-hero__media picture { width: 100%; height: 100%; object-fit: cover; }

    /* Overlay sobre la imagen del hero — garantiza contraste WCAG AA del
       texto blanco sobre cualquier imagen, sin depender de que la imagen
       sea oscura. Tokens permiten ajuste fino:
         --hero-overlay         · gradient/color completo (default = scrim oscuro)
         --hero-overlay-top     · opacidad arriba (default 0.25)
         --hero-overlay-bottom  · opacidad abajo (default 0.55)
       Children pueden overridear con un sólido o quitar pasando `none`.
       v2.5.2 — fix Accessibility 89 → 100 (contrast issues en hero). */
    .section-hero__media::after {
        content: "";
        position: absolute;
        inset: 0;
        z-index: 1;
        background: var(--hero-overlay,
            linear-gradient(180deg,
                rgba(0,0,0, var(--hero-overlay-top, 0.25)) 0%,
                rgba(0,0,0, var(--hero-overlay-bottom, 0.55)) 100%
            )
        );
        pointer-events: none;
    }
    /* Cuando un child explícitamente pase `--hero-overlay: none`, no pintamos */
    .section-hero[style*="--hero-overlay:none"] .section-hero__media::after,
    .section-hero[style*="--hero-overlay: none"] .section-hero__media::after { display: none; }

    /* ----- Grids comunes (servicios, galería, equipo, testimonios, stats) ----- */
    .section-servicios__grid,
    .section-galeria__grid,
    .section-equipo__grid,
    .section-testimonios__grid,
    .section-stats__grid {
        display: grid;
        gap: var(--sp-xl);
        grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    }

    /* ----- Card ----- */
    .card {
        background: var(--color-fondo-suave);
        border: 1px solid var(--color-borde);
        border-radius: var(--radio-lg);
        padding: var(--sp-xl);
        transition: transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
    }
    .card:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
    .card h3 { margin-bottom: var(--sp-sm); }

    /* Container queries — cards se adaptan al ancho de su contenedor, no del viewport */
    .card-grid { container-type: inline-size; container-name: card-grid; }
    @container card-grid (min-width: 600px) {
        .card { padding: var(--sp-xl); }
    }
    @container card-grid (min-width: 900px) {
        .card { padding: var(--sp-2xl); }
    }

    /* ----- Section header / encabezado ----- */
    .section-encabezado {
        text-align: center;
        max-width: 60ch;
        margin-inline: auto;
        margin-bottom: var(--sp-2xl);
    }
    .section-encabezado p { color: var(--color-texto-suave); margin-inline: auto; }

    /* ----- FAQ ----- */
    .faq-item { border-top: 1px solid var(--color-borde); padding: var(--sp-md) 0; }
    .faq-item summary { cursor: pointer; font-weight: 600; font-size: var(--fs-lg); list-style: none; display: flex; justify-content: space-between; align-items: center; }
    .faq-item summary::marker { display: none; }
    .faq-item summary::-webkit-details-marker { display: none; }
    .faq-item summary::after { content: '+'; font-size: var(--fs-xl); font-weight: 300; transition: transform var(--dur-base) var(--ease-out); }
    .faq-item[open] summary::after { transform: rotate(45deg); }
    .faq-item p { margin-top: var(--sp-sm); color: var(--color-texto-suave); }

    /* ----- Forms ----- */
    .form-grid { display: grid; gap: var(--sp-md); max-width: 600px; }
    .form-grid label { display: block; font-weight: 600; margin-bottom: var(--sp-sm); font-size: var(--fs-sm); }
    .form-grid input,
    .form-grid textarea,
    .form-grid select {
        width: 100%;
        padding: var(--sp-sm) var(--sp-md);
        border: 1px solid var(--color-borde);
        border-radius: var(--btn-radius);
        background: var(--color-fondo);
        color: var(--color-texto);
        min-height: 44px;
        transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
    }
    .form-grid input:focus-visible,
    .form-grid textarea:focus-visible,
    .form-grid select:focus-visible {
        border-color: var(--color-primario);
        outline: none;
        box-shadow: var(--shadow-focus);
    }
    .form-grid textarea { min-height: 140px; resize: vertical; }
    .form-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

    /* ----- Form errors per-field (a11y · WCAG 2.2 AA) ----- */
    /* Por defecto los .form-error son visualmente vacíos (sin tomar espacio
       hasta que tengan contenido). Los screen-readers los anuncian via
       aria-live="polite" en cuanto el contenido aparece. */
    .form-error {
        display: block;
        min-height: 0;
        margin-top: var(--sp-xs);
        font-size: var(--fs-small);
        color: var(--color-error);
        line-height: 1.4;
    }
    .form-error:empty { display: none; }
    .form-error__icon {
        vertical-align: -2px;
        margin-right: 0.35em;
        flex-shrink: 0;
    }

    /* Estado has-error: borde + halo en el input + foco visual sin perder contraste */
    .form-row.has-error input,
    .form-row.has-error textarea,
    .form-row.has-error select,
    .form-row__col.has-error input,
    .form-row__col.has-error textarea,
    .form-row__col.has-error select,
    [aria-invalid="true"] {
        border-color: var(--color-error);
        box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-error) 18%, transparent);
    }

    /* Validación :has() en runtime (cliente-side) — aplica el mismo borde a
       inputs que el browser marca como inválidos y NO están vacíos.
       :placeholder-shown evita pintar rojo apenas se carga la página. */
    .form-row:has(input:invalid:not(:placeholder-shown)),
    .form-row:has(textarea:invalid:not(:placeholder-shown)) {
        --tema-row-invalid: 1;
    }
    .form-row:has(input:invalid:not(:placeholder-shown)) input,
    .form-row:has(textarea:invalid:not(:placeholder-shown)) textarea {
        border-color: var(--color-error);
    }

    .form-msg { padding: var(--sp-sm) var(--sp-md); border-radius: var(--radio-md); margin-bottom: var(--sp-md); }
    .form-msg--ok { background: color-mix(in srgb, var(--color-exito) 15%, transparent); color: #064E3B; border: 1px solid var(--color-exito); }
    .form-msg--err { background: color-mix(in srgb, var(--color-error) 15%, transparent); color: #7F1D1D; border: 1px solid var(--color-error); }

    /* ----- Stats ----- */
    .stat-card { text-align: center; }
    .stat-card__n { font-size: var(--fs-3xl); font-weight: 800; color: var(--color-primario); font-variant-numeric: tabular-nums; }
    .stat-card__l { color: var(--color-texto-suave); font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: 0.08em; }

    /* ----- Testimonios ----- */
    .testimonio { display: grid; gap: var(--sp-md); }
    .testimonio__cita { font-size: var(--fs-lg); font-style: italic; }
    .testimonio__persona { display: flex; gap: var(--sp-sm); align-items: center; }
    .testimonio__persona img { width: 48px; height: 48px; border-radius: var(--radio-pill); }
    .testimonio__persona strong { display: block; }
    .testimonio__persona small { color: var(--color-texto-suave); }

    /* @scope — encapsular estilos a un componente sin pisar otros h3 del documento */
    @scope (.testimonio) {
        h3 { font-size: var(--fs-h4); margin-block-end: var(--sp-sm); }
        p { font-style: italic; }
    }

    /* ----- States · empty / error / loading / 404 (v2.5.0) -----
       Componente reutilizable para resultados vacíos, errores genéricos,
       loading async y 404. Usa currentColor en el SVG y se adapta al
       modo claro/oscuro automáticamente. */
    .tema-state {
        display: grid;
        place-items: center;
        text-align: center;
        gap: var(--sp-md);
        padding: clamp(2.5rem, 6vw, 5rem) var(--layout-padding-lado);
        max-width: 640px;
        margin-inline: auto;
    }
    .tema-state__art {
        color: var(--color-primario);
        opacity: 0.95;
        margin-bottom: var(--sp-sm);
    }
    .tema-state__art svg {
        max-width: 240px;
        height: auto;
        display: block;
    }
    .tema-state__eyebrow {
        font-size: var(--fs-sm);
        text-transform: uppercase;
        letter-spacing: 0.12em;
        color: var(--color-texto-suave);
        margin: 0;
        font-weight: 600;
    }
    .tema-state__title {
        font-size: var(--fs-h2);
        margin: 0;
        text-wrap: balance;
    }
    .tema-state__desc {
        color: var(--color-texto-suave);
        max-width: 48ch;
        margin: 0;
        text-wrap: pretty;
    }
    .tema-state__actions {
        display: flex;
        flex-wrap: wrap;
        gap: var(--sp-sm);
        justify-content: center;
        margin-top: var(--sp-sm);
    }
    .tema-state__search { width: 100%; max-width: 480px; margin-top: var(--sp-md); }

    /* Variantes — coloración del SVG según estado */
    .tema-state--error .tema-state__art { color: var(--color-error); }
    .tema-state--loading .tema-state__art { color: var(--color-primario); }
    .tema-state--empty .tema-state__art  { color: var(--color-primario); }

    /* Spinner del icono loading (entrega "vivo" sin JS) */
    @media (prefers-reduced-motion: no-preference) {
        .tema-state__icon--spin {
            animation: tema-spin 1.2s linear infinite;
            transform-origin: center;
        }
    }

    /* ----- Popovers / tooltips (anchor positioning preparado) ----- */
    [popover] {
        position: absolute;
        inset: unset;
        margin: 0;
        border: 1px solid var(--color-borde);
        background: var(--color-fondo);
        padding: var(--sp-sm) var(--sp-md);
        box-shadow: var(--shadow-md);
    }
    /* FIX-13 — `--anchor` queda como contract para popovers ancorables. Cada
       tooltip que use `.tema-tooltip` debe setear `--anchor: --mi-anchor;` inline
       o via clase. Sin valor, el popover degrada graceful sin position-anchor. */
    @supports (anchor-name: --foo) {
        [popover].tema-tooltip {
            position-anchor: var(--anchor);
            position-area: top;
        }
    }

    /* ----- Native <dialog> + view-transition para modales sin libs ----- */
    dialog::backdrop {
        background: color-mix(in srgb, var(--color-fondo) 0%, rgba(0,0,0,0.5));
        backdrop-filter: blur(4px);
    }
    dialog[open] {
        animation: tema-dialog-in var(--dur-base) var(--ease-out);
    }
    @keyframes tema-dialog-in {
        from { opacity: 0; transform: translateY(20px); }
        to   { opacity: 1; transform: translateY(0); }
    }
    @media (prefers-reduced-motion: reduce) {
        dialog[open] { animation: none; }
    }

    /* ----- Skeleton loader util ----- */
    .tema-skeleton {
        background: linear-gradient(90deg,
            var(--color-fondo-suave) 25%,
            color-mix(in srgb, var(--color-borde) 50%, var(--color-fondo-suave)) 50%,
            var(--color-fondo-suave) 75%
        );
        background-size: 200% 100%;
        animation: tema-skeleton 1.4s ease-in-out infinite;
        border-radius: var(--radio-md);
    }
    @keyframes tema-skeleton {
        from { background-position: 200% 0; }
        to   { background-position: -200% 0; }
    }
    @media (prefers-reduced-motion: reduce) {
        .tema-skeleton { animation: none; }
    }

    /* ----- :has() utilities a nivel section ----- */
    .section:has(> .contenedor:empty) { display: none; }
}

/* =========================================================
   @layer utilities — clases de propósito único + animations
   ========================================================= */
@layer utilities {

    /* ----- Animations on scroll ----- */
    @media (prefers-reduced-motion: no-preference) {
        [data-aos] {
            opacity: 0;
            transform: translateY(20px);
            transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
        }
        [data-aos].is-visible {
            opacity: 1;
            transform: translateY(0);
        }
    }

    /* ----- View Transitions (page-to-page navigation) ----- */
    @view-transition { navigation: auto; }
    ::view-transition-old(root),
    ::view-transition-new(root) {
        animation-duration: var(--dur-slow);
        animation-timing-function: var(--ease-out);
    }
    @media (prefers-reduced-motion: reduce) {
        ::view-transition-old(root),
        ::view-transition-new(root) { animation-duration: 0.01s; }
    }

    /* ----- Helpers ----- */
    .text-center { text-align: center; }
    .mt-4 { margin-top: var(--sp-md); }
    .mt-6 { margin-top: var(--sp-xl); }
    .flex { display: flex; }
    .grid { display: grid; }
    .hidden { display: none !important; }

    /* ----- Print ----- */
    @media print {
        .site-header, .site-footer, .wa-float, .hamburger, .mobile-nav { display: none !important; }
        body { background: #fff; color: #000; }
        a::after { content: ' (' attr(href) ')'; font-size: 0.9em; color: #555; }
    }
}

/* =========================================================
   @layer plugins — RESERVADO para children y plugins #512
   =========================================================
   Este layer queda VACÍO en el parent. Los childs y plugins
   pueden hacer:

       @layer plugins {
           .mi-clase { color: red; }
       }

   y GANAR contra cualquier regla de los layers superiores
   (reset/tokens/base/components/utilities) sin necesidad de
   `!important` ni specifity-war.

   Convención:
   - Childs: `@layer plugins.{nombre-del-child}` (ej: plugins.titanium)
   - Plugins #512: `@layer plugins.{nombre-del-plugin}` (ej: plugins.configurador)

   Esto permite que múltiples extensiones convivan en orden
   determinístico.
   ========================================================= */
