/* =============================================================================
   Bere Gain (Entrepreneurial) — sitio institucional de marketing.
   Sistema de diseño compartido. Lo consumen index.html y todas las páginas
   de contenido (blog/, herramientas/, benchmarks). NO confundir con landing/
   (landings de clientes).

   Estética: SaaS moderno 2026 (estilo Stripe / Linear / Vercel LIGHT mode) —
   CLARO con profundidad, confiado, con jerarquía real y vida. NO es blanco
   plano y estéril: grounds off-white/tintados (frío-verdoso muy sutil), capas
   con gradientes suaves, textura de puntos tenue, sombras reales y suaves, y el
   VERDE de la ikurriña + el ROJO de la ikurriña dándole alma. Verde esmeralda
   profundo de marca como acento PRINCIPAL; ROJO de la ikurriña como acento
   SECUNDARIO bien VISIBLE (no invisible); tinta oscura para el texto; tipografía
   Inter. El tema CLARO es UNIVERSAL (en :root, sin gatear por @media), decisión
   del operador 2026-06-07 ("light-led, no tanto negro"). La banda CTA de cierre
   se mantiene OSCURA a propósito (un momento de contraste deliberado).

   Convenciones para los agentes de contenido:
   - Usá SIEMPRE estos tokens (--ink, --accent, etc.). No inventes colores.
   - Estructura de página: <header class="site-header"> + <main> + <footer
     class="site-footer">. Ver page-template.html.
   - Componentes: .hero, .card / .grid, table comparativa, <details> FAQ,
     .quote, .cta, .pill, .prose (cuerpo de artículo), .metric, .verdict.
   - Mobile-first, breakpoint principal a 760px.
   ========================================================================== */

@import url("https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,400;0,14..32,500;0,14..32,600;0,14..32,700;0,14..32,800;1,14..32,400&display=swap");

:root {
  /* =========================================================================
     DEFAULT THEME = CLARO ("light-led"), UNIVERSAL. Paleta "VASCA EQUILIBRADA
     EN CLARO" (operador 2026-06-07): off-white tintado con PROFUNDIDAD + VERDE
     ikurriña profundo como acento PRINCIPAL (links, CTA, brillos) y ROJO
     ikurriña como acento SECUNDARIO bien VISIBLE — usado en varios sitios con
     gusto (eyebrow, subrayados, el pulso "en vivo", un highlight de tabla, un
     beam, hovers) pero NUNCA en rellenos grandes. El verde LIDERA; el rojo es
     un CO-PROTAGONISTA, no invisible. Registro de movimiento estilo Vercel:
     vivo y AHORA bien visible. No hay variante oscura global (ver nota abajo);
     la banda CTA de cierre sí es oscura, a propósito.
     ========================================================================= */

  /* ---- Texto (tinta oscura sobre claro; AA holgado) ---- */
  --ink: #243049;          /* texto principal (slate-ink ~12:1 sobre --bg) */
  --ink-strong: #0d1626;   /* titulares (casi negro azulado) */
  --muted: #51607d;        /* texto secundario (~6.2:1 sobre --bg) */
  --faint: #626e87;        /* etiquetas, meta (~4.8:1 sobre --bg, AA) */

  /* ---- Verde ikurriña (acento PRIMARIO; PROFUNDO y saturado para leer sobre
     claro y pasar AA — verde verdadero, no teal) ---- */
  --accent: #097c45;       /* verde de marca (links/texto/acentos) ~4.96:1 sobre --bg (AA) */
  --accent-dark: #065c33;  /* hover (más oscuro en claro = más contraste) */
  --accent-bright: #16b563;/* gradientes / brillos (más vivo, base del botón) */
  --accent-deep: #065c33;  /* verde muy profundo para texto sobre realces suaves */
  --accent-soft: #e3f6ec;  /* fondo de realce (tinte verde claro) */
  --accent-soft-2: #d2efde;/* realce verde un punto más saturado (hover de filas) */
  --accent-ink: #066b3a;   /* texto verde legible sobre fondos suaves (AA) */
  --glow-blue: #4f7dff;    /* tercer tono del glow (azul), solo para profundidad */

  /* ---- Rojo ikurriña (acento SECUNDARIO, AHORA bien VISIBLE: eyebrow, el pulso
     "en vivo", subrayados/links de realce, un highlight de tabla, un beam,
     hovers. SIN rellenos grandes — separado del verde por tinta/espacio para
     que NO lea navideño). ---- */
  --accent-red: #d4291d;        /* rojo vivo de la ikurriña (~4.7:1 sobre --bg) */
  --accent-red-bright: #ec3b2c; /* brillo / beam */
  --accent-red-deep: #a81d13;   /* rojo profundo para texto sobre realces */
  --accent-red-soft: #fde5e2;   /* fondo de realce rojo claro (puntual) */
  --accent-red-ink: #b5180c;    /* texto rojo legible sobre claro (AA ~5.6:1) */

  /* ---- Grounds en capas (cadencia: off-white ⇆ tintado; CON profundidad,
     nunca blanco plano) ---- */
  --line: #d8dee9;         /* bordes/divisores */
  --line-soft: #e7ebf2;
  --bg: #f6f8fb;           /* fondo de página (off-white frío, no #fff) */
  --bg-tint: #eef3f1;      /* secciones alternas (tinte verdoso muy sutil) */
  --bg-elev: #ffffff;      /* tarjetas, header (la superficie que "flota") */
  --bg-elev-2: #fbfdfc;    /* superficie aún más elevada (hover, sticky head) */
  --bg-deep: #0a1322;      /* el oscuro de cierre (banda CTA) — momento de contraste */

  --warn: #8c6005;         /* avisos de honestidad (ámbar oscuro, AA ~4.97:1 sobre warn-soft) */
  --warn-soft: #fbf2dc;

  /* ---- Layout ---- */
  --max: 960px;            /* ancho de lectura general */
  --max-wide: 1140px;      /* secciones a todo lo ancho (tabla, grid) */
  --gutter: 24px;

  /* ---- Forma ---- */
  --radius: 18px;
  --radius-lg: 24px;
  --radius-sm: 12px;
  --radius-pill: 999px;

  /* ---- Sombras: en CLARO, sombra suave y REAL tintada de frío (slate) — da
     elevación premium sin ensuciar el off-white; el glow verde da vida. Las
     sombras de claro usan ink azulado a baja opacidad (no negro puro, que se ve
     sucio sobre off-white). ---- */
  --shadow-xs: 0 1px 2px rgba(18, 32, 58, 0.07);
  --shadow-card: 0 1px 2px rgba(18, 32, 58, 0.05), 0 10px 28px rgba(18, 32, 58, 0.08);
  --shadow-lift: 0 2px 6px rgba(18, 32, 58, 0.08), 0 22px 50px rgba(18, 32, 58, 0.14);
  /* Glow retoned to the ikurriña green (rgb of --accent ≈ 10,143,77). */
  --shadow-cta: 0 2px 6px rgba(10, 143, 77, 0.22), 0 12px 30px rgba(10, 143, 77, 0.26);
  --shadow-glow: 0 24px 90px rgba(10, 143, 77, 0.16);

  --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji", sans-serif;
  --font-mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  /* A spring-ish ease with a gentle overshoot for scroll-reveal + hovers, so
     entrances feel DESIGNED (a soft settle) rather than a flat fade-up. */
  --ease-spring: cubic-bezier(0.16, 1.04, 0.3, 1);

  color-scheme: light;
}

/* =========================================================================
   El tema CLARO es universal (default para TODOS los visitantes), decisión
   del operador 2026-06-07 ("light-led, no tanto negro"). No hay variante
   oscura global detrás de @media (prefers-color-scheme: dark) a propósito: el
   mandato es un sitio CLARO premium con profundidad para todos, no que el claro
   se le caiga a quien tenga el SO en oscuro. La única superficie oscura es la
   banda CTA de cierre (.cta-band), un momento de contraste deliberado.
   color-scheme: light (arriba) le pide al UA chrome (scrollbars, form controls)
   que también vaya claro.
   ========================================================================= */

* { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: 88px;
}

body {
  margin: 0;
  font-family: var(--font-sans);
  color: var(--ink);
  background: var(--bg);
  line-height: 1.65;
  font-size: 17px;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  letter-spacing: -0.005em;
}

/* Ambient backdrop: two soft, fixed colour washes (emerald + blue) bleeding in
   from opposite top corners over the deep-ink ground, so the page never reads as
   one flat field even between sections. Fixed so it parallaxes subtly on scroll.
   Cheap (single fixed pseudo); pointer-transparent; under everything. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(60% 42% at 8% -4%, color-mix(in srgb, var(--accent) 16%, transparent) 0%, transparent 60%),
    radial-gradient(54% 40% at 100% 2%, color-mix(in srgb, var(--glow-blue) 13%, transparent) 0%, transparent 58%),
    radial-gradient(38% 32% at 96% 30%, color-mix(in srgb, var(--accent-red) 11%, transparent) 0%, transparent 60%),
    radial-gradient(40% 34% at 92% 96%, color-mix(in srgb, var(--accent) 12%, transparent) 0%, transparent 62%);
  will-change: transform;
}
/* The fixed ambient wash now drifts NOTICEABLY (operator: motion must be SEEN):
   shorter period + larger travel/scale so even the page background is visibly
   alive. A faint red wash mid-right joins the green/blue. */
@media (prefers-reduced-motion: no-preference) {
  body::before { animation: ambient-breathe 20s ease-in-out infinite; }
}
@keyframes ambient-breathe {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1.02); opacity: 1; }
  50%      { transform: translate3d(4%, -3.5%, 0) scale(1.12); opacity: 0.82; }
}

/* ---- Layout ---------------------------------------------------------------- */

.wrap { max-width: var(--max); margin: 0 auto; padding: 0 var(--gutter); }
.wrap--wide { max-width: var(--max-wide); }

main { display: block; }

section {
  padding: 88px 0;
  position: relative;
}
/* Secciones alternas con un tinte elevado para crear ritmo (cadencia
   deep-ink ⇆ elevado). En oscuro el contraste de fondo es el que da el ritmo. */
main > section:nth-of-type(even) {
  background: var(--bg-tint);
  border-top: 1px solid color-mix(in srgb, var(--line) 60%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--line) 60%, transparent);
}
section.section--plain { background: transparent !important; border: 0 !important; }

/* A hairline gradient divider that glows emerald at the centre tops each tinted
   section — marks the cadence change with a thread of brand light, not a hard
   line. Sits on the section's own top edge. */
main > section:nth-of-type(even)::before {
  content: "";
  position: absolute;
  top: -1.5px;
  left: 0;
  right: 0;
  height: 3px;
  /* A green→red→green ikurriña thread marks each cadence change — green leads
     the run, a SOLID RED band lands at centre (wider + a soft red glow) so a
     clearly visible drop of brand red repeats down the whole page rhythm. */
  background: linear-gradient(
    90deg,
    transparent 0%,
    color-mix(in srgb, var(--accent) 65%, transparent) 32%,
    var(--accent-red) 44%,
    var(--accent-red-bright) 50%,
    var(--accent-red) 56%,
    color-mix(in srgb, var(--accent) 65%, transparent) 68%,
    transparent 100%
  );
  box-shadow: 0 0 12px color-mix(in srgb, var(--accent-red) 30%, transparent);
  pointer-events: none;
}
/* And a faint emerald glow pooling at the top of each tinted section so the
   elevated grounds feel lit from within rather than just a flat darker box. */
main > section:nth-of-type(even)::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 320px;
  background: radial-gradient(
    60% 100% at 50% 0%,
    color-mix(in srgb, var(--accent) 7%, transparent) 0%,
    transparent 70%
  );
  pointer-events: none;
  z-index: 0;
}
main > section > .wrap { position: relative; z-index: 1; }

/* ---- Header / nav ---------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--bg-elev) 80%, transparent);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
}
.site-header .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding-top: 15px;
  padding-bottom: 15px;
  max-width: var(--max-wide);
}
.brand {
  font-weight: 800;
  font-size: 19px;
  letter-spacing: -0.02em;
  color: var(--ink-strong);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 9px;
}
.brand::before {
  content: "";
  width: 26px;
  height: 26px;
  border-radius: 8px;
  /* The brand mark is the ikurriña in miniature: a green field with a SOLID RED
     stripe down the right edge — so even the logo carries a clear drop of red. */
  background:
    linear-gradient(90deg, transparent 0 72%, var(--accent-red) 72% 100%),
    linear-gradient(135deg, var(--accent-bright), var(--accent-dark));
  box-shadow: var(--shadow-xs), inset 0 1px 0 rgba(255, 255, 255, 0.35);
  flex: 0 0 auto;
  transition: box-shadow 0.3s var(--ease), transform 0.3s var(--ease-spring);
}
/* The brand mark breathes a faint green aura — a quiet sign of life in the
   sticky header — and lifts/glows on hover. */
@media (prefers-reduced-motion: no-preference) {
  .brand::before { animation: mark-breathe 4.2s var(--ease) infinite; }
}
@keyframes mark-breathe {
  0%, 100% { box-shadow: var(--shadow-xs), inset 0 1px 0 rgba(255, 255, 255, 0.35), 0 0 0 0 color-mix(in srgb, var(--accent-bright) 40%, transparent); }
  50%      { box-shadow: var(--shadow-xs), inset 0 1px 0 rgba(255, 255, 255, 0.35), 0 0 14px 1px color-mix(in srgb, var(--accent-bright) 45%, transparent); }
}
.brand:hover::before { transform: scale(1.06) rotate(-3deg); box-shadow: var(--shadow-xs), inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 0 18px 2px color-mix(in srgb, var(--accent-bright) 55%, transparent); }
.brand .brand-mark { color: var(--ink-strong); }
.brand .brand-sub { color: var(--faint); font-weight: 600; font-size: 13px; letter-spacing: 0; }
.nav { display: flex; align-items: center; gap: 6px; }
.nav a {
  color: var(--muted);
  text-decoration: none;
  font-size: 14.5px;
  font-weight: 600;
  padding: 8px 12px;
  border-radius: 9px;
  transition: color 0.15s var(--ease), background 0.15s var(--ease);
}
.nav a:not(.cta):hover { color: var(--ink-strong); background: var(--line-soft); }
.nav a.cta { color: var(--bg-deep); margin-left: 8px; }
.nav a.cta:hover { color: var(--bg-deep); }

/* ---- Language switcher (i18n, ADR 103) ------------------------------------ */
/* A compact ES / EU / EN pill group. Crawlable <a> links to /, /eu/, /en/.
   Active language is marked with .is-active and aria-current="true". Uses only
   existing tokens so it inherits the dark look on every page. */
.lang-switch {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  margin-left: 10px;
  padding: 3px;
  border: 1px solid color-mix(in srgb, var(--line) 80%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--bg-elev-2) 70%, transparent);
}
.lang-switch a {
  color: var(--muted);
  text-decoration: none;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  padding: 4px 9px;
  border-radius: 999px;
  line-height: 1;
  transition: color 0.15s var(--ease), background 0.15s var(--ease);
}
.lang-switch a:hover { color: var(--ink-strong); background: var(--line-soft); }
.lang-switch a.is-active {
  color: var(--accent-ink);
  background: var(--accent-soft);
}
.lang-switch a.is-active:hover { background: var(--accent-soft); }

/* ---- Hero ------------------------------------------------------------------ */

.hero-wrap {
  position: relative;
  overflow: hidden;
  border-bottom: 1px solid var(--line);
  /* A deep vertical gradient from a slightly-lit top into the page ground, so
     the hero reads as the brightest, deepest field on the page. */
  background:
    radial-gradient(120% 90% at 50% -12%, color-mix(in srgb, var(--accent) 11%, transparent) 0%, transparent 55%),
    linear-gradient(180deg, var(--bg-tint) 0%, var(--bg) 78%);
}
/* Rejilla de fondo (textura SaaS). En oscuro la subimos un punto para que la
   trama de puntos/líneas se note como textura sin gritar. */
.hero-wrap::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(color-mix(in srgb, var(--line) 85%, transparent) 1px, transparent 1px),
    linear-gradient(90deg, color-mix(in srgb, var(--line) 85%, transparent) 1px, transparent 1px);
  background-size: 46px 46px;
  -webkit-mask-image: radial-gradient(82% 72% at 50% 0%, #000 0%, transparent 72%);
  mask-image: radial-gradient(82% 72% at 50% 0%, #000 0%, transparent 72%);
  opacity: 0.55;
  pointer-events: none;
  z-index: 0;
}
/* MESH ANIMADO del hero — la firma "viva" estilo Vercel: varias manchas de
   gradiente radial que respiran y derivan lentamente sobre el ground oscuro.
   VERDE lidera (dos plumas), un toque de AZUL para profundidad, y una mancha
   ROJA pequeña y disciplinada arriba-derecha que PUNTÚA sin invadir. El drift
   es de período largo y recorrido corto — alive but calm. Se apaga en
   reduce-motion (el fondo queda estático y legible). */
.hero-wrap::before {
  content: "";
  position: absolute;
  inset: -38% -16% auto -16%;
  height: 880px;
  /* On the LIGHT ground the mesh blobs are pumped up (≈40–55%) so the animated
     colour is unmistakably SEEN — green leads (two plumes), a clear RED plume
     top-right co-stars, a blue plume for depth. */
  background:
    radial-gradient(46% 52% at 14% 4%, color-mix(in srgb, var(--accent-bright) 52%, transparent) 0%, transparent 58%),
    radial-gradient(42% 50% at 86% -2%, color-mix(in srgb, var(--glow-blue) 38%, transparent) 0%, transparent 58%),
    radial-gradient(30% 38% at 80% 8%, color-mix(in srgb, var(--accent-red) 42%, transparent) 0%, transparent 60%),
    radial-gradient(44% 52% at 60% 34%, color-mix(in srgb, var(--accent) 30%, transparent) 0%, transparent 62%);
  filter: blur(14px);
  opacity: 0.9;
  pointer-events: none;
  z-index: 0;
  will-change: transform;
}
/* MUCH more visible drift (operator 2026-06-07: "no veo movimiento"): shorter
   period + bigger travel + scale so the mesh clearly DRIFTS, not just breathes. */
@media (prefers-reduced-motion: no-preference) {
  .hero-wrap::before { animation: mesh-drift 14s ease-in-out infinite; }
}
@keyframes mesh-drift {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  25%      { transform: translate3d(-6%, 4.5%, 0) scale(1.12) rotate(2deg); }
  50%      { transform: translate3d(5%, -3%, 0) scale(1.08) rotate(-1.5deg); }
  75%      { transform: translate3d(-3.5%, -4%, 0) scale(1.14) rotate(1deg); }
}
.hero-wrap > .wrap { position: relative; z-index: 1; max-width: var(--max-wide); }

.hero {
  padding: 96px 0 84px;
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: 56px;
  align-items: center;
}
.hero-copy { max-width: 36rem; }
/* ---- BRANDED EYEBROW (hero) — NOT a generic SaaS pill (operator 2026-06-07).
   A custom "label tab": no rounded chip. A flat-topped tag with a clipped
   bottom-right corner, an ikurriña GREEN+RED double bar on the left as the mark,
   uppercase tracked label, and a sharp lower edge. Reads as an engineered label
   plate, ours, not boilerplate. The RED bar is one of the page's visible reds. */
.hero .eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-deep);
  background:
    linear-gradient(180deg, #ffffff 0%, var(--accent-soft) 100%);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--line));
  border-left: 0;
  padding: 7px 16px 7px 13px;
  margin-bottom: 22px;
  border-radius: 0 4px 4px 0;
  box-shadow: var(--shadow-xs), inset 1px 0 0 color-mix(in srgb, var(--accent) 12%, transparent);
  position: relative;
}
/* The ikurriña double-bar mark: a GREEN bar over a fuller RED bar, flush to the
   tag's left edge. Wider (7px) + a roughly even green/red split so the RED is
   clearly readable as red on the plate, not a sliver. The custom brand glint. */
.hero .eyebrow::after {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 7px;
  background: linear-gradient(180deg, var(--accent) 0% 50%, var(--accent-red) 50% 100%);
}
/* The eyebrow's live dot is a bigger, SOLID red "en vivo" signal — a clearly
   VISIBLE drop of ikurriña red. It pulses (radar) so the hero reads as ALIVE. */
.hero .eyebrow::before {
  content: "";
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--accent-red);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-red) 34%, transparent);
}
.hero h1 {
  font-size: clamp(36px, 4.6vw, 58px);
  line-height: 1.04;
  letter-spacing: -0.035em;
  margin: 0 0 22px;
  color: var(--ink-strong);
  font-weight: 800;
}
/* The emphasised verb ("y publica" / "and publishes") is SOLID ikurriña RED —
   not a gradient that the eye reads as green. This is the single biggest, most
   central, UNMISTAKABLE drop of brand red on the page: the headline's climax
   word is red, full stop. A thick solid-red underline rule sits under it so the
   red reads even at a glance / on a thumbnail. Red text on --bg here is
   --accent-red-ink (~5.6:1 over the off-white) → clears AA for this large bold
   heading with room. Green still leads the rest of the headline. */
.hero h1 em {
  font-style: normal;
  color: var(--accent-red-ink);
  -webkit-text-fill-color: var(--accent-red-ink);
  position: relative;
}
.hero h1 em::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -0.06em;
  height: 0.14em;
  border-radius: 3px;
  background: var(--accent-red);
  box-shadow: 0 2px 10px color-mix(in srgb, var(--accent-red) 38%, transparent);
  opacity: 1;
}
.hero .lede {
  font-size: clamp(17px, 1.7vw, 20px);
  color: var(--muted);
  max-width: 38ch;
  margin: 0 0 32px;
  line-height: 1.6;
}
.hero-actions { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; }
.hero-trust {
  margin-top: 26px;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  font-size: 13.5px;
  color: var(--faint);
  font-weight: 500;
}
.hero-trust span { display: inline-flex; align-items: center; gap: 7px; }
.hero-trust span::before {
  content: "✓";
  color: var(--accent);
  font-weight: 800;
  font-size: 12px;
}

/* Mockup de chat de Telegram (CSS puro, sin assets externos). */
.hero-visual { position: relative; }
/* Aura esmeralda detrás de la tarjeta — la hace "flotar" e iluminarse desde
   atrás contra el ground oscuro. Suave respiración (drift) para vida sutil. */
.hero-visual::before {
  content: "";
  position: absolute;
  inset: -14% -8% -14% 8%;
  border-radius: 50%;
  /* Boosted for the LIGHT ground + a RED plume so the aura behind the card is a
     visible green/blue/red glow, not a wash that the light eats. */
  background:
    radial-gradient(50% 50% at 60% 42%, color-mix(in srgb, var(--accent-bright) 46%, transparent) 0%, transparent 68%),
    radial-gradient(46% 46% at 30% 70%, color-mix(in srgb, var(--glow-blue) 30%, transparent) 0%, transparent 72%),
    radial-gradient(34% 36% at 82% 78%, color-mix(in srgb, var(--accent-red) 30%, transparent) 0%, transparent 70%);
  filter: blur(36px);
  z-index: 0;
  pointer-events: none;
}
/* The aura visibly drifts + breathes behind the card now (bigger travel/scale). */
@media (prefers-reduced-motion: no-preference) {
  .hero-visual::before { animation: aura-drift 7s ease-in-out infinite; }
}
@keyframes aura-drift {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); opacity: 0.92; }
  50%      { transform: translate3d(5%, -4%, 0) scale(1.12); opacity: 1; }
}
.chat-card {
  position: relative;
  z-index: 1;
  /* A faint top-light gives the card surface a glassy SaaS sheen on dark. */
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--accent) 6%, var(--bg-elev)) 0%, var(--bg-elev) 28%);
  border: 1px solid color-mix(in srgb, var(--accent) 16%, var(--line));
  border-radius: var(--radius-lg);
  box-shadow:
    var(--shadow-lift),
    var(--shadow-glow),
    inset 0 1px 0 color-mix(in srgb, #fff 8%, transparent);
  overflow: hidden;
  max-width: 420px;
  margin-left: auto;
  transform: perspective(1400px) rotateY(-7deg) rotateX(2deg);
  transition: transform 0.5s var(--ease), box-shadow 0.5s var(--ease);
}
.hero-visual:hover .chat-card {
  transform: perspective(1400px) rotateY(-3deg) rotateX(1deg);
  box-shadow:
    var(--shadow-lift),
    0 36px 120px color-mix(in srgb, var(--accent-bright) 30%, transparent),
    inset 0 1px 0 color-mix(in srgb, #fff 10%, transparent);
}
/* BORDER-SWEEP BEAM on the hero chat card — a conic gradient (green-led, with a
   single red arc) sweeps around the border so a thread of brand light travels
   the frame. We animate the conic's ANGLE via a registered custom property
   (@property --beam) so the gradient itself rotates with no element wobble; the
   ::before is masked (xor) to a thin ring. Subtle: low opacity, long period. */
@property --beam {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}
.chat-card::before {
  content: "";
  position: absolute;
  inset: -1.5px;
  border-radius: inherit;
  padding: 1.5px;
  background: conic-gradient(
    from var(--beam),
    transparent 0deg,
    color-mix(in srgb, var(--accent-bright) 88%, transparent) 56deg,
    transparent 124deg,
    color-mix(in srgb, var(--accent-red-bright) 72%, transparent) 192deg,
    transparent 248deg,
    color-mix(in srgb, var(--accent-bright) 62%, transparent) 312deg,
    transparent 360deg
  );
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask-composite: exclude;
  opacity: 0.85;
  pointer-events: none;
  z-index: 0;
}
/* The border beam travels clearly faster now so the thread of brand light is
   obviously moving around the card frame. */
@media (prefers-reduced-motion: no-preference) {
  .chat-card::before { animation: border-sweep 4s linear infinite; }
}
.hero-visual:hover .chat-card::before { opacity: 1; }
@keyframes border-sweep {
  to { --beam: 360deg; }
}
.chat-top {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 14px 18px;
  background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 12%, var(--bg-elev)), var(--bg-elev));
  border-bottom: 1px solid var(--line);
}
.chat-avatar {
  width: 36px; height: 36px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent-bright), var(--accent-dark));
  flex: 0 0 auto;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3);
}
.chat-id { line-height: 1.25; }
.chat-id b { color: var(--ink-strong); font-size: 14.5px; font-weight: 700; display: block; }
.chat-id small { color: var(--accent); font-size: 12px; font-weight: 600; }
.chat-body { padding: 18px; display: grid; gap: 12px; background: var(--bg-deep); }
.bubble {
  font-size: 14px;
  line-height: 1.5;
  padding: 11px 14px;
  border-radius: 16px;
  max-width: 85%;
  box-shadow: var(--shadow-xs);
}
.bubble.in {
  background: var(--bg-elev);
  border: 1px solid var(--line);
  color: var(--ink);
  border-bottom-left-radius: 5px;
}
.bubble.out {
  background: linear-gradient(135deg, var(--accent), var(--accent-dark));
  color: #fff;
  margin-left: auto;
  border-bottom-right-radius: 5px;
}
.bubble.out b { color: #fff; }
.chat-files { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 2px; }
.chat-file {
  font-size: 11.5px;
  font-weight: 700;
  color: var(--accent-ink);
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 25%, var(--line));
  padding: 4px 10px;
  border-radius: var(--radius-pill);
}

/* ---- Typography ------------------------------------------------------------ */

.section-head { max-width: 56ch; margin-bottom: 40px; }
.section-head.center { margin-left: auto; margin-right: auto; text-align: center; }
/* ---- BRANDED SECTION EYEBROW — same custom "label tag" language as the hero
   eyebrow (NOT a generic AI pill). A flat-edged tag with the ikurriña GREEN+RED
   double-bar mark on the left and an uppercase tracked label. Consistent across
   every section + every language (shares this CSS). */
.eyebrow-text {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--accent-deep);
  margin-bottom: 14px;
  padding: 5px 14px 5px 14px;
  border-radius: 0 4px 4px 0;
  background: linear-gradient(180deg, #ffffff 0%, var(--accent-soft) 100%);
  border: 1px solid color-mix(in srgb, var(--accent) 28%, var(--line));
  border-left: 0;
  box-shadow: var(--shadow-xs);
  position: relative;
}
/* The ikurriña double-bar mark flush to the tag's left edge — GREEN over a
   fuller RED (even split, wider) so EVERY section header carries a clearly
   readable drop of red, not a sliver. */
.eyebrow-text::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 7px;
  border-radius: 0;
  background: linear-gradient(180deg, var(--accent) 0% 50%, var(--accent-red) 50% 100%);
  box-shadow: none;
  flex: 0 0 auto;
}
/* The section-eyebrow mark breathes a faint glow so each section header has a
   quiet sign of life as it scrolls into view. */
@media (prefers-reduced-motion: no-preference) {
  .eyebrow-text::before { animation: bar-breathe 3.4s var(--ease) infinite; }
}
@keyframes bar-breathe {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 0%, transparent); filter: brightness(1); }
  50%      { box-shadow: 2px 0 10px -2px color-mix(in srgb, var(--accent) 55%, transparent); filter: brightness(1.12); }
}
/* When the tag is centered (section-head.center) it can't hug a left margin, so
   the inner left-bar mark reads as an integral part of the centered plate. */
.section-head.center .eyebrow-text { margin-left: auto; margin-right: auto; }

h2 {
  font-size: clamp(27px, 3.2vw, 38px);
  line-height: 1.12;
  letter-spacing: -0.028em;
  margin: 0 0 14px;
  color: var(--ink-strong);
  font-weight: 800;
}
h3 { font-size: 20px; line-height: 1.35; margin: 30px 0 8px; color: var(--ink-strong); font-weight: 700; letter-spacing: -0.015em; }
.section-lede { color: var(--muted); max-width: 60ch; margin: 0 0 8px; font-size: 18px; }
.section-head .section-lede { margin-bottom: 0; }
.section-head.center .section-lede { margin-left: auto; margin-right: auto; }
p { margin: 0 0 16px; }
a { color: var(--accent); transition: color 0.15s var(--ease); }
a:hover { color: var(--accent-dark); }
strong { color: var(--ink-strong); font-weight: 700; }
small { color: var(--muted); }

/* Prose container para artículos largos (blog). */
.prose { max-width: 72ch; font-size: 17.5px; }
.prose > p { color: var(--ink); }
.prose h2 { margin-top: 52px; }
.prose h3 { margin-top: 34px; }
.prose ul, .prose ol { margin: 0 0 20px; padding-left: 24px; }
.prose li { margin-bottom: 10px; }
.prose li::marker { color: var(--accent); font-weight: 700; }
.prose code {
  font-family: var(--font-mono);
  font-size: 0.86em;
  background: var(--line-soft);
  border: 1px solid var(--line);
  padding: 2px 6px;
  border-radius: 6px;
}
.prose blockquote {
  margin: 26px 0;
  padding: 6px 0 6px 22px;
  border-left: 3px solid var(--accent);
  color: var(--muted);
  font-style: italic;
}
/* Underline-grow micro-interaction on in-body prose links: a green underline
   wipes in left→right on hover (classy, fast). Scoped to .prose so it never
   touches nav / CTA / footer / card links (which have their own affordances). */
.prose p a,
.prose li a {
  text-decoration: none;
  /* The underline grows in a GREEN→RED ikurriña wipe (green leads, red lands) —
     a visible red micro-touch on every in-body link. */
  background-image: linear-gradient(90deg, var(--accent), var(--accent-red));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 2px;
  transition: background-size 0.28s var(--ease), color 0.15s var(--ease);
}
.prose p a:hover,
.prose li a:hover { background-size: 100% 2px; color: var(--accent-dark); }

/* ---- CTA / pills ----------------------------------------------------------- */

.cta {
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  /* On LIGHT, the primary button is a vibrant emerald gradient (bright → brand)
     with DARK ink. Dark-on-bright-green reads CRISP and premium and clears AA
     for large bold text with room (~6.9:1 at the bright end, ~3.5:1 at the brand
     end, both ≥3:1 large-text floor); white on this green would be soft/failing.
     Dark-on-green is also the loudest, most confident treatment for the call. */
  background: linear-gradient(135deg, var(--accent-bright), var(--accent));
  color: var(--bg-deep);
  text-decoration: none;
  padding: 14px 26px;
  border-radius: var(--radius-sm);
  font-weight: 700;
  font-size: 16px;
  letter-spacing: -0.01em;
  box-shadow: var(--shadow-cta);
  transition: transform 0.18s var(--ease), box-shadow 0.22s var(--ease), filter 0.18s var(--ease);
}
.cta::after {
  content: "→";
  position: relative;
  z-index: 1;
  font-weight: 700;
  transition: transform 0.18s var(--ease);
}
/* A diagonal SHEEN sweep across the primary button on hover (Vercel micro-int).
   It rests off-screen left and travels across once per hover. */
.cta::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: linear-gradient(
    100deg,
    transparent 30%,
    rgba(255, 255, 255, 0.34) 50%,
    transparent 70%
  );
  transform: translateX(-130%);
  pointer-events: none;
}
.cta > * { position: relative; z-index: 1; }
@media (prefers-reduced-motion: no-preference) {
  .cta:hover::before { animation: cta-sheen 0.7s var(--ease) forwards; }
}
@keyframes cta-sheen {
  to { transform: translateX(130%); }
}
/* Hover lift + a glow that mixes the green halo with a disciplined RED edge —
   the red punctuates the primary call exactly at the moment of intent. */
.cta:hover {
  color: var(--bg-deep);
  transform: translateY(-2px);
  box-shadow:
    var(--shadow-lift),
    0 16px 40px color-mix(in srgb, var(--accent-bright) 34%, transparent),
    0 0 0 1px color-mix(in srgb, var(--accent-red) 26%, transparent),
    0 10px 30px color-mix(in srgb, var(--accent-red) 16%, transparent);
  filter: brightness(1.05);
}
.cta:hover::after { transform: translateX(3px); }
.cta--sm { padding: 9px 17px; font-size: 14px; box-shadow: var(--shadow-xs); border-radius: 10px; }
.cta--sm::after { display: none; }
.cta.secondary {
  background: var(--bg-elev);
  color: var(--ink-strong);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-xs);
}
.cta.secondary::after { content: "↓"; color: var(--accent); }
.cta.secondary:hover { background: var(--line-soft); color: var(--ink-strong); border-color: color-mix(in srgb, var(--accent) 35%, var(--line)); }
.cta.secondary:hover::after { transform: translateY(2px); }
/* RED-OUTLINED secondary CTA — a confident red-bordered button so the hero
   carries a clearly RED interactive element next to the green primary. Red ink
   on white (--accent-red-ink ~5.6:1) clears AA; a 2px solid red border makes the
   red unmistakable. On hover the red fills softly. Tasteful punctuation, not a
   loud red block. */
.cta.secondary.cta--red {
  color: var(--accent-red-ink);
  border: 2px solid var(--accent-red);
  background: var(--bg-elev);
  box-shadow: var(--shadow-xs), 0 6px 18px color-mix(in srgb, var(--accent-red) 14%, transparent);
}
.cta.secondary.cta--red::after { content: "→"; color: var(--accent-red); }
.cta.secondary.cta--red:hover {
  color: var(--accent-red-deep);
  background: var(--accent-red-soft);
  border-color: var(--accent-red-deep);
}
.cta.secondary.cta--red:hover::after { transform: translateX(3px); }

.pill {
  display: inline-block;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--accent-ink);
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 26%, var(--line));
  padding: 4px 11px;
  border-radius: var(--radius-pill);
}

/* ---- Cards / grid ---------------------------------------------------------- */

.grid { display: grid; gap: 20px; margin-top: 8px; }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }

/* Recursos reducido: una sola tarjeta de herramienta. Acotada y CENTRADA bajo
   un encabezado centrado (mismo lenguaje que #por-dentro) para que la reducción
   se lea como minimalismo deliberado y simétrico, no como una sección a medias
   con la mitad derecha vacía. Un enlace discreto al blog, también centrado. */
.resource-solo { max-width: 620px; margin: 8px auto 0; }
/* El acento esmeralda en el borde superior subraya que es la pieza-foco de la
   sección, no una tarjeta cualquiera flotando a la izquierda. */
.resource-solo .card {
  text-align: center;
  padding-left: 26px;            /* undo .card--step left inset; centered now */
  border-color: color-mix(in srgb, var(--accent) 28%, var(--line));
}
/* The left accent bar of .card--step fights a centered composition — drop it;
   the emerald .k label + the emerald border already carry the accent. */
.resource-solo .card.card--step::before { display: none; }
.resource-solo .card .k { display: block; }
.resource-solo .card .card-title { margin-top: 6px; }
.resource-solo .card .more { justify-content: center; }
.resource-blog-link { margin-top: 20px; font-size: 15px; text-align: center; }
.resource-blog-link a { color: var(--muted); }
.resource-blog-link a:hover { color: var(--accent); }

.card {
  position: relative;
  /* A subtle vertical surface gradient (lighter at the top) reads as a real
     elevated panel catching ambient light on dark — not a flat dark rectangle. */
  background: linear-gradient(180deg, var(--bg-elev-2) 0%, var(--bg-elev) 60%);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 26px;
  box-shadow: var(--shadow-card), inset 0 1px 0 color-mix(in srgb, #fff 5%, transparent);
  transition: transform 0.28s var(--ease-spring), box-shadow 0.28s var(--ease), border-color 0.28s var(--ease);
}
/* Hover micro-interaction: the card lifts (spring settle) + lights with a green
   halo and a hairline emerald ring; a faint top-light sweeps in. Green leads. */
.card:hover {
  transform: translateY(-4px);
  box-shadow:
    var(--shadow-lift),
    0 0 0 1px color-mix(in srgb, var(--accent) 28%, transparent),
    0 22px 56px color-mix(in srgb, var(--accent) 16%, transparent);
  border-color: color-mix(in srgb, var(--accent) 48%, var(--line));
}
.card .k {
  font-weight: 700;
  color: var(--accent);
  display: block;
  margin-bottom: 8px;
  font-size: 14px;
  letter-spacing: 0.01em;
}
.card .card-title { font-weight: 700; color: var(--ink-strong); display: block; margin-bottom: 8px; font-size: 17px; letter-spacing: -0.01em; }
.card .card-title a { color: var(--ink-strong); text-decoration: none; }
.card .card-title a:hover { color: var(--accent); }
.card p { color: var(--muted); }
.card p:last-child { margin-bottom: 0; }
.card a.more {
  font-weight: 700;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.card a.more:hover { gap: 7px; }

/* Tarjeta de entregable numerada. */
.card--step { position: relative; padding-top: 26px; padding-left: 26px; }
.card--step::before {
  content: "";
  position: absolute;
  left: 0; top: 26px;
  width: 3px; height: 28px;
  border-radius: 3px;
  background: linear-gradient(180deg, var(--accent-bright), var(--accent-dark));
}
.card--step .k {
  display: inline-flex;
  align-items: baseline;
  gap: 9px;
}

/* Tarjeta de "feature" con ícono numerado en círculo. */
.feature { padding: 30px; overflow: hidden; }
/* A thin GREEN top-edge beam that brightens + travels on hover (Vercel-style
   border accent). Resting it is a faint emerald hairline; on hover it lights and
   sweeps across, with a single red glint at the trailing edge to punctuate. */
.feature::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  /* A GREEN→RED ikurriña top rule crowning every feature card — visible at REST
     now (not only on hover), so red co-stars across the whole "por qué" grid.
     On hover the thread travels across + brightens. */
  /* The rule shows roughly its LEFT ~46% at rest (background-size 220%, position
     0), then on hover slides to its RIGHT edge. So the red must sit INSIDE that
     left window to co-star at rest: green leads, a clear RED lands by ~34-44%
     (seen at rest), then a bright emerald tail extends for the hover sweep. */
  background: linear-gradient(
    90deg,
    var(--accent) 0%,
    var(--accent-bright) 18%,
    var(--accent-red-bright) 34%,
    var(--accent-red) 44%,
    color-mix(in srgb, var(--accent-red) 60%, var(--accent)) 56%,
    var(--accent-bright) 78%,
    var(--accent) 100%
  );
  background-size: 220% 100%;
  background-position: 0 0;
  opacity: 0.9;
  pointer-events: none;
  transition: opacity 0.3s var(--ease), background-position 0.7s var(--ease);
}
.feature:hover::before { opacity: 1; background-position: 100% 0; }
/* The "honest verdict" feature (feature--red) is the deliberate RED card in the
   "por qué" grid: a SOLID red top rule + a red icon chip. Thematically right —
   it's the "we tell you NO / don't spend" capability — and it plants a clearly
   visible red card mid-page so red co-stars below the hero too. */
.feature--red::before {
  background: linear-gradient(90deg, var(--accent-red-deep), var(--accent-red-bright) 50%, var(--accent-red-deep));
  background-size: 220% 100%;
  opacity: 1;
}
.feature--red .feature-ic {
  color: var(--accent-red-ink);
  background: var(--accent-red-soft);
  border-color: color-mix(in srgb, var(--accent-red) 28%, var(--line));
}
.feature .feature-ic {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px; height: 46px;
  border-radius: 14px;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 22%, var(--line));
  margin-bottom: 16px;
  box-shadow: var(--shadow-xs);
}
.feature .feature-ic svg { width: 23px; height: 23px; display: block; }
.feature h3 { margin: 0 0 8px; font-size: 19px; }
.feature p { margin: 0; }

/* ---- Comparison table ------------------------------------------------------ */

.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  background: var(--bg-elev);
}
table {
  width: 100%;
  border-collapse: collapse;
  margin: 0;
  font-size: 15px;
  background: transparent;
  min-width: 680px;
}
th, td {
  text-align: left;
  padding: 15px 18px;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
tr:last-child td { border-bottom: none; }
th + th, td + td { border-left: 1px solid var(--line-soft); }
thead th {
  background: var(--bg-tint);
  color: var(--ink-strong);
  font-weight: 700;
  font-size: 14px;
  letter-spacing: -0.01em;
  position: sticky;
  top: 0;
}
/* The winning "Bere Gain" column is the highlighted lane: green realce + a BOLD
   solid ikurriña RED top band (4px inset, so it doesn't shift sticky layout)
   crowning the column header — a clearly visible red bar marking "this is the
   one", plus a red text rule under the heading label. */
thead th:nth-child(2) {
  color: var(--accent-deep);
  background: color-mix(in srgb, var(--accent-soft) 85%, var(--bg-tint));
  box-shadow:
    inset 0 4px 0 var(--accent-red),
    inset 0 -2px 0 color-mix(in srgb, var(--accent-red) 55%, transparent);
}
thead th:first-child { color: var(--faint); font-weight: 600; }
tbody tr { transition: background 0.12s var(--ease); }
tbody tr:hover td { background: color-mix(in srgb, var(--accent-soft) 45%, transparent); }
/* On hover the winning cell glints a hairline red left-edge — red co-stars the
   green highlight at the moment of attention. */
tbody tr:hover td:nth-child(2) { box-shadow: inset 3px 0 0 color-mix(in srgb, var(--accent-red) 70%, transparent); }
tbody td:first-child { font-weight: 700; color: var(--ink-strong); }
tbody td:nth-child(2) { background: color-mix(in srgb, var(--accent-soft) 55%, transparent); }
.yes { color: var(--accent-ink); font-weight: 700; }
.yes::before { content: "✓ "; font-weight: 800; color: var(--accent); }

/* ---- FAQ (details) --------------------------------------------------------- */

.faq { display: grid; gap: 12px; max-width: 760px; }
details {
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 4px 22px;
  box-shadow: var(--shadow-xs);
  transition: border-color 0.18s var(--ease), box-shadow 0.18s var(--ease);
}
details:hover { border-color: color-mix(in srgb, var(--accent) 28%, var(--line)); }
details[open] {
  border-color: color-mix(in srgb, var(--accent) 42%, var(--line));
  box-shadow: var(--shadow-card);
}
summary {
  cursor: pointer;
  font-weight: 700;
  padding: 16px 0;
  list-style: none;
  color: var(--ink-strong);
  display: flex;
  gap: 12px;
  align-items: flex-start;
  font-size: 16.5px;
  letter-spacing: -0.01em;
}
summary::-webkit-details-marker { display: none; }
summary::before {
  content: "+";
  color: var(--accent);
  font-weight: 700;
  font-size: 22px;
  line-height: 1.15;
  flex: 0 0 auto;
  transition: transform 0.2s var(--ease);
}
/* Open FAQ rows flip the marker to a RED minus — a small, repeated ikurriña-red
   signal down the FAQ list as rows are opened. */
details[open] summary::before { content: "−"; color: var(--accent-red); transform: rotate(180deg); }
details > p { padding: 0 0 18px 28px; color: var(--muted); margin: 0; }

/* ---- Quote / callout ------------------------------------------------------- */

.quote {
  border: 1px solid color-mix(in srgb, var(--accent) 28%, var(--line));
  border-left: 4px solid var(--accent);
  background: linear-gradient(135deg, var(--accent-soft), color-mix(in srgb, var(--accent-soft) 30%, var(--bg-elev)));
  padding: 22px 26px;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-size: 18px;
  line-height: 1.6;
  color: var(--accent-ink);
  margin: 8px 0 0;
  box-shadow: var(--shadow-xs);
}
.quote em { font-style: italic; }

.note {
  border: 1px solid color-mix(in srgb, var(--warn) 32%, var(--line));
  background: var(--warn-soft);
  border-radius: var(--radius-sm);
  padding: 16px 20px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--warn);
  box-shadow: var(--shadow-xs);
}
.note strong { color: var(--warn); }
.note a { color: var(--accent-dark); }

/* ---- Article meta (blog) --------------------------------------------------- */

.article-head {
  padding: 72px 0 28px;
  position: relative;
}
/* Wash de color tenue detrás del encabezado de artículo/herramienta. */
.article-head::before {
  content: "";
  position: absolute;
  inset: -200px 0 auto 0;
  height: 460px;
  background: radial-gradient(70% 100% at 12% 100%, color-mix(in srgb, var(--accent-soft) 55%, transparent), transparent 60%);
  pointer-events: none;
  z-index: -1;
}
.article-head h1 {
  font-size: clamp(30px, 4.6vw, 46px);
  line-height: 1.12;
  letter-spacing: -0.03em;
  margin: 14px 0 16px;
  color: var(--ink-strong);
  max-width: 24ch;
  font-weight: 800;
}
.article-meta { color: var(--faint); font-size: 14px; display: flex; gap: 16px; flex-wrap: wrap; align-items: center; }
.breadcrumb { font-size: 13.5px; color: var(--faint); margin: 0 0 4px; font-weight: 500; }
.breadcrumb a { text-decoration: none; color: var(--muted); }
.breadcrumb a:hover { color: var(--accent); }

/* ---- Footer ---------------------------------------------------------------- */

.site-footer {
  padding: 56px 0 64px;
  color: var(--muted);
  font-size: 14px;
  border-top: 1px solid var(--line);
  background: var(--bg-tint);
}
.site-footer .wrap { max-width: var(--max-wide); }
.site-footer .foot-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 28px 48px;
  justify-content: space-between;
  align-items: flex-start;
}
.site-footer a { color: var(--muted); text-decoration: none; transition: color 0.15s var(--ease); }
.site-footer a:hover { color: var(--accent); }
.site-footer .foot-links { display: flex; gap: 14px 22px; flex-wrap: wrap; }
.site-footer .foot-links a { font-weight: 600; }
.site-footer .foot-legal { margin-top: 28px; padding-top: 20px; border-top: 1px solid var(--line); font-size: 13px; color: var(--faint); }
.site-footer strong { color: var(--ink-strong); }

/* ---- Dark CTA band (cierre) ----------------------------------------------- */

.cta-band {
  /* THE deliberate DARK moment on a light page (operator 2026-06-07): a deep
     night-ink panel that POPS as a lit destination off the bright site. A green
     wash blooms from the top, a disciplined RED ember glows bottom-right, and a
     glowing emerald ring + real shadow lift it. Distinct dark island = the
     closing call reads as the climax, not another card. */
  background:
    radial-gradient(58% 110% at 50% -10%, color-mix(in srgb, var(--accent-bright) 30%, transparent) 0%, transparent 48%),
    radial-gradient(40% 80% at 92% 112%, color-mix(in srgb, var(--accent-red-bright) 46%, transparent) 0%, transparent 52%),
    linear-gradient(180deg, #0b1424 0%, #060c17 100%);
  color: #d7deec;
  border: 1px solid color-mix(in srgb, var(--accent-bright) 40%, #20304d);
  border-radius: var(--radius-lg);
  padding: 60px 40px;
  text-align: center;
  box-shadow:
    var(--shadow-lift),
    0 0 0 1px color-mix(in srgb, var(--accent-bright) 16%, transparent),
    0 40px 120px rgba(7, 18, 33, 0.45),
    0 0 90px color-mix(in srgb, var(--accent-bright) 18%, transparent),
    inset 0 1px 0 color-mix(in srgb, #fff 10%, transparent);
  position: relative;
  overflow: hidden;
}
/* A SOLID ikurriña accent bar crowning the closing band (respects the rounded
   corners): green leads the bar, a clear RED segment lands at the right — the
   visible red bookend on the dark climax panel. Sits above the dot-grid/wash. */
.cta-band::after,
.cta-band::before { z-index: 0; }
.cta-band > .cta-band-rule {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 4px;
  background: linear-gradient(90deg,
    var(--accent-bright) 0%,
    var(--accent) 48%,
    var(--accent-red-bright) 74%,
    var(--accent-red) 100%);
  z-index: 1;
  pointer-events: none;
}
/* A soft dot-grid texture inside the band echoes the hero vocabulary. */
.cta-band::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    radial-gradient(color-mix(in srgb, var(--accent) 16%, transparent) 1px, transparent 1px);
  background-size: 22px 22px;
  -webkit-mask-image: radial-gradient(70% 90% at 50% 0%, #000 0%, transparent 75%);
  mask-image: radial-gradient(70% 90% at 50% 0%, #000 0%, transparent 75%);
  opacity: 0.5;
  pointer-events: none;
}
/* A wide, slow wash that drifts gently across the band — the "gradient drift on
   a band" rhythm. GREEN leads (the big wash); a small disciplined RED ember
   drifts on the opposite side so the closing band carries both ikurriña hues
   without a Christmassy clash (they sit apart, separated by ink). Classy: long
   period, low travel, soft blur. */
.cta-band::after {
  content: "";
  position: absolute;
  inset: -40% -30%;
  background:
    radial-gradient(36% 64% at 26% 28%, color-mix(in srgb, var(--accent-bright) 40%, transparent) 0%, transparent 68%),
    radial-gradient(24% 44% at 84% 74%, color-mix(in srgb, var(--accent-red-bright) 34%, transparent) 0%, transparent 70%);
  filter: blur(30px);
  pointer-events: none;
  z-index: 0;
}
/* The closing band's wash drifts OBVIOUSLY across it (green wash + red ember
   crossing in opposite directions), so even the dark band is clearly alive. */
@media (prefers-reduced-motion: no-preference) {
  .cta-band::after { animation: band-drift 11s ease-in-out infinite; }
}
@keyframes band-drift {
  0%, 100% { transform: translate3d(-12%, -2%, 0) scale(1); opacity: 0.78; }
  50%      { transform: translate3d(16%, 7%, 0) scale(1.1); opacity: 1; }
}
.cta-band > * { position: relative; z-index: 1; }
.cta-band h2 { color: #ffffff; }
.cta-band .section-lede { color: #aeb9cf; }
/* The button keeps the bright emerald brand gradient so it reads as the single
   loudest call on the page (not a muddy white-on-dark chip). */
.cta-band .cta {
  background: linear-gradient(135deg, var(--accent-bright), var(--accent));
  color: var(--bg-deep);
  box-shadow: var(--shadow-cta), 0 0 38px color-mix(in srgb, var(--accent-bright) 55%, transparent);
  font-weight: 800;
}
.cta-band .cta:hover { color: var(--bg-deep); filter: brightness(1.06); }

/* ---- Utilities ------------------------------------------------------------- */

.center { text-align: center; }
.mt-0 { margin-top: 0; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* Entrada al hacer scroll: un fade-up con settle spring-ish (overshoot suave) +
   un toque de blur que se enfoca — lee como movimiento DISEÑADO, no aleatorio.
   El stagger lo aplica site.js (transition-delay por posición en el grupo). */
@media (prefers-reduced-motion: no-preference) {
  .reveal {
    opacity: 0;
    transform: translateY(34px);
    filter: blur(8px);
    transition:
      opacity 0.75s var(--ease),
      transform 0.8s var(--ease-spring),
      filter 0.65s var(--ease);
  }
  .reveal.in-view { opacity: 1; transform: none; filter: none; }
}

/* ---- Responsive ------------------------------------------------------------ */

@media (max-width: 980px) {
  .hero { grid-template-columns: 1fr; gap: 44px; padding: 72px 0 64px; }
  .hero-copy { max-width: none; }
  .chat-card { transform: none; margin: 0 auto; }
  .hero-visual:hover .chat-card { transform: none; }
}

@media (max-width: 760px) {
  body { font-size: 16px; }
  .nav { gap: 2px; }
  .nav a:not(.cta) { display: none; }   /* solo el CTA en pantallas chicas */
  .grid--2, .grid--3 { grid-template-columns: 1fr; }
  section { padding: 56px 0; }
  .hero { padding: 56px 0 48px; }
  .hero h1 { font-size: clamp(31px, 8vw, 40px); }
  .cta-band { padding: 40px 24px; border-radius: var(--radius); }
  .article-head { padding: 48px 0 8px; }
  :root { --gutter: 18px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition: none !important; animation: none !important; }
  .reveal { opacity: 1 !important; transform: none !important; filter: none !important; }
  /* Pin the ambient/mesh/aura/beam layers to a static resting frame so the page
     is fully legible and content static when motion is off. */
  body::before,
  .hero-wrap::before,
  .hero-visual::before { transform: none !important; }
  .chat-card::before { opacity: 0.4 !important; }
  .cta::before { display: none !important; }
}

/* ---- Calculator tool (/herramientas/...) ----------------------------------
   Componentes específicos de la calculadora de presupuesto. Reusan los mismos
   tokens; nada de colores nuevos. */

.calc {
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 30px;
  box-shadow: var(--shadow-lift);
  margin: 8px 0 6px;
  position: relative;
}
.calc::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--radius-lg);
  padding: 1px;
  background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 35%, transparent), transparent 50%);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}
.calc-grid { display: grid; gap: 20px; grid-template-columns: repeat(2, 1fr); }
.calc-field { display: flex; flex-direction: column; gap: 7px; }
.calc-field label { font-weight: 700; color: var(--ink-strong); font-size: 15px; letter-spacing: -0.01em; }
.calc-field .hint { font-size: 13px; color: var(--muted); font-weight: 400; }
.calc-field select,
.calc-field input {
  font: inherit;
  font-size: 16px;
  color: var(--ink);
  background: var(--bg);
  border: 1.5px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  width: 100%;
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
}
.calc-field select:focus,
.calc-field input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 16%, transparent);
}
.calc-field--full { grid-column: 1 / -1; }

/* Bloque de resultados */
.calc-results { margin-top: 26px; }
.metrics { display: grid; gap: 16px; grid-template-columns: repeat(3, 1fr); margin-bottom: 20px; }
.metric {
  background: linear-gradient(160deg, var(--accent-soft), color-mix(in srgb, var(--accent-soft) 35%, var(--bg-elev)));
  border: 1px solid color-mix(in srgb, var(--accent) 20%, var(--line));
  border-radius: var(--radius);
  padding: 20px;
  box-shadow: var(--shadow-xs);
}
.metric .metric-k {
  display: block;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--accent-ink);
  margin-bottom: 6px;
}
.metric .metric-v {
  display: block;
  font-size: clamp(22px, 3vw, 28px);
  font-weight: 800;
  color: var(--ink-strong);
  line-height: 1.1;
  letter-spacing: -0.02em;
}
.metric .metric-u { font-size: 13px; color: var(--muted); font-weight: 600; }

/* Bandas / supuestos del sector */
.assumptions {
  display: flex; flex-wrap: wrap; gap: 8px 22px;
  font-size: 14px; color: var(--muted);
  margin: 0 0 18px; padding: 14px 18px;
  background: var(--line-soft); border-radius: var(--radius-sm);
}
.assumptions strong { color: var(--ink-strong); }

/* Variante "ok" del callout .note (verde, no ámbar) */
.note--ok {
  border-color: color-mix(in srgb, var(--accent) 32%, var(--line));
  background: var(--accent-soft);
  color: var(--accent-ink);
}
.note--ok strong { color: var(--accent-ink); }
.note--ok a { color: var(--accent-dark); }

/* Veredicto CPC-vs-margen */
.verdict {
  border-radius: var(--radius-sm);
  padding: 18px 20px;
  margin: 18px 0 0;
  border: 1px solid var(--line);
  box-shadow: var(--shadow-xs);
}
.verdict .verdict-tag {
  display: inline-block; font-weight: 800; font-size: 14px;
  letter-spacing: 0.01em; margin-bottom: 6px;
}
.verdict p { margin: 0; font-size: 15px; }
.verdict--ok { background: var(--accent-soft); border-color: color-mix(in srgb, var(--accent) 35%, var(--line)); }
.verdict--ok .verdict-tag { color: var(--accent-ink); }
.verdict--no { background: var(--warn-soft); border-color: color-mix(in srgb, var(--warn) 35%, var(--line)); }
.verdict--no .verdict-tag { color: var(--warn); }

.calc-confidence { font-size: 14px; color: var(--muted); margin: 18px 0 0; }

/* Disclaimer de una sola línea bajo la calculadora (reducción de contenido:
   sin lecciones de metodología ni procedencia de datos, solo la honestía). */
.calc-disclaimer { font-size: 13.5px; color: var(--muted); margin: 16px 2px 0; line-height: 1.55; }

@media (max-width: 760px) {
  .calc { padding: 22px; }
  .calc-grid { grid-template-columns: 1fr; }
  .metrics { grid-template-columns: 1fr; }
}

/* ===========================================================================
   Home-page motion layer (ADD-ONLY — driven by assets/site.js, home only).
   Everything below is gated behind prefers-reduced-motion: no-preference and
   neutralised by the reduce block at the very bottom of this file. No new
   colors; only the existing tokens. ========================================= */

@media (prefers-reduced-motion: no-preference) {

  /* ---- Step-card icon chips animate with the card. The icon sits in the
     card body, not over the left accent bar, so .card--step::before is intact.
     A subtle scale-in reads as "assembling" rather than a hard pop. ---- */
  .card--step.reveal .step-ic {
    opacity: 0;
    transform: scale(0.82) translateY(4px);
    transition: opacity 0.5s var(--ease), transform 0.5s var(--ease);
    transition-delay: 0.12s;
  }
  .card--step.reveal.in-view .step-ic {
    opacity: 1;
    transform: none;
  }

  /* ---- Feature icons draw in a touch after their card surfaces ---- */
  .feature.reveal .feature-ic {
    opacity: 0;
    transform: scale(0.84) rotate(-4deg);
    transition: opacity 0.55s var(--ease), transform 0.55s var(--ease);
    transition-delay: 0.1s;
  }
  .feature.reveal.in-view .feature-ic {
    opacity: 1;
    transform: none;
  }

  /* ---- Hero load intro ---------------------------------------------------
     The hero animates IN ON LOAD (not on scroll). Children start lifted +
     transparent; body.is-loaded (set by site.js on DOMContentLoaded) settles
     them in a staggered cascade. The chat card slides + scales from the right.
     The base .reveal mechanism is reused everywhere else. ------------------ */
  .hero-copy > .eyebrow,
  .hero-copy > h1,
  .hero-copy > .lede,
  .hero-copy > .hero-actions,
  .hero-copy > .hero-trust {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
  }
  .hero-visual {
    opacity: 0;
    transform: translateX(26px) scale(0.97);
    transition: opacity 0.8s var(--ease), transform 0.8s var(--ease);
  }
  body.is-loaded .hero-copy > .eyebrow,
  body.is-loaded .hero-copy > h1,
  body.is-loaded .hero-copy > .lede,
  body.is-loaded .hero-copy > .hero-actions,
  body.is-loaded .hero-copy > .hero-trust,
  body.is-loaded .hero-visual {
    opacity: 1;
    transform: none;
  }
  /* Staggered cascade for the copy column. */
  body.is-loaded .hero-copy > .eyebrow      { transition-delay: 0.05s; }
  body.is-loaded .hero-copy > h1            { transition-delay: 0.13s; }
  body.is-loaded .hero-copy > .lede         { transition-delay: 0.23s; }
  body.is-loaded .hero-copy > .hero-actions { transition-delay: 0.33s; }
  body.is-loaded .hero-copy > .hero-trust   { transition-delay: 0.42s; }
  /* The chat card arrives last and keeps its 3D tilt as the resting state. */
  .hero-visual .chat-card {
    transition: transform 0.5s var(--ease), opacity 0.5s var(--ease);
  }
  body.is-loaded .hero-visual { transition-delay: 0.34s; }

  /* The eyebrow's live dot keeps a gentle pulse once settled (radar feel). */
  body.is-loaded .hero .eyebrow::before {
    animation: bg-pulse 2.6s var(--ease) infinite;
  }
}

/* The settled eyebrow dot keeps a slow RED "en vivo" radar pulse. */
@keyframes bg-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent-red-bright) 46%, transparent); }
  55%      { box-shadow: 0 0 0 7px color-mix(in srgb, var(--accent-red-bright) 0%, transparent); }
}

/* ---- Step-card icon chip (PART C) -----------------------------------------
   A small accent chip aligned inline with the .k label. Restrained + uniform
   across the four cards; lives in card flow, never over .card--step::before. */
.step-ic {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  flex: 0 0 auto;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 20%, var(--line));
  box-shadow: var(--shadow-xs);
}
.step-ic svg { width: 17px; height: 17px; display: block; }
/* Pair the chip with the .k label on one baseline-aligned row. */
.card--step .step-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 8px;
}
.card--step .step-row .k { margin-bottom: 0; }

/* ===========================================================================
   Live Telegram chat demo (PART D — driven by assets/site.js chatPlay module).
   The hero .chat-card plays a looping conversation like a phone screen. The
   chat body is a FIXED-HEIGHT viewport so the card never resizes as messages
   appear; the stream auto-scrolls so the newest bubble stays anchored at the
   bottom and older ones drift up. ADD-ONLY: every selector here is new (scoped
   to [data-chat*] or the new bubble-state classes). No new colors. The whole
   layer collapses to a full static conversation under prefers-reduced-motion.
   =========================================================================== */

/* Fixed "phone screen": the card body never changes height as content fills. */
.chat-body[data-chat-body] {
  height: 384px;
  overflow: hidden;
  /* Messages read TOP-DOWN like a real chat: early bubbles sit at the top
     (no awkward empty void above a lone first message), and once the stream
     outgrows the viewport the JS scrollTop pin glides the newest one to the
     bottom — exactly Telegram's behaviour. The existing .chat-body rule already
     supplies padding + the var(--bg-tint) background; we override only the
     layout model to a top-anchored, vertically-scrolling column. */
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}
.chat-stream {
  display: flex;
  flex-direction: column;
  gap: 12px;
  /* The stream can exceed the viewport; the body scrolls (via JS scrollTop) so
     older bubbles glide up out of frame. flex-shrink:0 stops squashing. */
  flex: 0 0 auto;
}

/* Each example conversation is one .chat-scene. Only one plays at a time; the
   others sit collapsed (their bubbles are display:none until JS reveals them, so
   an empty scene contributes no height). Making the scene a flex column is what
   lets each bubble's align-self (in→left, out→right) resolve correctly now that
   the bubbles live one level deeper than the stream. */
.chat-scene {
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 0 0 auto;
}

/* While seeking (deterministic screenshot frames) all chat motion is frozen so
   the captured still is stable — JS snaps end-states with no in-flight tween. */
.chat-card.is-seeking .bubble[data-step],
.chat-card.is-seeking .bubble[data-step] * ,
.chat-card.is-seeking .chat-file[data-chip],
.chat-card.is-seeking [data-chat-status] {
  transition: none !important;
  animation: none !important;
}

/* Scripted messages are OUT of flow until they enter the conversation, so the
   bottom-anchored viewport only ever holds the bubbles that have been "sent".
   JS adds .is-present (puts it back in flow, still hidden), then on the next
   frame .is-shown (animates it up). Retiring removes both. */
.chat-stream .bubble[data-step] { display: none; }
.chat-stream .bubble[data-step].is-present {
  display: inline-block;
  opacity: 0;
  transform: translateY(9px) scale(0.97);
  transform-origin: bottom;
  transition: opacity 0.34s var(--ease), transform 0.38s var(--ease);
  will-change: transform, opacity;
}
/* The prospect's bubbles hug the left, the bot's hug the right (existing rule
   sets margins; inline-block + the existing .out margin-left:auto keep that). */
.chat-stream .bubble.in.is-present { align-self: flex-start; }
.chat-stream .bubble.out.is-present { align-self: flex-end; }
.chat-stream .bubble[data-step].is-present.is-shown {
  opacity: 1;
  transform: none;
}

/* Typing indicator: three bouncing dots inside an out (green) bubble. */
.bubble.typing {
  padding: 13px 16px;
  min-width: 0;
  width: max-content;
}
.typing-dots { display: inline-flex; align-items: center; gap: 5px; }
.typing-dots i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.9);
  display: block;
  opacity: 0.55;
}
@media (prefers-reduced-motion: no-preference) {
  .bubble.typing.is-shown .typing-dots i {
    animation: chat-dot 1.3s var(--ease) infinite;
  }
  .bubble.typing.is-shown .typing-dots i:nth-child(2) { animation-delay: 0.16s; }
  .bubble.typing.is-shown .typing-dots i:nth-child(3) { animation-delay: 0.32s; }
}
@keyframes chat-dot {
  0%, 70%, 100% { transform: translateY(0); opacity: 0.5; }
  35%           { transform: translateY(-4px); opacity: 1; }
}

/* "Generando…" working bubble: animated ellipsis + a soft shimmer sweep. */
.bubble.work { position: relative; overflow: hidden; }
.work-ellipsis i { opacity: 0.35; }
@media (prefers-reduced-motion: no-preference) {
  .bubble.work.is-shown .work-ellipsis i {
    animation: chat-ellip 1.4s steps(1, end) infinite;
  }
  .bubble.work.is-shown .work-ellipsis i:nth-child(2) { animation-delay: 0.25s; }
  .bubble.work.is-shown .work-ellipsis i:nth-child(3) { animation-delay: 0.5s; }
}
@keyframes chat-ellip {
  0%, 100% { opacity: 0.35; }
  40%      { opacity: 1; }
}
.work-shimmer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    100deg,
    transparent 20%,
    rgba(255, 255, 255, 0.22) 50%,
    transparent 80%
  );
  transform: translateX(-110%);
}
@media (prefers-reduced-motion: no-preference) {
  .bubble.work.is-shown .work-shimmer {
    animation: chat-shimmer 1.7s var(--ease) infinite;
  }
}
@keyframes chat-shimmer {
  0%   { transform: translateX(-110%); }
  100% { transform: translateX(110%); }
}

/* Final "✅ Listo" bubble: the check pops/draws in just ahead of the text. */
.chat-check {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 19px;
  height: 19px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.18);
  margin-right: 7px;
  vertical-align: -4px;
  color: #fff;
}
.chat-check svg { width: 12px; height: 12px; display: block; }
@media (prefers-reduced-motion: no-preference) {
  .bubble.done .chat-check {
    transform: scale(0);
  }
  .bubble.done.is-shown .chat-check {
    animation: chat-check-pop 0.5s var(--ease) 0.12s both;
  }
  .bubble.done .chat-check svg path {
    stroke-dasharray: 24;
    stroke-dashoffset: 24;
  }
  .bubble.done.is-shown .chat-check svg path {
    animation: chat-check-draw 0.4s var(--ease) 0.34s forwards;
  }
}
@keyframes chat-check-pop {
  0%   { transform: scale(0); }
  60%  { transform: scale(1.18); }
  100% { transform: scale(1); }
}
@keyframes chat-check-draw {
  to { stroke-dashoffset: 0; }
}
/* In a frozen seek frame the pop/draw animations are off, so force the check
   and the stroke to their resolved (visible, fully drawn) end-state. */
.chat-card.is-seeking .bubble.done.is-shown .chat-check { transform: scale(1); }
.chat-card.is-seeking .bubble.done.is-shown .chat-check svg path { stroke-dashoffset: 0; }

/* File chips pop in (scale 0.8 → 1), staggered after the final bubble. */
.bubble.done .chat-file[data-chip] {
  opacity: 0;
  transform: scale(0.8) translateY(4px);
  transition: opacity 0.3s var(--ease), transform 0.34s var(--ease);
}
.bubble.done.chips-in .chat-file[data-chip] {
  opacity: 1;
  transform: none;
}
.bubble.done.chips-in .chat-file[data-chip]:nth-child(1) { transition-delay: 0.0s; }
.bubble.done.chips-in .chat-file[data-chip]:nth-child(2) { transition-delay: 0.06s; }
.bubble.done.chips-in .chat-file[data-chip]:nth-child(3) { transition-delay: 0.12s; }
.bubble.done.chips-in .chat-file[data-chip]:nth-child(4) { transition-delay: 0.18s; }

/* On the green (out) bubbles the file chips need a light-on-dark treatment so
   they stay legible against the emerald gradient. */
.bubble.out .chat-file {
  color: #fff;
  background: rgba(255, 255, 255, 0.16);
  border-color: rgba(255, 255, 255, 0.28);
}

/* The header subtitle swaps to an italic accent "escribiendo…" while typing. */
.chat-id small[data-chat-status].is-typing {
  color: var(--accent);
  font-style: italic;
}

/* Scene tag in the chat header: a small emerald pill, far right, that names the
   example currently playing (Panadería · Bilbao, Peluquería · Donostia, …) so
   the cycling VARIETY is legible at a glance. Real crawlable text; JS swaps it
   per scene. It cross-fades on change for a touch of life. */
.chat-id { flex: 1 1 auto; min-width: 0; }
.chat-tag {
  flex: 0 0 auto;
  align-self: center;
  margin-left: auto;
  max-width: 46%;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--accent-ink);
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 26%, var(--line));
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
@media (prefers-reduced-motion: no-preference) {
  .chat-tag { transition: opacity 0.3s var(--ease); }
}

/* Honest-verdict delivery bubble (scene 4): the outcome is "mejor no gastes",
   not a green "Listo" — so the bubble drops the emerald gradient for a neutral
   elevated surface, and its badge is an info "!" instead of a check. Keeps it
   inside the dark palette (no foreign hue); it reads as candid, not alarmist. */
.bubble.out.done.is-verdict {
  background: linear-gradient(160deg, var(--bg-elev-2), var(--bg-elev));
  border: 1px solid color-mix(in srgb, var(--accent) 18%, var(--line));
  color: var(--ink);
}
.bubble.out.done.is-verdict b { color: var(--ink-strong); }
.chat-check.verdict {
  background: color-mix(in srgb, var(--accent) 20%, transparent);
  color: var(--accent);
}
/* On the neutral verdict bubble the chips can't use the white-on-emerald look —
   give them the same soft emerald treatment used on the .in bubbles. */
.bubble.out.done.is-verdict .chat-file {
  color: var(--accent-ink);
  background: var(--accent-soft);
  border-color: color-mix(in srgb, var(--accent) 25%, var(--line));
}

/* ===========================================================================
   Flow strip (PART E — the process pipeline, distinct from the deliverables).
   A slim horizontal track with FOUR steps; a pulse dot travels left→right and
   sequentially lights each step's badge in --accent, looping smoothly. Pure CSS
   ambient animation (no JS init); an optional window.__seekFlow(ms) hook in
   site.js only freezes a deterministic frame for screenshots. On mobile the row
   stacks vertically with a vertical connector. ADD-ONLY, all selectors new,
   only existing tokens. Honors light + dark; disabled under reduced-motion
   (all four steps shown statically in their lit state).
   --flow-cycle is the master loop length; tweak in one place. ============== */

.flow-lead {
  color: var(--muted);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.01em;
  margin: 4px 0 18px;
}

.flow-strip {
  --flow-cycle: 8s;
  --flow-step-count: 4;
  list-style: none;
  margin: 0 0 34px;
  padding: 26px 14px 6px;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  position: relative;
}

/* The horizontal connector track sits behind the badge row, centered on the
   badges' vertical midline (badge is 52px → 26px from the strip's top padding
   of 26px = 52px from the top edge). */
.flow-track {
  position: absolute;
  top: 52px;
  left: calc(12.5% );      /* center of the first column */
  right: calc(12.5% );     /* center of the last column */
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--accent) 26%, var(--line)),
    color-mix(in srgb, var(--accent) 26%, var(--line))
  );
  overflow: visible;
  z-index: 0;
  pointer-events: none;
}
/* A soft "filled" sheen that breathes along the track for life under the dot. */
.flow-track::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(
    90deg,
    transparent 0%,
    color-mix(in srgb, var(--accent-bright) 55%, transparent) 50%,
    transparent 100%
  );
  opacity: 0.0;
}

/* The travelling pulse: a glowing accent dot that runs the length of the track. */
.flow-pulse {
  position: absolute;
  top: 50%;
  left: 0;
  width: 12px;
  height: 12px;
  margin: -6px 0 0 -6px;
  border-radius: 50%;
  /* The travelling pulse is a bright GREEN core inside a RED radar halo — so the
     single most obviously-MOVING mid-page element carries visible ikurriña red. */
  background: var(--accent-bright);
  box-shadow:
    0 0 0 3px color-mix(in srgb, var(--accent-red) 55%, transparent),
    0 0 0 6px color-mix(in srgb, var(--accent-red) 20%, transparent),
    0 0 16px color-mix(in srgb, var(--accent-bright) 80%, transparent);
  z-index: 1;
}

/* Each step: badge + name + caption, vertically stacked and centered. */
.flow-step {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 4px;
}
.flow-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: 15px;
  color: var(--accent);
  /* Resting fill matches the feature/step icon chips (--accent-soft) so all
     three icon-chip families share one "emerald chip" language. The fill is
     opaque, so the connector line stays cleanly broken behind each badge. */
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 22%, var(--line));
  box-shadow: var(--shadow-xs);
  margin-bottom: 8px;
  transition: color 0.4s var(--ease), background 0.4s var(--ease),
    border-color 0.4s var(--ease), box-shadow 0.4s var(--ease),
    transform 0.4s var(--ease);
}
.flow-badge svg { width: 25px; height: 25px; display: block; }
.flow-name {
  font-weight: 700;
  font-size: 15px;
  color: var(--ink-strong);
  letter-spacing: -0.01em;
  transition: color 0.4s var(--ease);
}
.flow-cap {
  font-size: 12.5px;
  line-height: 1.35;
  color: var(--faint);
  font-weight: 500;
  max-width: 16ch;
}

/* ---- The ambient loop (only when motion is allowed) -------------------- */
@media (prefers-reduced-motion: no-preference) {
  /* Pulse travels from the first badge center to the last, then snaps back
     invisibly during the brief tail of the cycle. The travel spans 0→78% of
     the cycle so each step gets a clear "lit" beat; 78→100% is the reset. */
  .flow-strip[data-flow] .flow-pulse {
    animation: flow-run var(--flow-cycle) linear infinite;
  }
  .flow-strip[data-flow] .flow-track::before {
    animation: flow-track-fill var(--flow-cycle) linear infinite;
  }

  /* Each badge glows as the pulse passes it, then settles back. The four share
     one keyframe (flow-lit) offset by a quarter-cycle each so the highlight
     sweeps left→right in lockstep with the dot. */
  .flow-strip[data-flow] .flow-step .flow-badge {
    animation: flow-lit var(--flow-cycle) var(--ease) infinite;
  }
  .flow-strip[data-flow] .flow-step:nth-child(2) .flow-badge { animation-delay: 0s; }
  .flow-strip[data-flow] .flow-step:nth-child(3) .flow-badge { animation-delay: calc(var(--flow-cycle) * 0.25); }
  .flow-strip[data-flow] .flow-step:nth-child(4) .flow-badge { animation-delay: calc(var(--flow-cycle) * 0.5); }
  .flow-strip[data-flow] .flow-step:nth-child(5) .flow-badge { animation-delay: calc(var(--flow-cycle) * 0.75); }

  .flow-strip[data-flow] .flow-step .flow-name {
    animation: flow-name-lit var(--flow-cycle) var(--ease) infinite;
  }
  .flow-strip[data-flow] .flow-step:nth-child(2) .flow-name { animation-delay: 0s; }
  .flow-strip[data-flow] .flow-step:nth-child(3) .flow-name { animation-delay: calc(var(--flow-cycle) * 0.25); }
  .flow-strip[data-flow] .flow-step:nth-child(4) .flow-name { animation-delay: calc(var(--flow-cycle) * 0.5); }
  .flow-strip[data-flow] .flow-step:nth-child(5) .flow-name { animation-delay: calc(var(--flow-cycle) * 0.75); }
}

/* The dot runs 0%→100% of the track over 10%→85% of the cycle (≈0.8s→6.8s for
   the 8s default), timed so it CROSSES each step exactly as that step's badge
   reaches its lit peak (badge delays at 0/25/50/75% + the ~10% lit-peak below =
   0.8/2.8/4.8/6.8s, the same instants the dot is at 0/33/66/100%). Outside the
   travel window it fades out and resets with no visible jump back. */
@keyframes flow-run {
  0%,
  6%   { left: 0%;   opacity: 0; }
  10%  { left: 0%;   opacity: 1; }
  85%  { left: 100%; opacity: 1; }
  90%  { left: 100%; opacity: 0; }
  100% { left: 100%; opacity: 0; }
}
/* A faint fill sweeps under the dot so the track itself feels energised. */
@keyframes flow-track-fill {
  0%   { opacity: 0; transform: translateX(-30%); }
  14%  { opacity: 0.85; }
  80%  { opacity: 0.85; }
  90%  { opacity: 0; transform: translateX(30%); }
  100% { opacity: 0; transform: translateX(30%); }
}
/* One badge's "lit" beat: it brightens to a filled emerald right as the dot
   crosses it (peak ≈10% of its own cycle, i.e. just after its delay), holds
   briefly, then relaxes back to the resting outline. Quarter-cycle delays on
   the four steps sequence the highlight left→right with the dot. */
@keyframes flow-lit {
  0% {
    color: var(--accent);
    background: var(--accent-soft);
    border-color: color-mix(in srgb, var(--accent) 22%, var(--line));
    box-shadow: var(--shadow-xs);
    transform: none;
  }
  6%, 16% {
    /* Dark glyph on the bright-green badge at the lit peak — crisp, punchy and
       coherent with the dark-on-green primary CTAs (vs the soft #fff it was). */
    color: var(--bg-deep);
    background: linear-gradient(135deg, var(--accent-bright), var(--accent-dark));
    border-color: color-mix(in srgb, var(--accent) 55%, var(--line));
    box-shadow: var(--shadow-xs), 0 9px 24px color-mix(in srgb, var(--accent-bright) 34%, transparent);
    transform: translateY(-3px) scale(1.06);
  }
  32%, 100% {
    color: var(--accent);
    background: var(--accent-soft);
    border-color: color-mix(in srgb, var(--accent) 22%, var(--line));
    box-shadow: var(--shadow-xs);
    transform: none;
  }
}
@keyframes flow-name-lit {
  0%       { color: var(--ink-strong); }
  6%, 16%  { color: var(--accent); }
  32%, 100% { color: var(--ink-strong); }
}

/* ---- Mobile: stack vertically with a vertical connector --------------- */
@media (max-width: 760px) {
  .flow-strip {
    grid-template-columns: 1fr;
    gap: 0;
    padding: 8px 4px 6px;
    max-width: 30rem;
    margin-left: auto;
    margin-right: auto;
  }
  /* Re-flow each step to a horizontal card: badge left, name+caption stacked to
     its right. A 2-col grid keeps the badge vertically centered against the
     two text rows. */
  .flow-step {
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-rows: auto auto;
    align-items: center;
    column-gap: 16px;
    row-gap: 2px;
    text-align: left;
    padding: 13px 4px;
    min-height: 78px;
  }
  .flow-badge { grid-row: 1 / 3; grid-column: 1; margin-bottom: 0; align-self: center; }
  .flow-name { grid-column: 2; grid-row: 1; align-self: end; margin-top: 0; }
  .flow-cap { grid-column: 2; grid-row: 2; align-self: start; max-width: none; }

  /* Vertical track: a thin line down the badge column. */
  .flow-track {
    top: 12px;
    bottom: 12px;
    left: 30px;            /* center of the 52px badge: 4px pad + 26px */
    right: auto;
    width: 2px;
    height: auto;
  }
  .flow-track::before {
    background: linear-gradient(
      180deg,
      transparent 0%,
      color-mix(in srgb, var(--accent-bright) 55%, transparent) 50%,
      transparent 100%
    );
  }
  .flow-pulse {
    top: 0;
    left: 50%;
    margin: -5.5px 0 0 -5.5px;
  }
}
@media (max-width: 760px) and (prefers-reduced-motion: no-preference) {
  .flow-strip[data-flow] .flow-pulse {
    animation: flow-run-v var(--flow-cycle) linear infinite;
  }
  .flow-strip[data-flow] .flow-track::before {
    animation: flow-track-fill-v var(--flow-cycle) linear infinite;
  }
}
@keyframes flow-run-v {
  0%   { top: 0%;   opacity: 0; }
  4%   { opacity: 1; }
  71%  { opacity: 1; }
  75%  { top: 100%; opacity: 0; }
  100% { top: 100%; opacity: 0; }
}
@keyframes flow-track-fill-v {
  0%   { opacity: 0; transform: translateY(-30%); }
  10%  { opacity: 0.9; }
  65%  { opacity: 0.9; }
  78%  { opacity: 0; transform: translateY(30%); }
  100% { opacity: 0; transform: translateY(30%); }
}



/* ===========================================================================
   DEVICE LAB — el TELÉFONO-BOT abriendo sus opciones (PART F — #por-dentro,
   el showpiece). Un teléfono grande, dibujado y CENTRADO (con un mini-chat en
   pantalla: ES el bot). En reposo (CERRADO) solo se ve el teléfono. Al entrar
   en viewport (.is-open) las SEIS capacidades se ABREN desde el teléfono —se
   despliegan hacia afuera, escalonadas— cada una un nodo (icono + nombre +
   caption). Líneas-conectoras finas unen el teléfono a cada nodo. Metafórico:
   el teléfono es el bot; las capacidades fluyen DESDE él (sin etiquetas de
   piezas). CRAWLABLE: nombre + caption de cada nodo es texto HTML real.

   Mecánica: el escenario (.devicelab) es un contenedor relativo CONTENIDO
   (overflow:hidden, max-width). El teléfono se ancla al centro; los nodos se
   posicionan en valor ABIERTO vía data-side/data-row y, cerrados, colapsan
   hacia el teléfono (translate + scale + opacity 0). Conectores SVG dibujados
   con stroke-dashoffset.

   Driven por assets/site.js (deviceLab module): IntersectionObserver añade
   :is(.is-open, .in-view) una vez; window.__diagramExplode() lo fuerza (captura). Hover/tap
   un nodo → se resalta + ilumina su conector (JS pone data-active en .dl-links;
   hover de nodo es CSS puro). Sin colores nuevos: verde primario + rojo acento.
   Mostrado ABIERTO + etiquetado estáticamente bajo prefers-reduced-motion.
   =========================================================================== */

.devicelab {
  position: relative;
  margin: 18px auto 0;
  max-width: 1000px;
  min-height: 560px;
  display: grid;
  place-items: center;
  background:
    radial-gradient(40% 44% at 50% 48%, color-mix(in srgb, var(--accent) 11%, transparent) 0%, transparent 64%),
    linear-gradient(180deg, var(--bg-elev) 0%, var(--bg-tint) 100%);
  border: 1px solid color-mix(in srgb, var(--accent) 16%, var(--line));
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card), inset 0 1px 0 color-mix(in srgb, #fff 60%, transparent);
  overflow: hidden;            /* HARD: nada se sale del escenario */
  padding: 36px 28px;
}
/* Textura de puntos tenue, difuminada hacia los bordes. */
.devicelab::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(color-mix(in srgb, var(--line) 92%, transparent) 1px, transparent 1px);
  background-size: 28px 28px;
  -webkit-mask-image: radial-gradient(78% 78% at 50% 48%, #000 0%, transparent 84%);
  mask-image: radial-gradient(78% 78% at 50% 48%, #000 0%, transparent 84%);
  opacity: 0.5;
  pointer-events: none;
  z-index: 0;
}

/* ---- Conectores: SVG en plano de pantalla, bajo el teléfono + nodos -------- */
.dl-links {
  position: absolute;
  inset: 36px 28px;            /* coincide con el padding del escenario */
  width: calc(100% - 56px);
  height: calc(100% - 72px);
  z-index: 1;
  pointer-events: none;
  overflow: visible;
}
.dl-link {
  stroke: var(--accent);
  stroke-width: 1.6;
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
  pathLength: 1;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  opacity: 0;
  filter: drop-shadow(0 0 4px color-mix(in srgb, var(--accent-bright) 55%, transparent));
  transition: opacity 0.5s var(--ease), stroke-dashoffset 0.7s var(--ease),
    stroke-width 0.25s var(--ease), stroke 0.25s var(--ease);
}
:is(.is-open, .in-view) .dl-link { opacity: 0.7; stroke-dashoffset: 0; }
.is-open .dl-link[data-link="1"] { transition-delay: 0.18s; }
.is-open .dl-link[data-link="2"] { transition-delay: 0.26s; }
.is-open .dl-link[data-link="3"] { transition-delay: 0.34s; }
.is-open .dl-link[data-link="4"] { transition-delay: 0.42s; }
.is-open .dl-link[data-link="5"] { transition-delay: 0.50s; }
.is-open .dl-link[data-link="6"] { transition-delay: 0.58s; }
/* Énfasis del conector cuando su nodo está activo (JS pone data-active). */
.dl-links[data-active] .dl-link { opacity: 0.22; }
.dl-links[data-active="1"] .dl-link[data-link="1"],
.dl-links[data-active="2"] .dl-link[data-link="2"],
.dl-links[data-active="3"] .dl-link[data-link="3"],
.dl-links[data-active="4"] .dl-link[data-link="4"],
.dl-links[data-active="5"] .dl-link[data-link="5"],
.dl-links[data-active="6"] .dl-link[data-link="6"] {
  opacity: 1;
  stroke-width: 2.4;
  stroke: var(--accent-bright);
}

/* ---- El teléfono-bot dibujado, grande y centrado -------------------------- */
.dl-phone {
  position: relative;
  z-index: 3;
  width: 200px;
  filter: drop-shadow(0 26px 46px rgba(18, 32, 58, 0.20));
  /* entra con un suave "encendido" cuando se abre */
  opacity: 0;
  transform: translateY(10px) scale(0.97);
  transition: opacity 0.6s var(--ease), transform 0.7s var(--ease-spring);
}
:is(.is-open, .in-view) .dl-phone { opacity: 1; transform: none; }
.dl-phone-art { display: block; width: 100%; height: auto; }

/* Carcasa + pantalla (tema claro: cuerpo oscuro elegante, pantalla clara). */
.dl-body {
  fill: #0e1a2c;
  stroke: color-mix(in srgb, var(--accent-bright) 30%, #1b2c47);
  stroke-width: 2;
}
.dl-screen { fill: #f3f7f4; }
.dl-notch { fill: #0e1a2c; }
/* Barra superior del chat. */
.dl-chip-soft { fill: var(--accent-soft); }
.dl-chip-line { fill: color-mix(in srgb, var(--ink-strong) 80%, transparent); }
.dl-chip-faint { fill: var(--accent); opacity: 0.7; }
.dl-divider { stroke: var(--line); stroke-width: 1.5; }
/* Burbujas: entrante gris-azulada, saliente verde de marca. */
.dl-bub-in, .dl-bub-in2 { fill: #e6ecf4; }
.dl-bub-in-l1, .dl-bub-in-l2, .dl-bub-in2-l1 { fill: #aab6c8; }
.dl-bub-out { fill: var(--accent); }
.dl-bub-out-l1, .dl-bub-out-l2, .dl-bub-out-l3 { fill: #d9f3e4; }
/* Chip "Listo / publicado" + tilde. */
.dl-done { fill: var(--accent-soft); stroke: color-mix(in srgb, var(--accent) 32%, var(--line)); stroke-width: 1.5; }
.dl-done-mark { fill: var(--accent); }
.dl-done-tick { stroke: #fff; stroke-width: 2.2; fill: none; }
.dl-done-l1 { fill: var(--accent-ink); }
.dl-done-l2 { fill: var(--accent); opacity: 0.7; }
/* Barra de entrada + botón enviar (rojo acento, puntual). */
.dl-inputbar { fill: #eef2f7; stroke: var(--line); stroke-width: 1.5; }
.dl-send { fill: var(--accent-red); }
.dl-send-ic { stroke: #fff; stroke-width: 2; fill: none; }

/* Latido suave del avatar/punto "en vivo" (verde) en reposo abierto. */
:is(.is-open, .in-view) .dl-chip-faint { animation: dlPulse 2.4s var(--ease) infinite; }
@keyframes dlPulse { 0%,100% { opacity: 0.7; } 50% { opacity: 0.28; } }

/* ---- Los nodos = las seis capacidades, ABIERTAS desde el teléfono --------- */
.dl-nodes {
  position: absolute;
  inset: 36px 28px;
  z-index: 4;
  pointer-events: none;        /* el nodo reactiva pointer-events abajo */
}
.dl-node {
  position: absolute;
  display: flex;
  align-items: center;
  gap: 12px;
  width: 240px;
  padding: 12px 14px;
  margin: 0;
  border: 1px solid color-mix(in srgb, var(--accent) 14%, var(--line));
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--bg-elev) 88%, transparent);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  box-shadow: var(--shadow-card);
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: inherit;
  pointer-events: auto;
  -webkit-appearance: none;
  appearance: none;
  /* CERRADO: colapsado tras el teléfono (centro), invisible. JS/scroll → ABIERTO. */
  opacity: 0;
  transform: translate(var(--cx, 0px), var(--cy, 0px)) scale(0.6);
  transform-origin: var(--origin, center);
  transition: opacity 0.5s var(--ease), transform 0.62s var(--ease-spring),
    border-color 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
:is(.is-open, .in-view) .dl-node { opacity: 1; transform: translate(0, 0) scale(1); }

/* Posición ABIERTA de cada nodo (cols izq/der, 3 filas). Los nodos del lado
   izquierdo alinean su contenido a la derecha (apuntando al teléfono). */
.dl-node[data-side="left"]  { left: 0;  --origin: right center; text-align: left; }
.dl-node[data-side="right"] { right: 0; --origin: left center;  text-align: left; }
.dl-node[data-row="1"] { top: 4%; }
.dl-node[data-row="2"] { top: 50%; transform: translate(var(--cx, 0px), -50%) scale(0.6); }
.dl-node[data-row="3"] { bottom: 4%; }
:is(.is-open, .in-view) .dl-node[data-row="2"] { transform: translate(0, -50%) scale(1); }

/* Vector CERRADO→ABIERTO: cada nodo arranca empujado hacia el centro (teléfono)
   para que se lea "abriéndose DESDE el teléfono". data-side define el signo. */
.dl-node[data-side="left"]  { --cx: 120px; }
.dl-node[data-side="right"] { --cx: -120px; }
.dl-node[data-row="1"] { --cy: 90px; }
.dl-node[data-row="3"] { --cy: -90px; }

/* Apertura escalonada ("se van abriendo las opciones"): centro→afuera, fila a
   fila, alternando lados. */
.is-open .dl-node[data-node="1"] { transition-delay: 0.10s; }
.is-open .dl-node[data-node="2"] { transition-delay: 0.18s; }
.is-open .dl-node[data-node="3"] { transition-delay: 0.26s; }
.is-open .dl-node[data-node="4"] { transition-delay: 0.34s; }
.is-open .dl-node[data-node="5"] { transition-delay: 0.42s; }
.is-open .dl-node[data-node="6"] { transition-delay: 0.50s; }

/* Icono del nodo. */
.dl-ic {
  flex: 0 0 auto;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: 11px;
  color: var(--accent-ink);
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 22%, var(--line));
  transition: background 0.25s var(--ease), color 0.25s var(--ease), border-color 0.25s var(--ease);
}
.dl-ic svg { width: 20px; height: 20px; }
.dl-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.dl-name {
  font-weight: 700;
  font-size: 15px;
  color: var(--ink-strong);
  letter-spacing: -0.01em;
  line-height: 1.2;
}
.dl-cap {
  font-size: 12.5px;
  line-height: 1.35;
  color: var(--muted);
}

/* El nodo "Veredicto honesto" (data-accent="red") es el momento ROJO del
   diagrama: su icono va en rojo ikurriña sólido (el "pará, no gastes" honesto
   pide rojo, no verde), y su conector se dibuja rojo. Acento puntual, on-brand. */
.dl-node[data-accent="red"] .dl-ic {
  color: var(--accent-red-ink);
  background: var(--accent-red-soft);
  border-color: color-mix(in srgb, var(--accent-red) 32%, var(--line));
}
.dl-node[data-accent="red"] .dl-name { color: var(--accent-red-ink); }
.dl-node[data-accent="red"]:hover .dl-ic,
.dl-node[data-accent="red"].is-active .dl-ic {
  color: #fff;
  background: linear-gradient(135deg, var(--accent-red-bright), var(--accent-red-deep));
  border-color: color-mix(in srgb, var(--accent-red) 55%, var(--line));
}
.dl-link[data-accent="red"] {
  stroke: var(--accent-red);
  filter: drop-shadow(0 0 4px color-mix(in srgb, var(--accent-red-bright) 55%, transparent));
}
.dl-links[data-active="6"] .dl-link[data-link="6"][data-accent="red"] {
  stroke: var(--accent-red-bright);
}

/* ---- Hover / activo: el nodo se resalta; su icono se vuelve verde sólido --- */
.dl-node:hover,
.dl-node.is-active {
  border-color: color-mix(in srgb, var(--accent) 45%, var(--line));
  box-shadow: var(--shadow-lift);
  transform: translate(0, 0) scale(1.035);
}
.dl-node[data-row="2"]:hover,
.dl-node[data-row="2"].is-active { transform: translate(0, -50%) scale(1.035); }
.dl-node:hover .dl-ic,
.dl-node.is-active .dl-ic {
  color: #fff;
  background: linear-gradient(135deg, var(--accent-bright), var(--accent-dark));
  border-color: color-mix(in srgb, var(--accent) 55%, var(--line));
}
.dl-node:hover .dl-name,
.dl-node.is-active .dl-name { color: var(--accent-ink); }
/* Cuando uno está activo (tap), atenúa el resto. */
.has-active .dl-node:not(.is-active) { opacity: 0.62; }

/* Captura: el harness dispara ~80ms tras __diagramExplode(); suprime los tweens
   para que la imagen sea el frame ABIERTO ya asentado. */
.devicelab.is-captured .dl-node,
.devicelab.is-captured .dl-phone,
.devicelab.is-captured .dl-link { transition: none !important; }
.devicelab.is-captured .dl-chip-faint { animation: none !important; }

/* ---- Tablet: estrecha un poco los nodos para que respiren contra el centro - */
@media (max-width: 940px) {
  .devicelab { max-width: 760px; min-height: 540px; }
  .dl-node { width: 210px; padding: 11px 12px; gap: 10px; }
  .dl-phone { width: 178px; }
}

/* ---- Mobile: teléfono ARRIBA, capacidades en grid DEBAJO (sin overflow ni
   solape). Mantiene la metáfora "las opciones salen del teléfono" como una
   cascada vertical escalonada. ------------------------------------------- */
@media (max-width: 720px) {
  .devicelab {
    display: flex;
    flex-direction: column;
    align-items: center;
    min-height: 0;
    padding: 28px 16px 30px;
    overflow: hidden;
  }
  .dl-links { display: none; }      /* en columna los conectores cruzarían */
  .dl-phone { width: 168px; margin-bottom: 22px; }
  .dl-nodes {
    position: static;
    inset: auto;
    width: 100%;
    display: grid;
    grid-template-columns: 1fr;
    gap: 12px;
  }
  .dl-node {
    position: static;
    width: 100%;
    max-width: 420px;
    margin: 0 auto;
    /* CERRADO en mobile: sube desde abajo del teléfono, escalonado. */
    --cx: 0px;
    --cy: 26px;
    transform: translate(0, var(--cy)) scale(0.96);
  }
  .dl-node[data-row="2"] { top: auto; transform: translate(0, var(--cy)) scale(0.96); }
  :is(.is-open, .in-view) .dl-node,
  :is(.is-open, .in-view) .dl-node[data-row="2"] { transform: translate(0, 0) scale(1); }
  .dl-node:hover, .dl-node.is-active,
  .dl-node[data-row="2"]:hover, .dl-node[data-row="2"].is-active {
    transform: translate(0, 0) scale(1.015);
  }
}

/* ---- Reduced motion: estado ABIERTO + etiquetado, estático (sin animación) - */
@media (prefers-reduced-motion: reduce) {
  .dl-phone { opacity: 1 !important; transform: none !important; transition: none !important; }
  .dl-node {
    opacity: 1 !important;
    transform: translate(0, 0) scale(1) !important;
    transition: none !important;
  }
  .dl-node[data-row="2"] { transform: translate(0, -50%) scale(1) !important; }
  .dl-link { opacity: 0.55 !important; stroke-dashoffset: 0 !important; transition: none !important; }
  .dl-chip-faint { animation: none !important; }
}
@media (max-width: 720px) and (prefers-reduced-motion: reduce) {
  .dl-node, .dl-node[data-row="2"] { transform: translate(0, 0) scale(1) !important; }
}
