/* ============================================================================
   AIGUA — sistema de diseño
   ----------------------------------------------------------------------------
   Una sola hoja para todo el sitio.

   IDEA CENTRAL
   El agua toma la forma de donde cae. La marca tiene una carcasa propia —tinta
   profunda, azul agua, verde hoja— y cada página de proyecto es esa misma agua
   tomando la forma de SU sector, con los colores reales de la aplicación:

     agro        verde #0E4D33 · #1FAA59 · neón #00FF88, cristal y foto de campo
                 (Frutiger Aero: es literalmente el look de Demether.IA)
     seguridad   cian #00C0FF sobre negro azulado #00080F, alerta #FF3333
                 (el HUD de Ojo de Orus)
     optica      teal #005A82 · #006699 sobre hielo #E0F0FF
                 (la paleta clínica de Velion)

   Por eso las páginas no son todas oscuras: la de agronomía es CLARA y la de
   óptica también. El sitio alterna superficies a propósito — una web que solo
   tiene un tono se lee plana por muy buen tipo que tenga.

   MECANISMO
   Todo componente lee tokens de superficie (--fondo, --texto, --panel, --linea)
   en vez de colores fijos. Cambiar de claro a oscuro es redefinir esos tokens
   en el <body> o en una sección; el componente no se entera.

   COMPATIBILIDAD
   Se probó en un motor deliberadamente antiguo. De ahí: nada de color-mix(),
   :has(), anidamiento ni oklch; margin-left/right en vez de margin-inline;
   top/right/bottom/left en vez de inset; márgenes en vez de gap en Flexbox
   (en Grid sí se usa gap, ahí funciona en todas partes).
   ========================================================================= */

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

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

body {
  margin: 0;
  background: var(--fondo);
  color: var(--texto);
  font-family: var(--fuente);
  font-size: 17px;
  line-height: 1.6;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img, svg, canvas { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; }
::selection { background: rgba(var(--acento-rgb), 0.3); }

/* ── Tokens ─────────────────────────────────────────────────────────────── */
:root {
  --fuente: "Sora", "SF Pro Display", -apple-system, BlinkMacSystemFont,
            "Segoe UI", "Helvetica Neue", Arial, sans-serif;
  --fuente-texto: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI",
                  "Helvetica Neue", Arial, sans-serif;
  --mono: "JetBrains Mono", "SF Mono", "Cascadia Code", Consolas, monospace;

  /* ── Marca ── */
  --agua:    #35B6F0;
  --agua-2:  #0E7BC4;
  --hoja:    #86D13B;
  --hoja-2:  #4CAF3F;
  --plata:   #C9D6DE;
  --tinta:   #04070A;

  /* ── Paletas reales de las tres aplicaciones ──
     No son decorativas: están sacadas del código de cada app para que la web
     y el producto se reconozcan como la misma cosa. */
  --agro-fondo:   #0E4D33;   /* ventana de Demether.IA */
  --agro-cuerpo:  #1FAA59;
  --agro-neon:    #00FF88;
  --agro-cielo:   #6FC4F2;   /* del fondo fotográfico */

  --orus-cian:    #00C0FF;   /* trazado del HUD de Ojo de Orus */
  --orus-alerta:  #FF3333;
  --orus-negro:   #00080F;
  --orus-panel:   #001220;
  --orus-hielo:   #E6F7FF;

  --velion-teal:  #005A82;   /* interfaz de Velion */
  --velion-teal2: #006699;
  --velion-prof:  #003D5C;
  --velion-hielo: #E0F0FF;

  /* ── Superficie: oscura por defecto ── */
  --fondo:        #04070A;
  --fondo-alto:   #080D14;
  --texto:        #E8F1F6;
  --texto-tenue:  #93A8B8;
  --linea:        rgba(160, 200, 225, 0.13);
  --linea-fuerte: rgba(160, 200, 225, 0.26);
  --panel:        rgba(255, 255, 255, 0.045);
  --panel-alto:   rgba(255, 255, 255, 0.075);
  --panel-borde:  rgba(255, 255, 255, 0.10);
  --sombra:       0 24px 70px rgba(0, 0, 0, 0.5);
  --sombra-corta: 0 8px 26px rgba(0, 0, 0, 0.4);
  --nav-fondo:    rgba(4, 7, 10, 0.55);
  --nav-solido:   rgba(4, 7, 10, 0.9);
  --scrim:        4, 7, 10;          /* rgb del fondo, para velos y degradados */

  /* Acento por página (lo reescribe [data-tema]) */
  --acento:     var(--agua);
  --acento-2:   var(--hoja);
  --acento-rgb: 53, 182, 240;

  /* Ritmo */
  --ancho: 1220px;
  --ancho-estrecho: 900px;
  --gutter: clamp(20px, 5vw, 68px);
  --radio: 22px;
  --radio-s: 14px;
  --suave: cubic-bezier(0.22, 1, 0.36, 1);
}

/* ══════════════════════════════════════════════════════════════════════════
   SUPERFICIES
   .zona-clara y .zona-oscura redefinen los tokens para su subárbol. Sirven
   tanto para una sección suelta como para una cabecera oscura dentro de una
   página clara. Es lo que permite que el sitio respire alternando tonos.
   ══════════════════════════════════════════════════════════════════════════ */
.zona-oscura {
  --fondo:        #04070A;
  --fondo-alto:   #080D14;
  --texto:        #E8F1F6;
  --texto-tenue:  #93A8B8;
  --linea:        rgba(160, 200, 225, 0.13);
  --linea-fuerte: rgba(160, 200, 225, 0.26);
  --panel:        rgba(255, 255, 255, 0.045);
  --panel-alto:   rgba(255, 255, 255, 0.075);
  --panel-borde:  rgba(255, 255, 255, 0.10);
  --sombra:       0 24px 70px rgba(0, 0, 0, 0.5);
  --sombra-corta: 0 8px 26px rgba(0, 0, 0, 0.4);
  --scrim:        4, 7, 10;
  color: var(--texto);
}

.zona-clara {
  --fondo:        #F2F7FB;
  --fondo-alto:   #FFFFFF;
  --texto:        #08161F;
  --texto-tenue:  #4F6675;
  --linea:        rgba(8, 30, 45, 0.11);
  --linea-fuerte: rgba(8, 30, 45, 0.2);
  --panel:        rgba(255, 255, 255, 0.72);
  --panel-alto:   #FFFFFF;
  --panel-borde:  rgba(255, 255, 255, 0.9);
  --sombra:       0 26px 60px rgba(10, 40, 60, 0.13);
  --sombra-corta: 0 6px 22px rgba(10, 40, 60, 0.09);
  --scrim:        242, 247, 251;
  color: var(--texto);
}

/* ── Temas de página ────────────────────────────────────────────────────── */

/* Demether.IA — claro, Frutiger Aero: cielo, campo, cristal */
body[data-tema="agro"] {
  --acento: #14A05A; --acento-2: #0E9BD8; --acento-rgb: 20, 160, 90;
  --fondo:        #E9F5FD;
  --fondo-alto:   #FFFFFF;
  --texto:        #062418;
  --texto-tenue:  #4B6E60;
  --linea:        rgba(14, 77, 51, 0.13);
  --linea-fuerte: rgba(14, 77, 51, 0.24);
  --panel:        rgba(255, 255, 255, 0.66);
  --panel-alto:   rgba(255, 255, 255, 0.9);
  --panel-borde:  rgba(255, 255, 255, 0.92);
  --sombra:       0 26px 64px rgba(9, 60, 45, 0.16);
  --sombra-corta: 0 8px 24px rgba(9, 60, 45, 0.1);
  --nav-fondo:    rgba(233, 245, 253, 0.35);
  --nav-solido:   rgba(240, 250, 254, 0.86);
  --scrim:        233, 245, 253;
  background:
    radial-gradient(1100px 620px at 82% -6%, rgba(111, 196, 242, 0.55), transparent 62%),
    radial-gradient(900px 560px at 6% 22%, rgba(31, 170, 89, 0.16), transparent 65%),
    linear-gradient(to bottom, #DDF0FC 0%, #EDF7FD 34%, #F4FAF6 100%);
  background-attachment: fixed;
}

/* Ojo de Orus — oscuro, HUD de vigilancia: cian sobre negro azulado */
body[data-tema="seguridad"] {
  --acento: #00C0FF; --acento-2: #FF3333; --acento-rgb: 0, 192, 255;
  --fondo:        #00080F;
  --fondo-alto:   #001220;
  --texto:        #E6F7FF;
  --texto-tenue:  #7FA4BA;
  --linea:        rgba(0, 192, 255, 0.16);
  --linea-fuerte: rgba(0, 192, 255, 0.34);
  --panel:        rgba(0, 40, 70, 0.34);
  --panel-alto:   rgba(0, 52, 88, 0.5);
  --panel-borde:  rgba(0, 192, 255, 0.22);
  --sombra:       0 24px 70px rgba(0, 0, 0, 0.62);
  --sombra-corta: 0 8px 26px rgba(0, 0, 0, 0.5);
  --nav-fondo:    rgba(0, 8, 15, 0.55);
  --nav-solido:   rgba(0, 12, 22, 0.92);
  --scrim:        0, 8, 15;
  background:
    radial-gradient(1200px 700px at 50% -10%, rgba(0, 120, 175, 0.2), transparent 66%),
    linear-gradient(to bottom, #00080F, #000B14 60%, #00080F 100%);
  background-attachment: fixed;
}

/* Velion — claro hielo, clínico: el teal de la interfaz del probador */
body[data-tema="optica"] {
  --acento: #005A82; --acento-2: #0E9BD8; --acento-rgb: 0, 90, 130;
  --fondo:        #EFF7FC;
  --fondo-alto:   #FFFFFF;
  --texto:        #052430;
  --texto-tenue:  #4E7488;
  --linea:        rgba(0, 61, 92, 0.12);
  --linea-fuerte: rgba(0, 61, 92, 0.22);
  --panel:        rgba(255, 255, 255, 0.74);
  --panel-alto:   #FFFFFF;
  --panel-borde:  rgba(255, 255, 255, 0.92);
  --sombra:       0 26px 62px rgba(0, 61, 92, 0.15);
  --sombra-corta: 0 8px 24px rgba(0, 61, 92, 0.09);
  --nav-fondo:    rgba(239, 247, 252, 0.4);
  --nav-solido:   rgba(244, 250, 253, 0.88);
  --scrim:        239, 247, 252;
  background:
    radial-gradient(1000px 600px at 88% 0%, rgba(14, 155, 216, 0.2), transparent 62%),
    radial-gradient(760px 520px at 0% 34%, rgba(0, 90, 130, 0.11), transparent 66%),
    linear-gradient(to bottom, #E4F1F9 0%, #F1F8FC 40%, #FFFFFF 100%);
  background-attachment: fixed;
}

/* ══════════════════════════════════════════════════════════════════════════
   MODO OSCURO A VOLUNTAD
   --------------------------------------------------------------------------
   Cada página tiene su tono por diseño: agronomía y óptica son claras,
   seguridad es oscura. El botón de la barra fuerza el oscuro en todas para
   quien lo prefiera, y la elección se recuerda.

   Como todos los componentes leen tokens de superficie, casi todo el trabajo
   es redefinirlos. Lo único que hay que perseguir a mano es lo que trae color
   propio: los paneles de cristal blanco y las fotos claras.
   ══════════════════════════════════════════════════════════════════════════ */
html[data-modo="oscuro"] .zona-clara,
html[data-modo="oscuro"] body[data-tema="agro"],
html[data-modo="oscuro"] body[data-tema="optica"] {
  --fondo:        #05090E;
  --fondo-alto:   #0A1119;
  --texto:        #E8F1F6;
  --texto-tenue:  #93A8B8;
  --linea:        rgba(160, 200, 225, 0.13);
  --linea-fuerte: rgba(160, 200, 225, 0.26);
  --panel:        rgba(255, 255, 255, 0.045);
  --panel-alto:   rgba(255, 255, 255, 0.075);
  --panel-borde:  rgba(255, 255, 255, 0.10);
  --sombra:       0 24px 70px rgba(0, 0, 0, 0.5);
  --sombra-corta: 0 8px 26px rgba(0, 0, 0, 0.4);
  --nav-fondo:    rgba(5, 9, 14, 0.55);
  --nav-solido:   rgba(5, 9, 14, 0.92);
  --scrim:        5, 9, 14;
  color: var(--texto);
}

/* Los acentos de las páginas claras están elegidos para contrastar sobre
   blanco; sobre negro se apagan. En oscuro suben de luminosidad. */
html[data-modo="oscuro"] body[data-tema="agro"] {
  --acento: #4ADE80; --acento-2: #38BDF8; --acento-rgb: 74, 222, 128;
}
html[data-modo="oscuro"] body[data-tema="optica"] {
  --acento: #4FC3F7; --acento-2: #8FE3FF; --acento-rgb: 79, 195, 247;
}
/* …y con el acento claro, el texto del botón vuelve a tinta */
html[data-modo="oscuro"] body[data-tema="agro"] .boton--lleno,
html[data-modo="oscuro"] body[data-tema="optica"] .boton--lleno { color: #04141C; }

html[data-modo="oscuro"] body[data-tema="agro"],
html[data-modo="oscuro"] body[data-tema="optica"] {
  background:
    radial-gradient(1100px 620px at 82% -6%, rgba(20, 90, 130, 0.35), transparent 62%),
    radial-gradient(900px 560px at 6% 22%, rgba(20, 110, 70, 0.22), transparent 65%),
    linear-gradient(to bottom, #05090E 0%, #070D14 40%, #05090E 100%);
  background-attachment: fixed;
}
html[data-modo="oscuro"] .seccion.zona-clara { background: var(--fondo); }

/* Cristal blanco → cristal ahumado */
html[data-modo="oscuro"] .portada__vidrio {
  background: rgba(8, 18, 26, 0.58);
  border-color: rgba(255, 255, 255, 0.14);
  color: #E8F1F6;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.12);
}
html[data-modo="oscuro"] .portada__vidrio .subtitulo { color: #9FBACB; }
html[data-modo="oscuro"] .portada__vidrio .migas { color: #8FA8B8; }

html[data-modo="oscuro"] .aero-cinta {
  background: linear-gradient(125deg, rgba(31,170,89,0.2), rgba(14,155,216,0.16) 55%, rgba(255,255,255,0.03));
  border-color: rgba(255, 255, 255, 0.1);
}
html[data-modo="oscuro"] .aero-cinta::before { opacity: 0.12; }
html[data-modo="oscuro"] .forma-mini {
  background: rgba(255, 255, 255, 0.055);
  border-color: rgba(255, 255, 255, 0.1);
}

html[data-modo="oscuro"] .lente {
  background: linear-gradient(145deg, rgba(255,255,255,0.06), rgba(0,40,62,0.42));
  border-color: rgba(255, 255, 255, 0.1);
}
html[data-modo="oscuro"] .lente::after { opacity: 0.25; }

/* Las fotos de campo son de día y a pleno sol: en oscuro se bajan, o el resto
   de la página parece apagada al lado. */
html[data-modo="oscuro"] .cabecera-proyecto__foto,
html[data-modo="oscuro"] .fijado__foto { filter: brightness(0.5) saturate(0.85); }

html[data-modo="oscuro"] .burbujas span { opacity: 0.5; }

/* ── Botón del modo ─────────────────────────────────────────────────────── */
.nav__modo {
  display: inline-grid; place-items: center;
  width: 38px; height: 38px; margin-left: 10px;
  border-radius: 999px;
  border: 1px solid var(--linea-fuerte);
  background: transparent;
  color: inherit; cursor: pointer;
  flex: 0 0 auto;
  transition: background .25s, border-color .25s, transform .25s var(--suave);
}
.nav__modo:hover {
  background: rgba(var(--acento-rgb), 0.14);
  border-color: rgba(var(--acento-rgb), 0.5);
  transform: rotate(-18deg);
}
.nav__modo svg { width: 18px; height: 18px; stroke: currentColor; fill: none;
                 stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
/* Luna cuando está apagado, sol cuando está encendido: el icono enseña a qué
   se cambia, no en qué estado se está. */
.nav__modo .sol { display: none; }
.nav__modo[aria-pressed="true"] .sol { display: block; }
.nav__modo[aria-pressed="true"] .luna { display: none; }
.nav[data-solido="no"] .nav__modo { border-color: rgba(255, 255, 255, 0.34); }

@media (max-width: 880px) {
  /* Fuera del menú desplegable: tiene que quedar siempre a la vista, al lado
     del botón de hamburguesa. */
  .nav__modo { margin-left: auto; margin-right: 4px; }
}

/* Grano finísimo sobre todo el sitio. No se ve; se nota. Es la diferencia
   entre un degradado plano de plantilla y una superficie con materia. */
body::after {
  content: "";
  position: fixed; top: 0; right: 0; bottom: 0; left: 0;
  z-index: 9999; pointer-events: none;
  opacity: 0.035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ── Tipografía ─────────────────────────────────────────────────────────── */
.gigante, .titulo, .subtitulo, .etiqueta, .titulo-s { margin: 0; }

.gigante {
  font-size: clamp(2.7rem, 6.6vw, 5.6rem);
  line-height: 1.0;
  letter-spacing: -0.038em;
  font-weight: 700;
  text-wrap: balance;
}

.titulo {
  font-size: clamp(2rem, 4.4vw, 3.5rem);
  line-height: 1.05;
  letter-spacing: -0.032em;
  font-weight: 600;
  text-wrap: balance;
}

.titulo-s {
  font-size: clamp(1.35rem, 2.4vw, 1.9rem);
  line-height: 1.18;
  letter-spacing: -0.024em;
  font-weight: 600;
}

.subtitulo {
  font-family: var(--fuente-texto);
  font-size: clamp(1.08rem, 1.55vw, 1.32rem);
  line-height: 1.55;
  font-weight: 400;
  color: var(--texto-tenue);
  letter-spacing: -0.006em;
}

.etiqueta {
  display: inline-flex; align-items: center;
  font-family: var(--fuente-texto);
  font-size: 0.7rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--acento);
}
/* Guioncito delante de la etiqueta: ancla la sección sin añadir un elemento */
.etiqueta::before {
  content: ""; width: 22px; height: 1px; margin-right: 12px;
  background: currentColor; opacity: 0.55; flex: 0 0 auto;
}
.centrado > .etiqueta::after,
.etiqueta.centrado::after {
  content: ""; width: 22px; height: 1px; margin-left: 12px;
  background: currentColor; opacity: 0.55; flex: 0 0 auto;
}
.etiqueta.centrado { justify-content: center; }
/* Dentro de un .paso (que ya centra el texto) la etiqueta se cierra por los
   dos lados sin tener que marcarla: si no, sale el guion de la izquierda solo
   y el bloque queda descuadrado. */
.paso .etiqueta { justify-content: center; }
.paso .etiqueta::after {
  content: ""; width: 22px; height: 1px; margin-left: 12px;
  background: currentColor; opacity: 0.55; flex: 0 0 auto;
}

p, li { font-family: var(--fuente-texto); }
strong { font-weight: 600; color: var(--texto); }
.destacado { color: var(--acento); }

.degradado {
  background: linear-gradient(105deg, var(--acento) 0%, var(--acento-2) 58%, var(--plata) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* Sin esto, la sombra del contenedor se ve A TRAVÉS de las letras (el color
     es transparente) y el degradado sale sucio y apagado. */
  text-shadow: none;
}
.zona-clara .degradado,
body[data-tema="agro"] .degradado,
body[data-tema="optica"] .degradado {
  background: linear-gradient(105deg, var(--acento) 0%, var(--acento-2) 100%);
  -webkit-background-clip: text; background-clip: text;
}

/* ── Estructura ─────────────────────────────────────────────────────────── */
/* margin-left/right en vez de margin-inline: la forma lógica no se aplica en
   motores algo antiguos y el contenido se queda pegado al borde izquierdo. */
.contenedor {
  width: min(var(--ancho), 100% - var(--gutter) * 2);
  max-width: var(--ancho);
  margin-left: auto;
  margin-right: auto;
}

.seccion { padding: clamp(84px, 13vh, 176px) 0; position: relative; }
.seccion--compacta { padding: clamp(52px, 8vh, 96px) 0; }
.seccion--alto { background: var(--fondo-alto); }

/* Sección clara dentro de una página oscura (y al revés). El fondo se pinta
   aquí porque .zona-clara solo cambia tokens, no dibuja. */
.seccion.zona-clara { background: var(--fondo); }
.seccion.zona-oscura { background: var(--fondo); }

/* Costura entre superficies: una línea de luz del color de acento. Evita el
   corte seco de un bloque claro pegado a uno oscuro. */
.seccion.zona-clara::before,
.seccion.zona-oscura::before {
  content: ""; position: absolute; top: 0; right: 0; left: 0; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(var(--acento-rgb), 0.5), transparent);
}

/* min(100%, …) y no el ancho a secas: en una pantalla de 360 px el contenedor
   mide menos que el mínimo de la pista, la columna se queda a su ancho fijo y
   la rejilla entera se sale por la derecha. Con min() la pista nunca puede
   pedir más de lo que hay. Es EL arreglo de móvil de toda la hoja. */
.rejilla { display: grid; gap: clamp(18px, 2.2vw, 28px); }
.rejilla--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }
/* 320 y no 260: con el contenedor a 1220 px, 260 dejaba entrar una cuarta
   columna y las tarjetas quedaban tan estrechas que los chips se partían en
   dos líneas. Con 320 se queda en tres, que es la lectura que se buscaba. */
.rejilla--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); }
.rejilla--4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 198px), 1fr)); }

/* Rejilla editorial 5/7: rompe la simetría de «todo en columnas iguales», que
   es lo que hace que una página se lea como plantilla. */
.rejilla--editorial { grid-template-columns: 1fr; }
@media (min-width: 900px) {
  .rejilla--editorial { grid-template-columns: 5fr 7fr; gap: clamp(34px, 5vw, 76px); }
  .rejilla--editorial--inv { grid-template-columns: 7fr 5fr; }
}

.pegajoso { position: sticky; top: 108px; }

/* Cabecera de sección reutilizable */
.cabecera-seccion { max-width: 720px; }
.cabecera-seccion.centrado { margin-left: auto; margin-right: auto; }
.cabecera-seccion .titulo { margin-top: 22px; }
.cabecera-seccion .subtitulo { margin-top: 20px; }

/* ══════════════════════════════════════════════════════════════════════════
   NOTA SOBRE EL ESPACIADO EN FLEX
   `gap` funciona en Grid en todas partes, pero en Flexbox falta en motores algo
   antiguos y los elementos salen pegados unos a otros («AIGUA/Proyectos/Óptica»
   sin respirar, chips con el punto encima del texto). Por eso las filas
   pequeñas separan con margen y no con gap: se ve igual en todos los motores.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Navegación ─────────────────────────────────────────────────────────── */
.nav {
  /* top/right/left explícitos: el atajo `inset` no se aplica en motores algo
     antiguos y la barra se quedaba a media anchura. */
  position: fixed; top: 0; right: 0; left: 0; z-index: 100;
  display: flex; align-items: center;
  padding: 13px var(--gutter);
  background: transparent;
  border-bottom: 1px solid transparent;
  /* El color va mucho más rápido que el fondo a propósito. En agronomía y
     óptica la barra pasa de transparente a CLARA mientras el texto pasa de
     blanco a tinta: si ambos tardan lo mismo, hay medio segundo de texto casi
     blanco sobre fondo casi blanco. Resolviendo el color primero, el fondo
     puede seguir fundiendo con calma. */
  transition: background .45s var(--suave), border-color .45s var(--suave),
              padding .45s var(--suave), color .16s linear;
}
/* Arriba del todo la barra flota sobre una cabecera oscura (o sobre la foto
   con velo), así que el texto va claro sí o sí. Al hacerse sólida pasa a los
   tokens de la página, que en agro y óptica son oscuros sobre claro. */
.nav[data-solido="no"] { color: #FFFFFF; }
.nav[data-solido="no"]::before {
  content: ""; position: absolute; top: 0; right: 0; left: 0; height: 190%;
  pointer-events: none; z-index: -1;
  background: linear-gradient(to bottom, rgba(2, 10, 16, 0.6), transparent);
}
.nav[data-solido="si"] {
  padding-top: 9px; padding-bottom: 9px;
  color: var(--texto);
  background: var(--nav-solido);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-bottom-color: var(--linea);
}

.nav__marca { display: flex; align-items: center; margin-right: auto; }
.nav__marca img {
  width: 30px; height: auto; margin-right: 11px;
  transition: transform .5s var(--suave);
}
.nav__marca:hover img { transform: rotate(-8deg) scale(1.08); }
.nav__marca span { font-weight: 700; letter-spacing: 0.14em; font-size: 1.02rem; }

.nav__enlaces { display: flex; align-items: center; }
.nav__enlaces > * + * { margin-left: 2px; }
.nav__enlaces a {
  position: relative;
  padding: 8px 14px; border-radius: 999px;
  font-family: var(--fuente-texto);
  font-size: 0.9rem; font-weight: 500;
  /* 0.82 y no 0.7: sobre la barra sólida CLARA de agronomía y óptica, un texto
     más tenue se quedaba por debajo del contraste legible. */
  opacity: 0.82;
  transition: opacity .25s, background .25s;
}
.nav__enlaces a:hover { opacity: 1; background: rgba(var(--acento-rgb), 0.12); }
.nav__enlaces a[aria-current="page"] { opacity: 1; color: var(--acento); font-weight: 600; }

.nav__menu { display: none; background: none; border: 0; cursor: pointer; padding: 8px; }
.nav__menu svg { width: 22px; height: 22px; stroke: currentColor; }

@media (max-width: 880px) {
  .nav__menu { display: block; }
  .nav__enlaces {
    position: absolute; top: 100%; right: 0; left: 0;
    flex-direction: column; align-items: stretch;
    color: var(--texto);
    background: var(--nav-solido);
    backdrop-filter: saturate(180%) blur(22px);
    -webkit-backdrop-filter: saturate(180%) blur(22px);
    border-bottom: 1px solid var(--linea);
    padding: 6px var(--gutter) 18px;
    display: none;
  }
  .nav__enlaces[data-abierto="si"] { display: flex; }
  .nav__enlaces > * + * { margin-left: 0; }
  .nav__enlaces a { padding: 13px 4px; font-size: 1rem; opacity: 0.85; }
}

/* Barra de progreso de lectura */
.progreso {
  position: fixed; top: 0; left: 0; height: 2px; z-index: 101;
  width: 0;
  background: linear-gradient(90deg, var(--acento), var(--acento-2));
  box-shadow: 0 0 14px rgba(var(--acento-rgb), 0.7);
  transition: width .1s linear;
}

/* ══════════════════════════════════════════════════════════════════════════
   VIDRIO
   El recurso que comparten las tres aplicaciones: paneles translúcidos con
   desenfoque por detrás. En la app de agronomía son botones sobre una foto de
   campo; aquí son tarjetas, fichas y pasos. Es lo que da el aire «Aero» sin
   caer en el pastiche.
   ══════════════════════════════════════════════════════════════════════════ */
.vidrio {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--panel-borde);
  border-radius: var(--radio);
  backdrop-filter: saturate(150%) blur(18px);
  -webkit-backdrop-filter: saturate(150%) blur(18px);
  box-shadow: var(--sombra-corta);
}
/* Reflejo superior: una sola línea clara arriba. Sin esto el panel parece un
   rectángulo con opacidad; con esto parece cristal. */
.vidrio::after {
  content: ""; position: absolute; top: 0; right: 14%; left: 14%; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.7), transparent);
  pointer-events: none;
}
.zona-oscura .vidrio::after,
body[data-tema="seguridad"] .vidrio::after {
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent);
}

/* ── Portada ────────────────────────────────────────────────────────────── */
.portada {
  position: relative;
  min-height: 100vh;          /* respaldo para motores sin svh */
  min-height: 100svh;
  display: grid;
  place-items: center;
  text-align: center;
  overflow: hidden;
}

.portada__lienzo {
  position: absolute; top: 0; left: 0;
  width: 100%; height: 100%;
  z-index: 0;
}

.portada__contenido {
  position: relative; z-index: 3;
  padding: 128px var(--gutter) 108px;
  width: min(var(--ancho), 100%);
  margin-left: auto;
  margin-right: auto;
}

.portada__logo {
  width: clamp(78px, 10vw, 112px);
  margin: 0 auto clamp(24px, 3vw, 34px);
  filter: drop-shadow(0 18px 44px rgba(var(--acento-rgb), 0.4));
  animation: flotar 7s ease-in-out infinite;
}
@keyframes flotar {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-11px); }
}

/* Píldora sobre el titular: sitúa a la empresa en una línea antes de que el
   visitante lea nada más. */
.pildora {
  display: inline-flex; align-items: center;
  padding: 7px 8px 7px 7px;
  border-radius: 999px;
  border: 1px solid var(--panel-borde);
  background: var(--panel);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  font-family: var(--fuente-texto);
  font-size: 0.79rem; font-weight: 500;
  margin-bottom: 26px;
}
.pildora__marca {
  display: inline-block;
  padding: 3px 11px; border-radius: 999px; margin-right: 11px;
  background: rgba(var(--acento-rgb), 0.18);
  color: var(--acento);
  font-weight: 600; font-size: 0.72rem; letter-spacing: 0.06em;
}
.pildora span:last-child { padding-right: 12px; opacity: 0.85; }

.portada__pie {
  position: absolute; bottom: 26px; left: 50%;
  transform: translateX(-50%);
  z-index: 3;
  display: flex; flex-direction: column; align-items: center;
  color: #FFFFFF; font-size: 0.7rem;
  letter-spacing: 0.22em; text-transform: uppercase;
  opacity: 0.75;
}
.portada__pie > * + * { margin-top: 9px; }
.portada__raton {
  width: 22px; height: 34px; border-radius: 12px;
  border: 1.5px solid rgba(255, 255, 255, 0.45);
  position: relative;
}
.portada__raton::after {
  content: ""; position: absolute; left: 50%; top: 7px;
  width: 3px; height: 6px; border-radius: 2px;
  background: currentColor;
  transform: translateX(-50%);
  animation: rueda 1.9s var(--suave) infinite;
}
@keyframes rueda {
  0%   { opacity: 0; transform: translate(-50%, -4px); }
  35%  { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, 12px); }
}

/* En agronomía el pie de la portada cae sobre el degradado que ya está
   fundiendo a blanco: en blanco no se leería. Pasa a tinta.
   (En óptica no hace falta: allí la cabecera entera es .zona-oscura.) */
body[data-tema="agro"] .portada__pie { color: var(--texto); opacity: 0.55; }
body[data-tema="agro"] .portada__raton { border-color: rgba(6, 36, 24, 0.35); }

/* Velo entre la escena 3D y el texto.
   Está calibrado: si es muy suave el titular no se lee; si es muy fuerte apaga
   la escena y el 3D deja de aportar. Se queda a media altura y la legibilidad
   se remata con la sombra de .portada__contenido / .paso, que oscurece solo
   detrás de las letras en vez de toda la imagen.
   Usa --scrim para que en las páginas claras el velo funda hacia blanco y no
   hacia negro. */
.velo {
  position: absolute; top: 0; right: 0; bottom: 0; left: 0;
  z-index: 1; pointer-events: none;
  background:
    radial-gradient(ellipse 68% 56% at 50% 50%, rgba(var(--scrim), 0.5) 0%,
                    rgba(var(--scrim), 0.28) 46%, transparent 80%),
    linear-gradient(to bottom, rgba(var(--scrim), 0.85) 0%, rgba(var(--scrim), 0.08) 26%,
                    rgba(var(--scrim), 0.14) 62%, var(--fondo) 100%);
}
/* Sobre una foto real hace falta más cuerpo, y oscuro aunque la página sea
   clara: si no, ni el texto blanco de la navegación ni el titular se leen. */
/* Muchas paradas y no cuatro: la foto tiene que pasar de un velo OSCURO arriba
   (para que se lea la navegación sobre el cielo) a uno CLARO abajo (para
   fundir con la página). Con pocos pasos el cruce entre ambos se ve como una
   banda horizontal a media altura. */
.velo--foto {
  background:
    linear-gradient(to bottom,
      rgba(2, 22, 34, 0.62) 0%,
      rgba(2, 22, 34, 0.14) 20%,
      rgba(2, 22, 34, 0.08) 44%,
      rgba(var(--scrim), 0.26) 66%,
      rgba(var(--scrim), 0.66) 82%,
      rgba(var(--scrim), 0.94) 94%,
      var(--fondo) 100%);
}

/* Aurora: manchas de color muy difusas detrás del contenido. Le quita a la
   portada el aspecto de «fondo negro con texto encima». */
.aurora {
  position: absolute; top: 0; right: 0; bottom: 0; left: 0;
  z-index: 1; pointer-events: none; overflow: hidden;
}
.aurora::before, .aurora::after {
  content: ""; position: absolute; border-radius: 50%;
  filter: blur(90px); opacity: 0.5;
}
.aurora::before {
  width: 46vw; height: 46vw; top: -12vw; left: -8vw;
  background: radial-gradient(circle, rgba(var(--acento-rgb), 0.5), transparent 70%);
  animation: derivaA 22s ease-in-out infinite alternate;
}
.aurora::after {
  width: 40vw; height: 40vw; right: -6vw; bottom: -14vw;
  background: radial-gradient(circle, rgba(134, 209, 59, 0.35), transparent 70%);
  animation: derivaB 26s ease-in-out infinite alternate;
}
@keyframes derivaA { to { transform: translate3d(9vw, 6vh, 0) scale(1.15); } }
@keyframes derivaB { to { transform: translate3d(-8vw, -5vh, 0) scale(1.1); } }

/* Sombra local: hace legible el texto sin tapar la escena que hay detrás.
   Solo en superficies oscuras — sobre fondo claro una sombra negra ensucia. */
.zona-oscura .portada__contenido,
.zona-oscura .cabecera-proyecto__contenido,
.zona-oscura .paso,
body[data-tema="seguridad"] .portada__contenido,
body[data-tema="seguridad"] .cabecera-proyecto__contenido,
body[data-tema="seguridad"] .paso,
body:not([data-tema]) .portada__contenido,
body:not([data-tema]) .paso {
  text-shadow: 0 2px 26px rgba(2, 6, 9, 0.95), 0 1px 5px rgba(2, 6, 9, 0.8);
}

/* ══════════════════════════════════════════════════════════════════════════
   TEXTO QUE ENTRA PALABRA A PALABRA
   --------------------------------------------------------------------------
   Un titular que aparece de golpe se lee y se olvida. Entrando por palabras,
   la vista lo sigue hasta el final — que es justo lo que se quiere de un
   titular. El reparto lo hace aigua.js envolviendo cada palabra y numerándola
   con --p; aquí solo se describe el movimiento.

   Se aplica SOLO a titulares. En un párrafo largo, animar palabra a palabra
   entorpece la lectura en vez de ayudarla.
   ══════════════════════════════════════════════════════════════════════════ */
[data-anim-texto] .pal {
  display: inline-block;
  /* Sin esto, cada palabra se alinea por su línea base y el hueco del trazo
     descendente se suma al alto de la línea: el titular abre el interlineado y
     deja de parecer el mismo. Todas las cajas miden lo mismo (el line-height
     heredado), así que alinearlas por arriba no descuadra nada. */
  vertical-align: top;
  opacity: 0;
  transform: translateY(0.55em) rotate(2.5deg);
  transition: opacity .62s var(--suave), transform .62s var(--suave);
  transition-delay: calc(var(--p, 0) * 45ms);
  will-change: opacity, transform;
}
[data-anim-texto][data-visto] .pal { opacity: 1; transform: none; }

/* ── Subrayado que se dibuja al entrar ──────────────────────────────────── */
.subrayado { position: relative; white-space: nowrap; }
.subrayado::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -0.08em;
  height: 0.16em; border-radius: 999px;
  background: linear-gradient(90deg, var(--acento), var(--acento-2));
  transform: scaleX(0); transform-origin: left center;
  transition: transform .8s var(--suave) .35s;
}
[data-visto] .subrayado::after, [data-revelar="visible"] .subrayado::after { transform: scaleX(1); }

/* ── Trazo SVG que se dibuja con el scroll ──────────────────────────────── */
/* El recorrido lo fija aigua.js en --trazo (de 1 a 0). */
[data-trazo] { stroke-dasharray: var(--largo, 1000); stroke-dashoffset: calc(var(--largo, 1000) * var(--trazo, 1)); }

/* ── Revelado al hacer scroll ───────────────────────────────────────────── */
[data-revelar] {
  opacity: 0;
  transform: translateY(34px);
  transition: opacity .9s var(--suave), transform .9s var(--suave);
  transition-delay: var(--retardo, 0ms);
  will-change: opacity, transform;
}
[data-revelar="visible"] { opacity: 1; transform: none; }

[data-revelar="escala"] { transform: scale(0.94) translateY(28px); }
[data-revelar="escala"][data-visible] { transform: none; }

/* ══════════════════════════════════════════════════════════════════════════
   EL MODO OSCURO ES EL INTERRUPTOR DEL MOVIMIENTO
   --------------------------------------------------------------------------
   REGLA DEL SITIO: la web se mueve SIEMPRE, en cualquier equipo. Claro =
   animado, sí o sí. Oscuro = quieto. No hay más niveles y no se pregunta nada.

   Antes esto lo decidía `prefers-reduced-motion`, la preferencia de
   accesibilidad del sistema. Se dejó de mirar porque en Windows se enciende
   sola con muchísima facilidad —la activa el ahorro de batería y viene puesta
   de fábrica en muchos equipos— y la web aparecía inmóvil ante gente que no
   había pedido nada.

   La contrapartida, dicha claramente: quien tenga esa preferencia puesta por
   NECESIDAD ya no la recibe. Su salida es el modo oscuro, y por eso el botón
   de la barra lo anuncia en su rótulo — una salida que no se encuentra no
   sirve de nada.

   Ojo con la distinción: esto es el MODO oscuro (`html[data-modo="oscuro"]`,
   el botón de la luna), no el TEMA oscuro. La página de seguridad es negra por
   diseño y sigue moviéndose como todas.
   ══════════════════════════════════════════════════════════════════════════ */
html[data-modo="oscuro"] { scroll-behavior: auto; }

/* Los textos siguen apareciendo, pero se FUNDEN en vez de subir: si no, media
   página se queda en blanco hasta que pasas por encima. Se toca
   `transition-property` y no la abreviatura `transition`, que reiniciaría el
   retardo — y el retardo es lo que escalona la entrada de los hermanos del
   titular. */
html[data-modo="oscuro"] [data-revelar],
html[data-modo="oscuro"] [data-revelar="escala"] {
  transform: none !important;
  transition-property: opacity !important;
}
html[data-modo="oscuro"] [data-anim-texto] .pal {
  transform: none !important;
  transition-property: opacity !important;
}
/* En los pasos de las secciones fijadas se quita el escalonado: entran juntos */
html[data-modo="oscuro"] .paso > * {
  transform: none !important;
  transition-property: opacity !important;
  transition-delay: 0s !important;
}
html[data-modo="oscuro"] .subrayado::after { transform: scaleX(1) !important; }
html[data-modo="oscuro"] [data-trazo] { stroke-dashoffset: 0 !important; }

/* Todo lo que cruza la pantalla, apagado */
html[data-modo="oscuro"] .portada__raton::after,
html[data-modo="oscuro"] .portada__logo,
html[data-modo="oscuro"] .burbujas span,
html[data-modo="oscuro"] .hojas span,
html[data-modo="oscuro"] .barrido,
html[data-modo="oscuro"] .telemetria .rec,
html[data-modo="oscuro"] .medio__chapa .rec,
html[data-modo="oscuro"] .aurora::before,
html[data-modo="oscuro"] .aurora::after,
html[data-modo="oscuro"] .cinta-texto__pista { animation: none !important; }
html[data-modo="oscuro"] .portada__pie { display: none; }
/* La tarjeta deja de inclinarse y de encender el halo bajo el cursor */
html[data-modo="oscuro"] .tarjeta { transform: none !important; }
html[data-modo="oscuro"] .tarjeta::before { opacity: 0 !important; }

@keyframes respirar       { from { opacity: 0.32; } to { opacity: 0.62; } }
@keyframes respirar-tenue { from { opacity: 0.12; } to { opacity: 0.50; } }

/* ── Versión sin movimiento de las secciones fijadas ────────────────────── */
/* Cuando el usuario pide reducir movimiento, la sección deja de fijarse y sus
   pasos pasan a ser bloques normales, uno debajo de otro. Hay que devolverles
   el flujo: si se quedan en `position:absolute` se apilan todos en el mismo
   punto y el texto se vuelve ilegible. */
[data-fijado][data-plano="si"] { height: auto !important; }

[data-fijado][data-plano="si"] .fijado__panel {
  position: static;
  height: auto;
  display: block;
  padding: clamp(60px, 9vh, 110px) 0;
}

[data-fijado][data-plano="si"] .fijado__lienzo,
[data-fijado][data-plano="si"] .fijado__foto,
[data-fijado][data-plano="si"] .velo { display: none; }

[data-fijado][data-plano="si"] .paso {
  position: static;
  opacity: 1;
  /* `transform: none` sin `transition: none` deja al paso animándose desde su
     posición fijada (translateX(-50%) …) hasta el flujo normal. Quien pidió
     reducir movimiento no debería ver esa transición, y mientras dura el texto
     aparece descentrado. */
  transform: none;
  transition: none;
  left: auto;
  pointer-events: auto;
  width: min(760px, calc(100% - var(--gutter) * 2));
  margin: 0 auto;
  padding: clamp(34px, 5vh, 62px) 0;
  border-top: 1px solid var(--linea);
}
[data-fijado][data-plano="si"] .paso:first-of-type { border-top: 0; }
[data-fijado][data-plano="si"] .pasos__indice { display: none; }

/* ── Sección fijada ─────────────────────────────────────────────────────── */
/* Un contenedor alto; dentro, un panel pegajoso cuyo contenido cambia según
   cuánto se ha recorrido. Es lo que da la sensación de que la página cuenta
   algo mientras bajas, en vez de solo desplazarse. */
.fijado { position: relative; }
.fijado__panel {
  position: sticky; top: 0;
  height: 100vh;              /* respaldo */
  height: 100svh;
  display: grid; place-items: center;
  overflow: hidden;
}
.fijado__lienzo { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 0; }
/* Foto de fondo para la sección fijada de agronomía */
.fijado__foto {
  position: absolute; top: 0; left: 0; width: 100%; height: 100%;
  object-fit: cover; z-index: 0;
}

.paso {
  position: absolute;
  width: min(760px, calc(100% - var(--gutter) * 2));
  left: 50%;
  transform: translateX(-50%) translateY(26px) scale(0.98);
  text-align: center;
  opacity: 0;
  transition: opacity .55s var(--suave), transform .55s var(--suave);
  pointer-events: none;
  z-index: 3;
}
.paso[data-activo="si"] {
  opacity: 1;
  transform: translateX(-50%) translateY(0) scale(1);
  pointer-events: auto;
}

/* El contenido del paso entra escalonado, no de golpe con el bloque. Antes el
   paso solo cambiaba de opacidad y el resultado era un cartel que parpadea:
   ahora la etiqueta, el titular y el párrafo suben uno detrás de otro, que es
   lo que hace que la sección fijada se sienta viva mientras bajas. */
.paso > * {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity .55s var(--suave), transform .55s var(--suave);
}
.paso[data-activo="si"] > * { opacity: 1; transform: none; }
.paso[data-activo="si"] > *:nth-child(1) { transition-delay: .06s; }
.paso[data-activo="si"] > *:nth-child(2) { transition-delay: .12s; }
.paso[data-activo="si"] > *:nth-child(3) { transition-delay: .18s; }
.paso[data-activo="si"] > *:nth-child(4) { transition-delay: .24s; }
.paso[data-activo="si"] > *:nth-child(5) { transition-delay: .30s; }
.paso[data-activo="si"] > *:nth-child(6) { transition-delay: .36s; }
.paso[data-activo="si"] > *:nth-child(7) { transition-delay: .42s; }
.paso[data-activo="si"] > *:nth-child(8) { transition-delay: .48s; }

/* Contenedor que solo se funde: el movimiento lo llevan las palabras del
   titular, y dos desplazamientos superpuestos se ven blandos. */
[data-revelar].revelar--suave { transform: none; }

/* Índice de pasos: dice cuántos hay y en cuál vas. Sin esto la sección fijada
   se siente como un scroll que no avanza. */
.pasos__indice {
  position: absolute; right: clamp(18px, 3vw, 46px); top: 50%;
  transform: translateY(-50%);
  z-index: 4;
  display: flex; flex-direction: column; align-items: center;
}
.pasos__indice > * + * { margin-top: 12px; }
.pasos__indice i {
  display: block; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; opacity: 0.28;
  transition: opacity .4s, transform .4s var(--suave), background .4s;
}
.pasos__indice i[data-activo="si"] {
  opacity: 1; background: var(--acento);
  transform: scale(1.7);
  box-shadow: 0 0 12px rgba(var(--acento-rgb), 0.8);
}
@media (max-width: 700px) { .pasos__indice { display: none; } }

/* ── Tarjetas ───────────────────────────────────────────────────────────── */
.tarjeta {
  position: relative;
  padding: clamp(24px, 2.6vw, 36px);
  border-radius: var(--radio);
  background: var(--panel);
  border: 1px solid var(--panel-borde);
  overflow: hidden;
  backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
  box-shadow: var(--sombra-corta);
  transition: transform .5s var(--suave), border-color .5s, box-shadow .5s;
}
/* Halo que sigue al cursor */
.tarjeta::before {
  content: ""; position: absolute; top: 0; right: 0; bottom: 0; left: 0;
  background: radial-gradient(440px circle at var(--mx, 50%) var(--my, 0%),
              rgba(var(--acento-rgb), 0.16), transparent 62%);
  opacity: 0; transition: opacity .45s;
  pointer-events: none;
}
.tarjeta::after {
  content: ""; position: absolute; top: 0; right: 16%; left: 16%; height: 1px;
  background: linear-gradient(90deg, transparent, var(--panel-borde), transparent);
  pointer-events: none;
}
/* La tarjeta se inclina siguiendo al cursor. --rx/--ry los escribe aigua.js;
   van en la MISMA declaración que el levantamiento porque `transform` es una
   sola propiedad: si el hover la reescribiera aparte, mataría la inclinación. */
.tarjeta {
  transform:
    perspective(950px)
    rotateX(var(--rx, 0deg))
    rotateY(var(--ry, 0deg))
    translateY(var(--ty, 0px));
}
.tarjeta:hover {
  --ty: -7px;
  border-color: rgba(var(--acento-rgb), 0.42);
  box-shadow: var(--sombra);
}
.tarjeta:hover::before { opacity: 1; }
/* Nada de translateZ en los hijos para «levantar» el contenido: .tarjeta lleva
   overflow:hidden, que aplana el contexto 3D, y la regla no haría nada. La
   sensación de volumen la dan la inclinación y el halo que sigue al cursor. */

.tarjeta__icono {
  width: 48px; height: 48px; margin-bottom: 20px;
  display: grid; place-items: center;
  border-radius: 14px;
  background: rgba(var(--acento-rgb), 0.13);
  border: 1px solid rgba(var(--acento-rgb), 0.3);
  color: var(--acento);
}
.tarjeta__icono svg { width: 23px; height: 23px; }
.tarjeta h3 {
  margin: 0 0 10px; font-size: 1.18rem; font-weight: 600;
  letter-spacing: -0.02em; line-height: 1.25;
}
.tarjeta p { margin: 0; color: var(--texto-tenue); font-size: 0.95rem; }

/* Tarjeta numerada: el número grande da jerarquía sin gastar un titular */
.tarjeta--num { padding-top: clamp(28px, 3vw, 42px); }
.tarjeta__num {
  position: absolute; top: 14px; right: 22px;
  font-size: clamp(3.4rem, 6vw, 5rem); font-weight: 700;
  line-height: 1; letter-spacing: -0.06em;
  color: var(--texto);
  opacity: 0.07;
  pointer-events: none;
}

/* ── Tarjeta de proyecto ────────────────────────────────────────────────── */
.proyecto {
  position: relative;
  display: block;
  min-height: 470px;
  border-radius: 26px;
  overflow: hidden;
  border: 1px solid var(--linea);
  /* Degradado del color del proyecto POR DEBAJO del lienzo: se ve mientras
     Three.js carga, y es lo único que queda en un móvil, donde la escena se
     retira para no abrir cinco contextos WebGL en un teléfono. Sin esto la
     tarjeta se quedaba en un rectángulo negro. */
  background:
    radial-gradient(120% 88% at 18% 0%, rgba(var(--acento-rgb), 0.3), transparent 62%),
    radial-gradient(90% 70% at 100% 100%, rgba(var(--acento-rgb), 0.14), transparent 66%),
    var(--fondo-alto);
  box-shadow: var(--sombra-corta);
  transition: transform .6s var(--suave), border-color .6s, box-shadow .6s;
}
.proyecto:hover {
  transform: translateY(-9px);
  border-color: rgba(var(--acento-rgb), 0.45);
  box-shadow: 0 30px 70px rgba(var(--acento-rgb), 0.16), var(--sombra);
}
.proyecto__fondo {
  position: absolute; top: 0; left: 0; width: 100%; height: 100%;
  z-index: 0; opacity: .8;      /* la escena ambienta la tarjeta, no la manda */
  transition: transform .8s var(--suave);
}
.proyecto:hover .proyecto__fondo { transform: scale(1.05); }
.proyecto__contenido {
  position: relative; z-index: 2;
  height: 100%; min-height: 470px;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: clamp(26px, 3vw, 38px);
  background: linear-gradient(to top, rgba(3, 8, 12, 0.95) 10%,
              rgba(3, 8, 12, 0.6) 46%, rgba(3, 8, 12, 0.08) 88%);
  color: #EAF3F9;
}
.proyecto h3 {
  font-size: clamp(1.55rem, 2.4vw, 2.05rem); margin: 10px 0 12px;
  letter-spacing: -0.03em; font-weight: 600;
}
.proyecto p { color: #9FB6C4; margin: 0 0 20px; font-size: 0.95rem; }
.proyecto__ir {
  display: inline-flex; align-items: center;
  color: var(--acento); font-weight: 600; font-size: .92rem;
  font-family: var(--fuente-texto);
}
.proyecto__ir svg { width: 16px; height: 16px; margin-left: 8px; transition: transform .4s var(--suave); }
.proyecto:hover .proyecto__ir svg { transform: translateX(6px); }
/* Filo de color arriba: identifica el proyecto antes de leer una palabra */
.proyecto::after {
  content: ""; position: absolute; top: 0; right: 0; left: 0; height: 3px; z-index: 3;
  background: linear-gradient(90deg, var(--acento), var(--acento-2));
  opacity: 0.85;
}

/* ── Cifras ─────────────────────────────────────────────────────────────── */
.cifra { text-align: center; }
.cifra__valor {
  font-size: clamp(2.5rem, 5.2vw, 4rem);
  font-weight: 700; letter-spacing: -0.045em; line-height: 1;
  font-variant-numeric: tabular-nums;
  background: linear-gradient(160deg, var(--acento), var(--acento-2));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.cifra__texto {
  margin-top: 12px; color: var(--texto-tenue); font-size: 0.86rem;
  max-width: 22ch; margin-left: auto; margin-right: auto;
}

/* Banda de cifras: separada por líneas verticales, no flotando en el aire */
.banda-cifras {
  display: grid; gap: 0;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr));
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  overflow: hidden;
  background: var(--panel);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
}
.banda-cifras > * {
  padding: clamp(28px, 3.6vw, 46px) 20px;
  border-right: 1px solid var(--linea);
  border-bottom: 1px solid var(--linea);
}

/* ── Botones ────────────────────────────────────────────────────────────── */
.boton {
  display: inline-flex; align-items: center;
  padding: 14px 28px; border-radius: 999px;
  font-family: var(--fuente-texto);
  font-weight: 600; font-size: 0.95rem;
  border: 1px solid transparent; cursor: pointer;
  transition: transform .3s var(--suave), box-shadow .3s, background .3s, border-color .3s;
}
.boton:hover { transform: translateY(-2px); }
/* El texto va en tinta, no en blanco: el degradado de marca (azul agua → verde
   hoja) y el cian de seguridad son colores CLAROS, y el blanco encima se lee
   fatal. En agronomía y óptica, cuyos acentos sí son oscuros, se invierte. */
.boton--lleno {
  background: linear-gradient(135deg, var(--acento), var(--acento-2));
  color: #04141C;
  box-shadow: 0 12px 34px rgba(var(--acento-rgb), 0.34);
}
body[data-tema="agro"] .boton--lleno,
body[data-tema="optica"] .boton--lleno { color: #FFFFFF; }
.boton--lleno:hover { box-shadow: 0 18px 46px rgba(var(--acento-rgb), 0.48); }
.boton--linea {
  border-color: var(--linea-fuerte); color: var(--texto);
  background: var(--panel);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
}
.boton--linea:hover { border-color: rgba(var(--acento-rgb), 0.6); background: rgba(var(--acento-rgb), 0.08); }
.boton > * + *, .boton svg { margin-left: 9px; }

.acciones { display: flex; flex-wrap: wrap; margin-top: 34px; }
.acciones.centrado, .centrado .acciones { justify-content: center; }
.acciones > * { margin: 7px; }
.centrado .acciones > *:first-child { margin-left: 7px; }

/* ── Detalle de proyecto ────────────────────────────────────────────────── */
.cabecera-proyecto {
  position: relative;
  min-height: 92vh;           /* respaldo */
  min-height: 92svh;
  display: grid; place-items: center; text-align: center; overflow: hidden;
}
.cabecera-proyecto__lienzo {
  position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 0;
}
.cabecera-proyecto__foto {
  position: absolute; top: 0; left: 0; width: 100%; height: 100%;
  object-fit: cover; z-index: 0;
}
.cabecera-proyecto__contenido {
  position: relative; z-index: 3; padding: 132px var(--gutter) 96px;
  margin-left: auto; margin-right: auto;
  width: min(var(--ancho), 100%);
}

/* Panel de cristal para la portada de agronomía y óptica: el titular va dentro
   de vidrio, en tinta oscura, en vez de blanco sobre una foto luminosa donde
   no se leería. */
.portada__vidrio {
  display: inline-block; text-align: center;
  padding: clamp(30px, 4vw, 52px) clamp(26px, 4vw, 62px);
  border-radius: 30px;
  background: rgba(255, 255, 255, 0.6);
  border: 1px solid rgba(255, 255, 255, 0.85);
  backdrop-filter: saturate(170%) blur(24px);
  -webkit-backdrop-filter: saturate(170%) blur(24px);
  box-shadow: 0 30px 80px rgba(4, 40, 60, 0.28), inset 0 1px 0 rgba(255,255,255,0.9);
  color: #062418;
  text-shadow: none;
}
.portada__vidrio .subtitulo { color: #315549; }

.migas {
  display: flex; justify-content: center; align-items: center; flex-wrap: wrap;
  font-family: var(--fuente-texto);
  color: var(--texto-tenue); font-size: 0.82rem; margin-bottom: 22px;
}
.migas > * { margin: 0 5px; }
.migas a:hover { color: var(--acento); }

.ficha {
  display: grid; gap: 1px; background: var(--linea);
  border: 1px solid var(--linea); border-radius: var(--radio); overflow: hidden;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 170px), 1fr));
  box-shadow: var(--sombra-corta);
}
.ficha > div { background: var(--fondo-alto); padding: 24px; }
.ficha dt {
  font-family: var(--fuente-texto);
  font-size: 0.7rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--texto-tenue); margin: 0 0 8px; font-weight: 600;
}
.ficha dd { margin: 0; font-weight: 600; font-size: 1.02rem; }

/* Lista de capacidades con línea de tiempo */
.flujo { position: relative; padding-left: 36px; }
.flujo::before {
  content: ""; position: absolute; left: 9px; top: 8px; bottom: 8px; width: 2px;
  background: linear-gradient(to bottom, var(--acento), transparent);
}
.flujo__paso { position: relative; padding-bottom: 34px; }
.flujo__paso::before {
  content: ""; position: absolute; left: -32px; top: 7px;
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--fondo); border: 2px solid var(--acento);
  box-shadow: 0 0 0 4px rgba(var(--acento-rgb), 0.13);
}
.flujo__paso h4 { margin: 0 0 8px; font-size: 1.06rem; font-weight: 600; }
.flujo__paso p  { margin: 0; color: var(--texto-tenue); font-size: 0.94rem; }

/* ══════════════════════════════════════════════════════════════════════════
   PARES, SECUENCIAS Y CADENAS
   --------------------------------------------------------------------------
   Sustituyen a los bloques de consola y al diagrama en ASCII que había antes.
   Esta web es material comercial, no documentación interna: una terminal o un
   esquema de flechas dibujado con caracteres hace que la página parezca una
   captura del repositorio, y obliga a leer en monoespaciada algo que se
   entiende mejor con tipografía normal.

   La monoespaciada se reserva ahora para lo que de verdad es un dato de
   máquina: telemetría, medidas de montura y numeración de pasos.
   ══════════════════════════════════════════════════════════════════════════ */

/* Pares «lo que se observa → lo que significa» */
.pares {
  display: grid; gap: 1px;
  background: var(--linea);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  overflow: hidden;
  margin: 0;
  box-shadow: var(--sombra-corta);
}
.pares > div {
  background: var(--fondo-alto);
  padding: 15px clamp(18px, 2.2vw, 24px);
  display: flex; flex-wrap: wrap; align-items: baseline;
}
.pares dt {
  flex: 1 1 200px;
  font-family: var(--fuente-texto);
  font-weight: 500; font-size: 0.94rem;
  margin-right: 16px;
}
.pares dd {
  flex: 0 1 auto; margin: 0;
  font-family: var(--fuente-texto);
  font-size: 0.92rem; font-weight: 600;
  color: var(--acento);
}
/* Filas de «esto no se puede saber mirando una foto»: el valor va apagado y en
   cursiva, no en acento — es una limitación, no un resultado. */
.pares > div[data-limite] dd {
  color: var(--texto-tenue); font-weight: 400; font-style: italic;
}

.pares__titulo {
  font-family: var(--fuente-texto);
  font-size: 0.7rem; letter-spacing: 0.18em; text-transform: uppercase;
  font-weight: 600; color: var(--texto-tenue);
  margin: 0 0 12px;
}

/* Secuencias de acciones */
.secuencias { display: grid; gap: 10px; }
.secuencia {
  display: flex; flex-wrap: wrap; align-items: center;
  padding: 15px clamp(16px, 2vw, 22px);
  border-radius: var(--radio-s);
  border: 1px solid var(--linea);
  background: var(--panel);
}
.secuencia__nombre {
  font-weight: 600; font-size: 0.95rem;
  flex: 0 0 auto; min-width: 8.5em; margin-right: 14px;
}
.secuencia__pasos {
  display: flex; flex-wrap: wrap; align-items: center;
  list-style: none; margin: 0; padding: 0;
}
.secuencia__pasos li { display: inline-flex; align-items: center; }
.secuencia__pasos li + li::before {
  content: "→"; margin: 0 9px; opacity: 0.45; font-size: 0.9rem;
}
.secuencia__pasos span {
  padding: 5px 13px; border-radius: 999px;
  background: rgba(var(--acento-rgb), 0.1);
  border: 1px solid var(--linea);
  font-family: var(--fuente-texto); font-size: 0.83rem;
}
/* La fila que importa: misma estructura, otro color. Se ve la diferencia sin
   leer, que es justo lo que cuesta explicar con palabras. */
.secuencia--alerta {
  border-color: rgba(255, 51, 51, 0.4);
  background: rgba(255, 51, 51, 0.07);
}
.secuencia--alerta .secuencia__nombre { color: #FF6B6B; }
.secuencia--alerta .secuencia__pasos span {
  background: rgba(255, 51, 51, 0.13);
  border-color: rgba(255, 51, 51, 0.32);
}

/* Cadena de proceso numerada, en vertical */
.cadena {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 12px;
  counter-reset: cadena;
}
.cadena li {
  position: relative;
  padding: 15px clamp(18px, 2vw, 22px) 15px 62px;
  border-radius: var(--radio-s);
  border: 1px solid var(--linea);
  background: var(--panel);
}
.cadena li::before {
  counter-increment: cadena;
  content: counter(cadena, decimal-leading-zero);
  position: absolute; left: 22px; top: 16px;
  font-family: var(--mono); font-size: 0.74rem;
  color: var(--acento); letter-spacing: 0.06em;
}
/* Conector entre eslabones: lo que antes hacía una flecha de ASCII */
.cadena li:not(:last-child)::after {
  content: ""; position: absolute; left: 30px; bottom: -12px;
  width: 1px; height: 12px; background: var(--linea-fuerte);
}
.cadena b { display: block; font-weight: 600; font-size: 0.97rem; margin-bottom: 3px; }
.cadena span {
  display: block; color: var(--texto-tenue);
  font-family: var(--fuente-texto); font-size: 0.89rem;
}
.cadena li[data-salida] {
  border-color: rgba(var(--acento-rgb), 0.5);
  background: rgba(var(--acento-rgb), 0.09);
}

/* ── Pareja de imágenes ─────────────────────────────────────────────────── */
.galeria { display: grid; gap: clamp(14px, 2vw, 22px); grid-template-columns: 1fr; }
@media (min-width: 780px) { .galeria { grid-template-columns: 1fr 1fr; } }
.galeria .medio { box-shadow: var(--sombra-corta); }
/* Las dos fotos de una pareja casi nunca tienen la misma proporción, y el grid
   estira ambas celdas a la altura de la más alta: la más baja dejaba una banda
   del fondo oscuro del marco debajo. Recortando por el centro se llenan las
   dos sin deformar nada. */
.galeria .medio img { width: 100%; height: 100%; object-fit: cover; }
/* Los vídeos de ejemplo van en `contain` y no en `cover`: llevan contadores y
   rótulos pegados a los bordes, y recortarlos se come justo la parte que
   demuestra lo que hace el sistema. Las bandas que quedan a los lados caen
   sobre el fondo oscuro del marco y se leen como encuadre, no como error. */
.galeria .medio video {
  width: 100%; height: 100%; object-fit: contain; background: #04070A;
}
/* Las proporciones de los dos clips son muy distintas (uno casi cuadrado, otro
   muy apaisado). Sin una altura común la fila se descuadra. */
.galeria .medio { min-height: 340px; }

/* ══════════════════════════════════════════════════════════════════════════
   AERO — solo agronomía
   Burbujas de cristal subiendo, como en la foto de la aplicación. Son CSS puro
   y muy pocas: si se llenan de burbujas, la página pasa de Frutiger Aero a
   protector de pantalla.
   ══════════════════════════════════════════════════════════════════════════ */
.burbujas { position: absolute; top: 0; right: 0; bottom: 0; left: 0;
            overflow: hidden; pointer-events: none; z-index: 2; }
.burbujas span {
  position: absolute; bottom: -18vh; border-radius: 50%;
  background:
    radial-gradient(circle at 32% 28%, rgba(255,255,255,0.85), rgba(255,255,255,0.15) 42%,
                    rgba(150, 220, 255, 0.14) 62%, rgba(255,255,255,0.05) 100%);
  border: 1px solid rgba(255, 255, 255, 0.5);
  box-shadow: inset 0 -8px 18px rgba(120, 200, 255, 0.28),
              0 8px 24px rgba(30, 110, 160, 0.16);
  animation: subir linear infinite;
}
@keyframes subir {
  0%   { transform: translateY(0) translateX(0) scale(0.9); opacity: 0; }
  12%  { opacity: 0.9; }
  85%  { opacity: 0.75; }
  100% { transform: translateY(-125vh) translateX(38px) scale(1.06); opacity: 0; }
}

/* Hojas subiendo. Mismo mecanismo que las burbujas, otra silueta: el
   border-radius asimétrico da la forma de hoja sin necesidad de un SVG, y el
   giro durante la subida evita que se lean como confeti. */
.hojas { position: absolute; top: 0; right: 0; bottom: 0; left: 0;
         overflow: hidden; pointer-events: none; z-index: 2; }
.hojas span {
  position: absolute; bottom: -14vh;
  border-radius: 0 62% 0 62%;
  background: linear-gradient(140deg, rgba(31,170,89,0.5), rgba(134,209,59,0.28));
  border: 1px solid rgba(255, 255, 255, 0.35);
  box-shadow: 0 6px 18px rgba(20, 90, 55, 0.14);
  animation: caer-hoja linear infinite;
}
@keyframes caer-hoja {
  0%   { transform: translateY(0) translateX(0) rotate(0deg); opacity: 0; }
  12%  { opacity: 0.85; }
  85%  { opacity: 0.6; }
  100% { transform: translateY(-122vh) translateX(64px) rotate(320deg); opacity: 0; }
}

/* ── Vegetación de sección (solo agronomía) ─────────────────────────────── */
/* Ramas dibujadas en SVG, ancladas a una esquina de la sección y muy tenues.
   No son ilustración: son textura. Si compiten con el texto, sobran. */
/* `.tinte > *` fuerza position:relative en sus hijos directos para dejarlos por
   encima del resplandor. La rama es hija directa y también entra en esa regla,
   así que necesita ganarle en especificidad o se queda en el flujo. */
.rama,
.tinte > .rama {
  position: absolute; z-index: 0; pointer-events: none;
  color: var(--acento);
  opacity: 0.18;
}
.rama svg { width: 100%; height: auto; display: block; }
/* Los desplazamientos son pequeños porque .tinte recorta por overflow: la rama
   tiene que asomar por la esquina, no quedarse fuera del recorte. */
.rama--ai { top: -14px; left: -26px; width: clamp(180px, 22vw, 330px); }
.rama--ad { top: -14px; right: -26px; width: clamp(160px, 19vw, 290px);
            transform: scaleX(-1); }
.rama--bi { bottom: -18px; left: -22px; width: clamp(170px, 20vw, 300px);
            transform: scaleY(-1); }
.rama--bd { bottom: -18px; right: -26px; width: clamp(190px, 23vw, 340px);
            transform: scale(-1, -1); }
@media (max-width: 820px) { .rama { display: none; } }

/* Cenefa de hojas que separa dos secciones */
.cenefa {
  display: block; width: 100%; height: 34px;
  color: var(--acento); opacity: 0.28;
}
.cenefa svg { width: 100%; height: 100%; display: block; }

/* Cinta de texto en marcha. Es puro ritmo visual: dice de un vistazo dónde
   trabaja la empresa sin obligar a leer un párrafo. */
.cinta-texto {
  overflow: hidden;
  padding: 18px 0;
  border-top: 1px solid var(--linea);
  border-bottom: 1px solid var(--linea);
  background: rgba(var(--acento-rgb), 0.05);
}
.cinta-texto__pista {
  display: flex; width: max-content;
  animation: desfilar 34s linear infinite;
}
.cinta-texto__pista > * {
  display: inline-flex; align-items: center;
  font-size: clamp(1.3rem, 3vw, 2.3rem);
  font-weight: 600; letter-spacing: -0.02em;
  padding: 0 26px;
  white-space: nowrap;
}
.cinta-texto__pista i {
  font-style: normal; color: var(--acento); padding: 0 4px;
}
.cinta-texto__pista span:nth-child(even) { color: var(--texto-tenue); }
@keyframes desfilar { to { transform: translateX(-50%); } }
.cinta-texto:hover .cinta-texto__pista { animation-play-state: paused; }

/* Rejilla del ecosistema: hoja + ciudad, verde y azul, como el logotipo */
.aero-cinta {
  position: relative; overflow: hidden;
  border-radius: 28px;
  padding: clamp(34px, 5vw, 66px);
  background: linear-gradient(125deg, rgba(31,170,89,0.16), rgba(14,155,216,0.16) 55%, rgba(255,255,255,0.5));
  border: 1px solid rgba(255,255,255,0.8);
  box-shadow: var(--sombra);
}
.aero-cinta::before {
  content: ""; position: absolute; top: -40%; right: -10%;
  width: 52%; height: 180%; border-radius: 50%;
  background: radial-gradient(circle, rgba(255,255,255,0.7), transparent 66%);
  pointer-events: none;
}

/* Fichita de proyecto dentro de la cinta. Va como clase y no como estilo en
   línea para que el modo oscuro pueda reescribirla: un `style=` gana a
   cualquier hoja y dejaría estos tres recuadros en blanco sobre negro. */
.forma-mini {
  padding: 16px 14px; border-radius: 14px;
  background: rgba(255, 255, 255, 0.62);
  border: 1px solid rgba(255, 255, 255, 0.9);
}
.forma-mini__cat {
  font-family: var(--fuente-texto);
  font-size: 0.68rem; letter-spacing: 0.18em; text-transform: uppercase;
  font-weight: 600;
}
.forma-mini__nom { font-weight: 600; margin-top: 5px; }

/* ══════════════════════════════════════════════════════════════════════════
   HUD — solo seguridad
   La página imita el visor de Ojo de Orus: retícula, corchetes de esquina,
   telemetría en monoespaciada y una línea de barrido. Es literalmente lo que
   la aplicación pinta encima del video.
   ══════════════════════════════════════════════════════════════════════════ */
.reticula {
  position: absolute; top: 0; right: 0; bottom: 0; left: 0;
  z-index: 1; pointer-events: none; opacity: 0.5;
  background-image:
    linear-gradient(rgba(0, 192, 255, 0.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 192, 255, 0.07) 1px, transparent 1px);
  background-size: 62px 62px;
  mask-image: radial-gradient(ellipse 80% 70% at 50% 45%, #000 30%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 80% 70% at 50% 45%, #000 30%, transparent 78%);
}

/* La figura de la escena queda justo detrás del titular, y con el esqueleto en
   cian claro el texto dejaba de leerse. Este velo hunde el centro bastante más
   que el general, que está calibrado para una nube de partículas difusa. */
body[data-tema="seguridad"] .cabecera-proyecto .velo,
body[data-tema="seguridad"] .fijado__panel .velo {
  background:
    radial-gradient(ellipse 64% 52% at 50% 50%, rgba(0, 8, 15, 0.88) 0%,
                    rgba(0, 8, 15, 0.6) 50%, transparent 84%),
    linear-gradient(to bottom, rgba(0, 8, 15, 0.88) 0%, rgba(0, 8, 15, 0.18) 24%,
                    rgba(0, 8, 15, 0.34) 62%, var(--fondo) 100%);
}

/* Encuadre de las tarjetas de seguridad: esquinas asimétricas y un filo cian a
   la izquierda, como los recuadros que el visor pinta sobre cada persona.
   Se hace con border-radius y box-shadow y NO con pseudoelementos a propósito:
   .tarjeta ya usa ::before para el halo del cursor y ::after para el reflejo
   superior, y una segunda clase que los reclamara mataría los dos. */
body[data-tema="seguridad"] .tarjeta {
  border-radius: 4px 20px 4px 20px;
  box-shadow: inset 2px 0 0 rgba(0, 192, 255, 0.45), var(--sombra-corta);
}
body[data-tema="seguridad"] .tarjeta:hover {
  box-shadow: inset 2px 0 0 var(--acento), var(--sombra);
}
body[data-tema="seguridad"] .tarjeta__icono { border-radius: 3px 12px 3px 12px; }

.telemetria {
  display: flex; flex-wrap: wrap; align-items: center;
  font-family: var(--mono); font-size: 0.72rem;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--acento);
  margin: -6px;
}
.telemetria > * { margin: 6px; display: inline-flex; align-items: center; }
.telemetria b { font-weight: 500; color: var(--texto-tenue); margin-right: 7px; }
.telemetria .rec {
  width: 8px; height: 8px; border-radius: 50%; background: var(--orus-alerta);
  margin-right: 8px; flex: 0 0 auto;
  animation: latido 1.6s ease-in-out infinite;
}
@keyframes latido { 0%,100% { opacity: 1; } 50% { opacity: 0.25; } }

/* Barrido descendente sobre la cabecera del proyecto de seguridad */
.barrido {
  position: absolute; top: 0; right: 0; left: 0; height: 26vh;
  z-index: 2; pointer-events: none;
  background: linear-gradient(to bottom, transparent, rgba(0, 192, 255, 0.11) 76%,
              rgba(0, 192, 255, 0.55));
  animation: barrer 6.5s cubic-bezier(0.6, 0, 0.4, 1) infinite;
}
@keyframes barrer {
  0%   { transform: translateY(-30vh); opacity: 0; }
  14%  { opacity: 1; }
  86%  { opacity: 1; }
  100% { transform: translateY(102vh); opacity: 0; }
}
/* El barrido descendente se retira entero en modo oscuro: parado a media
   altura se ve como una banda rara sobre la cabecera, no como un escáner. */
html[data-modo="oscuro"] .barrido { display: none; }

/* ══════════════════════════════════════════════════════════════════════════
   ÓPTICA — el aire clínico de Velion: hielo, teal, mucho blanco
   ══════════════════════════════════════════════════════════════════════════ */
.lente {
  position: relative; overflow: hidden;
  border-radius: 26px;
  background: linear-gradient(145deg, rgba(255,255,255,0.94), rgba(224, 240, 255, 0.72));
  border: 1px solid rgba(255,255,255,0.9);
  box-shadow: var(--sombra);
}
/* Reflejo diagonal, como el de un cristal de gafa. Pegado al borde izquierdo
   y flojo: centrado y opaco cruzaba el titular por la mitad y el corte del
   degradado se veía como una raya sobre las letras. */
.lente::after {
  content: ""; position: absolute; top: -60%; left: -34%;
  width: 44%; height: 220%;
  transform: rotate(22deg);
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.5), transparent);
  pointer-events: none;
}

/* ══════════════════════════════════════════════════════════════════════════
   MEDIO — video y capturas
   Marco común para el metraje real de las páginas de proyecto. El video va
   silenciado, en bucle y con `playsinline`; si no puede reproducirse queda el
   póster, que es un fotograma del propio clip. Nunca hay audio ni controles:
   es material de apoyo, no un reproductor.
   ══════════════════════════════════════════════════════════════════════════ */
.medio {
  position: relative;
  border-radius: 24px;
  overflow: hidden;
  border: 1px solid var(--linea-fuerte);
  background: #04070A;
  box-shadow: var(--sombra);
}
.medio video, .medio img { display: block; width: 100%; height: auto; }

/* Capa para la retícula y las anotaciones dibujadas encima del video */
.medio__capa {
  position: absolute; top: 0; right: 0; bottom: 0; left: 0;
  pointer-events: none;
}
.medio__capa svg { width: 100%; height: 100%; display: block; }

/* Chapa de esquina: «EN VIVO», «CÁM 04»… */
.medio__chapa {
  position: absolute; top: 14px; left: 14px; z-index: 3;
  display: inline-flex; align-items: center;
  padding: 6px 12px; border-radius: 999px;
  background: rgba(4, 10, 16, 0.72);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 255, 255, 0.16);
  font-family: var(--mono); font-size: 0.68rem;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: #E8F4FA;
}
.medio__chapa .rec {
  width: 7px; height: 7px; border-radius: 50%; background: var(--orus-alerta);
  margin-right: 8px; flex: 0 0 auto;
  animation: latido 1.6s ease-in-out infinite;
}

/* Crédito y aviso bajo el video. Va SIEMPRE: el metraje es de terceros y hay
   que decir de dónde sale y qué parte es ilustración nuestra. */
.pie-medio {
  margin-top: 14px;
  font-family: var(--fuente-texto);
  font-size: 0.79rem; line-height: 1.55;
  color: var(--texto-tenue);
}
.pie-medio a { text-decoration: underline; text-underline-offset: 2px; }
.pie-medio a:hover { color: var(--acento); }


/* ══════════════════════════════════════════════════════════════════════════
   MONTURAS — el catálogo de Velion, dibujado en vectorial
   Son SVG y no fotos a propósito: el producto es geometría (radio del aro,
   ancho del puente, caída de la patilla), y un dibujo limpio enseña esa
   geometría mejor que una foto de estudio. Además pesan nada y no dependen
   de ningún banco de imágenes.
   ══════════════════════════════════════════════════════════════════════════ */
/* 330 y no 210: son seis monturas, y a cinco columnas la sexta se quedaba
   sola en una fila. A tres columnas salen dos filas llenas y el dibujo tiene
   sitio para leerse. */
.monturas {
  display: grid; gap: clamp(14px, 1.8vw, 22px);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 330px), 1fr));
}
.montura {
  position: relative;
  padding: 22px 20px 18px;
  border-radius: 18px;
  background: var(--panel);
  border: 1px solid var(--panel-borde);
  box-shadow: var(--sombra-corta);
  transition: transform .45s var(--suave), border-color .45s, box-shadow .45s;
}
.montura:hover {
  transform: translateY(-5px);
  border-color: rgba(var(--acento-rgb), 0.45);
  box-shadow: var(--sombra);
}
.montura svg { width: 100%; height: auto; display: block; color: var(--acento); }
.montura__nombre {
  margin: 16px 0 3px; font-weight: 600; font-size: 1rem; letter-spacing: -0.015em;
}
.montura__dato {
  margin: 0; font-family: var(--mono); font-size: 0.72rem;
  color: var(--texto-tenue); letter-spacing: 0.04em;
}

/* ══════════════════════════════════════════════════════════════════════════
   VISOR — la montura en 3D, girando y cambiable
   ══════════════════════════════════════════════════════════════════════════ */
.visor {
  position: relative;
  border-radius: 26px;
  overflow: hidden;
  border: 1px solid var(--linea-fuerte);
  background: linear-gradient(160deg, #00293A, #00161F 60%, #001824);
  box-shadow: var(--sombra);
}
.visor__lienzo { display: block; width: 100%; height: clamp(300px, 46vh, 460px); }
.visor__mandos {
  position: absolute; right: 0; bottom: 0; left: 0; z-index: 3;
  display: flex; flex-wrap: wrap; justify-content: center; align-items: center;
  padding: 16px;
  background: linear-gradient(to top, rgba(0, 12, 20, 0.86), transparent);
  margin: 0;
}
.visor__mandos > * { margin: 5px; }
.visor__medidas {
  position: absolute; top: 14px; left: 16px; z-index: 3;
  font-family: var(--mono); font-size: 0.7rem; line-height: 1.7;
  color: rgba(190, 232, 250, 0.8);
  letter-spacing: 0.05em;
  pointer-events: none;
}
.visor__medidas b { color: #7FE0FF; font-weight: 500; }

/* Botón-pastilla, para cambiar de montura o de color */
.pastilla {
  display: inline-flex; align-items: center;
  padding: 8px 16px; border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.22);
  background: rgba(255, 255, 255, 0.08);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  color: #E4F3FB;
  font-family: var(--fuente-texto); font-size: 0.82rem; font-weight: 500;
  cursor: pointer;
  transition: background .25s, border-color .25s, transform .25s var(--suave);
}
.pastilla:hover { background: rgba(255, 255, 255, 0.16); transform: translateY(-2px); }
.pastilla[aria-pressed="true"] {
  background: #4FC3F7; border-color: #8FE3FF; color: #00212F; font-weight: 600;
}
.pastilla__muestra {
  width: 12px; height: 12px; border-radius: 50%; margin-right: 8px;
  border: 1px solid rgba(255, 255, 255, 0.5); flex: 0 0 auto;
}

/* ══════════════════════════════════════════════════════════════════════════
   DÚO — dos mitades enfrentadas (la hoja y la ciudad, cámara normal vs. leída)
   ══════════════════════════════════════════════════════════════════════════ */
.duo { display: grid; gap: 1px; background: var(--linea);
       border: 1px solid var(--linea); border-radius: var(--radio);
       overflow: hidden; grid-template-columns: 1fr; }
@media (min-width: 820px) { .duo { grid-template-columns: 1fr 1fr; } }
.duo > div { background: var(--fondo-alto); padding: clamp(26px, 3.4vw, 44px); }
.duo__icono {
  width: 40px; height: 40px; margin-bottom: 18px;
  display: grid; place-items: center; border-radius: 12px;
  background: rgba(var(--acento-rgb), 0.12);
  border: 1px solid rgba(var(--acento-rgb), 0.28);
  color: var(--acento);
}
.duo__icono svg { width: 20px; height: 20px; }
.duo h3 { margin: 0 0 10px; font-size: 1.16rem; font-weight: 600; letter-spacing: -0.02em; }
.duo p  { margin: 0 0 14px; color: var(--texto-tenue); font-size: 0.95rem; }
.duo ul { margin: 0; padding-left: 18px; color: var(--texto-tenue); font-size: 0.92rem; }
.duo li { margin-bottom: 7px; }

/* ── Comparativa / tabla técnica ────────────────────────────────────────── */
.tabla {
  width: 100%; border-collapse: collapse;
  font-family: var(--fuente-texto); font-size: 0.93rem;
}
.tabla th, .tabla td {
  text-align: left; padding: 15px 18px;
  border-bottom: 1px solid var(--linea);
}
.tabla th {
  font-size: 0.7rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--texto-tenue); font-weight: 600;
}
.tabla td { color: var(--texto-tenue); }
.tabla td:first-child { color: var(--texto); font-weight: 500; }
.tabla tr:last-child td { border-bottom: 0; }
.tabla-envoltorio {
  overflow-x: auto;
  border: 1px solid var(--linea); border-radius: var(--radio);
  background: var(--panel);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
}

/* ── Cita / manifiesto ──────────────────────────────────────────────────── */
.manifiesto {
  position: relative;
  padding: clamp(34px, 5vw, 64px);
  border-radius: 28px;
  border: 1px solid var(--linea);
  background:
    radial-gradient(700px 380px at 12% 0%, rgba(var(--acento-rgb), 0.14), transparent 68%),
    var(--panel);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  box-shadow: var(--sombra-corta);
}
.manifiesto q { quotes: none; }
.manifiesto__firma {
  display: flex; align-items: center; margin-top: 28px;
  font-family: var(--fuente-texto); font-size: 0.88rem; color: var(--texto-tenue);
}
.manifiesto__firma img { width: 34px; margin-right: 12px; }

/* ── Pie ────────────────────────────────────────────────────────────────── */
.pie {
  position: relative;
  border-top: 1px solid var(--linea);
  padding: 76px 0 40px;
  background: var(--fondo-alto);
}
.pie::before {
  content: ""; position: absolute; top: -1px; right: 0; left: 0; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(var(--acento-rgb), 0.6), transparent);
}
.pie__filas { display: flex; flex-wrap: wrap; justify-content: space-between; margin: -24px; }
.pie__filas > * { margin: 24px; }
.pie__marca { display: flex; align-items: center; margin-bottom: 16px; }
.pie__marca img { width: 38px; margin-right: 12px; }
.pie__marca span { font-weight: 700; letter-spacing: 0.14em; font-size: 1.1rem; }
.pie h4 {
  font-family: var(--fuente-texto);
  font-size: 0.7rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--texto-tenue); margin: 0 0 16px; font-weight: 600;
}
.pie ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 11px; }
.pie ul a { color: var(--texto-tenue); font-size: 0.92rem; transition: color .25s; }
.pie ul a:hover { color: var(--acento); }
.pie__legal {
  margin-top: 52px; padding-top: 24px; border-top: 1px solid var(--linea);
  display: flex; flex-wrap: wrap; justify-content: space-between;
  font-family: var(--fuente-texto);
  color: var(--texto-tenue); font-size: 0.8rem;
}
.pie__legal > * { margin: 4px 0; }
.pie__legal > * + * { margin-left: 14px; }

/* ══════════════════════════════════════════════════════════════════════════
   COLOR POR SECCIÓN
   --------------------------------------------------------------------------
   Cada bloque de la página tiene su propio acento. Como todos los componentes
   leen --acento / --acento-2 / --acento-rgb, basta con redefinirlos en la
   sección: las etiquetas, los halos de las tarjetas, los subrayados, las
   cifras y los botones cambian de color solos.

   Los tonos salen de la marca y de las tres aplicaciones, no de una rueda de
   color al azar: así la página es variada sin dejar de ser la misma empresa.
   ══════════════════════════════════════════════════════════════════════════ */
[data-color="agua"]   { --acento: #35B6F0; --acento-2: #0E7BC4; --acento-rgb: 53, 182, 240; }
[data-color="hoja"]   { --acento: #6FCB3A; --acento-2: #1FAA59; --acento-rgb: 111, 203, 58; }
[data-color="menta"]  { --acento: #16C79A; --acento-2: #0E9BD8; --acento-rgb: 22, 199, 154; }
[data-color="ambar"]  { --acento: #F5A524; --acento-2: #F76B15; --acento-rgb: 245, 165, 36; }
[data-color="coral"]  { --acento: #FF6B6B; --acento-2: #F5A524; --acento-rgb: 255, 107, 107; }
[data-color="violeta"]{ --acento: #9B6BFF; --acento-2: #35B6F0; --acento-rgb: 155, 107, 255; }
[data-color="cian"]   { --acento: #00C0FF; --acento-2: #4FC3F7; --acento-rgb: 0, 192, 255; }

/* Resplandor de fondo del color de la sección. Muy difuso y muy flojo: se
   nota que el bloque «tiene color» sin que compita con el texto. */
.tinte { position: relative; overflow: hidden; }
.tinte::before {
  content: ""; position: absolute; top: -30%; left: 50%;
  width: 120%; height: 90%;
  transform: translateX(-50%);
  background: radial-gradient(closest-side, rgba(var(--acento-rgb), 0.16), transparent 72%);
  pointer-events: none;
}
.tinte > * { position: relative; z-index: 1; }

/* ── Utilidades ─────────────────────────────────────────────────────────── */
.centrado { text-align: center; }
.medido { max-width: 62ch; }
.medido.centrado { margin-left: auto; margin-right: auto; }
.espacio-s  { height: 24px; }
.espacio-m  { height: 54px; }
.espacio-l  { height: 96px; }
.oculto-visualmente {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}

.chip {
  display: inline-flex; align-items: center;
  padding: 7px 15px; border-radius: 999px;
  border: 1px solid var(--linea-fuerte);
  background: rgba(var(--acento-rgb), 0.08);
  font-family: var(--fuente-texto);
  font-size: 0.78rem; color: var(--texto-tenue); font-weight: 500;
}
.chip__punto {
  width: 6px; height: 6px; border-radius: 50%; background: var(--acento);
  box-shadow: 0 0 10px var(--acento);
  margin-right: 8px; flex: 0 0 auto;
}
.chips { display: flex; flex-wrap: wrap; margin: -5px; }
.chips.centrado { justify-content: center; }
.chips > * { margin: 5px; }

/* ══════════════════════════════════════════════════════════════════════════
   AMBIENTE — el fondo de cada sección se mueve
   --------------------------------------------------------------------------
   Antes, quitando la portada y las dos secciones fijadas, el fondo de la
   página era un color liso: se bajaba por bloques de texto sobre nada. Aquí
   cada sección recibe una o varias CAPAS de ambiente, y cada capa es una
   familia de objetos distinta:

     orbes     manchas de color muy difusas que se desplazan
     motas     partículas diminutas que suben
     malla     una retícula que corre despacio, con nodos que laten
     ondas     olas anchas meciéndose abajo (agua)
     anillos   círculos que se expanden y se apagan (lente, sonar)
     figuras   contornos geométricos girando (aire de laboratorio)
     hojas     hojas subiendo (solo agronomía)
     escaneo   una línea que recorre la sección de arriba abajo (vigilancia)

   Todas heredan --acento, así que la MISMA capa se ve verde en agronomía,
   cian en seguridad y ámbar en la sección del problema: el fondo es distinto
   en cada bloque sin tener que escribir un fondo por bloque.

   El reparto (cuántos objetos, dónde, a qué velocidad) lo hace aigua.js con
   números al azar, y lo escribe en variables en línea. Aquí solo se describe
   la forma y el movimiento.

   Coste: son transform y opacity, que no obligan a recalcular la página, y
   las capas fuera de pantalla se pausan.
   ══════════════════════════════════════════════════════════════════════════ */
/* `.tinte > *` fuerza position:relative en sus hijos directos; la capa es hija
   directa y tiene que ganarle o se cuela en el flujo (el mismo caso de .rama). */
.ambiente,
.tinte > .ambiente {
  position: absolute; top: 0; right: 0; bottom: 0; left: 0;
  z-index: 0; pointer-events: none; overflow: hidden;
}
.ambiente i { display: block; position: absolute; }
/* El contenido por encima del ambiente. En .tinte ya lo hace `.tinte > *`;
   esto cubre las secciones que no llevan tinte. */
.seccion > .contenedor,
.pie > .contenedor { position: relative; z-index: 1; }
/* En las portadas el orden es lienzo(0) · velo(1) · ambiente(2) · texto(3) */
.portada > .ambiente,
.cabecera-proyecto > .ambiente { z-index: 2; }
/* Capa dormida: fuera de pantalla no gasta nada */
.ambiente[data-quieto="si"] i,
.ambiente[data-quieto="si"] { animation-play-state: paused; }

/* ── Orbes ──────────────────────────────────────────────────────────────── */
.ambiente--orbes i {
  left: var(--x); top: var(--y);
  width: var(--d); height: var(--d);
  margin-left: calc(var(--d) / -2);
  margin-top: calc(var(--d) / -2);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(var(--acento-rgb), 0.55), transparent 70%);
  filter: blur(46px);
  opacity: 0.5;
  animation: vagar var(--dur, 26s) ease-in-out infinite alternate;
  animation-delay: var(--esp, 0s);
}
/* Uno de cada dos con el color secundario, sólido y más flojo: dos tonos hacen
   que el fondo respire; uno solo se lee como una mancha y ya. */
.ambiente--orbes i:nth-child(even) {
  background: radial-gradient(circle, var(--acento-2), transparent 70%);
  opacity: 0.24;
}
@keyframes vagar {
  to { transform: translate3d(var(--dx, 6vw), var(--dy, -4vh), 0) scale(var(--esc, 1.18)); }
}

/* ── Motas ──────────────────────────────────────────────────────────────── */
.ambiente--motas i {
  left: var(--x); bottom: -10vh;
  width: var(--d); height: var(--d);
  border-radius: 50%;
  background: var(--acento);
  box-shadow: 0 0 9px rgba(var(--acento-rgb), 0.75);
  opacity: 0;
  animation: subir-mota var(--dur, 22s) linear infinite;
  animation-delay: var(--esp, 0s);
}
@keyframes subir-mota {
  0%   { transform: translate3d(0, 0, 0); opacity: 0; }
  12%  { opacity: 0.55; }
  88%  { opacity: 0.4; }
  100% { transform: translate3d(var(--dx, 30px), -122vh, 0); opacity: 0; }
}

/* ── Malla ──────────────────────────────────────────────────────────────── */
.ambiente--malla {
  background-image:
    linear-gradient(rgba(var(--acento-rgb), 0.11) 1px, transparent 1px),
    linear-gradient(90deg, rgba(var(--acento-rgb), 0.11) 1px, transparent 1px);
  background-size: 68px 68px;
  /* Sin máscara, la retícula llega a los bordes y la sección parece una hoja
     de cuaderno. Difuminada por fuera se lee como profundidad. */
  mask-image: radial-gradient(ellipse 84% 72% at 50% 42%, #000 18%, transparent 76%);
  -webkit-mask-image: radial-gradient(ellipse 84% 72% at 50% 42%, #000 18%, transparent 76%);
  animation: correr-malla 34s linear infinite;
}
@keyframes correr-malla { to { background-position: 68px 68px; } }
.ambiente--malla i {
  left: var(--x); top: var(--y);
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--acento);
  box-shadow: 0 0 14px rgba(var(--acento-rgb), 0.9);
  opacity: 0.2;
  animation: latir-nodo var(--dur, 5s) ease-in-out infinite;
  animation-delay: var(--esp, 0s);
}
@keyframes latir-nodo {
  0%, 100% { opacity: 0.14; transform: scale(1); }
  50%      { opacity: 0.9;  transform: scale(1.8); }
}

/* ── Ondas ──────────────────────────────────────────────────────────────── */
/* Elipses muy anchas asomando por abajo. Con dos, a distinta velocidad, se lee
   como agua meciéndose; con una sola parece una curva decorativa. */
.ambiente--ondas i {
  left: -52%; width: 204%;
  bottom: var(--b, -14%); height: var(--h, 40%);
  border-radius: 46% 46% 0 0 / 34% 34% 0 0;
  background: linear-gradient(to top, rgba(var(--acento-rgb), 0.16), transparent);
  animation: ondear var(--dur, 18s) ease-in-out infinite alternate;
  animation-delay: var(--esp, 0s);
}
@keyframes ondear { to { transform: translate3d(5%, -2.5%, 0); } }

/* ── Anillos ────────────────────────────────────────────────────────────── */
.ambiente--anillos i {
  left: var(--x); top: var(--y);
  width: var(--d); height: var(--d);
  margin-left: calc(var(--d) / -2);
  margin-top: calc(var(--d) / -2);
  border-radius: 50%;
  border: 1px solid rgba(var(--acento-rgb), 0.45);
  opacity: 0;
  animation: expandir var(--dur, 9s) ease-out infinite;
  animation-delay: var(--esp, 0s);
}
@keyframes expandir {
  0%   { transform: scale(0.25); opacity: 0; }
  18%  { opacity: 0.55; }
  100% { transform: scale(1.9); opacity: 0; }
}

/* ── Figuras ────────────────────────────────────────────────────────────── */
.ambiente--figuras i {
  left: var(--x); top: var(--y);
  width: var(--d); height: var(--d);
  border: 1.5px solid rgba(var(--acento-rgb), 0.32);
  border-radius: var(--r, 50%);
  opacity: 0.55;
  animation: girar-figura var(--dur, 34s) linear infinite;
  animation-delay: var(--esp, 0s);
}
@keyframes girar-figura {
  0%   { transform: rotate(0deg) translateY(0); }
  50%  { transform: rotate(180deg) translateY(-26px); }
  100% { transform: rotate(360deg) translateY(0); }
}

/* ── Hojas de fondo ─────────────────────────────────────────────────────── */
/* Misma silueta que .hojas, pero repartidas por aigua.js y por sección. */
.ambiente--hojas i {
  left: var(--x); bottom: -12vh;
  width: var(--d); height: var(--d);
  border-radius: 0 62% 0 62%;
  background: linear-gradient(140deg, rgba(31, 170, 89, 0.45), rgba(134, 209, 59, 0.24));
  border: 1px solid rgba(255, 255, 255, 0.3);
  opacity: 0;
  animation: volar-hoja var(--dur, 26s) linear infinite;
  animation-delay: var(--esp, 0s);
}
@keyframes volar-hoja {
  0%   { transform: translate3d(0, 0, 0) rotate(0deg); opacity: 0; }
  12%  { opacity: 0.8; }
  86%  { opacity: 0.5; }
  100% { transform: translate3d(var(--dx, 70px), -124vh, 0) rotate(340deg); opacity: 0; }
}

/* ── Escaneo ────────────────────────────────────────────────────────────── */
/* Se anima `top` y no `transform`: la sección puede medir 700 px o 1600, y con
   un desplazamiento en vh la línea se quedaría parada fuera media vuelta. En
   porcentaje recorre exactamente la sección, mida lo que mida. */
.ambiente--escaneo i {
  left: 0; right: 0; top: 0; height: 2px;
  background: linear-gradient(90deg, transparent,
              rgba(var(--acento-rgb), 0.8) 20%, rgba(var(--acento-rgb), 0.8) 80%, transparent);
  box-shadow: 0 0 24px rgba(var(--acento-rgb), 0.55);
  animation: barrer-seccion var(--dur, 8s) linear infinite;
  animation-delay: var(--esp, 0s);
}
@keyframes barrer-seccion {
  0%   { top: -4%;  opacity: 0; }
  10%  { opacity: 0.9; }
  88%  { opacity: 0.9; }
  100% { top: 104%; opacity: 0; }
}

/* Quien pide reducir movimiento se queda con las capas que siguen teniendo
   sentido quietas —los orbes y las olas son fondo, no animación— y sin las que
   solo existen mientras se mueven. */
/* En modo oscuro el ambiente se queda quieto. Las cuatro capas que SOLO
   existen mientras viajan se retiran; las que son fondo se quedan fijas, que
   siguen dando color al bloque sin moverse. */
html[data-modo="oscuro"] .ambiente,
html[data-modo="oscuro"] .ambiente i { animation: none !important; }
html[data-modo="oscuro"] .ambiente--motas,
html[data-modo="oscuro"] .ambiente--anillos,
html[data-modo="oscuro"] .ambiente--escaneo,
html[data-modo="oscuro"] .ambiente--hojas { display: none; }
/* Sin animación, un orbe se queda en la opacidad que le toque por defecto;
   aquí se fija para que el fondo no dependa de en qué punto del ciclo estaba. */
html[data-modo="oscuro"] .ambiente--orbes i { opacity: 0.4; }
html[data-modo="oscuro"] .ambiente--malla i { opacity: 0.25; }

/* ══════════════════════════════════════════════════════════════════════════
   MÓVIL
   --------------------------------------------------------------------------
   El sitio se diseñó en pantalla ancha y se comprobó en estrecha. Lo que
   cambia en un teléfono no es solo el tamaño:

     · las rejillas no pueden pedir una columna más ancha que la pantalla
       (arreglado arriba con min(100%, …), no aquí);
     · `background-attachment: fixed` va a tirones en los navegadores móviles,
       porque repinta el fondo entero en cada fotograma de scroll;
     · el desenfoque de los paneles de cristal es de lo más caro que hay en un
       móvil, y con dieciocho píxeles de radio se nota al desplazar;
     · un botón dentro de una fila se queda de dos palabras de ancho: en
       vertical tienen que ocupar la línea entera.
   ══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 900px) {
  body[data-tema="agro"],
  body[data-tema="seguridad"],
  body[data-tema="optica"],
  html[data-modo="oscuro"] body[data-tema="agro"],
  html[data-modo="oscuro"] body[data-tema="optica"] { background-attachment: scroll; }
}

@media (max-width: 700px) {
  body { font-size: 16px; }

  .seccion { padding: clamp(58px, 9vh, 104px) 0; }
  .seccion--compacta { padding: 42px 0; }

  .gigante { font-size: clamp(2.15rem, 9.2vw, 3.2rem); letter-spacing: -0.03em; }
  .titulo  { font-size: clamp(1.65rem, 7.2vw, 2.4rem); letter-spacing: -0.026em; }
  .titulo-s { font-size: 1.22rem; }
  .subtitulo { font-size: 1rem; }

  /* En una columna, un bloque pegajoso se queda clavado encima de lo que
     debería empujar: aquí no hay dos columnas que emparejar. */
  .pegajoso { position: static; }

  .portada__contenido { padding: 104px var(--gutter) 92px; }
  .cabecera-proyecto { min-height: 86vh; min-height: 86svh; }
  .cabecera-proyecto__contenido { padding: 108px var(--gutter) 76px; }
  .portada__vidrio { padding: 26px 20px; border-radius: 22px; }

  .acciones { margin-top: 26px; }
  .acciones .boton { flex: 1 1 auto; justify-content: center; }

  .proyecto { min-height: 400px; }
  .proyecto__contenido { min-height: 400px; }

  .tarjeta__num { font-size: 3rem; top: 8px; right: 16px; }
  .banda-cifras > * { padding: 26px 14px; }
  .cifra__valor { font-size: clamp(2rem, 11vw, 2.9rem); }

  .galeria .medio { min-height: 0; }
  .duo > div, .aero-cinta, .manifiesto, .lente { padding: 26px 22px; }
  .manifiesto, .aero-cinta, .lente { border-radius: 22px; }
  .medio { border-radius: 18px; }
  .medio__chapa { font-size: 0.6rem; padding: 5px 10px; }
  .telemetria { font-size: 0.64rem; }
  .tabla th, .tabla td { padding: 12px 13px; }
  .flujo { padding-left: 30px; }

  .visor__lienzo { height: clamp(230px, 38vh, 330px); }
  .visor__medidas { font-size: 0.62rem; line-height: 1.5; }
  .visor__mandos { padding: 10px 6px; }
  .pastilla { padding: 7px 13px; font-size: 0.77rem; }

  /* El pie en fila deja columnas de dos palabras; en bloque se lee. */
  .pie { padding: 54px 0 34px; }
  .pie__filas { display: block; margin: 0; }
  .pie__filas > * { margin: 0 0 32px; }
  .pie__legal { margin-top: 34px; }
  .pie__legal > * + * { margin-left: 0; }

  /* Desenfoques y difuminados más baratos */
  .vidrio, .tarjeta, .pildora, .boton--linea {
    backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  }
  .aurora::before, .aurora::after { filter: blur(58px); }
  .ambiente--orbes i { filter: blur(34px); }
}

/* ══════════════════════════════════════════════════════════════════════════
   COPIAR EN VEZ DE ABRIR
   Los datos de contacto copian su texto y no abren el gestor de correo ni la
   app de teléfono. El único que sale fuera es WhatsApp, que es a donde de
   verdad se quiere ir.
   ══════════════════════════════════════════════════════════════════════════ */
[data-copiar] { cursor: pointer; }
.chip[data-copiar] { transition: border-color .25s, color .25s, background .25s; }
.chip[data-copiar]:hover {
  border-color: rgba(var(--acento-rgb), 0.55);
  background: rgba(var(--acento-rgb), 0.13);
  color: var(--texto);
}
/* Confirmación: el rótulo cambia a «¡Copiado!» desde JavaScript y aquí se le
   pone el color de acento. Sin señal visible, quien pulsa no sabe si pasó
   algo — y es lo que hace que vuelva a pulsar tres veces. */
[data-copiar].copiado { border-color: rgba(var(--acento-rgb), 0.85); }
.chip.copiado { color: var(--acento); background: rgba(var(--acento-rgb), 0.16); }
.chip.fallo { color: var(--texto-tenue); }
.boton.copiado { box-shadow: 0 0 0 3px rgba(var(--acento-rgb), 0.28), var(--sombra-corta); }

@media (max-width: 440px) {
  .portada__logo { width: 72px; }
  .pildora { font-size: 0.74rem; }
  .chip { font-size: 0.73rem; padding: 6px 12px; }
  .tarjeta { padding: 22px 20px; }
  .seccion--compacta { padding: 34px 0; }
}
