/* ==========================================================================
   CSS por pieza · pipeline-acceleration-measurement
   Es insights-lib.css ENTERA, servida solo en este slug por la convencion
   insights-fig-{slug}.css que hub-chrome.php ya carga despues del core.
   Se sirve asi, y no sumando la libreria al enqueue global del hub, porque
   la libreria define 30+ clases que las 3 piezas publicadas tambien usan
   (.ins-spec, .ins-box, .ins-seq, .ins-fig, .ins-prose). Acotada al slug,
   esa colision no puede ocurrir. Cuando una segunda pieza use la libreria,
   corresponde promoverla a su propia hoja compartida y dejar de duplicarla.
   Generado el 2026-08-17 desde assets/css/insights-lib.css
   ========================================================================== */

/* ==========================================================================
   TIPOGRAFIA: TODO POPPINS (2026-08-11)
   Una sola familia, en cinco pesos: 200 extralight, 300 light, 400 normal,
   700 bold, 800 extrabold. No hay 500 ni 600 y no hay familia mono: lo que
   antes era chrome en Geist Mono ahora es Poppins.
   OJO con el resto del sistema: sention.css todavia declara Geist en
   --font-sans y Geist Mono en --font-mono, y tokens.css declara Poppins. Como
   tokens.css carga despues, gana Poppins para el sans, pero --font-mono sigue
   saliendo de sention.css. Esta libreria ya no lo usa.
   ========================================================================== */

/* ==========================================================================
   INSIGHTS LIB - libreria de instrumentos del hub.
   Portada del catalogo v7 (2026-08-11). El mockup venia en Poppins y con 383
   hex a mano; aca todo sale de tokens y de la fuente del sistema.
   Carga SIEMPRE despues de insights-core.css y antes del CSS por articulo.
   Fuente de verdad de cada componente: component-catalog.md
   Los cuatro componentes en conflicto con el catalogo (FUNNEL trapecio, FAN
   torta, LAYERS piramide, STEPS con vino alternado) conservan aca su version
   v7 con sufijo -v7, y su version de doctrina vive en el mismo archivo mas
   abajo. Se muestran lado a lado en el lab hasta que Carlos elija.
   ========================================================================== */

/* --------------------------------------------------------------------------
   LA PLACA DEL INSTRUMENTO ES BLANCA (2026-08-11)
   La pagina es arena; el instrumento va sobre blanco para que se despegue.
   El core deja `.ins-fig__panel { background: none }` y cada figura declaraba
   su forma; aca la libreria fija una sola: superficie blanca con aire.

   `--ins-paper` es el color de "papel" DENTRO del instrumento: el anillo que
   despega un nodo del eje, el fondo de una marca hueca, el relleno de un
   eslabon. Antes era arena porque el instrumento vivia sobre arena. Ahora
   apunta al mismo blanco de la placa, y si alguna figura vuelve a ir sobre
   arena se cambia esta sola variable.
   -------------------------------------------------------------------------- */
.ins-fig__panel {
  --ins-paper: var(--bg-raised);
  background: var(--ins-paper);
  padding: clamp(1rem, 0.6rem + 1.2vw, 1.75rem);
}

/* --------------------------------------------------------------------------
   REGLA DE PISO DE LA LIBRERIA
   El core mide la prosa: `.ins-prose p { max-width: var(--ins-measure) }`, y
   `--ins-measure` son 44rem. Un instrumento que use <p> como pieza
   estructural (la cadena, la barra de un galon, el rotulo de una espina)
   hereda ese tope y se queda corto aunque su contenedor sea mas ancho. Paso
   tres veces antes de escribirse esta regla. Un instrumento no es prosa: lo
   mide su figura, no la columna de lectura.
   -------------------------------------------------------------------------- */
/* Especificidad: `.ins-prose p` es (0,1,1). `.ins-fig__panel > *` es (0,1,0)
   y PIERDE, aunque cargue despues. Hay que subir a (0,2,1). */
.ins-prose .ins-fig__panel > *,
.ins-prose .ins-fig__panel > * > p,
.ins-prose .ins-fig__panel p { max-width: none; }


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

button,
    input {
      font: inherit;
    }

.ins-label {
  font-family: var(--font-sans);
      color: var(--text-primary);
      font-size: 0.7rem;
      font-weight: 700;
      letter-spacing: 0.11em;
      text-transform: uppercase;
    }

.ins-value {
      color: var(--accent);
      font-weight: 700;
    }

.ins-loss {
      color: var(--accent-alt);
      font-weight: 700;
    }

/* 02 CHAIN */

/* 03 STEPS */

/* 04 FIELDS */

/* 05 SPEC */

/* 06 LEDGER */

/* 07 MATRIX */

/* 08 FAN */

/* 09 MAGNITUDE */

/* 10 OVERWRITE */

/* 11 SHOT */

/* 12 TABLE — el componente vive mas abajo, reescrito. Lo que habia aca era un
   selector huerfano (`.ins-table th,`) que quedo colgado al retirar las
   reglas del port y se pegaba a la regla siguiente: BULLET terminaba
   aplicandole display:grid a los <th> de cualquier tabla del sistema. */

/* 13 BULLET */









/* 14 WATERFALL */










/* 15 FUNNEL */

/* 16 SPLIT */










/* 17 DELTA */







/* 22 QUADRANT */





/* 27 LAYERS */

/* 33 SCORECARD */









/* ==========================================================================
   35 CRITERIA  ·  .ins-criteria
   Reconstruido el 2026-08-12. Lo que habia era el stub del port de v7: un
   cuadrado que se distinguia SOLO por color, un filete por fila y ningun
   estado intermedio.

   Que compara: cumple o no cumple, contra una lista cerrada. Si hay grados,
   va SCORECARD; lo que hace a este componente es que el patron de faltantes
   se lee de un golpe.

   Dos formas, dos lecturas distintas:
   --list  una fila por criterio, con su nota. Se lee de arriba abajo y sirve
           cuando cada faltante necesita explicacion.
   --grid  mosaico compacto sin notas, para cuando el argumento es la FORMA
           del hueco y no cada caso.

   La marca nunca se distingue solo por color: cumple es un disco lleno con el
   tilde en blanco, parcial es medio disco, y falta es un anillo hueco cruzado
   por una barra. Ademas cada fila lleva su estado escrito en un `.ins-sr`.

   Sin filete por fila: las filas se separan por aire, por el presupuesto de
   filetes del playbook.
   ========================================================================== */
.ins-criteria { display: grid; gap: 0.15rem; width: 100%; }

.ins-criteria__row {
  display: grid;
  grid-template-columns: 1.35rem minmax(0, 24rem) minmax(0, 1fr);
  gap: 0.85rem;
  align-items: baseline;
  padding: 0.6rem 0.15rem;
}

.ins-criteria__row + .ins-criteria__row { padding-top: 0.6rem; }

/* La marca. Un span vacio: toda la forma la hacen los pseudo-elementos. */
.ins-criteria__mark {
  position: relative;
  align-self: center;
  justify-self: start;
  width: 1.05rem;
  height: 1.05rem;
  border: 2px solid var(--accent);
  border-radius: 50%;
}

/* Cumple: disco lleno y tilde en blanco. */
.ins-criteria__row[data-met="yes"] .ins-criteria__mark { background: var(--accent); }

.ins-criteria__row[data-met="yes"] .ins-criteria__mark::after {
  content: "";
  position: absolute;
  top: 43%;
  left: 50%;
  width: 0.24rem;
  height: 0.46rem;
  border: solid var(--bg-raised);
  border-width: 0 2px 2px 0;
  transform: translate(-50%, -50%) rotate(45deg);
}

/* Parcial: medio disco. El corte es la forma; el color es el mismo azul. */
.ins-criteria__row[data-met="partial"] .ins-criteria__mark {
  background: linear-gradient(to right, var(--accent) 0 50%, transparent 50% 100%);
}

/* Falta: anillo en vino cruzado por una barra. Es lo que el registro no puede
   certificar, y esa es la unica razon por la que este componente usa vino. */
.ins-criteria__row[data-met="no"] .ins-criteria__mark {
  border-color: var(--accent-alt);
  background: none;
}

.ins-criteria__row[data-met="no"] .ins-criteria__mark::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0.62rem;
  height: 2px;
  background: var(--accent-alt);
  transform: translate(-50%, -50%) rotate(-45deg);
}

.ins-criteria__k {
  max-width: none;
  margin: 0;
  font-size: 0.88rem;
  font-weight: 700;
  line-height: 1.35;
  color: var(--ink, var(--text-primary));
}

.ins-criteria__row[data-met="no"] .ins-criteria__k { color: var(--accent-alt); }

.ins-criteria__note {
  max-width: none;
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--text-muted);
  text-wrap: pretty;
}

/* El recuento. Va debajo, separado por el unico filete del instrumento. */
.ins-criteria__tally {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1.4rem;
  margin-top: 0.5rem;
  padding-top: 0.85rem;
  border-top: 1px solid var(--line);
  font-size: 0.78rem;
  color: var(--text-muted);
}

.ins-criteria__tally b {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink, var(--text-primary));
}

.ins-criteria__tally b[data-met="no"] { color: var(--accent-alt); }

/* --- forma 2: mosaico ---------------------------------------------------- */
.ins-criteria--grid {
  grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
  gap: 0.5rem;
}

.ins-criteria--grid .ins-criteria__row {
  grid-template-columns: 1.05rem minmax(0, 1fr);
  gap: 0.6rem;
  align-items: start;
  padding: 0.7rem 0.75rem;
  box-shadow: inset 0 0 0 1px var(--line);
}

/* El faltante se marca tambien en el fondo del mosaico: a este tamanio, un
   anillo de 17px no alcanza para que el hueco se lea como patron. */
.ins-criteria--grid .ins-criteria__row[data-met="no"] {
  background: color-mix(in srgb, var(--accent-alt) 8%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent-alt) 35%, transparent);
}

.ins-criteria--grid .ins-criteria__k { font-size: 0.8rem; font-weight: 400; }

.ins-criteria--grid .ins-criteria__row[data-met="yes"] .ins-criteria__k,
.ins-criteria--grid .ins-criteria__row[data-met="partial"] .ins-criteria__k { color: var(--text-primary); }

.ins-criteria--grid .ins-criteria__note { display: none; }

.ins-criteria--grid .ins-criteria__tally { grid-column: 1 / -1; }

/* A dos columnas y 700px de placa, la nota queda en 150px y se parte en
   cuatro renglones. Debajo del criterio lee mejor que al lado. */
@media (max-width: 860px) {
  .ins-criteria__row { grid-template-columns: 1.35rem minmax(0, 1fr); row-gap: 0.3rem; }

  .ins-criteria__note { grid-column: 2; }
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-criteria-in {
    from { opacity: 0; transform: translateY(0.4rem); }
    to   { opacity: 1; transform: none; }
  }

  @keyframes ins-criteria-mark {
    from { opacity: 0; transform: scale(0.4); }
    to   { opacity: 1; transform: none; }
  }

  .ins-fig.is-in .ins-criteria__row {
    animation: ins-criteria-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.07s);
  }

  .ins-fig.is-in .ins-criteria__mark {
    animation: ins-criteria-mark var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.07s + 0.12s);
  }
}

/* ==========================================================================
   29 SANKEY  ·  .ins-sankey
   Reconstruido el 2026-08-12. Lo que habia eran cinco declaraciones sueltas,
   sin SVG y sin geometria.

   Que compara: un volumen que se reparte en ramas y se cae por el camino. Es
   el instrumento mas potente para el contenido de Sention, porque muestra en
   una sola figura cuanto entra, por donde se va y cuanto queda.

   Si hay una sola rama lineal va FUNNEL, no esto.

   Techo: tres columnas y ocho flujos. Arriba de eso las cintas se cruzan y el
   dibujo deja de significar.

   Color: azul es lo que sobrevive; vino es lo que se pierde, que es
   exactamente lo que el registro no puede certificar. La cinta ademas se
   distingue por posicion (las perdidas caen) y por su rotulo, no solo por
   color.

   El ancho de cada cinta es proporcional al volumen, y esa proporcion es toda
   la promesa del instrumento. La geometria la calcula el generador.
   ========================================================================== */
.ins-sankey { display: grid; gap: 0.7rem; width: 100%; }

.ins-sankey__scroll { max-width: 100%; }

.ins-sankey__plot { display: block; width: 100%; height: auto; overflow: visible; }

/* La cinta. Rellena, no trazada: el ancho ES el dato. El relleno es un
   degradado horizontal del color de donde sale al color de donde llega, asi
   que una cinta que va de lo vivo a lo perdido se vuelve vino en el camino.
   El id del degradado lleva el indice del flujo porque en una misma pieza
   puede haber dos SANKEY y dos defs con el mismo id se pisan. */
.ins-sankey__flow { stroke: none; }

.ins-sankey__stop { stop-color: var(--accent); stop-opacity: 0.3; }

.ins-sankey__stop[data-kind="loss"] { stop-color: var(--accent-alt); stop-opacity: 0.28; }

.ins-sankey__node { fill: var(--accent); }

.ins-sankey__node[data-kind="loss"] { fill: var(--accent-alt); }

.ins-sankey__label {
  fill: var(--ink, var(--text-primary));
  font-family: var(--font-sans);
  font-size: 16px;
  font-weight: 700;
}

.ins-sankey__label[data-kind="loss"] { fill: var(--accent-alt); }

.ins-sankey__label tspan {
  font-size: 14px;
  font-weight: 400;
  fill: var(--text-muted);
}

.ins-sankey__label[data-kind="loss"] tspan { fill: var(--accent-alt); }

/* Rotulo de la columna, arriba de todo. */
.ins-sankey__col {
  fill: var(--text-muted);
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.ins-sankey__scale {
  margin: 0;
  max-width: none;
  font-size: 0.74rem;
  color: var(--text-muted);
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-sankey-flow {
    from { opacity: 0; }
    to   { opacity: 1; }
  }

  @keyframes ins-sankey-node {
    from { opacity: 0; transform: scaleY(0.2); }
    to   { opacity: 1; transform: none; }
  }

  /* Los nodos crecen desde su propio centro. Sin `transform-box: fill-box` el
     origen es el del SVG entero y las barras salen disparadas: es el mismo
     error que costo el motor de anillos de la GEA. */
  .ins-fig.is-in .ins-sankey__node {
    transform-box: fill-box;
    transform-origin: center;
    animation: ins-sankey-node var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.12s);
  }

  .ins-fig.is-in .ins-sankey__flow {
    animation: ins-sankey-flow 0.6s var(--ease-out) both;
    animation-delay: calc(0.3s + (var(--i) - 1) * 0.12s);
  }

  .ins-fig.is-in .ins-sankey__label,
  .ins-fig.is-in .ins-sankey__col {
    animation: ins-sankey-flow var(--dur-base) var(--ease-out) both;
    animation-delay: calc(0.5s + (var(--i) - 1) * 0.1s);
  }
}

/* Mismo caso que el TREND: un SVG que se achica entero achica su tipografia.
   Bajo este ancho el dibujo deja de encogerse y scrollea en su caja. */
@media (max-width: 760px) {
  .ins-sankey__scroll { overflow-x: auto; overscroll-behavior-x: contain; }

  /* 76rem, no 54: el viewBox mide 1560, asi que a 864px de ancho la
     tipografia de 16 se renderiza en 9px. El minimo se calcula desde el
     viewBox, no a ojo: ancho = viewBox * (tamanio deseado / tamanio del SVG). */
  .ins-sankey__plot { min-width: 76rem; }

  .ins-sankey__scroll ~ .ins-sankey__scale::after { content: " Scroll to see the whole diagram."; }
}

/* ==========================================================================
   26 SYSTEM FLOW CHART  ·  .ins-arch
   Reconstruido el 2026-08-12 y rehecho dos veces el mismo dia. La forma final
   la fijo una referencia de Carlos: barra de titulo, banda de fase, carriles
   rotulados de costado y simbolos RELLENOS. Las dos versiones anteriores
   (cajas por zona, y despues siluetas huecas) quedaron descartadas.

   Absorbe al 30 SWIMLANE, que era el mismo instrumento con otro nombre.

   Que muestra: por donde pasa un registro, quien lo toca en cada tramo, donde
   se decide algo y donde el recorrido termina mal. Si no hay decisiones ni
   cambio de responsable, va CHAIN o STEPS.

   Los simbolos son los del diagrama de flujo y cada uno significa una cosa:
   terminador (capsula), proceso (rectangulo), decision (rombo), base de datos
   (cilindro), documento (pie ondulado) y operacion manual (trapecio).

   Color: la referencia usa tres colores por tipo de simbolo. Aca el tipo ya lo
   dice la FORMA, asi que el color queda libre para decir otra cosa: azul es el
   camino que sigue vivo y vino el paso donde el registro deja de poder
   probarse. El cilindro es la unica excepcion, va hueco: guarda, no hace.

   Techo: doce nodos. Con mas, se parte en dos figuras.
   ========================================================================== */
.ins-arch { display: grid; gap: 0.8rem; width: 100%; }

.ins-arch__scroll { max-width: 100%; }

.ins-arch__plot { display: block; width: 100%; height: auto; overflow: visible; }

.ins-arch__title { fill: var(--accent); }

.ins-arch__titletext {
  fill: var(--bg-raised);
  font-family: var(--font-sans);
  font-size: 17px;
  font-weight: 700;
  dominant-baseline: middle;
}

.ins-arch__phase { fill: color-mix(in srgb, var(--accent) 16%, var(--ins-paper, var(--bg-raised))); }

.ins-arch__phasetext {
  fill: var(--accent);
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  dominant-baseline: middle;
}

/* El carril: banda de nombre a la izquierda, pista a la derecha. El carril
   nunca va en vino: es un responsable, no un veredicto. El vino es del PASO
   donde el registro deja de poder probarse. */
.ins-arch__lane { fill: var(--accent); }

.ins-arch__track { fill: var(--ins-paper, var(--bg-raised)); stroke: var(--line); stroke-width: 1; }

/* El nombre del carril, rotado. Es una PESTANIA de una o dos palabras, la
   misma excepcion que ya se acepto en el balanced scorecard. */
.ins-arch__who {
  fill: var(--bg-raised);
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-anchor: middle;
}

/* Los simbolos, rellenos. */
.ins-arch__shape { fill: var(--accent); stroke: none; }

.ins-arch__shape[data-kind="loss"] { fill: var(--accent-alt); }

/* El cilindro guarda, no hace: va hueco. */
.ins-arch__shape[data-kind="store"] {
  fill: var(--ins-paper, var(--bg-raised));
  stroke: var(--accent);
  stroke-width: 2;
}

.ins-arch__text {
  fill: var(--bg-raised);
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 700;
  text-anchor: middle;
  dominant-baseline: middle;
}

.ins-arch__text[data-kind="store"] { fill: var(--ink, var(--text-primary)); }

.ins-arch__link { fill: none; stroke: var(--accent); stroke-width: 2; }

.ins-arch__head { fill: var(--accent); stroke: none; }

.ins-arch__branch {
  fill: var(--text-muted);
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 700;
  text-anchor: middle;
}

/* El corchete de acotacion, en vino, marcando el tramo que el registro no
   puede certificar. Es el mismo operador del TREND, aca en horizontal. */
.ins-arch__bracket { fill: none; stroke: var(--accent-alt); stroke-width: 2; }

.ins-arch__brackettext {
  fill: var(--accent-alt);
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 700;
  font-style: italic;
  text-anchor: middle;
}

.ins-arch__scale {
  margin: 0;
  max-width: none;
  font-size: 0.74rem;
  color: var(--text-muted);
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-arch-in {
    from { opacity: 0; transform: translateY(0.4rem); }
    to   { opacity: 1; transform: none; }
  }

  @keyframes ins-arch-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
  }

  .ins-fig.is-in .ins-arch__shape,
  .ins-fig.is-in .ins-arch__text {
    animation: ins-arch-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.1s);
  }

  .ins-fig.is-in .ins-arch__link,
  .ins-fig.is-in .ins-arch__head,
  .ins-fig.is-in .ins-arch__branch {
    animation: ins-arch-fade 0.5s var(--ease-out) both;
    animation-delay: calc(0.3s + (var(--i) - 1) * 0.1s);
  }

  .ins-fig.is-in .ins-arch__bracket,
  .ins-fig.is-in .ins-arch__brackettext {
    animation: ins-arch-fade var(--dur-base) var(--ease-out) 1.1s both;
  }
}

/* El minimo se calcula desde el viewBox, no a ojo:
   ancho = viewBox x (tamanio deseado / tamanio del SVG). */
@media (max-width: 760px) {
  .ins-arch__scroll { overflow-x: auto; overscroll-behavior-x: contain; }

  .ins-arch__plot { min-width: 58rem; }

  .ins-arch__scroll ~ .ins-arch__scale::after { content: " Scroll to see the whole chart."; }
}

/* ==========================================================================
   21 CYCLE  ·  .ins-cycle
   Reconstruido el 2026-08-12 y rehecho el mismo dia sobre una referencia de
   Carlos: anillo de sectores en GALON, cada uno con su titulo, su bajada y su
   lista rotulada. La version de discos sueltos unidos por arcos quedo
   descartada.

   Adentro de cada sector va titulo y una bajada corta, todo horizontal. Cada
   renglon de mas es un renglon que se sale del sector, y como el texto es
   blanco, lo que se sale cae sobre el hueco blanco y desaparece.

   Que muestra: un proceso que se retroalimenta, donde la salida de la ultima
   etapa alimenta a la primera. Si el proceso termina, va STEPS.

   Entre tres y cinco etapas. Con dos no hay ciclo y con seis no se lee.

   La punta de galon de cada sector encastra en la muesca del siguiente: la
   direccion la dice la FORMA, no una flecha agregada encima.

   Color: la referencia usa cuatro tintas distintas. El sistema tiene un solo
   azul, asi que los cuatro sectores son el mismo azul en cuatro
   intensidades. Aca la escala SI significa: las etapas de un ciclo estan
   ordenadas, y la intensidad refuerza por donde se empieza. (En el balanced
   scorecard se rechazo por lo contrario: ahi las cuatro perspectivas no
   tienen orden.)

   El corte que cierra el circulo puede estar condicionado: cuando lo esta se
   marca en vino sobre su propio borde, porque es un cierre que el registro no
   puede garantizar.
   ========================================================================== */
.ins-cycle { display: grid; gap: 0.7rem; width: 100%; }

/* El instrumento es cuadrado. A ancho completo se centra en vez de estirarse:
   un circulo de 1000px de diametro no es mas legible, solo mas grande. */
.ins-cycle__plot {
  display: block;
  width: 100%;
  max-width: 40rem;
  height: auto;
  margin-inline: auto;
  overflow: visible;
}

/* El sector. La intensidad la fija --k (1 = el mas oscuro). */
.ins-cycle__seg {
  fill: color-mix(in srgb, var(--accent) calc(100% - (var(--k) - 1) * 8%), var(--ins-paper, var(--bg-raised)));
  stroke: none;
}

.ins-cycle__title {
  fill: var(--bg-raised);
  font-family: var(--font-sans);
  font-size: 30px;
  font-weight: 700;
}

.ins-cycle__sub {
  fill: color-mix(in srgb, var(--bg-raised) 88%, var(--accent));
  font-family: var(--font-sans);
  font-size: 18px;
  font-weight: 400;
}

/* El numeral de etapa. Es un indice, y los indices van en vino. Vive fuera del
   anillo porque adentro seria vino sobre azul. */
.ins-cycle__n {
  fill: var(--accent-alt);
  font-family: var(--font-sans);
  font-size: 17px;
  font-weight: 700;
  text-anchor: middle;
  dominant-baseline: middle;
}

/* El borde del corte condicionado. */
.ins-cycle__cut {
  fill: none;
  stroke: var(--accent-alt);
  stroke-width: 3;
  stroke-dasharray: 9 7;
}

.ins-cycle__cond {
  fill: var(--accent-alt);
  font-family: var(--font-sans);
  font-size: 18px;
  font-weight: 700;
  font-style: italic;
  text-anchor: middle;
}

.ins-cycle__hub {
  fill: var(--ink, var(--text-primary));
  font-family: var(--font-sans);
  font-size: 22px;
  font-weight: 700;
  text-anchor: middle;
}

.ins-cycle__scale {
  margin: 0;
  max-width: none;
  font-size: 0.74rem;
  color: var(--text-muted);
  text-align: center;
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-cycle-in {
    from { opacity: 0; transform: scale(0.94); }
    to   { opacity: 1; transform: none; }
  }

  @keyframes ins-cycle-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
  }

  /* Los sectores crecen desde el centro del ANILLO, no desde el suyo propio:
     con `fill-box` cada uno se expandiria desde su propio centroide y el
     anillo se desarmaria. Por eso el origen va en coordenadas del viewBox. */
  .ins-fig.is-in .ins-cycle__seg {
    transform-origin: 50% 50%;
    animation: ins-cycle-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.12s);
  }

  .ins-fig.is-in .ins-cycle__title,
  .ins-fig.is-in .ins-cycle__sub,
  .ins-fig.is-in .ins-cycle__n {
    animation: ins-cycle-fade var(--dur-base) var(--ease-out) both;
    animation-delay: calc(0.35s + (var(--i) - 1) * 0.12s);
  }

  .ins-fig.is-in .ins-cycle__hub {
    animation: ins-cycle-fade var(--dur-base) var(--ease-out) 0.9s both;
  }

  .ins-fig.is-in .ins-cycle__cut,
  .ins-fig.is-in .ins-cycle__cond {
    animation: ins-cycle-fade var(--dur-base) var(--ease-out) 1.2s both;
  }
}

/* El instrumento es cuadrado, asi que no puede scrollear como los anchos: en
   una placa de 390px el dibujo entero mide 390 y un tipo de 19 se renderiza en
   8px. La solucion es al reves que en el TREND: se AGRANDA el tipo dentro del
   viewBox, que es coordenada del dibujo y escala con el. */
@media (max-width: 700px) {
  .ins-cycle__title { font-size: 38px; }

  .ins-cycle__sub { font-size: 24px; }

  .ins-cycle__n { font-size: 22px; }

  .ins-cycle__hub { font-size: 28px; }

  .ins-cycle__cond { font-size: 23px; }
}

/* ==========================================================================
   37 RANGE  ·  .ins-range
   Reconstruido el 2026-08-12. Lo que habia eran tres reglas con los
   porcentajes escritos a mano (`left: 8%`, `left: 58%`): una figura que
   dibujaba siempre lo mismo pasara lo que pasara con el dato.

   Que muestra: que un pronostico de un solo numero es falso. Cada fila va del
   peor al mejor caso, con la marca del valor probable.

   Si hay certeza, va BULLET.

   Color, y es lo que hace a este componente: el AZUL es el valor probable, la
   respuesta, el numero que alguien va a repetir. El VINO es la banda, que es
   la distancia que el registro no puede cerrar. No es decoracion: la banda es
   literalmente lo que no se puede certificar, medida en la misma escala que
   la respuesta.

   Una sola escala para todas las filas, declarada al pie. Dos escalas en un
   mismo grafico de rangos convierten la comparacion en una mentira.
   ========================================================================== */
.ins-range { display: grid; gap: 0.2rem; width: 100%; }

.ins-range__row {
  display: grid;
  grid-template-columns: minmax(0, 15rem) minmax(0, 1fr) minmax(0, 13rem);
  gap: 1.1rem;
  align-items: center;
  padding: 0.75rem 0;
}

.ins-range__k {
  max-width: none;
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.35;
  color: var(--text-primary);
}

.ins-range__row[data-total] .ins-range__k {
  font-weight: 700;
  color: var(--ink, var(--text-primary));
}

/* La pista. El fondo es la escala entera; lo que se pinta es el tramo. */
.ins-range__track {
  position: relative;
  height: 2.4rem;
  background: color-mix(in srgb, var(--text-primary) 4%, transparent);
}

.ins-range__span {
  position: absolute;
  top: 50%;
  left: calc(var(--min) * 1%);
  width: calc((var(--max) - var(--min)) * 1%);
  height: 0.8rem;
  transform: translateY(-50%);
  background: color-mix(in srgb, var(--accent-alt) 22%, transparent);
}

/* Los topes de la banda: sin ellos, el extremo se lee como un degradado que
   se apaga en vez de como un limite declarado. */
.ins-range__span::before,
.ins-range__span::after {
  content: "";
  position: absolute;
  top: -0.35rem;
  width: 2px;
  height: 1.5rem;
  background: var(--accent-alt);
}

.ins-range__span::before { left: 0; }

.ins-range__span::after { right: 0; }

/* El valor probable. */
.ins-range__pin {
  position: absolute;
  top: 0;
  left: calc(var(--likely) * 1%);
  width: 4px;
  height: 100%;
  transform: translateX(-2px);
  background: var(--accent);
}

.ins-range__vals {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.5rem;
  margin: 0;
  max-width: none;
  font-size: 0.72rem;
  color: var(--text-muted);
  text-align: right;
}

.ins-range__vals b {
  display: block;
  font-size: 0.94rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
}

/* La cifra del medio es la respuesta, y va en azul. Las de los bordes son los
   limites de lo que no se puede cerrar, y van en vino. */
.ins-range__vals span:nth-child(2) b { color: var(--accent); }

.ins-range__vals span:nth-child(1) b,
.ins-range__vals span:nth-child(3) b { color: var(--accent-alt); }

/* El eje va en una fila con la MISMA grilla que las de datos, y ocupa solo la
   columna de la pista. Colgado del contenedor se estiraba a todo el panel y
   las marcas caian fuera de lugar: un eje corrido miente sobre cada barra. */
.ins-range__row--axis { padding: 0; }

.ins-range__row--axis > .ins-range__axis { grid-column: 2; }

.ins-range__axis {
  position: relative;
  height: 1.4rem;
  margin-top: 0.2rem;
  border-top: 1px solid var(--line);
}

.ins-range__tick {
  position: absolute;
  top: 0.3rem;
  left: calc(var(--x) * 1%);
  transform: translateX(-50%);
  font-size: 0.7rem;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
  white-space: nowrap;
}

.ins-range__scale {
  margin: 0;
  max-width: none;
  font-size: 0.74rem;
  color: var(--text-muted);
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-range-grow {
    from { transform: translateY(-50%) scaleX(0); }
    to   { transform: translateY(-50%) scaleX(1); }
  }

  @keyframes ins-range-in {
    from { opacity: 0; }
    to   { opacity: 1; }
  }

  .ins-fig.is-in .ins-range__span {
    transform-origin: left center;
    animation: ins-range-grow var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.1s);
  }

  .ins-fig.is-in .ins-range__pin,
  .ins-fig.is-in .ins-range__vals {
    animation: ins-range-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc(0.35s + (var(--i) - 1) * 0.1s);
  }
}

@media (max-width: 820px) {
  /* A dos columnas la pista queda en 120px y la banda deja de medir nada. La
     fila se apila: nombre, cifras, y la pista a lo ancho. */
  .ins-range__row { grid-template-columns: minmax(0, 1fr) auto; row-gap: 0.5rem; }

  .ins-range__track { grid-column: 1 / -1; }

  .ins-range__vals { grid-template-columns: repeat(3, auto); gap: 1.1rem; text-align: left; }

  /* La pista pasa a ocupar la fila entera, asi que el eje tiene que seguirla.
     Dejado en la columna 2 caia en la columna angosta y desaparecia. */
  .ins-range__row--axis > .ins-range__axis { grid-column: 1 / -1; }
}

/* ==========================================================================
   39 SPREAD  ·  .ins-spread
   Reconstruido el 2026-08-12. Lo que habia eran nueve puntos con la posicion
   escrita a mano (`--dot--1` a `--dot--9`): el dibujo no dependia del dato.

   Que muestra: que el promedio miente. Cada punto es un caso real; la banda
   es donde vive la mitad del medio; la linea es el promedio que alguien
   repite. Si la distribucion es estrecha, este componente no hace falta.

   Color: AZUL es el promedio, la respuesta que se cita. VINO es la banda
   intercuartil, la distancia que ese promedio esconde. Los puntos van en
   tinta: son la poblacion, el contexto contra el que se mide la afirmacion.
   Es el mismo reparto que el RANGE.

   Las posiciones las calcula el generador desde los valores reales: bin,
   apilado y cuartiles. Ninguna cifra del pie esta escrita a mano.
   ========================================================================== */
.ins-spread { display: grid; gap: 0.6rem; width: 100%; }

/* El alto lo fija la pila mas alta, no un numero redondo: con 15rem sobraba
   media figura de aire y la banda se leia como un muro. */
.ins-spread__plot {
  position: relative;
  height: 10.5rem;
  border-bottom: 1px solid color-mix(in srgb, var(--text-primary) 45%, transparent);
}

/* La banda intercuartil: donde vive la mitad del medio. */
.ins-spread__band {
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(var(--q1) * 1%);
  width: calc((var(--q3) - var(--q1)) * 1%);
  background: color-mix(in srgb, var(--accent-alt) 9%, transparent);
  border-inline: 2px solid color-mix(in srgb, var(--accent-alt) 55%, transparent);
}

/* Se apoya en el borde IZQUIERDO de la banda, no en su centro: el promedio
   cae dentro de la banda y su linea vertical partia el rotulo al medio. */
.ins-spread__bandlabel {
  position: absolute;
  top: 0.2rem;
  left: calc(var(--q1) * 1%);
  padding-left: 0.4rem;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--accent-alt);
  white-space: nowrap;
}

/* El promedio. */
.ins-spread__mean {
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(var(--mean) * 1%);
  width: 3px;
  transform: translateX(-1.5px);
  background: var(--accent);
}

/* Escalonado respecto del rotulo de la banda: el promedio cae DENTRO de la
   banda, asi que a la misma altura los dos textos se pisan. */
.ins-spread__meanlabel {
  position: absolute;
  top: 1.5rem;
  left: calc(var(--mean) * 1%);
  padding-left: 0.4rem;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--accent);
  white-space: nowrap;
}

/* Cada punto es un caso. Se apilan donde caen en el mismo tramo. */
.ins-spread__dot {
  position: absolute;
  bottom: calc(0.35rem + var(--row) * 0.66rem);
  left: calc(var(--x) * 1%);
  width: 0.55rem;
  height: 0.55rem;
  transform: translateX(-50%);
  border-radius: 50%;
  background: color-mix(in srgb, var(--text-primary) 55%, transparent);
}

/* Los casos que quedan fuera de la banda son el argumento: el promedio no los
   representa. Van llenos, no como los del medio. */
.ins-spread__dot[data-out] { background: var(--text-primary); }

.ins-spread__axis { position: relative; height: 1.4rem; }

.ins-spread__tick {
  position: absolute;
  top: 0.3rem;
  left: calc(var(--x) * 1%);
  transform: translateX(-50%);
  font-size: 0.7rem;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
  white-space: nowrap;
}

.ins-spread__foot {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1.6rem;
  margin: 0;
  max-width: none;
  font-size: 0.76rem;
  color: var(--text-muted);
}

.ins-spread__foot b {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
}

.ins-spread__foot b[data-kind="mean"] { color: var(--accent); }

.ins-spread__foot b[data-kind="iqr"] { color: var(--accent-alt); }

.ins-spread__scale {
  margin: 0;
  max-width: none;
  font-size: 0.74rem;
  color: var(--text-muted);
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-spread-dot {
    from { opacity: 0; transform: translateX(-50%) scale(0.3); }
    to   { opacity: 1; transform: translateX(-50%) scale(1); }
  }

  @keyframes ins-spread-in {
    from { opacity: 0; }
    to   { opacity: 1; }
  }

  /* El retraso lo da --i, que es el ORDEN del valor, no su posicion: los
     puntos aparecen de izquierda a derecha como se leerian. */
  .ins-fig.is-in .ins-spread__dot {
    animation: ins-spread-dot 0.4s var(--ease-out) both;
    animation-delay: calc(var(--i) * 0.012s);
  }

  .ins-fig.is-in .ins-spread__band,
  .ins-fig.is-in .ins-spread__bandlabel,
  .ins-fig.is-in .ins-spread__mean,
  .ins-fig.is-in .ins-spread__meanlabel {
    animation: ins-spread-in var(--dur-base) var(--ease-out) 0.9s both;
  }
}

@media (max-width: 640px) {
  .ins-spread__plot { height: 9rem; }

  .ins-spread__dot { width: 0.45rem; height: 0.45rem; bottom: calc(0.3rem + var(--row) * 0.54rem); }

  /* En angosto la banda mide 90px y su rotulo no entra sin que la linea del
     promedio lo parta. Se cae: el pie ya nombra la banda, en vino, y la
     figura sigue diciendo lo mismo. */
  .ins-spread__bandlabel { display: none; }
}

/* ==========================================================================
   36 PARALLEL  ·  .ins-parallel
   Reconstruido el 2026-08-12. Lo que habia era una grilla con filete en cada
   celda: doce filetes en una figura, contra el presupuesto del playbook.

   Que muestra: dos caminos paso a paso, cuando la divergencia es el punto.
   Con mas de dos, va TABLE.

   La forma: los dos caminos se enfrentan contra un EJE central que dice el
   paso. El de la izquierda se alinea a la derecha y el de la derecha a la
   izquierda, asi que las dos versiones del mismo paso se tocan en el eje y la
   diferencia se lee sin buscarla.

   El vino marca el camino que deja de poder probarse, desde la fila donde se
   parte y hasta el final. No es "el camino malo": es el que el registro ya no
   puede certificar.

   Filetes: uno solo, debajo del encabezado. Las filas se separan por aire.
   ========================================================================== */
.ins-parallel { display: grid; gap: 0; width: 100%; }

.ins-parallel__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(7rem, 11rem) minmax(0, 1fr);
  gap: 1.1rem;
  align-items: center;
  padding: 0.7rem 0;
}

.ins-parallel__head {
  padding-bottom: 0.7rem;
  border-bottom: 1px solid color-mix(in srgb, var(--text-primary) 30%, transparent);
}

.ins-parallel__who {
  max-width: none;
  margin: 0;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
}

.ins-parallel__who[data-side="a"] { text-align: right; }

.ins-parallel__who[data-side="b"] { text-align: left; }

.ins-parallel__who[data-kind="loss"] { color: var(--accent-alt); }

/* El eje. Dice el paso, y es lo unico que las dos columnas comparten. */
.ins-parallel__step {
  max-width: none;
  margin: 0;
  padding: 0.35rem 0.6rem;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.3;
  text-align: center;
  color: var(--text-muted);
  background: color-mix(in srgb, var(--text-primary) 5%, transparent);
}

.ins-parallel__a,
.ins-parallel__b {
  max-width: none;
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.4;
  color: var(--text-primary);
  text-wrap: pretty;
}

.ins-parallel__a { text-align: right; }

.ins-parallel__b { text-align: left; }

/* Desde donde se parten, el lado que deja de poder probarse va en vino. */
.ins-parallel__row[data-diff] .ins-parallel__b {
  font-weight: 700;
  color: var(--accent-alt);
}

.ins-parallel__row[data-diff] .ins-parallel__a { font-weight: 700; color: var(--ink, var(--text-primary)); }

/* La fila donde se parten. El eje lo dice una sola vez. */
.ins-parallel__fork {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(7rem, 11rem) minmax(0, 1fr);
  gap: 1.1rem;
  align-items: center;
  padding: 0.2rem 0;
}

.ins-parallel__forkmark {
  grid-column: 2;
  margin: 0;
  max-width: none;
  padding: 0.3rem 0.5rem;
  font-size: 0.7rem;
  font-weight: 700;
  font-style: italic;
  text-align: center;
  color: var(--accent-alt);
  border-top: 2px solid var(--accent-alt);
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-parallel-in {
    from { opacity: 0; transform: translateY(0.4rem); }
    to   { opacity: 1; transform: none; }
  }

  .ins-fig.is-in .ins-parallel__row,
  .ins-fig.is-in .ins-parallel__fork {
    animation: ins-parallel-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.08s);
  }
}

@media (max-width: 760px) {
  /* Enfrentados a 700px cada columna queda en 200px y el paso, en el medio,
     en 110: se rompen las tres. Se apila por paso: primero el paso, y debajo
     los dos caminos, cada uno con su rotulo. */
  .ins-parallel__row,
  .ins-parallel__fork { grid-template-columns: 1fr; gap: 0.35rem; }

  .ins-parallel__head { display: none; }

  /* Apilado, el eje tiene que ENCABEZAR los dos caminos. En el orden del DOM
     va en el medio, porque enfrentados esa es su posicion. */
  .ins-parallel__step { order: -1; text-align: left; }

  .ins-parallel__a,
  .ins-parallel__b { text-align: left; padding-left: 0.9rem; }

  .ins-parallel__a { box-shadow: inset 2px 0 0 var(--accent); }

  .ins-parallel__b { box-shadow: inset 2px 0 0 color-mix(in srgb, var(--text-primary) 30%, transparent); }

  .ins-parallel__row[data-diff] .ins-parallel__b { box-shadow: inset 2px 0 0 var(--accent-alt); }

  .ins-parallel__forkmark { grid-column: 1; }

  /* En apilado hace falta decir de quien es cada renglon: enfrentados lo decia
     la posicion, y apilados no lo dice nadie. */
  .ins-parallel__a::before,
  .ins-parallel__b::before {
    display: block;
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-muted);
    content: attr(data-who);
  }
}

/* ==========================================================================
   34 TRADEOFF  ·  .ins-tradeoff
   Reconstruido el 2026-08-12. Lo que habia eran tres fichas con la posicion
   escrita a mano (`--one`, `--two`, `--three`): el eje no medía nada.

   Que muestra: que no hay opcion optima, solo posiciones en una tension entre
   dos cosas que las dos se quieren. Si una opcion gana en todo, va SCORECARD.

   El eje tiene dos polos rotulados y las opciones se ubican a lo largo. La
   posicion es el dato: moverla es cambiar la afirmacion.

   Vino: la opcion que NO tiene posicion. Cuando algo depende del criterio de
   cada persona, no cae en un punto del eje, cae en un tramo, y ese tramo es
   exactamente lo que el registro no puede certificar. Se dibuja como banda,
   con la misma gramatica que el RANGE.

   El escalonado de las fichas lo calcula el generador midiendo si se pisan.
   ========================================================================== */
.ins-tradeoff { display: grid; gap: 0.9rem; width: 100%; }

.ins-tradeoff__poles {
  display: flex;
  justify-content: space-between;
  gap: 1.5rem;
  margin: 0;
  max-width: none;
}

.ins-tradeoff__pole {
  max-width: 16rem;
  font-size: 0.78rem;
  line-height: 1.35;
  color: var(--text-muted);
}

.ins-tradeoff__pole b {
  display: block;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--accent);
}

.ins-tradeoff__pole[data-side="right"] { text-align: right; }

/* El eje. Las puntas dicen que la tension sigue mas alla de las opciones. */
.ins-tradeoff__axis {
  position: relative;
  height: 2px;
  background: color-mix(in srgb, var(--text-primary) 45%, transparent);
}

.ins-tradeoff__axis::before,
.ins-tradeoff__axis::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 0;
  height: 0;
  border-block: 5px solid transparent;
}

.ins-tradeoff__axis::before {
  left: -1px;
  transform: translateY(-50%);
  border-right: 9px solid color-mix(in srgb, var(--text-primary) 45%, transparent);
}

.ins-tradeoff__axis::after {
  right: -1px;
  transform: translateY(-50%);
  border-left: 9px solid color-mix(in srgb, var(--text-primary) 45%, transparent);
}

/* La banda de la opcion sin posicion. Va sobre el eje mismo. */
.ins-tradeoff__band {
  position: absolute;
  top: 50%;
  left: calc(var(--from) * 1%);
  width: calc((var(--to) - var(--from)) * 1%);
  height: 0.7rem;
  transform: translateY(-50%);
  background: color-mix(in srgb, var(--accent-alt) 22%, transparent);
}

.ins-tradeoff__band::before,
.ins-tradeoff__band::after {
  content: "";
  position: absolute;
  top: -0.3rem;
  width: 2px;
  height: 1.3rem;
  background: var(--accent-alt);
}

.ins-tradeoff__band::before { left: 0; }

.ins-tradeoff__band::after { right: 0; }

/* La pista donde caen las fichas. El alto sale de cuantos renglones necesito,
   y viaja como VARIABLE, no como `height` inline: un alto inline no lo puede
   pisar una media query, y en apilado el pie se dibujaba encima de las
   fichas. */
.ins-tradeoff__field {
  position: relative;
  height: calc(var(--rows) * 4.6rem + 3.6rem);
}

.ins-tradeoff__opt {
  position: absolute;
  top: calc(var(--row) * 4.6rem);
  left: calc(var(--x) * 1%);
  width: 12rem;
  padding: 0.5rem 0.65rem;
  transform: translateX(-50%);
  background: var(--ins-paper, var(--bg-raised));
  box-shadow: inset 0 0 0 1px var(--line);
}

/* En los bordes, la ficha se ancla en vez de centrarse: centrada se sale de
   la placa y el instrumento genera scroll horizontal. */
.ins-tradeoff__opt[data-anchor="start"] { transform: none; }

.ins-tradeoff__opt[data-anchor="end"] { transform: translateX(-100%); }

.ins-tradeoff__opt[data-kind="loose"] {
  background: color-mix(in srgb, var(--accent-alt) 7%, var(--ins-paper, var(--bg-raised)));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent-alt) 40%, transparent);
}

/* El tallo que une la ficha con su punto del eje. Sin el, una ficha corrida
   dos renglones para abajo deja de decir donde estaba. */
.ins-tradeoff__opt::before {
  content: "";
  position: absolute;
  bottom: 100%;
  left: 50%;
  width: 1px;
  height: calc(0.9rem + var(--row) * 4.6rem);
  background: color-mix(in srgb, var(--text-primary) 30%, transparent);
}

.ins-tradeoff__opt[data-anchor="start"]::before { left: 1px; }

.ins-tradeoff__opt[data-anchor="end"]::before { left: auto; right: 1px; }

.ins-tradeoff__opt[data-kind="loose"]::before { background: var(--accent-alt); }

.ins-tradeoff__n {
  display: block;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--accent-alt);
}

.ins-tradeoff__name {
  max-width: none;
  margin: 0;
  font-size: 0.84rem;
  font-weight: 700;
  line-height: 1.3;
  color: var(--ink, var(--text-primary));
}

.ins-tradeoff__opt[data-kind="loose"] .ins-tradeoff__name { color: var(--accent-alt); }

.ins-tradeoff__cost {
  max-width: none;
  margin: 0.2rem 0 0;
  font-size: 0.74rem;
  line-height: 1.35;
  color: var(--text-muted);
}

.ins-tradeoff__scale {
  margin: 0;
  max-width: none;
  font-size: 0.74rem;
  color: var(--text-muted);
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-tradeoff-in {
    from { opacity: 0; transform: translateY(0.4rem); }
    to   { opacity: 1; transform: none; }
  }

  /* Las fichas ancladas no pueden usar el keyframe con translateY solo: su
     transform tambien lleva el anclaje horizontal, y una animacion que lo
     ignora las manda al centro. Entran solo con opacidad. */
  .ins-fig.is-in .ins-tradeoff__opt {
    animation: ins-tradeoff-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.1s);
  }

  .ins-fig.is-in .ins-tradeoff__opt[data-anchor] {
    animation-name: ins-tradeoff-fade;
  }

  @keyframes ins-tradeoff-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
  }
}

@media (max-width: 760px) {
  /* Cuatro fichas de 12rem no entran en 340px de placa por mucho que se
     escalonen. El eje se cae y las opciones pasan a lista, en el mismo orden
     en que estan sobre el eje, con su posicion escrita. */
  .ins-tradeoff__axis,
  .ins-tradeoff__poles { display: none; }

  .ins-tradeoff__field { display: grid; height: auto; gap: 0.5rem; }

  .ins-tradeoff__opt {
    position: static;
    width: auto;
    transform: none;
  }

  .ins-tradeoff__opt::before { display: none; }

  .ins-tradeoff__opt[data-anchor] { transform: none; }
}

/* ==========================================================================
   43 SELF-CHECK  ·  .ins-check
   Construido el 2026-08-12. Primero de la Ola 3, y el primero de la libreria
   con JS propio: `assets/js/insights-check.js`.

   Que hace: cuatro preguntas de si o no, y un veredicto por conteo.

   Donde va: en el punto de maxima tension del articulo, antes de la
   resolucion. Convierte el CTA en consecuencia de lo que el lector acaba de
   descubrir sobre si mismo, en vez de un boton al final.

   SIN JS EL CONTENIDO NO SE ESCONDE. Las tres lecturas posibles estan en el
   HTML, cada una con su condicion escrita ("zero or one", "two or three",
   "all four"), y se leen como una lista. El JS solo TAPA las dos que no
   aplican, y solo despues de que el lector contesto todo. Por eso el ocultado
   cuelga de `.is-live`, que la pone el script: si el script no corre, no hay
   nada oculto.

   Color: azul el camino que se puede defender, vino el que no. El veredicto
   del medio va en tinta, porque a mitad de camino no hay veredicto.

   Prohibido pedir datos personales aca. El dato se pide en la landing del
   magnet.
   ========================================================================== */
.ins-check { display: grid; gap: 0; width: 100%; }

.ins-check__intro {
  max-width: none;
  margin: 0 0 0.4rem;
  font-size: 0.82rem;
  color: var(--text-muted);
}

/* Una pregunta. Un `fieldset` con `legend` seria lo canonico, pero el legend
   NO participa de la grilla del fieldset: se renderiza aparte y las dos
   respuestas se reparten las columnas solas, con el "Yes" comiendose la fila
   entera. Un `role="radiogroup"` con `aria-labelledby` da lo mismo al lector
   de pantalla y deja el layout en nuestras manos. */
.ins-check__q {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.6rem 1rem;
  align-items: center;
  padding: 0.7rem 0;
}

.ins-check__opts { display: flex; gap: 0.4rem; }

.ins-check__label {
  max-width: none;
  padding: 0;
  font-size: 0.9rem;
  line-height: 1.4;
  color: var(--ink, var(--text-primary));
}

.ins-check__n {
  margin-right: 0.5rem;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--accent-alt);
}

/* El boton de respuesta. El radio real sigue ahi, invisible pero enfocable:
   un boton falso rompe el teclado y el lector de pantalla. */
.ins-check__opt {
  position: relative;
  display: grid;
  place-items: center;
  min-width: 4.4rem;
  padding: 0.4rem 0.9rem;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--text-muted);
  cursor: pointer;
  box-shadow: inset 0 0 0 1px var(--line);
  transition: color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}

.ins-check__opt input {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.ins-check__opt:hover { color: var(--text-primary); }

.ins-check__opt:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Elegida. El "si" es lo que se puede probar y va en azul; el "no" es lo que
   el registro no puede certificar y va en vino. */
.ins-check__opt:has(input:checked) {
  color: var(--bg-raised);
  background: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}

.ins-check__opt[data-answer="no"]:has(input:checked) {
  background: var(--accent-alt);
  box-shadow: inset 0 0 0 1px var(--accent-alt);
}

/* El contador. Solo aparece cuando el script corre. */
.ins-check__progress {
  display: none;
  margin: 0.3rem 0 0;
  max-width: none;
  font-size: 0.74rem;
  font-weight: 700;
  color: var(--text-muted);
}

.ins-check.is-live .ins-check__progress { display: block; }

.ins-check__outs { display: grid; gap: 0.5rem; margin-top: 1rem; }

.ins-check__out {
  padding: 0.9rem 1rem;
  background: color-mix(in srgb, var(--text-primary) 4%, transparent);
  box-shadow: inset 3px 0 0 var(--text-primary);
}

.ins-check__out[data-band="high"] {
  background: color-mix(in srgb, var(--accent) 7%, transparent);
  box-shadow: inset 3px 0 0 var(--accent);
}

.ins-check__out[data-band="low"] {
  background: color-mix(in srgb, var(--accent-alt) 7%, transparent);
  box-shadow: inset 3px 0 0 var(--accent-alt);
}

.ins-check__cond {
  max-width: none;
  margin: 0 0 0.25rem;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.ins-check__out[data-band="high"] .ins-check__cond { color: var(--accent); }

.ins-check__out[data-band="low"] .ins-check__cond { color: var(--accent-alt); }

.ins-check__verdict {
  max-width: none;
  margin: 0;
  font-size: 0.94rem;
  font-weight: 700;
  line-height: 1.4;
  color: var(--ink, var(--text-primary));
}

.ins-check__why {
  max-width: none;
  margin: 0.35rem 0 0;
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--text-primary);
}

.ins-check__cta {
  display: inline-block;
  margin-top: 0.7rem;
  font-size: 0.84rem;
  font-weight: 700;
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.ins-check__out[data-band="low"] .ins-check__cta { color: var(--accent-alt); }

/* Con el script vivo, las lecturas se tapan hasta que el lector contesto todo,
   y despues queda solo la suya. */
.ins-check.is-live .ins-check__out { display: none; }

.ins-check.is-live[data-band="low"] .ins-check__out[data-band="low"],
.ins-check.is-live[data-band="mid"] .ins-check__out[data-band="mid"],
.ins-check.is-live[data-band="high"] .ins-check__out[data-band="high"] { display: block; }

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-check-out {
    from { opacity: 0; transform: translateY(0.5rem); }
    to   { opacity: 1; transform: none; }
  }

  .ins-check.is-live[data-band] .ins-check__out {
    animation: ins-check-out var(--dur-base) var(--ease-out) both;
  }
}

@media (max-width: 620px) {
  /* La pregunta pasa arriba y las dos respuestas debajo, a lo ancho: en una
     sola fila el texto queda en 140px. */
  .ins-check__q { grid-template-columns: 1fr; }

  .ins-check__opts > * { flex: 1; }
}

/* ==========================================================================
   40 CALCULATOR  ·  .ins-calc
   Construido el 2026-08-12. Segundo de la Ola 3, con JS propio:
   `assets/js/insights-calc.js`.

   Que hace: el lector mete sus numeros y ve su resultado. Sirve cuando la
   formula del articulo aplica a cualquier empresa con sus propios datos.

   SIN JS MUESTRA LOS VALORES POR DEFECTO Y SU RESULTADO YA CALCULADO. El
   generador calcula ese resultado y lo escribe en el HTML; el script solo lo
   vuelve a calcular cuando el lector cambia algo. Una calculadora que sin JS
   muestra ceros o guiones es una calculadora rota.

   Color: azul el numero que se puede accionar, vino el que el registro no
   puede certificar. El mismo reparto del RANGE y el SPREAD.

   Los defaults son realistas a proposito: son lo primero que el lector lee, y
   un default absurdo desacredita la formula antes de que la pruebe.
   ========================================================================== */
.ins-calc { display: grid; gap: 1.2rem; width: 100%; }

.ins-calc__ins { display: grid; gap: 0.15rem; }

.ins-calc__in {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 11rem;
  gap: 0.8rem;
  align-items: center;
  padding: 0.5rem 0;
}

.ins-calc__label {
  max-width: none;
  margin: 0;
  font-size: 0.88rem;
  line-height: 1.35;
  color: var(--text-primary);
}

/* El campo. Con la unidad pegada adentro, no como sufijo suelto al lado. */
.ins-calc__field {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.45rem 0.7rem;
  background: var(--ins-paper, var(--bg-raised));
  box-shadow: inset 0 0 0 1px var(--line);
}

.ins-calc__field:focus-within { box-shadow: inset 0 0 0 2px var(--accent); }

.ins-calc__unit { font-size: 0.9rem; font-weight: 700; color: var(--text-muted); }

.ins-calc__field input {
  width: 100%;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  font-family: inherit;
  font-size: 1rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink, var(--text-primary));
  text-align: right;
}

.ins-calc__field input:focus { outline: none; }

/* Los resultados. */
.ins-calc__outs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 0.5rem;
}

.ins-calc__out {
  padding: 0.8rem 0.9rem;
  background: color-mix(in srgb, var(--text-primary) 4%, transparent);
  box-shadow: inset 3px 0 0 var(--text-primary);
}

.ins-calc__out[data-kind="answer"] {
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  box-shadow: inset 3px 0 0 var(--accent);
}

.ins-calc__out[data-kind="loss"] {
  background: color-mix(in srgb, var(--accent-alt) 8%, transparent);
  box-shadow: inset 3px 0 0 var(--accent-alt);
}

.ins-calc__v {
  display: block;
  font-size: 1.5rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
  color: var(--ink, var(--text-primary));
}

.ins-calc__out[data-kind="answer"] .ins-calc__v { color: var(--accent); }

.ins-calc__out[data-kind="loss"] .ins-calc__v { color: var(--accent-alt); }

.ins-calc__k {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.74rem;
  line-height: 1.35;
  color: var(--text-muted);
}

.ins-calc__read {
  max-width: none;
  margin: 0;
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--text-primary);
}

.ins-calc__read b { font-weight: 700; color: var(--ink, var(--text-primary)); }

.ins-calc__read b[data-kind="loss"] { color: var(--accent-alt); }

.ins-calc__read b[data-kind="answer"] { color: var(--accent); }

.ins-calc__note {
  max-width: none;
  margin: 0;
  font-size: 0.74rem;
  color: var(--text-muted);
}

@media (prefers-reduced-motion: no-preference) {
  /* El valor parpadea cuando cambia, para que se note que respondio. Sin esto
     el lector escribe y no sabe si algo paso. */
  @keyframes ins-calc-bump {
    from { opacity: 0.35; }
    to   { opacity: 1; }
  }

  .ins-calc__v.is-new { animation: ins-calc-bump 0.35s var(--ease-out); }
}

@media (max-width: 620px) {
  .ins-calc__in { grid-template-columns: 1fr; gap: 0.35rem; }

  .ins-calc__outs { grid-template-columns: 1fr; }
}

/* ==========================================================================
   41 TOGGLE  ·  .ins-toggle
   Construido el 2026-08-12. Tercero de la Ola 3, con JS propio:
   `assets/js/insights-toggle.js`.

   Que hace: un control de dos posiciones que alterna dos estados de la MISMA
   figura. Sirve cuando el antes y el despues comparten estructura y el cambio
   es el argumento: al no moverse nada mas que los valores, el ojo ve la
   diferencia sin compararla a mano.

   SIN JS SE VEN LOS DOS ESTADOS, apilados y cada uno con su rotulo. El control
   no aparece, porque sin script no controlaria nada: un boton muerto es peor
   que no tener boton.

   La transicion es solo opacidad y transform, como todo el resto.
   ========================================================================== */
.ins-toggle { display: grid; gap: 1rem; width: 100%; }

/* El control solo existe si el script corre. */
.ins-toggle__controls { display: none; gap: 0.4rem; }

.ins-toggle.is-live .ins-toggle__controls { display: flex; flex-wrap: wrap; }

.ins-toggle__control {
  min-height: 2.5rem;
  padding: 0.5rem 1rem;
  border: 0;
  background: var(--ins-paper, var(--bg-raised));
  box-shadow: inset 0 0 0 1px var(--line);
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--text-muted);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
}

.ins-toggle__control[aria-pressed="true"] {
  background: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
  color: var(--bg-raised);
}

.ins-toggle__control[aria-pressed="true"][data-kind="loss"] {
  background: var(--accent-alt);
  box-shadow: inset 0 0 0 1px var(--accent-alt);
}

.ins-toggle__states { display: grid; gap: 0.9rem; }

/* El rotulo del estado. Con el script vivo sobra: lo dice el control. */
.ins-toggle__who {
  max-width: none;
  margin: 0 0 0.4rem;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.ins-toggle__state[data-kind="loss"] .ins-toggle__who { color: var(--accent-alt); }

.ins-toggle.is-live .ins-toggle__who { display: none; }

.ins-toggle.is-live .ins-toggle__state[hidden] { display: none; }

.ins-toggle__cells {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: 0.5rem;
}

.ins-toggle__cell {
  padding: 0.9rem 1rem;
  background: color-mix(in srgb, var(--text-primary) 4%, transparent);
  box-shadow: inset 3px 0 0 var(--accent);
}

.ins-toggle__state[data-kind="loss"] .ins-toggle__cell { box-shadow: inset 3px 0 0 var(--accent-alt); }

.ins-toggle__v {
  display: block;
  font-size: 1.5rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
  color: var(--accent);
}

.ins-toggle__state[data-kind="loss"] .ins-toggle__v { color: var(--accent-alt); }

/* El valor que no existe en ese estado. Vale mas escribirlo que dejarlo vacio:
   un hueco se lee como un error de carga, y esto es un dato. */
.ins-toggle__v[data-none] { font-size: 1.1rem; font-style: italic; }

.ins-toggle__k {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.74rem;
  line-height: 1.35;
  color: var(--text-muted);
}

.ins-toggle__note {
  max-width: none;
  margin: 0;
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--text-primary);
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-toggle-in {
    from { opacity: 0; transform: translateY(0.35rem); }
    to   { opacity: 1; transform: none; }
  }

  .ins-toggle.is-live .ins-toggle__state:not([hidden]) .ins-toggle__cell {
    animation: ins-toggle-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc(var(--i) * 0.05s);
  }
}

/* ==========================================================================
   42 STEPPER  ·  .ins-stepper
   Construido el 2026-08-12. Ultimo de la Ola 3, con JS propio:
   `assets/js/insights-stepper.js`.

   Que hace: revela una figura compleja paso a paso. Sirve cuando el
   instrumento tiene mas de cinco elementos y el orden de lectura importa.

   Lo que se revela ACUMULA: al llegar al paso 4 estan los cuatro renglones a
   la vista, no solo el cuarto. Si cada paso reemplazara al anterior seria un
   carrusel, y un carrusel no deja ver una cuenta.

   SIN JS ESTAN TODOS LOS PASOS VISIBLES, con su explicacion. La navegacion no
   aparece: sin script no navegaria nada.
   ========================================================================== */
.ins-stepper { display: grid; gap: 1rem; width: 100%; }

.ins-stepper__nav { display: none; align-items: center; gap: 0.6rem; }

.ins-stepper.is-live .ins-stepper__nav { display: flex; }

.ins-stepper__button {
  min-height: 2.5rem;
  padding: 0.5rem 1rem;
  border: 0;
  background: var(--accent);
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--bg-raised);
  cursor: pointer;
}

.ins-stepper__button:disabled {
  background: color-mix(in srgb, var(--text-primary) 10%, transparent);
  color: var(--text-muted);
  cursor: default;
}

.ins-stepper__count {
  margin: 0;
  max-width: none;
  font-size: 0.74rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

/* Los renglones de la cuenta. */
.ins-stepper__rows { display: grid; gap: 0.15rem; }

.ins-stepper__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 1rem;
  align-items: baseline;
  padding: 0.55rem 0;
  transition: opacity var(--dur-base) var(--ease-out);
}

/* Todavia no revelado: se atenua, no se borra. Que el lector vea cuanto falta
   es parte de la lectura. */
.ins-stepper.is-live .ins-stepper__row[data-pending] { opacity: 0.22; }

.ins-stepper__rk {
  max-width: none;
  margin: 0;
  font-size: 0.88rem;
  line-height: 1.35;
  color: var(--text-primary);
}

.ins-stepper__rn {
  margin-right: 0.5rem;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--accent-alt);
}

.ins-stepper__rv {
  margin: 0;
  max-width: none;
  font-size: 1rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink, var(--text-primary));
}

.ins-stepper__row[data-kind="loss"] .ins-stepper__rv { color: var(--accent-alt); }

.ins-stepper__row[data-kind="total"] {
  margin-top: 0.4rem;
  padding-top: 0.8rem;
  border-top: 1px solid color-mix(in srgb, var(--text-primary) 30%, transparent);
}

.ins-stepper__row[data-kind="total"] .ins-stepper__rk { font-weight: 700; color: var(--ink, var(--text-primary)); }

.ins-stepper__row[data-kind="total"] .ins-stepper__rv { font-size: 1.3rem; color: var(--accent); }

/* La explicacion del paso. */
.ins-stepper__stage {
  padding: 0.9rem 1rem;
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  box-shadow: inset 3px 0 0 var(--accent);
}

.ins-stepper__title {
  max-width: none;
  margin: 0;
  font-size: 0.94rem;
  font-weight: 700;
  line-height: 1.35;
  color: var(--ink, var(--text-primary));
}

.ins-stepper__body {
  max-width: none;
  margin: 0.3rem 0 0;
  font-size: 0.84rem;
  line-height: 1.5;
  color: var(--text-primary);
}

.ins-stepper.is-live .ins-stepper__stage[hidden] { display: none; }

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-stepper-in {
    from { opacity: 0; transform: translateY(0.35rem); }
    to   { opacity: 1; transform: none; }
  }

  .ins-stepper.is-live .ins-stepper__stage:not([hidden]) {
    animation: ins-stepper-in var(--dur-base) var(--ease-out) both;
  }
}

@media (max-width: 560px) {
  .ins-stepper__nav { flex-wrap: wrap; }

  .ins-stepper__row { grid-template-columns: 1fr; gap: 0.1rem; }
}


/* 19 COHORT */
    .ins-cohort { display: grid; grid-template-columns: 5rem repeat(4, 1fr); border-top: 1px solid var(--line); border-left: 1px solid var(--line); }

.ins-cohort > span { min-height: 2.6rem; display: grid; place-items: center; padding: 0.35rem; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); font-size: 0.65rem; }

.ins-cohort__h { background: var(--bg-base); font-weight: 700; }

.ins-cohort__v--high { background: var(--accent); color: var(--bg-raised); }

.ins-cohort__v--mid { background: var(--line); }

.ins-cohort__v--low { background: var(--bg-base); }

/* 20 GANTT */
    .ins-gantt { display: grid; grid-template-columns: 6rem repeat(6, 1fr); border-top: 1px solid var(--line); border-left: 1px solid var(--line); }

.ins-gantt > span { min-height: 2.8rem; display: grid; align-items: center; padding: 0.35rem; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); font-size: 0.62rem; }

.ins-gantt__h { justify-items: center; background: var(--bg-base); font-weight: 700; }

.ins-gantt__bar { background: var(--accent); color: var(--bg-raised); }

.ins-gantt__bar--outline { border: 2px solid var(--accent); background: var(--bg-raised); color: var(--text-primary); }

/* 23 SCATTER */
    .ins-scatter { width: 100%; height: auto; }

.ins-scatter__axis { stroke: var(--text-primary); stroke-width: 1; }

.ins-scatter__grid { stroke: var(--line); stroke-width: 1; }

.ins-scatter__dot { fill: var(--accent); }

.ins-scatter__dot--outlier { fill: var(--bg-raised); stroke: var(--accent-alt); stroke-width: 3; }

.ins-scatter__text { fill: var(--text-primary); font-family: var(--font-sans); font-size: 10px; }

/* 24 LAG */
    .ins-lag { width: 100%; height: auto; }

.ins-lag__grid { stroke: var(--line); stroke-width: 1; }

.ins-lag__serie { fill: none; stroke: var(--accent); stroke-width: 3; }

.ins-lag__serie--late { stroke: var(--text-primary); }

.ins-lag__gap { stroke: var(--accent-alt); stroke-width: 2; }

.ins-lag__text { fill: var(--text-primary); font-family: var(--font-sans); font-size: 10px; }

/* 25 TREE */
    .ins-tree { display: grid; gap: 0.65rem; }

.ins-tree__node { padding: 0.7rem; border-left: 3px solid var(--accent); background: var(--bg-base); font-size: 0.74rem; }

.ins-tree__branch { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.65rem; padding-left: 1.2rem; border-left: 1px solid var(--line); }

.ins-tree__leaf { padding: 0.65rem; border: 1px solid var(--line); font-size: 0.68rem; }

/* 28 VENN */
    .ins-venn { position: relative; width: 19rem; max-width: 100%; height: 12rem; margin: 0 auto; }

.ins-venn__set { position: absolute; top: 1rem; width: 10rem; height: 10rem; display: grid; align-items: start; padding-top: 1.4rem; border: 2px solid var(--accent); border-radius: 50%; background: color-mix(in srgb, var(--accent) 8%, transparent); color: var(--accent); font-size: 0.7rem; font-weight: 700; text-align: center; }

.ins-venn__set--one { left: 1rem; }

.ins-venn__set--two { right: 1rem; }

.ins-venn__overlap { position: absolute; top: 5.4rem; left: 50%; width: 5rem; transform: translateX(-50%); color: var(--text-primary); font-size: 0.68rem; text-align: center; }

/* 31 DECISION */
    .ins-decision { display: grid; gap: 0.8rem; text-align: center; }

.ins-decision__q { width: 70%; margin: 0 auto; padding: 0.75rem; border: 2px solid var(--accent); color: var(--accent); font-weight: 700; }

.ins-decision__stem { height: 1.2rem; border-left: 2px solid var(--text-primary); justify-self: center; }

.ins-decision__branches { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; position: relative; padding-top: 1rem; }

.ins-decision__branches::before { content: ""; position: absolute; top: 0; right: 25%; left: 25%; border-top: 1px solid var(--text-primary); }

.ins-decision__answer { padding: 0.75rem; border: 1px solid var(--line); font-size: 0.72rem; }

.ins-decision__answer strong { display: block; margin-bottom: 0.4rem; color: var(--accent); font-weight: 700; }

/* 32 STATE */
    .ins-state { display: grid; grid-template-columns: repeat(7, auto); gap: 0.45rem; align-items: center; justify-content: center; }

.ins-state__node { min-width: 4.3rem; padding: 0.65rem 0.4rem; border: 1px solid var(--accent); color: var(--accent); font-size: 0.66rem; text-align: center; }

.ins-state__arrow { color: var(--accent); }

.ins-state__arrow--broken { color: var(--accent-alt); }

.ins-state__node--blocked { border-color: var(--accent-alt); color: var(--accent-alt); }

/* 38 HEATMAP */
    .ins-heat { display: grid; grid-template-columns: 5rem repeat(5, 1fr); border-top: 1px solid var(--line); border-left: 1px solid var(--line); }

.ins-heat > span { min-height: 2.5rem; display: grid; place-items: center; padding: 0.25rem; border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); font-size: 0.62rem; }

.ins-heat__h { background: var(--bg-base); font-weight: 700; }

.ins-heat__v--1 { background: color-mix(in srgb, var(--accent) 12%, transparent); }

.ins-heat__v--2 { background: color-mix(in srgb, var(--accent) 28%, transparent); }

.ins-heat__v--3 { background: color-mix(in srgb, var(--accent) 48%, transparent); color: var(--bg-raised); }

.ins-heat__v--4 { background: color-mix(in srgb, var(--accent) 72%, transparent); color: var(--bg-raised); }

.ins-heat__v--5 { background: var(--accent); color: var(--bg-raised); }

/* V7 — COMPONENTS REDIRECTED FROM THE APPROVED REFERENCES */






















/* Aca quedaba otra media query vaciada por el barrido: sus reglas eran todas
   de componentes -v7 ya reemplazados, y la llave abierta se comia el bloque
   siguiente. Borrada el 2026-08-12. */

/* CTA */

@keyframes sention-catalog-line {
      from { transform: scaleX(0); }
      to { transform: scaleX(1); }
    }

@media (prefers-reduced-motion: reduce) {
      *,
      *::before,
      *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
      }
    }

@media (max-width: 820px) {
      .ins-fig__cap { min-height: 0; }
    }

/* Movil de los componentes que TODAVIA vienen del port de v7 y no fueron
   rehechos uno por uno. El bloque original arrastraba una regla SIN SELECTOR
   (el scope #sention-component-catalog-v7 quedo colgado al desarmar el
   mockup) que desbalanceaba el archivo, y reglas de componentes que ya se
   reemplazaron: mkat-chain, mkat-ledger, mkat-fan, mkat-ow, ins-units__row.
   Limpiado el 2026-08-12; queda solo lo que existe. */
@media (max-width: 520px) {
  .ins-criteria__row { grid-template-columns: 1.35rem minmax(0, 1fr); }
  .ins-criteria__note { grid-column: 2; }
  .ins-criteria--grid { grid-template-columns: 1fr; }
  .ins-lanes__lane { grid-template-columns: 4.5rem minmax(0, 1fr); }
  .ins-state { grid-template-columns: 1fr; }
  .ins-state__arrow { text-align: center; }
}

/* ==========================================================================
   VERSIONES DE DOCTRINA de los cuatro componentes en conflicto.
   Toman el lenguaje visual de v7 (escala, peso, columna de detalle, la cifra
   como protagonista) y sacan la forma que component-catalog.md prohibe.
   Se muestran al lado de la version -v7 en el lab hasta que Carlos elija.
   Cuando elija, la que pierda se borra de este archivo.
   ========================================================================== */

/* 15 FUNNEL - doctrina. Barras RECTANGULARES decrecientes alineadas a la
   izquierda. El trapecio de v7 distorsiona: el ancho variable hace que el ojo
   compare areas y no longitudes, y la caida se lee mas grande de lo que es.
   La tasa de conversion vive en el aire ENTRE etapas, que es donde ocurre. */




/* La escala es el ANCHO, y arranca todo desde el mismo cero a la izquierda. */


/* La caida: el aire entre dos barras, con su tasa. En vino porque es lo que
   se PERDIO, y el registro no puede decir adonde se fue. */


/* 08 FAN - doctrina. El abanico se lee por LONGITUD, no por angulo. La torta
   de v7 obliga a comparar sectores, que es justo lo que el catalogo prohibe, y
   ademas insinua que las cinco lecturas son porciones medidas de un total: no
   lo son, son cinco cosas distintas que el mismo valor podria significar. */
/* Las cinco lecturas cuelgan de un corchete abierto: el documento mide la
   distancia entre el dato y su significado, y no puede cerrarla. */
/* 27 LAYERS - doctrina. Bandas de ANCHO CONSTANTE. La piramide de v7 sugiere
   que las capas de arriba son menores, y casi nunca es el argumento: una capa
   superior no es mas chica, descansa sobre la de abajo. La dependencia se
   marca con el filete lateral que las encadena, no con el ancho. */


/* La intensidad baja hacia el cimiento: la capa de arriba es la que se ve, la
   de abajo la que sostiene. Es profundidad, no tamanio. */





/* Aca vivia un bloque huerfano del port: un comentario de la vieja version de
   STEPS y una media query SIN CERRAR con reglas de .mkat-fan, .ins-seq__step y
   .ins-funnel__stage, todas de componentes ya reemplazados. La llave abierta
   se comia el bloque siguiente. Borrado el 2026-08-12. */

/* ==========================================================================
   01 TIMELINE - DOS FORMAS DISTINTAS
   Referencias de Carlos (2026-08-11). Dos, no cuatro: variantes que se
   parecen entre si no son opciones, son la misma decision disfrazada.

   1. EJE          horizontal, nodos alternados sobre una regla graduada.
   2. REGISTRO     vertical, fecha en mono, marca, texto. Otro genero.

   Comun a las dos:
   - Un solo azul. Cinco tonos prometen cinco categorias, y los hitos de una
     linea de tiempo no son categorias: son lo mismo en momentos distintos.
   - Vino solo con data-state="loss", en el hito que el registro no certifica.
   - Plano: ni sombra ni degradado. El halo de la referencia es un anillo del
     color del papel, que despega el nodo del eje sin fingir relieve.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1 · EJE  ·  .ins-line--axis

   UNA SOLA GRILLA para toda la figura, con SIETE filas explicitas:

       1  texto de los hitos de abajo
       2  nodos de arriba          (alto fijo)
       3  vastago de arriba        (alto fijo)
       4  el eje                   (1px)
       5  vastago de abajo         (alto fijo)
       6  nodos de abajo           (alto fijo)
       7  texto de los hitos de arriba

   Dos decisiones que salieron de mirar el render, no de imaginarlo:

   a) El nodo NO toca el eje. Entre los dos hay un vastago, como en la
      referencia. Cuando el nodo se apoyaba directo sobre la linea, la marca
      del eje le quedaba pegada al borde de abajo y se leia como una mancha.

   b) Los hijos se colocan por fila y columna explicitas, sin contenedor por
      hito. Cuando cada hito armaba su propia grilla, las filas de uno no
      coincidian con las del vecino y el texto caia encima del nodo. Con una
      grilla unica eso es imposible por construccion.
   -------------------------------------------------------------------------- */
.ins-line--axis {
  --tl-node: 4.6rem;    /* diametro del nodo, y alto de las filas 2 y 6 */
  --tl-ring: 0.4rem;    /* anillo de papel                              */
  --tl-stem: 1.5rem;    /* separacion entre el nodo y el eje            */

  display: grid;
  grid-template-columns: repeat(var(--n, 4), minmax(0, 1fr));
  grid-template-rows:
    auto              /* 1 · texto de abajo    */
    var(--tl-node)    /* 2 · nodo de arriba    */
    var(--tl-stem)    /* 3 · vastago de arriba */
    1px               /* 4 · eje               */
    var(--tl-stem)    /* 5 · vastago de abajo  */
    var(--tl-node)    /* 6 · nodo de abajo     */
    auto;             /* 7 · texto de arriba   */
  width: 100%;
  padding-block: 0.25rem;
}

/* El eje es un ELEMENTO, no un ::before del contenedor: con grid-auto-flow un
   pseudo se convierte en una columna mas y la linea sale como un segmento
   suelto a la izquierda. Ya paso una vez. */
.ins-line--axis .ins-line__axis {
  position: relative;
  grid-row: 4;
  grid-column: 1 / -1;
  width: 100%;
  height: 1px;
  background: var(--line);
}

/* La graduacion: marcas menores sobre el propio eje, tres por tramo, en el
   color de la hairline. Convierten la linea en una regla sin agregar un solo
   elemento al DOM. */
.ins-line--axis .ins-line__axis::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: 0.3rem;
  margin-top: -0.15rem;
  background-image: radial-gradient(circle at center, var(--line) 0.14rem, transparent 0.15rem);
  background-size: calc(100% / (var(--n, 4) * 3)) 100%;
}

.ins-line--axis .ins-line__node {
  grid-column: var(--i);
  justify-self: center;
  position: relative;
  width: var(--tl-node);
  height: var(--tl-node);
  display: grid;
  place-items: center;
  border: var(--tl-ring) solid var(--ins-paper);
  border-radius: 50%;
  background: var(--accent);
  color: var(--bg-raised);
}

.ins-line--axis .ins-line__node::after {
  content: '';
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: 50%;
  border-radius: 0 0 999px 999px;
  background: color-mix(in srgb, var(--accent) 62%, var(--bg-raised));
}

.ins-line--axis .ins-line__node[data-pos="up"]   { grid-row: 2; }
.ins-line--axis .ins-line__node[data-pos="down"] { grid-row: 6; }

.ins-line--axis .ins-line__n {
  position: relative;
  z-index: 1;
  font-family: var(--font-sans);
  font-size: 0.85rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

/* El vastago llena su fila entera, asi que su largo sale de la grilla y no de
   un numero inventado que despues no coincide con nada. */
.ins-line--axis .ins-line__stem {
  grid-column: var(--i);
  justify-self: center;
  align-self: stretch;
  width: 1px;
  background: var(--line);
}

.ins-line--axis .ins-line__stem[data-pos="up"]   { grid-row: 3; }
.ins-line--axis .ins-line__stem[data-pos="down"] { grid-row: 5; }

/* La marca mayor, centrada EN el eje. */
.ins-line--axis .ins-line__dot {
  grid-row: 4;
  grid-column: var(--i);
  justify-self: center;
  align-self: center;
  position: relative;
  z-index: 1;
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 50%;
  background: var(--accent);
}

.ins-line--axis .ins-line__read {
  grid-column: var(--i);
  display: grid;
  gap: 0.25rem;
  padding-inline: 0.55rem;
  text-align: center;
}

.ins-line--axis .ins-line__read[data-pos="up"]   { grid-row: 7; align-self: start; padding-top: 0.9rem; }
.ins-line--axis .ins-line__read[data-pos="down"] { grid-row: 1; align-self: end; padding-bottom: 0.9rem; }

.ins-line--axis .ins-line__when {
  position: static;
  font-family: var(--font-sans);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.ins-line--axis .ins-line__what {
  position: static;
  margin: 0;
  font-size: 0.72rem;
  line-height: 1.4;
  color: var(--text-primary);
  text-wrap: pretty;
}

/* El hito que el registro no puede certificar. */
.ins-line--axis [data-state="loss"].ins-line__node { background: var(--accent-alt); }

.ins-line--axis [data-state="loss"].ins-line__node::after {
  background: color-mix(in srgb, var(--accent-alt) 62%, var(--bg-raised));
}

.ins-line--axis [data-state="loss"].ins-line__dot  { background: var(--accent-alt); }
.ins-line--axis [data-state="loss"] .ins-line__when { color: var(--accent-alt); }

/* Abajo de 760px cuatro columnas dejan 100px por hito y el texto se parte en
   una palabra por renglon. El instrumento se para: una fila por hito, nodo a
   la izquierda, texto a la derecha. No se hace scrollable. */
@media (max-width: 760px) {
  .ins-line--axis {
    --tl-node: 3.2rem;
    grid-template-columns: var(--tl-node) minmax(0, 1fr);
    grid-template-rows: none;
    grid-auto-rows: auto;
    gap: 1rem;
  }

  .ins-line--axis .ins-line__axis,
  .ins-line--axis .ins-line__stem,
  .ins-line--axis .ins-line__dot { display: none; }

  .ins-line--axis .ins-line__node,
  .ins-line--axis .ins-line__node[data-pos="up"],
  .ins-line--axis .ins-line__node[data-pos="down"] {
    grid-row: var(--i);
    grid-column: 1;
  }

  .ins-line--axis .ins-line__read,
  .ins-line--axis .ins-line__read[data-pos="up"],
  .ins-line--axis .ins-line__read[data-pos="down"] {
    grid-row: var(--i);
    grid-column: 2;
    align-self: center;
    padding: 0;
    text-align: left;
  }
}

/* --------------------------------------------------------------------------
   2 · ESPINA  ·  .ins-line--spine
   Referencia de Carlos (venngage, 2026-08-11). Eje vertical central con riel,
   marcas sobre la linea, y los rotulos alternando lados en forma de flecha
   que apunta al eje. Reemplaza al "registro" anterior, que era una lista con
   una linea al costado y no una linea de tiempo.

   Lo que se adapto:
   - En la referencia los lados alternan COLOR (azul a la izquierda, rojo a la
     derecha). Aca alternan LADO, no color: el rojo de la referencia es
     decorativo y en este sistema el vino significa una cosa sola. Los rotulos
     son azules, y uno pasa a vino solo con data-state="loss".
   - Sin iconos: no hay set de marca.
   - El riel de la referencia tiene una banda gris con una linea negra adentro
     y topes arriba y abajo. Eso se conserva: la banda da el cuerpo, la linea
     el recorrido y los topes dicen que la serie empieza y termina, no que se
     corta.
   -------------------------------------------------------------------------- */
.ins-line--spine {
  --sp-rail: 2.6rem;    /* ancho de la banda del riel      */
  --sp-bar: 2.5rem;     /* alto del rotulo, fija el punto  */
  --sp-arrow: 1.1rem;   /* profundidad de la punta         */

  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--sp-rail) minmax(0, 1fr);
  /* FILAS EXPLICITAS, una por hito. Sin esto la grilla auto-coloca un hito de
     la izquierda y el siguiente de la derecha en la MISMA fila (no chocan, asi
     que caben), y ademas el riel con grid-row: 1 / -1 se encoge a la unica
     fila explicita que habia. Se veia como una capsula suelta arriba. */
  grid-template-rows: repeat(var(--rows, 1), auto);
  align-items: start;
  row-gap: 1.75rem;
  width: 100%;
  padding-block: 0.5rem;
}

/* El riel corre por la columna del medio y atraviesa todas las filas. Es un
   elemento, no un pseudo: en un grid un pseudo se vuelve otra celda. */
.ins-line--spine .ins-line__rail {
  position: relative;
  grid-column: 2;
  grid-row: 1 / -1;
  justify-self: center;
  width: 100%;
  height: 100%;
  background: color-mix(in srgb, var(--line) 45%, transparent);
  border-radius: 999px;
}

/* La linea del recorrido, adentro de la banda. */
.ins-line--spine .ins-line__rail::before {
  content: '';
  position: absolute;
  top: 0.9rem;
  bottom: 0.9rem;
  left: 50%;
  width: 2px;
  margin-left: -1px;
  background: var(--ink, var(--text-primary));
}

/* Los topes: la serie empieza y termina, no se corta. */
.ins-line--spine .ins-line__rail::after {
  content: '';
  position: absolute;
  top: 0.55rem;
  bottom: 0.55rem;
  left: 50%;
  width: 1.1rem;
  margin-left: -0.55rem;
  border-top: 3px solid var(--ink, var(--text-primary));
  border-bottom: 3px solid var(--ink, var(--text-primary));
}

.ins-line--spine .ins-line__entry {
  position: relative;
  display: grid;
  gap: 0.6rem;
}

.ins-line--spine .ins-line__entry { grid-row: var(--r); }

.ins-line--spine .ins-line__entry[data-side="left"]  { grid-column: 1; }
.ins-line--spine .ins-line__entry[data-side="right"] { grid-column: 3; }

/* El rotulo en flecha. La punta mira SIEMPRE al eje, que es lo que hace que
   el rotulo se lea como una marca sobre la linea y no como una tarjeta
   suelta al costado. */
.ins-line--spine .ins-line__bar {
  /* El core tiene `.ins-prose p { max-width: var(--ins-measure) }` = 704px, y
     esta barra es un <p>. Sin esto la barra se topaba en 704 aunque su
     columna midiera mas, y la punta no llegaba al eje: a 1280 parecia tocar y
     a 1711 quedaba a 73px. Todo componente de la libreria que use <p> como
     pieza estructural tiene que soltar ese tope. */
  max-width: none;
  min-height: var(--sp-bar);
  display: flex;
  align-items: center;
  padding: 0.5rem 1rem;
  background: var(--accent);
  color: var(--bg-raised);
  font-family: var(--font-sans);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* La punta LLEGA AL EJE. El rotulo se mete media banda dentro de la columna
   del riel, asi que la flecha termina sobre la linea y no en el borde de la
   banda. Sin esto quedaba un aire de 1.3rem entre la punta y la linea, y el
   rotulo se leia como una tarjeta al costado en vez de una marca sobre el
   recorrido. Vale para los dos lados: si solo tocara uno, la asimetria se
   leeria como que ese hito es distinto. */
.ins-line--spine [data-side="left"] .ins-line__bar {
  justify-content: flex-end;
  margin-right: calc(-1 * var(--sp-rail) / 2);
  padding-right: calc(var(--sp-arrow) + var(--sp-rail) / 2 + 0.4rem);
  clip-path: polygon(0 0, calc(100% - var(--sp-arrow)) 0, 100% 50%, calc(100% - var(--sp-arrow)) 100%, 0 100%);
}

.ins-line--spine [data-side="right"] .ins-line__bar {
  margin-left: calc(-1 * var(--sp-rail) / 2);
  padding-left: calc(var(--sp-arrow) + var(--sp-rail) / 2 + 0.4rem);
  clip-path: polygon(var(--sp-arrow) 0, 100% 0, 100% 100%, var(--sp-arrow) 100%, 0 50%);
}

.ins-line--spine [data-state="loss"] .ins-line__bar { background: var(--accent-alt); }

/* La marca sobre el eje, a la altura del centro del rotulo. El alto del
   rotulo es fijo justamente para que esta posicion no dependa del texto. */
.ins-line--spine .ins-line__dot {
  position: absolute;
  z-index: 2;   /* por encima de la punta del rotulo, que ahora llega al eje */
  top: calc(var(--sp-bar) / 2);
  width: 0.75rem;
  height: 0.75rem;
  margin-top: -0.375rem;
  border-radius: 50%;
  background: var(--accent);
}

.ins-line--spine [data-side="left"]  .ins-line__dot { right: calc(-1 * (var(--sp-rail) / 2) - 0.375rem); }
.ins-line--spine [data-side="right"] .ins-line__dot { left:  calc(-1 * (var(--sp-rail) / 2) - 0.375rem); }

.ins-line--spine [data-state="loss"] .ins-line__dot { background: var(--accent-alt); }

.ins-line--spine .ins-line__what {
  max-width: none;   /* mismo motivo que la barra */
  margin: 0;
  padding-inline: 0.2rem;
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--text-primary);
  text-wrap: pretty;
}

.ins-line--spine [data-side="left"] .ins-line__what { text-align: right; }

.ins-line--spine .ins-line__stamp {
  font-family: var(--font-sans);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.ins-line--spine [data-side="left"] .ins-line__stamp { text-align: right; }

.ins-line--spine [data-state="loss"] .ins-line__stamp { color: var(--accent-alt); }

/* Abajo de 640px la alternancia no cabe: dos columnas de 130px parten el
   texto en una palabra por renglon. El riel se corre al borde y todos los
   rotulos pasan al mismo lado, apuntando a el. */
@media (max-width: 640px) {
  .ins-line--spine {
    --sp-rail: 1.6rem;
    grid-template-columns: var(--sp-rail) minmax(0, 1fr);
    column-gap: 0.5rem;
  }

  .ins-line--spine .ins-line__rail { grid-column: 1; }

  .ins-line--spine .ins-line__entry,
  .ins-line--spine .ins-line__entry[data-side="left"],
  .ins-line--spine .ins-line__entry[data-side="right"] { grid-column: 2; grid-row: var(--r); }

  .ins-line--spine [data-side="left"] .ins-line__bar,
  .ins-line--spine [data-side="right"] .ins-line__bar {
    justify-content: flex-start;
    margin: 0 0 0 calc(-1 * var(--sp-rail) / 2 - 0.25rem);
    padding: 0.5rem 1rem 0.5rem calc(var(--sp-arrow) + var(--sp-rail) / 2 + 0.4rem);
    clip-path: polygon(var(--sp-arrow) 0, 100% 0, 100% 100%, var(--sp-arrow) 100%, 0 50%);
  }

  .ins-line--spine [data-side="left"] .ins-line__dot,
  .ins-line--spine [data-side="right"] .ins-line__dot {
    right: auto;
    left: calc(-1 * (var(--sp-rail) / 2) - 0.375rem - 0.25rem);
  }

  .ins-line--spine [data-side="left"] .ins-line__what,
  .ins-line--spine [data-side="left"] .ins-line__stamp { text-align: left; }
}


/* ==========================================================================
   03 STEPS - DOS FORMAS, COPIADAS DE LAS REFERENCIAS DE CARLOS (2026-08-11)

     A · ESCUADRAS  escalera ascendente de escuadras con triangulo en el
                    vertice. Copia de la referencia "process chart".
     B · GALONES    cinta horizontal de galones encastrados, circulo numerado
                    debajo de cada uno y texto abajo. Copia de la referencia
                    "5 steps infographics".

   Lo unico que se adapta es el color. Las referencias usan cinco tonos de un
   arcoiris; aca es UN azul que se aclara paso a paso, porque lo unico que esa
   graduacion tiene que decir es "esto avanza". El vino sigue reservado al
   paso que el registro no puede certificar (data-state="loss").

   Animacion: solo opacity y transform, disparada por .is-in que pone
   reveal.js en la figura, y siempre con el reposo VISIBLE. Sin JS no hay
   .is-in, no hay animacion, y los pasos se ven igual.
   ========================================================================== */

/* --------------------------------------------------------------------------
   A · ESCUADRAS  ·  .ins-seq--squares
   -------------------------------------------------------------------------- */
.ins-seq--squares {
  --sq-rise: 3.2rem;    /* cuanto sube cada peldanio         */
  --sq-stroke: 0.55rem; /* grosor de la escuadra             */
  --sq-tri: 0.85rem;    /* lado del triangulo del vertice    */

  display: grid;
  grid-template-columns: repeat(var(--n, 5), minmax(0, 1fr));
  align-items: start;
  width: 100%;
  padding-top: calc(var(--sq-tri) + 0.4rem);
}

.ins-seq--squares .ins-seq__step {
  --tint: calc(100% - (var(--i) - 1) * 8%);
  grid-column: var(--i);
  /* El primer paso es el mas bajo. Cada uno sube un peldanio. */
  margin-top: calc((var(--n, 5) - var(--i)) * var(--sq-rise));
  padding-right: 0.6rem;
}

/* La escuadra: barra de arriba y montante de la izquierda, un solo elemento
   con dos bordes. La barra sale hacia la derecha para encastrar con el
   montante del paso siguiente, igual que en la referencia. */
.ins-seq--squares .ins-seq__frame {
  position: relative;
  display: block;
  height: 2.6rem;
  border-top: var(--sq-stroke) solid color-mix(in srgb, var(--accent) var(--tint), var(--bg-raised));
  border-left: var(--sq-stroke) solid color-mix(in srgb, var(--accent) var(--tint), var(--bg-raised));
}

/* El triangulo del vertice: apoyado sobre el extremo IZQUIERDO de la barra,
   arriba del montante, como en la referencia. Va posicionado contra el borde
   exterior (de ahi los offsets negativos del grosor): si se lo cuelga del
   padding box queda tapado por el propio borde de la escuadra. */
.ins-seq--squares .ins-seq__frame::after {
  content: '';
  position: absolute;
  left: calc(-1 * var(--sq-stroke));
  bottom: calc(100% + var(--sq-stroke));
  width: 0;
  height: 0;
  border-left: var(--sq-tri) solid color-mix(in srgb, var(--accent) var(--tint), var(--bg-raised));
  border-top: var(--sq-tri) solid transparent;
}

.ins-seq--squares .ins-seq__step[data-state="loss"] {
  --tint: 100%;
}

.ins-seq--squares .ins-seq__step[data-state="loss"] .ins-seq__frame {
  border-top-color: var(--accent-alt);
  border-left-color: var(--accent-alt);
}

.ins-seq--squares .ins-seq__step[data-state="loss"] .ins-seq__frame::after {
  border-left-color: var(--accent-alt);
}

.ins-seq--squares .ins-seq__verb,
.ins-seq--squares .ins-seq__what { max-width: none; margin: 0; }

.ins-seq--squares .ins-seq__verb {
  padding: 0.7rem 0 0.25rem 0.9rem;
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--ink, var(--text-primary));
}

.ins-seq--squares .ins-seq__what {
  padding-left: 0.9rem;
  font-size: 0.76rem;
  line-height: 1.45;
  text-wrap: pretty;
}

/* --------------------------------------------------------------------------
   B · GALONES  ·  .ins-seq--chevron
   -------------------------------------------------------------------------- */
.ins-seq--chevron {
  --cv-point: 1.35rem;   /* profundidad de la punta */
  --cv-h: 3rem;          /* alto de la cinta        */

  display: grid;
  grid-template-columns: repeat(var(--n, 5), minmax(0, 1fr));
  grid-template-rows: var(--cv-h) auto auto;
  width: 100%;
}

.ins-seq--chevron .ins-seq__step { display: contents; }

/* El galon. El primero arranca recto; el resto lleva la muesca izquierda que
   encastra con la punta del anterior. */
.ins-seq--chevron .ins-seq__flag {
  --tint: calc(100% - (var(--i) - 1) * 7%);
  grid-row: 1;
  grid-column: var(--i);
  display: flex;
  align-items: center;
  justify-content: center;
  padding-inline: calc(var(--cv-point) + 0.3rem) calc(var(--cv-point) + 0.3rem);
  background: color-mix(in srgb, var(--accent) var(--tint), var(--bg-raised));
  color: var(--bg-raised);
  font-size: 0.86rem;
  font-weight: 700;
  text-align: center;
  clip-path: polygon(0 0, calc(100% - var(--cv-point)) 0, 100% 50%,
                     calc(100% - var(--cv-point)) 100%, 0 100%, var(--cv-point) 50%);
}

.ins-seq--chevron .ins-seq__step + .ins-seq__step .ins-seq__flag {
  margin-left: calc(-1 * var(--cv-point));
}

.ins-seq--chevron .ins-seq__step:first-child .ins-seq__flag {
  clip-path: polygon(0 0, calc(100% - var(--cv-point)) 0, 100% 50%,
                     calc(100% - var(--cv-point)) 100%, 0 100%);
}

.ins-seq--chevron .ins-seq__step[data-state="loss"] .ins-seq__flag {
  background: var(--accent-alt);
}

/* El circulo numerado, debajo de su galon. */
.ins-seq--chevron .ins-seq__n {
  grid-row: 2;
  grid-column: var(--i);
  justify-self: center;
  width: 2.4rem;
  height: 2.4rem;
  margin-block: 1rem 0.7rem;
  display: grid;
  place-items: center;
  border: 2px solid var(--accent);
  border-radius: 50%;
  font-family: var(--font-sans);
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.ins-seq--chevron .ins-seq__step[data-state="loss"] .ins-seq__n {
  border-color: var(--accent-alt);
  color: var(--accent-alt);
}

.ins-seq--chevron .ins-seq__what {
  grid-row: 3;
  grid-column: var(--i);
  max-width: none;
  margin: 0;
  padding-inline: 0.7rem;
  font-size: 0.78rem;
  line-height: 1.45;
  text-align: center;
  text-wrap: pretty;
}

/* --------------------------------------------------------------------------
   MOVIMIENTO. Reposo visible, .is-in lo dispara, y nada que mueva layout.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-seq-rise {
    from { opacity: 0; transform: translateY(0.75rem); }
    to   { opacity: 1; transform: none; }
  }

  @keyframes ins-seq-slide {
    from { opacity: 0; transform: translateX(-0.9rem); }
    to   { opacity: 1; transform: none; }
  }

  .ins-fig.is-in .ins-seq--squares .ins-seq__step {
    animation: ins-seq-rise var(--dur-slow) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.12s);
  }

  .ins-fig.is-in .ins-seq--chevron .ins-seq__flag,
  .ins-fig.is-in .ins-seq--chevron .ins-seq__n,
  .ins-fig.is-in .ins-seq--chevron .ins-seq__what {
    animation: ins-seq-slide var(--dur-slow) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.1s);
  }
}

/* --------------------------------------------------------------------------
   MOVIL. Ninguna de las dos genera scroll horizontal: se paran.
   -------------------------------------------------------------------------- */
@media (max-width: 760px) {
  .ins-seq--squares {
    grid-template-columns: 1fr;
    gap: 0.4rem;
  }

  .ins-seq--squares .ins-seq__step {
    grid-column: 1;
    margin-top: 0;
    margin-left: calc((var(--i) - 1) * 1.1rem);
  }

  /* La barra horizontal no tiene sentido apilado, pero el montante SI: es lo
     que queda de la escuadra y lo que sigue diciendo de que paso es cada
     texto. Antes se ocultaban los dos y el instrumento se quedaba en una
     lista indentada sin una sola marca de color. */
  .ins-seq--squares .ins-seq__frame { display: none; }

  .ins-seq--squares .ins-seq__step {
    padding-left: 0.9rem;
    border-left: var(--sq-stroke) solid color-mix(in srgb, var(--accent) var(--tint), var(--bg-raised));
  }

  .ins-seq--squares .ins-seq__step[data-state="loss"] { border-left-color: var(--accent-alt); }

  .ins-seq--squares .ins-seq__verb { padding: 0.1rem 0 0.2rem; }

  .ins-seq--squares .ins-seq__what { padding-left: 0; }

  .ins-seq--chevron {
    grid-template-columns: 1fr;
    grid-template-rows: none;
    grid-auto-rows: auto;
  }

  .ins-seq--chevron .ins-seq__flag,
  .ins-seq--chevron .ins-seq__n,
  .ins-seq--chevron .ins-seq__what { grid-column: 1; }

  .ins-seq--chevron .ins-seq__flag {
    grid-row: calc(var(--i) * 3 - 2);
    justify-content: flex-start;
    padding-inline: 1rem;
    clip-path: polygon(0 0, calc(100% - var(--cv-point)) 0, 100% 50%,
                       calc(100% - var(--cv-point)) 100%, 0 100%);
  }

  .ins-seq--chevron .ins-seq__n {
    grid-row: calc(var(--i) * 3 - 1);
    justify-self: start;
    margin-block: 0.7rem 0.4rem;
  }

  .ins-seq--chevron .ins-seq__what {
    grid-row: calc(var(--i) * 3);
    padding: 0 0 1.1rem;
    text-align: left;
  }
}

/* ==========================================================================
   02 CHAIN - DOS FORMAS  ·  .ins-chain
   Secuencia donde algo se transmite entre estaciones y en algun punto se
   pierde. Renombrado de mkat-chain a ins-chain: el catalogo manda que un
   componente que sale de su pieza de origen pierde el namespace de la pieza.
   El CSS viejo sigue vivo en insights-fig-marketing-attribution y esa pieza
   no se toca; esto es la version de libreria.

   UNA sola forma: ESLABONES. La variante de estaciones se descarto el
   2026-08-11; su CSS sigue vivo solo dentro de la pieza publicada
   marketing-attribution, que no se toca.

   Comun: azul = todavia lleva el dato. Vino = el eslabon donde se pierde, y
   desde ahi el gris del que ya no puede probar nada. Tres estados, no dos, y
   ninguno depende solo del color: cada estacion lleva su .ins-sr en palabras.
   ========================================================================== */

/* La marca: llena mientras el dato viaja, hueca cuando ya no esta. La forma
   cambia junto con el color, asi que en monocromo se sigue leyendo. */
/* El conector. Vivo mientras el dato viaja; punteado a partir del eslabon
   roto, que es lo que el registro ya no puede certificar. */
/* --------------------------------------------------------------------------
   B · ESLABONES  ·  .ins-chain--links
   -------------------------------------------------------------------------- */
.ins-chain--links {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  width: 100%;
  margin: 0;
  padding: 1rem 0.5rem;
}

.ins-chain__link {
  position: relative;
  z-index: 1;
  width: 10rem;
  min-width: 0;
  min-height: 7.6rem;
  display: grid;
  place-content: center;
  gap: 0.12rem;
  margin-left: -1.5rem;
  padding: 1.1rem 1.6rem;
  border: 0.65rem solid var(--line);
  border-radius: 999px;
  background: var(--ins-paper);
  text-align: center;
}

.ins-chain__link:first-child { margin-left: 0; }

.ins-chain__link:nth-child(odd) { z-index: 2; }

/* Los que todavia llevan el dato, en azul. Los de despues quedan en la
   hairline: no es que sean menos importantes, es que ya no prueban nada. */
.ins-chain__link[data-carries] { border-color: var(--accent); }

.ins-chain__link[data-state="loss"] { border-color: var(--accent-alt); }

/* El desfase alternado de la referencia v7, que es lo que hace que se lean
   como eslabones encastrados y no como una fila de circulos. */
.ins-chain__link:nth-child(even) { transform: translateY(0.6rem); }

.ins-chain__n {
  font-family: var(--font-sans);
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.ins-chain__link:not([data-carries]) .ins-chain__n { color: var(--text-muted); }
.ins-chain__link[data-state="loss"] .ins-chain__n { color: var(--accent-alt); }

.ins-chain__link b {
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--ink, var(--text-primary));
}

.ins-chain__link small {
  font-size: 0.6rem;
  line-height: 1.25;
  color: var(--text-muted);
}

/* --------------------------------------------------------------------------
   MOVIMIENTO. El dato recorre la cadena: las estaciones entran en orden y el
   conector se estira. Reposo visible.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-chain-in {
    from { opacity: 0; transform: translateY(0.5rem); }
    to   { opacity: 1; transform: none; }
  }

  @keyframes ins-chain-draw {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
  }



  .ins-fig.is-in .ins-chain--links .ins-chain__link {
    animation: ins-chain-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.12s);
  }

  /* El desfase par es parte de la forma, no del movimiento: si la animacion
     lo pisara, los eslabones pares terminarian alineados y la cadena se
     desarmaria al final. */
  .ins-fig.is-in .ins-chain--links .ins-chain__link:nth-child(even) {
    animation-name: ins-chain-in-even;
  }

  @keyframes ins-chain-in-even {
    from { opacity: 0; transform: translateY(1.1rem); }
    to   { opacity: 1; transform: translateY(0.6rem); }
  }
}

/* --------------------------------------------------------------------------
   MOVIL
   -------------------------------------------------------------------------- */
@media (max-width: 700px) {




  .ins-chain--links { flex-direction: column; }

  .ins-chain__link,
  .ins-chain__link:nth-child(even) {
    width: 100%;
    max-width: 15rem;
    height: auto;
    margin: -0.9rem 0 0;
    padding: 0.9rem 1.2rem;
    transform: none;
  }

  .ins-chain__link:first-child { margin-top: 0; }
}

/* ==========================================================================
   04 FIELDS  ·  .ins-box
   Pares clave/valor SIN orden que definen un objeto. Tres a seis.
   Que no tengan orden es la diferencia con STEPS, y por eso no llevan
   numeral: numerarlos afirmaria una secuencia que el objeto no tiene.

     A · CAJA   la forma del catalogo: una caja partida en celdas, cada campo
                en la suya. El objeto ES la caja; los campos son sus partes.

   La clave va en azul: es lo que el registro SI define. Un campo que el
   registro deja abierto lleva data-state="loss" y pasa a vino.
   ========================================================================== */
.ins-box {
  display: grid;
  grid-template-columns: repeat(var(--cols, 2), minmax(0, 1fr));
  width: 100%;
  /* Un solo filete por borde compartido: la caja se dibuja con el borde de
     arriba y el de la izquierda del contenedor, y cada celda aporta el suyo
     de la derecha y el de abajo. Asi no hay lineas dobles entre celdas. */
  border-top: 1px solid var(--line);
  border-left: 1px solid var(--line);
}

.ins-box__field {
  min-height: 6rem;
  display: grid;
  align-content: start;
  gap: 0.6rem;
  padding: 1.1rem 1.2rem;
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.ins-box__k {
  font-family: var(--font-sans);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
}

.ins-box__v {
  max-width: none;
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.5;
  color: var(--text-primary);
  text-wrap: pretty;
}

/* El campo que el registro deja abierto. La clave cambia de color Y el campo
   gana un borde izquierdo: en monocromo se sigue distinguiendo. */
.ins-box__field[data-state="loss"] {
  border-left: 3px solid var(--accent-alt);
  margin-left: -1px;
}

.ins-box__field[data-state="loss"] .ins-box__k { color: var(--accent-alt); }

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-box-in {
    from { opacity: 0; transform: translateY(0.4rem); }
    to   { opacity: 1; transform: none; }
  }

  /* La caja se completa campo por campo: el articulo dice que esta terminada
     cuando lleva los cuatro, y el movimiento cuenta hasta cuatro. */
  .ins-fig.is-in .ins-box__field {
    animation: ins-box-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.1s);
  }
}

/* Cuatro campos en columna siguen siendo una caja; dos columnas de 150px no. */
@media (max-width: 640px) {
  .ins-box__field { min-height: 0; }
}

/* --------------------------------------------------------------------------
   B · TABLA  ·  .ins-box--table
   Copia de la referencia de Carlos (2026-08-11), con dos cambios que el
   pidio o que el sistema impone:

   - SIN ICONOS. Los circulos con icono de arriba se reemplazan por celdas de
     encabezado, que era el pedido. Los de la izquierda tambien salen: no hay
     set de iconos de marca, y media forma con icono y media sin se lee como
     un error.
   - La referencia alterna rojo y azul fila por fila. Eso es decoracion: la
     fila 2 no es de otra naturaleza que la 1. Todas las claves van en azul y
     el vino queda para la fila que el registro no puede certificar.

   La marca de estado de la derecha distingue por FORMA ademas de por color:
   check cuando el registro lo prueba, guion cuando no.
   -------------------------------------------------------------------------- */
.ins-box--table {
  display: grid;
  grid-template-columns:
    minmax(7rem, 0.85fr)          /* la clave, como barra llena */
    auto                          /* el galon de direccion      */
    repeat(var(--vals, 2), minmax(0, 1fr))
    auto;                         /* la marca de estado         */
  align-items: stretch;
  gap: 0.55rem 0;
  width: 100%;
  border: 0;
}

/* Encabezados: celdas, no rotulos colgados. La ultima va llena, como en la
   referencia, porque es la columna que cierra la lectura. */
/* Los encabezados van en SANS, no en mono. Geist Mono solo carga 400 y 500,
   asi que pedirle bold da faux-bold, que este proyecto prohibe. Geist sans si
   tiene 600 real. De paso pierden la caja alta y el tracking de la banda de
   chrome: son encabezados de tabla, no telemetria. */
.ins-box__h {
  padding: 0.65rem 0.9rem 0.75rem;
  border-bottom: 1px solid var(--line);
  font-family: var(--font-sans);
  font-size: 0.86rem;
  font-weight: 700;
  letter-spacing: -0.005em;
  color: var(--ink, var(--text-primary));
}

.ins-box__h--fill {
  border-bottom: 0;
  background: var(--accent);
  color: var(--bg-raised);
  text-align: center;
}

/* La clave, barra llena. */
.ins-box--table .ins-box__k {
  display: flex;
  align-items: center;
  padding: 0.9rem 1rem;
  background: var(--accent);
  color: var(--bg-raised);
  font-family: var(--font-sans);
  font-size: 0.86rem;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
}

.ins-box--table [data-state="loss"] .ins-box__k { background: var(--accent-alt); }

/* El galon de direccion de la referencia, en tres puntas. Es geometria, no
   un icono: se dibuja con bordes. */
.ins-box__chev {
  display: flex;
  align-items: center;
  gap: 0.18rem;
  padding-inline: 0.9rem;
  background: color-mix(in srgb, var(--accent) 8%, var(--bg-raised));
}

.ins-box--table [data-state="loss"] .ins-box__chev {
  background: color-mix(in srgb, var(--accent-alt) 8%, var(--bg-raised));
}

.ins-box__chev i {
  width: 0.34rem;
  height: 0.34rem;
  border-top: 1.5px solid color-mix(in srgb, var(--accent) 60%, transparent);
  border-right: 1.5px solid color-mix(in srgb, var(--accent) 60%, transparent);
  transform: rotate(45deg);
}

.ins-box--table [data-state="loss"] .ins-box__chev i {
  border-color: color-mix(in srgb, var(--accent-alt) 60%, transparent);
}

/* Las celdas de valor son CELDAS: superficie propia con un tinte del color de
   su fila, no texto suelto sobre el papel. Con la hairline sola se leian como
   renglones de un parrafo largo; con el tinte, la fila se lee como fila.
   El tinte sale del mismo acento de la fila, asi que la de vino se tinta en
   vino y no hace falta una regla nueva por estado. */
.ins-box--table .ins-box__v {
  display: flex;
  align-items: center;
  padding: 0.9rem 1rem;
  background: color-mix(in srgb, var(--accent) 8%, var(--bg-raised));
  font-size: 0.8rem;
  line-height: 1.45;
}

.ins-box--table [data-state="loss"] .ins-box__v {
  background: color-mix(in srgb, var(--accent-alt) 8%, var(--bg-raised));
}

/* Una hairline vertical separa una celda de valor de la siguiente. Es la
   unica linea que queda adentro de la fila: el resto lo separa el color. */
.ins-box--table .ins-box__v + .ins-box__v {
  border-left: 1px solid color-mix(in srgb, var(--accent) 18%, transparent);
}

.ins-box--table [data-state="loss"] .ins-box__v + .ins-box__v {
  border-left-color: color-mix(in srgb, var(--accent-alt) 18%, transparent);
}

/* La marca de estado: circulo con check o con guion. La forma cambia, asi que
   en monocromo se sigue leyendo cual es cual. */
.ins-box__flag {
  display: grid;
  place-items: center;
  padding-inline: 1rem;
  background: color-mix(in srgb, var(--accent) 8%, var(--bg-raised));
}

.ins-box--table [data-state="loss"] .ins-box__flag {
  background: color-mix(in srgb, var(--accent-alt) 8%, var(--bg-raised));
}

.ins-box__flag span {
  position: relative;
  width: 1.35rem;
  height: 1.35rem;
  border-radius: 50%;
  background: var(--accent);
}

.ins-box__flag span::before {
  content: '';
  position: absolute;
  top: 0.34rem;
  left: 0.42rem;
  width: 0.32rem;
  height: 0.6rem;
  border-right: 2px solid var(--bg-raised);
  border-bottom: 2px solid var(--bg-raised);
  transform: rotate(45deg);
}

.ins-box--table [data-state="loss"] .ins-box__flag span { background: var(--accent-alt); }

/* Guion en vez de check: lo que el registro no puede certificar no se marca
   con una cruz (eso seria "esta mal"), se marca con un tramo abierto. */
.ins-box--table [data-state="loss"] .ins-box__flag span::before {
  top: 50%;
  left: 0.3rem;
  width: 0.75rem;
  height: 0;
  border-right: 0;
  border-bottom: 2px solid var(--bg-raised);
  transform: translateY(-1px);
}

/* Cada fila es un display: contents para que sus celdas caigan en la grilla
   madre y las columnas queden alineadas de punta a punta. */
.ins-box__row { display: contents; }

@media (prefers-reduced-motion: no-preference) {
  .ins-fig.is-in .ins-box--table .ins-box__k,
  .ins-fig.is-in .ins-box--table .ins-box__chev,
  .ins-fig.is-in .ins-box--table .ins-box__v,
  .ins-fig.is-in .ins-box--table .ins-box__flag {
    animation: ins-box-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.09s);
  }
}

@media (max-width: 760px) {
  .ins-box--table {
    grid-template-columns: 1fr auto;
    gap: 0;
  }

  /* Los encabezados de columna no sobreviven al apilado: cada celda pasa a
     llevar su propia etiqueta con data-label, igual que las tablas del core. */
  .ins-box--table .ins-box__h { display: none; }

  .ins-box--table .ins-box__k { grid-column: 1 / -1; margin-top: 0.9rem; }

  .ins-box__chev { display: none; }

  .ins-box--table .ins-box__v {
    grid-column: 1;
    display: grid;
    gap: 0.2rem;
    padding: 0.7rem 0 0.7rem 0.9rem;
  }

  .ins-box--table .ins-box__v::before {
    content: attr(data-label);
    font-family: var(--font-sans);
    font-size: 0.6rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--text-muted);
  }

  .ins-box__flag { grid-column: 2; padding-inline: 0.6rem; }
}

/* ==========================================================================
   05 SPEC  ·  .ins-spec
   Items comparados que se descomponen en sub-elementos atomicos. Caso
   canonico: acronimos. Es el patron mas fuerte del catalogo para AEO porque
   cada letra y cada palabra son texto real en el DOM, extraible y citable.

   Forma copiada de la referencia de Carlos (2026-08-11): barra de nombre a
   todo el ancho con la cuenta de criterios alineada a la derecha adentro de
   la misma barra, y debajo la tira de celdas, una por letra. Una hairline
   cierra cada grupo.

   El alternado claro/oscuro de las celdas es RITMO, no significado: separa
   una celda de la siguiente sin gastar un filete por celda. Lo que si
   significa es el vino, reservado a la celda que un framework agrega y los
   otros no pueden ver.
   ========================================================================== */
.ins-spec { display: grid; gap: 1.4rem; width: 100%; }

.ins-spec__row { display: grid; gap: 0.55rem; }

.ins-spec__row + .ins-spec__row { border-top: 1px solid var(--line); padding-top: 1.4rem; }

/* La barra: nombre a la izquierda, cuenta a la derecha, misma linea. */
.ins-spec__id {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.75rem 1.1rem;
  background: var(--accent);
  color: var(--bg-raised);
}

.ins-spec__name {
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1.15;
}

.ins-spec__n {
  font-size: 0.82rem;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
}

/* Por defecto la tira pone una columna por criterio (`--cells`). Cuando son
   muchos no entran: ocho criterios dentro de la placa de 44rem dan 78px por
   celda y "Competition" se parte al medio.

   La solucion NO puede ser una media query, porque lo que limita es el ancho
   de la PLACA, que no cambia con el viewport arriba de 1025px. Entonces el
   autor lo declara: `--cols` parte la tira en la cantidad de columnas que
   quiera, y ocho criterios se leen como dos renglones de cuatro. */
.ins-spec__strip {
  display: grid;
  grid-template-columns: repeat(var(--cols, var(--cells, 4)), minmax(0, 1fr));
  gap: 0.6rem;
}

/* En pantalla angosta manda el piso, no la cuenta declarada. */
@media (max-width: 700px) {
  .ins-spec__strip { grid-template-columns: repeat(auto-fit, minmax(6.5rem, 1fr)); }
}

.ins-spec__cell {
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 0.35rem;
  min-height: 4.6rem;
  padding: 0.7rem 0.35rem;
  border: 1px solid var(--line);
  background: var(--bg-base);
  text-align: center;
}

/* El alternado de la referencia. Ritmo, no categoria. */
.ins-spec__cell:nth-child(even) { background: var(--line); }

.ins-spec__cell b {
  font-size: 1.3rem;
  font-weight: 700;
  line-height: 1;
  color: var(--accent);
}

.ins-spec__cell i {
  font-style: normal;
  font-size: 0.72rem;
  line-height: 1.25;
  color: var(--text-primary);
  /* "Competition" no tiene donde partirse y en una tira de ocho no entra en
     un renglon. `anywhere` es lo unico que reduce el minimo intrinseco que el
     grid usa para dimensionar la columna; `break-word` no alcanza. */
  min-width: 0;
  overflow-wrap: anywhere;
}

/* Lo que este framework agrega y los otros no ven. Pisa al alternado, porque
   el ritmo no puede tapar lo unico que ahi significa algo. */
.ins-spec__cell--new,
.ins-spec__cell--new:nth-child(even) {
  border-color: var(--accent-alt);
  background: color-mix(in srgb, var(--accent-alt) 10%, var(--bg-raised));
  box-shadow: inset 0 -3px 0 var(--accent-alt);
}

.ins-spec__cell--new b { color: var(--accent-alt); }

/* Linea opcional de "cuando aplica". No va en la referencia; queda
   disponible para las piezas que la necesiten. */
.ins-spec__fit {
  max-width: none;
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--text-muted);
  text-wrap: pretty;
}

.ins-spec__legend {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  font-size: 0.74rem;
  color: var(--text-muted);
}

.ins-spec__swatch {
  width: 1.4rem;
  height: 1.4rem;
  flex: none;
  border: 1px solid var(--accent-alt);
  background: color-mix(in srgb, var(--accent-alt) 10%, var(--bg-raised));
  box-shadow: inset 0 -3px 0 var(--accent-alt);
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-spec-in {
    from { opacity: 0; transform: translateY(0.4rem); }
    to   { opacity: 1; transform: none; }
  }

  .ins-fig.is-in .ins-spec__row {
    animation: ins-spec-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.11s);
  }
}

@media (max-width: 760px) {
  /* Ocho celdas no entran en una fila de 340px. La tira se parte en renglones
     de cuatro; el acronimo se sigue leyendo en orden y no aparece scroll. */
  .ins-spec__strip { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.4rem; }

  .ins-spec__cell { min-height: 3.8rem; padding-inline: 0.2rem; }

  .ins-spec__cell b { font-size: 1.1rem; }

  .ins-spec__cell i { font-size: 0.64rem; }
}

@media (max-width: 420px) {
  .ins-spec__strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ==========================================================================
   06 LEDGER  ·  .ins-ledger
   Aritmetica visible sobre una cifra: la operacion importa tanto como el
   resultado. Renombrado de mkat-ledger e ins-filterfig, que eran el mismo
   instrumento con dos nombres y dos piezas de origen.

     A · REPARTO     un total y sus partes. La parte que el registro no puede
                     trazar se acota con el corchete de vino.
     B · SUSTRACCION una cifra declarada de la que se van restando los casos
                     sin evidencia. Termina en una incognita, no en un numero:
                     el resultado es del lector, no nuestro.

   El aria-label dice la operacion COMPLETA en palabras. Es lo que un motor de
   IA cita, y sin eso la figura es invisible para AEO.
   ========================================================================== */

/* --------------------------------------------------------------------------
   A · REPARTO  ·  .ins-ledger--split
   -------------------------------------------------------------------------- */
/* 2.4rem de aire porque el corchete cuelga de la barra y necesita respirar
   antes de las celdas: con 1.6rem tocaba el borde de la primera y se leia
   como parte de ella. */
.ins-ledger--split { display: grid; gap: 2.4rem; width: 100%; }

.ins-ledger__bar {
  position: relative;
  height: 2.8rem;
  background: color-mix(in srgb, var(--accent) 12%, var(--bg-raised));
}

/* La parte trazable, llena. El resto queda como fondo: lo que no se puede
   probar no se dibuja lleno, se deja abierto. */
.ins-ledger__fill {
  display: block;
  width: var(--w, 50%);
  height: 100%;
  background: var(--accent);
}

/* El corchete acota el tramo sin trazar y NO CIERRA: es una medicion que
   nadie termino. Es la marca de vino de la figura. */
.ins-ledger__brk {
  position: absolute;
  right: 0;
  bottom: -1.15rem;
  width: calc(100% - var(--w, 50%));
  height: 0.8rem;
  border: 1.5px solid var(--accent-alt);
  border-top: 0;
}

.ins-ledger__rows {
  display: grid;
  grid-template-columns: repeat(var(--parts, 3), minmax(0, 1fr));
  gap: 0.6rem;
}

.ins-ledger__row {
  display: grid;
  gap: 0.3rem;
  padding: 0.9rem 1rem;
  background: color-mix(in srgb, var(--accent) 8%, var(--bg-raised));
}

.ins-ledger__row--void {
  background: color-mix(in srgb, var(--accent-alt) 10%, var(--bg-raised));
  box-shadow: inset 0 -3px 0 var(--accent-alt);
}

.ins-ledger__v {
  font-size: 1.35rem;
  font-weight: 700;
  line-height: 1.05;
  color: var(--ink, var(--text-primary));
  font-variant-numeric: tabular-nums;
}

.ins-ledger__row--void .ins-ledger__v { color: var(--accent-alt); }

.ins-ledger__k {
  font-size: 0.7rem;
  line-height: 1.3;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
}

/* --------------------------------------------------------------------------
   B · SUSTRACCION  ·  .ins-ledger--filter
   -------------------------------------------------------------------------- */
.ins-ledger--filter { display: grid; width: 100%; }

.ins-ledger__head,
.ins-ledger__foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.9rem 1.1rem;
}

.ins-ledger__head { background: var(--accent); color: var(--bg-raised); }

.ins-ledger__head .ins-ledger__k { color: color-mix(in srgb, var(--bg-raised) 80%, var(--accent)); }

.ins-ledger__head .ins-ledger__v,
.ins-ledger__foot .ins-ledger__v { font-size: 1.5rem; }

.ins-ledger__head .ins-ledger__v { color: var(--bg-raised); }

.ins-ledger__steps { display: grid; }

.ins-ledger__step {
  display: grid;
  grid-template-columns: 1.6rem minmax(0, 1fr);
  align-items: baseline;
  gap: 0.7rem;
  max-width: none;
  margin: 0;
  /* Sin hairline por fila (playbook §1.4): un instrumento lleva DOS filetes,
     el que abre y el que cierra. Aca abre la banda llena del encabezado y
     cierra el filete de vino del remate; las restas se separan por aire. */
  padding: 0.95rem 1.1rem;
  font-size: 0.84rem;
  line-height: 1.45;
}

.ins-ledger__minus {
  font-size: 1rem;
  font-weight: 700;
  color: var(--accent-alt);
  text-align: center;
}

/* El remate. La incognita va en vino porque es exactamente lo que el registro
   no puede certificar: pintarla de azul seria decir que es la respuesta. */
.ins-ledger__foot {
  border-bottom: 3px solid var(--accent-alt);
  background: color-mix(in srgb, var(--accent-alt) 8%, var(--bg-raised));
}

.ins-ledger__foot .ins-ledger__v { color: var(--accent-alt); }

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-ledger-fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }

  @keyframes ins-ledger-in {
    from { opacity: 0; transform: translateY(0.4rem); }
    to   { opacity: 1; transform: none; }
  }

  .ins-fig.is-in .ins-ledger__fill {
    transform-origin: 0 50%;
    animation: ins-ledger-fill var(--dur-slow) var(--ease-out) both;
  }

  .ins-fig.is-in .ins-ledger__brk {
    animation: ins-ledger-in var(--dur-base) var(--ease-out) 0.45s both;
  }

  .ins-fig.is-in .ins-ledger__row,
  .ins-fig.is-in .ins-ledger__step {
    animation: ins-ledger-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.1s + 0.2s);
  }
}

@media (max-width: 640px) {
  .ins-ledger__rows { grid-template-columns: 1fr; }

  .ins-ledger__head,
  .ins-ledger__foot { flex-direction: column; align-items: flex-start; gap: 0.2rem; }
}

/* ==========================================================================
   07 MATRIX  ·  .ins-matrix
   Grid de casos contra criterios, donde el PATRON de marcas es el argumento:
   una fila se comporta distinto de otra a lo largo de varias columnas.
   Renombrado de mkat-two.

   La marca dice una cosa sola: si en esa columna el caso se escribio o no.
   Escrito = cuadro lleno azul. No escrito = cuadro hueco en hairline.

   OJO CON EL VINO: que una fila no se escriba NO es una perdida por si mismo.
   En la pieza de attribution, que First Origin no se reescriba es el
   comportamiento correcto. El vino entra solo con data-state="loss" en la
   celda donde el registro efectivamente pierde algo.
   ========================================================================== */
.ins-matrix {
  display: grid;
  grid-template-columns: minmax(7rem, 0.7fr) repeat(var(--cols, 3), minmax(0, 1fr));
  gap: 0.45rem;
  width: 100%;
}

/* Encabezado de columna: el numero de la interaccion. Sans en bold, como los
   encabezados de FIELDS. */
.ins-matrix__h {
  padding: 0.5rem 0.4rem 0.7rem;
  border-bottom: 1px solid var(--line);
  font-size: 0.86rem;
  font-weight: 700;
  text-align: center;
  color: var(--ink, var(--text-primary));
  font-variant-numeric: tabular-nums;
}

.ins-matrix__h--corner { border-bottom-color: transparent; }

/* La clave de fila, barra llena. */
.ins-matrix__k {
  display: flex;
  align-items: center;
  padding: 0.85rem 1rem;
  background: var(--accent);
  color: var(--bg-raised);
  font-size: 0.86rem;
  font-weight: 700;
}

.ins-matrix__row { display: contents; }

.ins-matrix__cell {
  display: grid;
  place-items: center;
  min-height: 3.2rem;
  background: color-mix(in srgb, var(--accent) 8%, var(--ins-paper, var(--bg-raised)));
}

/* Escrito. Cuadro lleno. */
.ins-matrix__mark {
  width: 1.05rem;
  height: 1.05rem;
  background: var(--accent);
}

/* No escrito. Mismo cuadro, hueco: la diferencia es de RELLENO, no de color,
   asi que sobrevive al monocromo. */
.ins-matrix__cell[data-writes="no"] { background: var(--ins-paper, var(--bg-raised)); }

.ins-matrix__cell[data-writes="no"] .ins-matrix__mark {
  background: none;
  border: 1.5px solid var(--line);
}

/* Celda que lleva una CIFRA. La tipografia es la misma para el positivo y
   para el negativo: mismo cuerpo, mismo peso, mismas cifras tabulares. Lo
   unico que cambia entre uno y otro es el color, y el signo escrito. Si el
   positivo se compusiera distinto, la comparacion entre celdas dejaria de ser
   una comparacion de numeros y pasaria a ser una de estilos. */
.ins-matrix__cell[data-val] {
  color: var(--ink, var(--text-primary));
  font-size: 0.9rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* VALOR NEGATIVO (regla 2026-08-12): toda caida, resta o saldo en contra va
   en vino, y el signo se escribe ademas del color. */
.ins-matrix__cell[data-neg] {
  background: color-mix(in srgb, var(--accent-alt) 10%, var(--ins-paper, var(--bg-raised)));
  box-shadow: inset 0 -3px 0 var(--accent-alt);
  color: var(--accent-alt);
}

/* La celda donde el registro pierde algo. */
.ins-matrix__cell[data-state="loss"] {
  background: color-mix(in srgb, var(--accent-alt) 10%, var(--ins-paper, var(--bg-raised)));
  box-shadow: inset 0 -3px 0 var(--accent-alt);
}

.ins-matrix__cell[data-state="loss"] .ins-matrix__mark {
  background: none;
  border: 1.5px solid var(--accent-alt);
}

.ins-matrix__legend {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  margin-top: 0.3rem;
  font-size: 0.74rem;
  color: var(--text-muted);
}

.ins-matrix__legend span { display: flex; align-items: center; gap: 0.45rem; }

.ins-matrix__legend i {
  width: 0.9rem;
  height: 0.9rem;
  flex: none;
  background: var(--accent);
}

.ins-matrix__legend span + span i { background: none; border: 1.5px solid var(--line); }

.ins-matrix__legend span + span + span i {
  border: 0;
  background: color-mix(in srgb, var(--accent-alt) 10%, var(--ins-paper, var(--bg-raised)));
  box-shadow: inset 0 -3px 0 var(--accent-alt);
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-matrix-in {
    from { opacity: 0; transform: scale(0.72); }
    to   { opacity: 1; transform: none; }
  }

  /* Entran las marcas, no las celdas: lo que la figura afirma es el patron. */
  .ins-fig.is-in .ins-matrix__mark {
    animation: ins-matrix-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.08s);
  }
}

@media (max-width: 640px) {
  /* La clave pasa a ocupar la fila entera y las celdas quedan debajo, cada
     una con el numero de su columna. Sin scroll horizontal. */
  .ins-matrix { grid-template-columns: repeat(var(--cols, 3), minmax(0, 1fr)); }

  /* Los encabezados salen enteros: cada celda ya lleva el numero de su
     columna, y tenerlos arriba ademas era decir dos veces lo mismo. */
  .ins-matrix__h { display: none; }

  .ins-matrix__k { grid-column: 1 / -1; margin-top: 0.6rem; }

  .ins-matrix__cell::after {
    content: attr(data-col);
    position: absolute;
    margin: -2.1rem 0 0 0;
    font-size: 0.6rem;
    color: var(--text-muted);
  }

  .ins-matrix__cell { position: relative; }
}

/* ==========================================================================
   08 FAN  ·  .ins-fan
   Un valor unico que se abre en multiples interpretaciones posibles. El
   argumento es que el dato es AMBIGUO. Renombrado de mkat-fan.

   Forma copiada de la referencia de Carlos: abanico de sectores iguales que
   se abren desde un nucleo, con el dato en el centro.

   LOS SECTORES SON SIEMPRE IGUALES. Es la unica regla dura de este
   componente. En el momento en que uno se hace mas grande que otro deja de
   ser un abanico y pasa a ser una torta: afirma proporciones medidas y un
   total que suma 100%, y aca no hay ni proporciones ni total. Son
   posibilidades, y ninguna es mas probable que otra hasta que alguien mire
   el registro. Por eso tampoco llevan cifra ni porcentaje.

   El nucleo lleva el aro de vino: el dato que no se puede certificar.
   ========================================================================== */
.ins-fan { display: grid; justify-items: center; width: 100%; }

.ins-fan__svg { width: 100%; max-width: 34rem; height: auto; }

/* Los sectores se tinan alternando para separarse entre si, no para
   ordenarse: es el mismo recurso que el alternado de SPEC. */
.ins-fan__sector { stroke: var(--ins-paper, var(--bg-raised)); stroke-width: 3; }

.ins-fan__sector[data-t="1"] { fill: var(--accent); }
.ins-fan__sector[data-t="2"] { fill: var(--line); }
.ins-fan__sector[data-t="3"] { fill: color-mix(in srgb, var(--line) 45%, var(--ins-paper, var(--bg-raised))); }

.ins-fan__hub {
  fill: var(--ins-paper, var(--bg-raised));
  stroke: var(--accent-alt);
  stroke-width: 4;
}

.ins-fan__label {
  fill: var(--text-primary);
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 700;
  text-anchor: middle;
}

.ins-fan__label[data-on="fill"] { fill: var(--bg-raised); }

.ins-fan__hubtext {
  fill: var(--accent);
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 700;
  text-anchor: middle;
}

/* La lista de lecturas, debajo del abanico: es el texto que un motor de IA
   extrae. El abanico dibuja, la lista dice. */
.ins-fan__read {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.4rem 0.6rem;
  margin: 1.2rem 0 0;
  max-width: none;
  font-size: 0.78rem;
  color: var(--text-muted);
  text-align: center;
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-fan-open {
    from { opacity: 0; transform: scale(0.86) rotate(-8deg); }
    to   { opacity: 1; transform: none; }
  }

  @keyframes ins-fan-hub {
    from { opacity: 0; transform: scale(0.7); }
    to   { opacity: 1; transform: none; }
  }

  /* El abanico se abre desde el nucleo. transform-box: fill-box no sirve aca:
     cada sector rotaria sobre SU propio centro y el abanico se desarmaria.
     Con view-box todos giran sobre el mismo punto, que es el del nucleo. */
  .ins-fig.is-in .ins-fan__sector {
    transform-box: view-box;
    transform-origin: 50% 78%;
    animation: ins-fan-open var(--dur-slow) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.09s);
  }

  .ins-fig.is-in .ins-fan__core {
    transform-box: view-box;
    transform-origin: 50% 78%;
    animation: ins-fan-hub var(--dur-base) var(--ease-out) 0.5s both;
  }
}

/* ==========================================================================
   09 MAGNITUDE  ·  .ins-units
   Dos cantidades donde la diferencia de ESCALA es el punto. Una barra dejaria
   al numero chico invisible; una grilla de unidades deja las dos contables y
   la razon se vuelve fisica.

   LA REGLA QUE COSTO UN BUG DE VERDAD. El campo se dibuja con un degradado
   repetido, no con 400 nodos en el DOM: mismo resultado, cero costo. Pero el
   tamanio de la caja tiene que salir de filas x columnas, NUNCA de un ancho
   que envuelva. Con `max-width: 100%` el campo se recortaba en pantallas
   angostas y a 390px dibujaba 352 puntos mientras la cifra al lado seguia
   diciendo 400. Una figura que afirma 400 y dibuja 352, en un articulo sobre
   no confiar en numeros que no podes defender, es el peor error posible.

   Por eso la geometria se declara POR BREAKPOINT en clases, y nunca inline:
   un custom property inline le gana a la media query y el campo no podria
   reformarse. El producto filas x columnas es el mismo en todos los anchos.
   ========================================================================== */
.ins-units { display: grid; gap: 1.4rem; width: 100%; }


/* --------------------------------------------------------------------------
   09b · ESCALA  ·  .ins-units--scale
   Forma de la referencia de Carlos (2026-08-12): una columna que se ensancha
   nivel a nivel, con la cifra escrita en cada uno. Sirve cuando las
   cantidades no se diferencian en un factor de dos sino en ORDENES DE
   MAGNITUD, y una grilla de unidades ya no alcanza porque el nivel de abajo
   necesitaria un millon de puntos.

   EL ANCHO ES LOGARITMICO Y HAY QUE DECIRLO. Si fuera lineal, el nivel de 1
   mediria un pixel contra los mil del ultimo y no se veria; si fuera libre,
   seria un dibujo. Es log10, se declara en el pie, y la cifra exacta va
   escrita en cada nivel: el ancho da la sensacion, el numero da el dato.
   -------------------------------------------------------------------------- */
.ins-units--scale { display: grid; gap: 0.2rem; width: 100%; }

.ins-units__tier {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
  width: var(--w);
  margin-inline: auto;
  padding: 0.6rem 0.5rem;
  /* Un solo azul que se profundiza hacia abajo: la graduacion dice "esto
     crece", que es lo unico que tiene que decir. */
  background: color-mix(in srgb, var(--accent) calc(18% + var(--i) * 11%), var(--ins-paper, var(--bg-raised)));
  color: var(--ink, var(--text-primary));
}

/* Del cuarto nivel para abajo el fondo ya es oscuro y la tinta se invierte. */
.ins-units__tier[data-ink="light"] { color: var(--bg-raised); }

.ins-units__tier[data-state="loss"] {
  background: color-mix(in srgb, var(--accent-alt) calc(18% + var(--i) * 11%), var(--ins-paper, var(--bg-raised)));
}

.ins-units__n {
  font-size: 0.95rem;
  font-weight: 700;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

.ins-units__note {
  max-width: none;
  margin: 0.1rem 0 0;
  font-size: 0.7rem;
  line-height: 1.3;
  opacity: 0.85;
  text-align: center;
  text-wrap: pretty;
}

.ins-units__scalefoot {
  max-width: none;
  margin: 0.9rem 0 0;
  font-size: 0.72rem;
  color: var(--text-muted);
  text-align: center;
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-units-grow {
    from { opacity: 0; transform: scaleX(0.35); }
    to   { opacity: 1; transform: none; }
  }

  /* Crece de arriba hacia abajo, que es el orden en que la escala se abre. */
  .ins-fig.is-in .ins-units__tier {
    animation: ins-units-grow var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.09s);
  }
}

@media (max-width: 520px) {
  .ins-units__tier { padding-inline: 0.25rem; }
  .ins-units__n { font-size: 0.82rem; }
  .ins-units__note { font-size: 0.64rem; }
}

/* ==========================================================================
   10 OVERWRITE  ·  .ins-ow
   El mismo campo en dos momentos, donde el segundo destruye al primero.
   Renombrado de mkat-ow.

   LA DECISION QUE DEFINE ESTE COMPONENTE: la fila vieja NO muestra el valor
   que tenia. Muestra el hueco. Es tentador escribir "LinkedIn Paid" tachado,
   pero eso seria mentir: el registro ya no lo tiene, y si la figura lo
   imprime esta afirmando un dato que nadie puede ir a buscar. Lo que la
   figura sabe es que ahi habia algo y que hoy no esta.

   Por eso el hueco lleva la trama de vino y su texto en palabras, y el valor
   vigente va lleno en azul: uno es lo que el registro puede probar hoy, el
   otro es lo que perdio.
   ========================================================================== */
.ins-ow { display: grid; gap: 0.45rem; width: 100%; }

.ins-ow__row {
  display: grid;
  grid-template-columns: minmax(5rem, 0.28fr) minmax(0, 1fr) auto;
  align-items: stretch;
  gap: 0.45rem;
}

.ins-ow__when {
  display: flex;
  align-items: center;
  padding: 0.85rem 1rem;
  background: var(--accent);
  color: var(--bg-raised);
  font-size: 0.82rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.ins-ow__row[data-state="loss"] .ins-ow__when { background: var(--accent-alt); }

/* La celda del campo. Vigente: llena, con el valor. */
.ins-ow__slot {
  display: flex;
  align-items: center;
  padding: 0.85rem 1rem;
  background: color-mix(in srgb, var(--accent) 8%, var(--ins-paper, var(--bg-raised)));
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--ink, var(--text-primary));
}

/* Perdida: el hueco. Trama diagonal de vino, sin ningun valor impreso. */
.ins-ow__row[data-state="loss"] .ins-ow__slot {
  background:
    repeating-linear-gradient(
      -45deg,
      color-mix(in srgb, var(--accent-alt) 22%, transparent) 0 2px,
      transparent 2px 9px),
    color-mix(in srgb, var(--accent-alt) 7%, var(--ins-paper, var(--bg-raised)));
  color: var(--accent-alt);
  font-weight: 400;
  font-style: italic;
}

.ins-ow__state {
  display: flex;
  align-items: center;
  padding: 0.85rem 1rem;
  background: color-mix(in srgb, var(--accent) 8%, var(--ins-paper, var(--bg-raised)));
  font-size: 0.68rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.ins-ow__row[data-state="loss"] .ins-ow__state {
  background: color-mix(in srgb, var(--accent-alt) 7%, var(--ins-paper, var(--bg-raised)));
  color: var(--accent-alt);
}

/* La flecha de sobrescritura entre las dos filas. Es el operador, no un
   adorno: por eso va en vino como el menos de la sustraccion. */
.ins-ow__over {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding-left: 1rem;
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent-alt);
}

.ins-ow__over::before {
  content: '';
  width: 1px;
  height: 1.4rem;
  background: var(--accent-alt);
  margin-left: 1.4rem;
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-ow-in {
    from { opacity: 0; transform: translateY(-0.4rem); }
    to   { opacity: 1; transform: none; }
  }

  /* Entra el estado nuevo DESPUES del viejo: el orden del movimiento es el
     orden en que ocurrio la sobrescritura. */
  .ins-fig.is-in .ins-ow__row,
  .ins-fig.is-in .ins-ow__over {
    animation: ins-ow-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.22s);
  }
}

@media (max-width: 640px) {
  .ins-ow__row { grid-template-columns: 1fr; gap: 0.2rem; }

  .ins-ow__state { padding-block: 0.5rem; }

  .ins-ow__over::before { margin-left: 0.4rem; }
}

/* ==========================================================================
   12 TABLE  ·  .ins-table
   Comparacion tabular con texto en las celdas. Es el formato que mejor
   extraen los motores de IA, asi que se prefiere siempre que el contenido
   quepa: una <table> real, con thead y th, es dato estructurado gratis.

   Va como CLASE sobre la tabla, no como estilo de toda `table` dentro de
   prosa: el core ya estiliza las tablas de los articulos publicados y esas
   no se tocan.

   Hereda el lenguaje de celda de FIELDS: encabezado en sans bold, primera
   columna llena, celdas con tinte propio. Y hereda la regla de los valores
   negativos: la fila que lleva uno se tine en vino y el signo va escrito.
   ========================================================================== */
.ins-prose .ins-table {
  width: 100%;
  /* El core le pone `min-width: 34rem` a .ins-table para que su version con
     scroll horizontal no se aplaste. Esta no scrollea, se vuelve tarjetas,
     asi que ese piso hay que sacarlo: con el puesto, a 380px la tabla media
     544px y el `overflow-x: clip` de .ins-page le cortaba la ultima columna
     sin avisar. */
  min-width: 0;
  border-collapse: separate;
  border-spacing: 0 0.45rem;
  font-size: 0.82rem;
}

.ins-prose .ins-table th,
.ins-prose .ins-table td { text-align: left; vertical-align: middle; }

/* Encabezado: no lleva superficie, solo la hairline que lo separa del cuerpo. */
.ins-prose .ins-table thead th {
  padding: 0.5rem 1rem 0.7rem;
  border-bottom: 1px solid var(--line);
  font-size: 0.86rem;
  font-weight: 700;
  color: var(--ink, var(--text-primary));
}

.ins-prose .ins-table thead th:last-child { text-align: center; }

/* Primera columna: la clave, llena, igual que en FIELDS.

   El `tr:first-child` de la segunda linea no es un capricho: el core trae
   `.ins-prose table tr:first-child th`, que con la pseudo-clase suma (0,2,3)
   y le ganaba a este bloque. Resultado: la PRIMERA fila del cuerpo se
   dibujaba como encabezado y las otras como clave. Con la pseudo-clase de
   este lado el bloque llega a (0,3,3) y la tabla vuelve a ser pareja. */
.ins-prose .ins-table tbody tr:first-child th,
.ins-prose .ins-table tbody th {
  padding: 0.85rem 1rem;
  background: var(--accent);
  color: var(--bg-raised);
  font-size: 0.86rem;
  font-weight: 700;
  /* El core compone su fila de encabezado en caja alta y con tracking; hay
     que apagarlos los dos o la primera clave del cuerpo sale gritando. */
  text-transform: none;
  letter-spacing: 0;
}

.ins-prose .ins-table tbody td {
  padding: 0.85rem 1rem;
  background: color-mix(in srgb, var(--accent) 8%, var(--ins-paper, var(--bg-raised)));
  line-height: 1.45;
  color: var(--text-primary);
}

.ins-prose .ins-table tbody td + td {
  border-left: 1px solid color-mix(in srgb, var(--accent) 18%, transparent);
}

/* Fila que el registro no puede certificar. */
.ins-prose .ins-table tbody tr[data-state="loss"] th { background: var(--accent-alt); }

.ins-prose .ins-table tbody tr[data-state="loss"] td {
  background: color-mix(in srgb, var(--accent-alt) 8%, var(--ins-paper, var(--bg-raised)));
}

.ins-prose .ins-table tbody tr[data-state="loss"] td + td {
  border-left-color: color-mix(in srgb, var(--accent-alt) 18%, transparent);
}

/* Celda con cifra: misma tipografia para el positivo y para el negativo, y
   el signo escrito. Solo cambia el color. */
.ins-prose .ins-table td[data-val] {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink, var(--text-primary));
  text-align: right;
}

.ins-prose .ins-table td[data-neg] { color: var(--accent-alt); }

/* Marca de estado, distinguible por forma ademas de por color. */
.ins-prose .ins-table td[data-flag] { text-align: center; }

.ins-prose .ins-table td[data-flag] span {
  position: relative;
  display: inline-block;
  width: 1.35rem;
  height: 1.35rem;
  border-radius: 50%;
  background: var(--accent);
}

.ins-prose .ins-table td[data-flag] span::before {
  content: '';
  position: absolute;
  top: 0.34rem;
  left: 0.42rem;
  width: 0.32rem;
  height: 0.6rem;
  border-right: 2px solid var(--bg-raised);
  border-bottom: 2px solid var(--bg-raised);
  transform: rotate(45deg);
}

.ins-prose .ins-table tr[data-state="loss"] td[data-flag] span { background: var(--accent-alt); }

.ins-prose .ins-table tr[data-state="loss"] td[data-flag] span::before {
  top: 50%;
  left: 0.3rem;
  width: 0.75rem;
  height: 0;
  border-right: 0;
  transform: translateY(-1px);
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-table-in {
    from { opacity: 0; transform: translateY(0.35rem); }
    to   { opacity: 1; transform: none; }
  }

  .ins-fig.is-in .ins-table tbody tr {
    animation: ins-table-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.08s);
  }
}

/* Abajo de 640px la tabla se vuelve tarjetas: cada celda se lleva su
   encabezado con data-label. Es el mismo mecanismo del core, y es lo que
   evita el scroll horizontal sin sacrificar la <table> real del DOM. */
@media (max-width: 640px) {
  .ins-prose .ins-table,
  .ins-prose .ins-table tbody,
  .ins-prose .ins-table tr,
  .ins-prose .ins-table td,
  .ins-prose .ins-table th { display: block; width: 100%; }

  .ins-prose .ins-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

  .ins-prose .ins-table tbody tr { margin-bottom: 1rem; }

  .ins-prose .ins-table tbody td { display: grid; gap: 0.15rem; }

  .ins-prose .ins-table tbody td::before {
    content: attr(data-label);
    font-size: 0.62rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-muted);
  }

  .ins-prose .ins-table tbody td + td { border-left: 0; border-top: 1px solid var(--ins-paper, var(--bg-raised)); }

  .ins-prose .ins-table td[data-val],
  .ins-prose .ins-table td[data-flag] { text-align: left; }
}

/* --------------------------------------------------------------------------
   07b · TABLERO  ·  .ins-matrix--board
   Forma de la referencia de Carlos (2026-08-12): encabezados como chips,
   etiqueta de fila en pastilla a la izquierda, y cada cruce como una pastilla
   con una marca circular adentro.

   Sirve cuando hay MUCHAS filas y muchas columnas y lo que se lee es el
   tablero completo, no una fila contra otra. Con dos o tres filas conviene la
   forma A, donde el patron se lee de un golpe.

   Lo que se adapto: la referencia pinta cada columna de un color distinto.
   Seis colores prometen seis categorias y estas columnas son criterios del
   mismo tipo. Van todas en azul y se distinguen por su rotulo, que es lo que
   el lector va a leer igual. El vino sigue reservado a lo que el registro no
   puede certificar, y el gris a lo que simplemente no cumple.
   -------------------------------------------------------------------------- */
.ins-matrix--board {
  display: grid;
  grid-template-columns: minmax(7rem, 0.8fr) repeat(var(--cols, 5), minmax(0, 1fr));
  gap: 0.45rem;
  width: 100%;
}

.ins-matrix--board .ins-matrix__h {
  padding: 0.6rem 0.5rem;
  border-bottom: 0;
  background: var(--accent);
  color: var(--bg-raised);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: center;
}

.ins-matrix--board .ins-matrix__h--corner {
  background: color-mix(in srgb, var(--line) 45%, var(--ins-paper, var(--bg-raised)));
  color: var(--text-primary);
}

/* La etiqueta de fila, en pastilla clara: es una referencia, no un valor. */
.ins-matrix--board .ins-matrix__k {
  display: flex;
  align-items: center;
  padding: 0.7rem 0.9rem;
  background: color-mix(in srgb, var(--line) 45%, var(--ins-paper, var(--bg-raised)));
  color: var(--text-primary);
  font-size: 0.8rem;
  font-weight: 700;
}

.ins-matrix--board .ins-matrix__cell {
  min-height: 2.9rem;
  background: color-mix(in srgb, var(--line) 30%, var(--ins-paper, var(--bg-raised)));
}

/* La marca: circulo lleno con tilde cuando cumple, circulo hueco cuando no.
   Cambia el relleno Y la forma interna, asi que aguanta el monocromo. */
.ins-matrix--board .ins-matrix__mark {
  position: relative;
  width: 1.3rem;
  height: 1.3rem;
  border-radius: 50%;
  background: var(--accent);
}

.ins-matrix--board .ins-matrix__mark::before {
  content: '';
  position: absolute;
  top: 0.32rem;
  left: 0.42rem;
  width: 0.3rem;
  height: 0.58rem;
  border-right: 2px solid var(--bg-raised);
  border-bottom: 2px solid var(--bg-raised);
  transform: rotate(45deg);
}

.ins-matrix--board .ins-matrix__cell[data-writes="no"] { background: color-mix(in srgb, var(--line) 30%, var(--ins-paper, var(--bg-raised))); }

.ins-matrix--board .ins-matrix__cell[data-writes="no"] .ins-matrix__mark {
  background: none;
  border: 2px solid color-mix(in srgb, var(--text-primary) 28%, transparent);
}

.ins-matrix--board .ins-matrix__cell[data-writes="no"] .ins-matrix__mark::before { display: none; }

/* Lo que el registro no puede certificar: vino, y un guion en vez de tilde.
   Un guion no dice "esta mal", dice "no se sabe", que es lo que pasa. */
.ins-matrix--board .ins-matrix__cell[data-state="loss"] {
  background: color-mix(in srgb, var(--accent-alt) 10%, var(--ins-paper, var(--bg-raised)));
}

.ins-matrix--board .ins-matrix__cell[data-state="loss"] .ins-matrix__mark {
  background: var(--accent-alt);
  border: 0;
}

.ins-matrix--board .ins-matrix__cell[data-state="loss"] .ins-matrix__mark::before {
  display: block;
  top: 50%;
  left: 0.28rem;
  width: 0.72rem;
  height: 0;
  border-right: 0;
  transform: translateY(-1px);
}

@media (max-width: 760px) {
  /* El tablero completo no entra: se lee fila por fila, cada una con sus
     criterios en dos columnas y el nombre del criterio al lado de la marca. */
  .ins-matrix--board { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .ins-matrix--board .ins-matrix__h { display: none; }

  .ins-matrix--board .ins-matrix__k { grid-column: 1 / -1; margin-top: 0.7rem; }

  .ins-matrix--board .ins-matrix__cell {
    display: grid;
    grid-template-columns: 1.3rem minmax(0, 1fr);
    justify-items: start;
    align-items: center;
    gap: 0.55rem;
    padding: 0.5rem 0.7rem;
  }

  .ins-matrix--board .ins-matrix__cell::after {
    content: attr(data-col);
    font-size: 0.66rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
  }
}

/* ==========================================================================
   13 BULLET  ·  .ins-bullet
   Una metrica contra su objetivo y sus umbrales. Es el reemplazo del
   velocimetro: mismo mensaje, un quinto del espacio, y sin el maximo
   arbitrario que un gauge se inventa para poder dibujar la aguja.

   NO SE USA SIN OBJETIVO. Sin meta declarada esto es un numero con una barra
   al lado, y para eso alcanza el cuerpo del texto.

   La cifra va SIEMPRE escrita: la barra da la sensacion, el numero da el
   dato. Y la brecha contra el objetivo se escribe como valor negativo, asi
   que va en vino con el signo, por la regla de 2026-08-12.
   ========================================================================== */
.ins-bullet { display: grid; gap: 1.5rem; width: 100%; }

/* El rotulo del objetivo se posiciona ARRIBA de la pista, fuera del flujo, y
   por lo tanto no empuja nada. Sin reservarle altura propia, se metia encima
   de la barra de la fila anterior. `padding-top` le da su renglon: el aire no
   es estetico, es el alto que ese rotulo necesita para existir. */
.ins-bullet__row {
  display: grid;
  grid-template-columns: minmax(7rem, 0.5fr) minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 0.6rem 1rem;
  padding-top: 1.15rem;
}

.ins-bullet__k {
  max-width: none;
  margin: 0;
  font-size: 0.84rem;
  color: var(--text-primary);
}

/* La pista, con sus bandas de referencia. Tres intensidades del mismo azul:
   no son tres categorias, son la misma escala mas o menos exigida. */
.ins-bullet__track {
  position: relative;
  height: 2rem;
  background: color-mix(in srgb, var(--accent) 6%, var(--ins-paper, var(--bg-raised)));
}

.ins-bullet__band {
  position: absolute;
  inset-block: 0;
  left: var(--from);
  width: calc(var(--to) - var(--from));
  background: color-mix(in srgb, var(--accent) calc(var(--b, 1) * 5%), transparent);
}

/* El valor, barra solida y mas fina que la pista: se lee ENCIMA de la escala,
   no como otra barra al lado. */
.ins-bullet__fill {
  position: absolute;
  top: 50%;
  left: 0;
  width: var(--v);
  height: 0.7rem;
  margin-top: -0.35rem;
  background: var(--accent);
}

/* El objetivo: una marca vertical que cruza la pista entera. */
.ins-bullet__target {
  position: absolute;
  top: -0.3rem;
  bottom: -0.3rem;
  left: var(--t);
  width: 2px;
  margin-left: -1px;
  background: var(--ink, var(--text-primary));
}

.ins-bullet__target::after {
  content: attr(data-label);
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  padding-bottom: 0.2rem;
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
  white-space: nowrap;
}

.ins-bullet__v,
.ins-bullet__gap {
  font-size: 0.95rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.ins-bullet__v { color: var(--ink, var(--text-primary)); }

/* La brecha es un valor negativo: vino y signo escrito. Si la metrica llega
   al objetivo, este elemento no se emite. */
.ins-bullet__gap { color: var(--accent-alt); min-width: 3.5rem; }

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-bullet-fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }

  .ins-fig.is-in .ins-bullet__fill {
    transform-origin: 0 50%;
    animation: ins-bullet-fill var(--dur-slow) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.12s);
  }
}

@media (max-width: 640px) {
  /* Apilado, el rotulo del objetivo pasa a colgar ENCIMA de la pista, y arriba
     de la pista ya no hay aire: ahi esta el rotulo de la fila. El `padding-top`
     de la regla base le reserva el renglon en dos columnas, donde el rotulo va
     al lado; apilado hay que reservarlo en el row-gap o los dos textos se
     dibujan uno sobre el otro. Costo la Fig. 05 de la pieza 4. */
  .ins-bullet__row {
    grid-template-columns: minmax(0, 1fr) auto auto;
    row-gap: 1.5rem;
  }

  .ins-bullet__k { grid-column: 1 / -1; }

  .ins-bullet__track { grid-column: 1; }

  /* Y tampoco puede ir centrado en su marca: con la pista en 154px y el
     objetivo al final de la escala, la mitad del texto queda fuera de la
     placa. Anclado al borde derecho de la marca, el rotulo crece hacia
     adentro. Vale porque el objetivo del BULLET es el maximo de la escala. */
  .ins-bullet__target::after {
    left: auto;
    right: 0;
    transform: none;
  }
}

/* ==========================================================================
   14 WATERFALL  ·  .ins-fall
   Como se llega de una cifra inicial a una final, sumando y restando. Se usa
   cuando el RECORRIDO entre dos numeros es el argumento; si solo importan
   inicio y fin, va DELTA.

   LA TRAMPA DE ESTE COMPONENTE, y costo un render roto: las columnas se
   posicionan en PORCENTAJE del alto, y en CSS un `margin-bottom: 40%` se
   resuelve contra el ANCHO del contenedor, no contra su alto. Con eso las
   barras caian en cualquier lado y las de altura grande colapsaban a cero,
   porque una altura porcentual contra un padre de alto automatico no resuelve.
   La unica forma correcta es posicion absoluta dentro de una columna de alto
   fijo: ahi `bottom` y `height` en porcentaje si miden contra el alto.

   Positivo y negativo se distinguen por TRES cosas a la vez: el signo escrito
   en la cifra, el color (vino para el negativo) y la direccion en que la
   columna cuelga. Nunca solo por color.
   ========================================================================== */
.ins-fall {
  --fall-h: 15rem;

  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  width: 100%;
  padding: 1.8rem 0 3.2rem;   /* aire para las cifras arriba y los rotulos abajo */
}

.ins-fall__col {
  position: relative;
  height: var(--fall-h);
}

.ins-fall__bar {
  position: absolute;
  left: 0.35rem;
  right: 0.35rem;
  bottom: calc(var(--base) * 1%);
  height: calc(var(--h) * 1%);
  min-height: 2px;
  background: var(--accent);
}

/* Los tres estados de una columna, en una sola familia:
   TOTAL   azul lleno      el saldo, que el registro prueba
   POSITIVO azul aclarado  una suma, del mismo signo que el saldo
   NEGATIVO vino en hueco  una resta, y ademas queda ABIERTA: lo que se fue
                           no se dibuja macizo.
   El negro para los totales se probo y pesaba demasiado: partia la figura en
   dos objetos distintos en vez de leerse como una sola cuenta. */
.ins-fall__col[data-sign="pos"] .ins-fall__bar {
  background: color-mix(in srgb, var(--accent) 55%, var(--ins-paper, var(--bg-raised)));
}

.ins-fall__col[data-sign="neg"] .ins-fall__bar {
  background: color-mix(in srgb, var(--accent-alt) 12%, var(--ins-paper, var(--bg-raised)));
  box-shadow: inset 0 0 0 1.5px var(--accent-alt);
}

.ins-fall__col[data-sign="total"] .ins-fall__bar {
  background: var(--accent);
}

/* La linea de continuidad: del techo de esta columna al de la siguiente. */
.ins-fall__col::after {
  content: '';
  position: absolute;
  left: 50%;
  right: -50%;
  bottom: calc((var(--base) + var(--h)) * 1%);
  height: 1px;
  background: color-mix(in srgb, var(--text-primary) 28%, transparent);
}

.ins-fall__col:last-child::after { display: none; }

.ins-fall__v {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc((var(--base) + var(--h)) * 1% + 0.45rem);
  font-size: 0.82rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink, var(--text-primary));
  text-align: center;
  white-space: nowrap;
}

.ins-fall__col[data-sign="neg"] .ins-fall__v { color: var(--accent-alt); }

.ins-fall__k {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  padding: 0.7rem 0.3rem 0;
  font-size: 0.72rem;
  line-height: 1.3;
  color: var(--text-muted);
  text-align: center;
  text-wrap: pretty;
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-fall-in {
    from { opacity: 0; transform: translateY(0.5rem); }
    to   { opacity: 1; transform: none; }
  }

  /* Las columnas entran en el orden de la cuenta: es una operacion leida de
     izquierda a derecha, no un grupo de barras. */
  .ins-fig.is-in .ins-fall__col {
    animation: ins-fall-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.12s);
  }
}

@media (max-width: 700px) {
  /* Seis columnas a 55px no dejan leer ni la cifra ni el rotulo. La cuenta se
     para: cada paso es una fila con su barra proporcional debajo. */

  .ins-fall__col {
    height: auto;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: baseline;
    gap: 0.3rem 0.8rem;
  }

  .ins-fall__bar {
    position: static;
    grid-column: 1 / -1;
    width: calc(var(--h) * 1%);
    height: 0.7rem;
    margin-left: calc(var(--base) * 1%);
  }

  .ins-fall__col::after { display: none; }

  .ins-fall__v { position: static; grid-column: 2; text-align: right; }

  .ins-fall__k { position: static; grid-column: 1; padding: 0; text-align: left; }
}

/* ==========================================================================
   15 FUNNEL  ·  .ins-funnel
   Etapas con caida, y la tasa de conversion de cada paso. El punto es DONDE y
   CUANTO se pierde entre una etapa y la siguiente.

   BARRAS RECTANGULARES, SIEMPRE. El trapecio esta prohibido y no es una
   cuestion de gusto: con el ancho variable el ojo compara AREAS en vez de
   longitudes, y una caida del 30% se lee como una del 50%. Ademas el trapecio
   obliga a centrar, y centrado no hay linea de base contra la cual comparar.
   Todas las barras arrancan del mismo cero, a la izquierda.

   La caida entre etapas vive en el AIRE entre las dos barras, que es donde
   ocurre. Va en vino con el signo escrito: es un valor negativo.

   Si lo que hay que mostrar es como se reparte el volumen entre ramas, esto
   no sirve: va SANKEY.
   ========================================================================== */
.ins-funnel { display: grid; width: 100%; }

/* El rotulo va FUERA de la barra. Adentro solo entra mientras la barra sea
   ancha; en la ultima etapa la barra mide el 0.3% del total y el texto se le
   desborda por los cuatro costados. Con el rotulo en su propia columna, la
   barra puede medir lo que el dato diga sin romper nada. */
.ins-funnel__stage {
  display: grid;
  /* La cifra tiene COLUMNA PROPIA. Puesta a continuacion de la barra dentro
     de la pista, la etapa de arriba (barra al 100%) la empujaba encima del
     detalle. Con columna propia, la barra puede llegar al borde de la pista y
     la cifra siempre tiene su lugar. */
  grid-template-columns: minmax(8rem, 0.4fr) minmax(0, 1fr) 4.5rem minmax(7rem, 0.3fr);
  align-items: center;
  gap: 0.9rem;
}

.ins-funnel__k {
  max-width: none;
  margin: 0;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--ink, var(--text-primary));
}

/* La pista: solo la barra. La escala arranca en el mismo cero para todas. */
.ins-funnel__track { display: flex; align-items: center; }

.ins-funnel__bar {
  width: calc(var(--w) * 1%);
  min-width: 3px;
  height: 2.3rem;
  flex: none;
  /* Un solo azul que se aclara etapa a etapa. La graduacion dice "esto va
     quedando menos", no cinco categorias distintas. */
  background: color-mix(in srgb, var(--accent) calc(100% - (var(--i) - 1) * 13%), var(--ins-paper, var(--bg-raised)));
}

.ins-funnel__n {
  font-size: 0.86rem;
  font-weight: 700;
  color: var(--ink, var(--text-primary));
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.ins-funnel__detail {
  max-width: none;
  margin: 0;
  padding-left: 0.9rem;
  border-left: 1px solid var(--line);
  font-size: 0.72rem;
  line-height: 1.35;
  color: var(--text-muted);
}

/* La etapa final: hueca con contorno, porque es el resultado y no un tramo
   mas de la caida. */
.ins-funnel__stage--end .ins-funnel__bar {
  background: none;
  box-shadow: inset 0 0 0 2px var(--accent);
}

.ins-funnel__stage--end .ins-funnel__n { color: var(--accent); }

/* La caida: el aire entre dos barras, con su tasa. */
.ins-funnel__drop {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  max-width: none;
  /* Alineada con la pista, no con el borde de la figura: la caida ocurre
     entre dos barras, y tiene que empezar donde empiezan las barras. */
  margin-left: calc(0.4fr);
  margin: 0 0 0 clamp(0rem, 8rem, 28%);
  padding: 0.45rem 0;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--accent-alt);
  font-variant-numeric: tabular-nums;
}

.ins-funnel__drop::after {
  content: '';
  height: 1px;
  flex: 1;
  background: color-mix(in srgb, var(--accent-alt) 30%, transparent);
}

/* La etapa final: la unica que no se aclara, porque es el resultado. */
.ins-funnel__stage--end .ins-funnel__bar {
  background: none;
  color: var(--accent);
  box-shadow: inset 0 0 0 2px var(--accent);
}

.ins-funnel__stage--end[data-ink="dark"] .ins-funnel__bar { color: var(--accent); }

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-funnel-in { from { transform: scaleX(0); } to { transform: scaleX(1); } }

  @keyframes ins-funnel-drop { from { opacity: 0; } to { opacity: 1; } }

  .ins-fig.is-in .ins-funnel__bar {
    transform-origin: 0 50%;
    animation: ins-funnel-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.14s);
  }

  /* La caida aparece DESPUES de las dos barras que separa: primero se ve que
     hay menos, despues cuanto menos. */
  .ins-fig.is-in .ins-funnel__drop {
    animation: ins-funnel-drop var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.14s + 0.2s);
  }
}

@media (max-width: 700px) {
  .ins-funnel__stage { grid-template-columns: minmax(0, 1fr) auto; gap: 0.3rem 0.7rem; }

  .ins-funnel__k { grid-column: 1; }

  .ins-funnel__n { grid-column: 2; grid-row: 1; }

  .ins-funnel__track { grid-column: 1 / -1; }

  .ins-funnel__detail { grid-column: 1 / -1; }

  .ins-funnel__detail { padding: 0 0 0 0.1rem; border-left: 0; }

  .ins-funnel__drop { margin-left: 0; }
}

/* --------------------------------------------------------------------------
   15b · CONO  ·  .ins-funnel--cone
   Forma de la referencia de Carlos (2026-08-12): cortes trapezoidales
   apilados, centrados, que se angostan parejo hasta un ultimo corte recto.

   EL CONO NO MIDE. Sus escalones son IGUALES entre si y salen de la posicion
   de la etapa, no de su cifra. Se probo la version proporcional, donde el
   ancho de cada corte era su valor, y con datos reales quedaba desproporcionada
   al punto de ser ilegible: 25.000 arriba contra 74 abajo deja los ultimos
   tres cortes en una astilla.

   Que no mida es lo que lo vuelve honesto. Un embudo de escalones parejos se
   lee como lo que es, un diagrama de secuencia, y nadie puede confundir su
   ancho con una cantidad. La cantidad vive en la cifra escrita al lado, y la
   caida entre etapas en su porcentaje. Si lo que hay que comparar son las
   magnitudes, la forma correcta es la B, de barras.

   Por eso tampoco lleva texto adentro de los cortes: el rotulo se corta con
   el ancho y el ancho no significa nada.
   -------------------------------------------------------------------------- */
.ins-funnel--cone {
  --cone-h: 3.4rem;     /* alto de cada corte, constante */
  --cone-top: 100;      /* ancho del primer corte, en % */
  --cone-end: 34;       /* ancho del ultimo, en %       */

  display: grid;
  grid-template-columns: minmax(0, 1fr) 4.5rem minmax(7rem, 0.34fr);
  align-items: center;
  gap: 0.3rem 0.9rem;
  width: 100%;
}

.ins-funnel--cone .ins-funnel__stage { display: contents; }

/* Con `display: contents` los hijos entran directo a la grilla del
   contenedor, asi que hay que fijarles la columna: la caida ocupa una celda
   de la columna 1 y sin columna explicita corre todo lo que sigue. */
.ins-funnel--cone .ins-funnel__track  { grid-column: 1; height: var(--cone-h); display: block; }
.ins-funnel--cone .ins-funnel__n      { grid-column: 2; }
.ins-funnel--cone .ins-funnel__detail { grid-column: 3; }

.ins-funnel--cone .ins-funnel__bar {
  /* La barra es un <span>: en la variante de barras la pista es flex y lo
     blockifica sola, aca la pista es un bloque y sin esto queda inline y mide
     0x0. El poligono se emite ya calculado desde el generador porque un
     calc() con variables adentro de clip-path no resuelve. */
  display: block;
  width: 100%;
  height: 100%;
  min-width: 0;
  background: color-mix(in srgb, var(--accent) calc(100% - (var(--i) - 1) * 12%), var(--ins-paper, var(--bg-raised)));
}

.ins-funnel--cone .ins-funnel__stage[data-state="loss"] .ins-funnel__bar {
  background: var(--accent-alt);
}

.ins-funnel--cone .ins-funnel__drop {
  grid-column: 1;
  justify-content: center;
  margin: 0;
  padding: 0.1rem 0;
}

.ins-funnel--cone .ins-funnel__drop::after { display: none; }

@media (max-width: 700px) {
  .ins-funnel--cone { grid-template-columns: minmax(0, 1fr) auto; }

  .ins-funnel--cone .ins-funnel__track { grid-column: 1 / -1; }

  .ins-funnel--cone .ins-funnel__detail { grid-column: 1; }

  .ins-funnel--cone .ins-funnel__n { grid-column: 2; }
}

/* --------------------------------------------------------------------------
   15c · DOBLE  ·  .ins-funnel--double
   Forma de la referencia de Carlos (2026-08-12): el reloj de arena. Un lado
   se angosta hasta la cintura y el otro se abre. Sirve cuando el argumento
   tiene DOS movimientos opuestos y una bisagra en el medio: se filtra hasta
   quedarse con lo que importa, y desde ahi se expande.

   Igual que el cono, ESTE INSTRUMENTO NO MIDE: los escalones son parejos y
   salen de la posicion, no de la cifra. Es un diagrama de secuencia con una
   bisagra, y las cantidades viven en las cifras de abajo.

   Los dos lados NO se distinguen por color, porque el sistema tiene un solo
   azul. Se distinguen por RELLENO: el lado que filtra va macizo, el que se
   abre va en hueco con contorno. Ademas cada mitad lleva su rotulo. Con eso
   la lectura sobrevive al monocromo y no hace falta inventar un segundo tono.
   -------------------------------------------------------------------------- */
.ins-funnel--double {
  --dbl-h: 9rem;      /* alto del cuerpo                     */
  --dbl-waist: 26;    /* alto de la cintura, en % del cuerpo */

  display: grid;
  gap: 0.7rem 0;
  width: 100%;
}

.ins-funnel__ends {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Los dos rotulos de mitad, cada uno sobre su lado. */
.ins-funnel__halves {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.5rem;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--accent);
  text-align: center;
}

.ins-funnel__halves span:last-child { color: var(--text-primary); }

.ins-funnel__body {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  height: var(--dbl-h);
}

/* Cada tramo es una banda cuyo alto de entrada y de salida se emiten ya
   calculados: el clip-path no admite calc() con variables. */
.ins-funnel__seg {
  position: relative;
  display: grid;
  place-items: center;
}

.ins-funnel__seg::before {
  content: '';
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--accent) calc(100% - (var(--i) - 1) * 9%), var(--ins-paper, var(--bg-raised)));
  clip-path: var(--clip);
}

/* El lado que se abre: hueco. Se dibuja con dos capas, el contorno y el
   relleno del papel, porque un clip-path recorta el borde de la caja. */
.ins-funnel__seg[data-side="out"]::before {
  background: color-mix(in srgb, var(--accent) 26%, var(--ins-paper, var(--bg-raised)));
}

.ins-funnel__n {
  position: relative;
  z-index: 1;
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--bg-raised);
  font-variant-numeric: tabular-nums;
}

.ins-funnel__seg[data-side="out"] .ins-funnel__n { color: var(--ink, var(--text-primary)); }

/* La cintura: la bisagra del argumento. Va en el BORDE del ultimo tramo que
   filtra, que es donde la figura es mas angosta de verdad; centrada en el
   tramo quedaba 100px antes del punto que marca. */
.ins-funnel__waist {
  position: absolute;
  top: -0.4rem;
  bottom: -0.4rem;
  left: 100%;
  width: 2px;
  margin-left: -1px;
  background: var(--accent-alt);
}

.ins-funnel__waist::after {
  content: attr(data-label);
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  padding-top: 0.35rem;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-alt);
  white-space: nowrap;
}

/* Los pies, una columna por tramo, como en la referencia. */
.ins-funnel__feet {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 0.9rem;
  margin-top: 1.4rem;
}

.ins-funnel__foot { display: grid; gap: 0.25rem; align-content: start; }

.ins-funnel__foot b {
  font-size: 0.78rem;
  color: var(--accent);
}

.ins-funnel__foot[data-side="out"] b { color: var(--text-primary); }

.ins-funnel__foot span {
  font-size: 0.7rem;
  line-height: 1.35;
  color: var(--text-muted);
  text-wrap: pretty;
}

@media (max-width: 900px) {
  /* Ocho columnas de pie no entran. El cuerpo se mantiene, que es la forma, y
     los pies pasan a dos columnas. */
  .ins-funnel__feet {
    grid-auto-flow: row;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1rem;
  }
}

@media (max-width: 520px) {
  .ins-funnel--double { --dbl-h: 6.5rem; }

  .ins-funnel__feet { grid-template-columns: 1fr; }

  .ins-funnel__n { font-size: 0.78rem; }
}

/* ==========================================================================
   16 SPLIT  ·  .ins-split
   Un total al 100% repartido en partes. Maximo cinco: con mas, los segmentos
   chicos dejan de ser comparables y conviene una tabla.

   Se usa cuando la COMPOSICION del total es el argumento. No sirve para
   comparar partes de totales distintos: para eso cada total necesita su
   propia barra, y ahi ya es otra figura.

   MONOCROMO. Los segmentos no se distinguen solo por intensidad: cada uno
   lleva ademas su TRAMA. Si el lector no ve color, sigue pudiendo emparejar
   cada tramo con su entrada en la leyenda.

   La cifra y el porcentaje van escritos en la leyenda, siempre. Una barra de
   porcentaje sin la cifra al lado esta prohibida por el catalogo.
   ========================================================================== */
.ins-split { display: grid; gap: 1.3rem; width: 100%; }

.ins-split__bar {
  display: grid;
  grid-auto-flow: column;
  height: 3rem;
  overflow: hidden;
}

.ins-split__seg {
  position: relative;
  background: color-mix(in srgb, var(--accent) calc(100% - (var(--i) - 1) * 18%), var(--ins-paper, var(--bg-raised)));
}

/* SIN TRAMAS (2026-08-12). Se probaron rayas y puntos sobre cada tramo y
   Carlos las saco: ensuciaban el color. No hacen falta para el monocromo, que
   era el motivo por el que estaban: la escalera de este componente es de
   LUMINOSIDAD, no de tono, y la luminosidad sobrevive al gris por definicion.
   Lo que si hace falta es que los tramos se separen entre si, y de eso se
   encarga la hairline de papel que va entre uno y otro. */
.ins-split__seg + .ins-split__seg {
  box-shadow: inset 1px 0 0 var(--ins-paper, var(--bg-raised));
}

/* La parte que el registro no puede certificar. */
.ins-split__seg[data-state="loss"] {
  background: color-mix(in srgb, var(--accent-alt) 16%, var(--ins-paper, var(--bg-raised)));
  box-shadow: inset 0 0 0 1.5px var(--accent-alt);
}

.ins-split__legend { display: grid; gap: 0.45rem; }

.ins-split__item {
  display: grid;
  grid-template-columns: 1rem minmax(0, 1fr) auto auto;
  align-items: baseline;
  gap: 0.75rem;
  font-size: 0.82rem;
}

/* La muestra repite la intensidad exacta del segmento que nombra. */
.ins-split__swatch {
  position: relative;
  width: 1rem;
  height: 1rem;
  align-self: center;
  background: color-mix(in srgb, var(--accent) calc(100% - (var(--i) - 1) * 18%), var(--ins-paper, var(--bg-raised)));
}

.ins-split__item[data-state="loss"] .ins-split__swatch {
  background: color-mix(in srgb, var(--accent-alt) 16%, var(--ins-paper, var(--bg-raised)));
  box-shadow: inset 0 0 0 1.5px var(--accent-alt);
}

.ins-split__k { color: var(--text-primary); }

.ins-split__item[data-state="loss"] .ins-split__k { color: var(--accent-alt); }

.ins-split__v,
.ins-split__pct {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.ins-split__v { min-width: 5rem; color: var(--ink, var(--text-primary)); }

.ins-split__pct { min-width: 3rem; color: var(--text-muted); }

.ins-split__item[data-state="loss"] .ins-split__v,
.ins-split__item[data-state="loss"] .ins-split__pct { color: var(--accent-alt); }

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-split-in { from { transform: scaleX(0); } to { transform: scaleX(1); } }

  .ins-fig.is-in .ins-split__seg {
    transform-origin: 0 50%;
    animation: ins-split-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.1s);
  }
}

@media (max-width: 560px) {
  .ins-split__item { grid-template-columns: 1rem minmax(0, 1fr) auto; }

  .ins-split__pct { grid-column: 3; }

  .ins-split__v { grid-column: 2 / 4; text-align: left; min-width: 0; }
}



/* ==========================================================================
   22 QUADRANT  ·  .ins-quad
   Matriz 2x2 de posicionamiento, con la forma de la referencia de Carlos
   (2026-08-12): los dos ejes se cruzan en el centro, cada cuadrante es una
   caja llena con la esquina EXTERIOR redondeada, titulo centrado con su
   filete y texto debajo.

   Reglas del componente, que la forma no cambia:
   - Los cuatro cuadrantes llevan NOMBRE. Un 2x2 con cuadrantes sin nombre no
     dice nada.
   - Los items caen dentro del cuadrante, sin posicion interna: afinar la
     posicion afirmaria una precision que dos ejes binarios no tienen. Si los
     ejes son continuos, va SCATTER.
   - La referencia usa cuatro azules de distinta profundidad. Se conserva:
     son cuatro intensidades del mismo tono, no cuatro colores, y la
     graduacion no promete categorias distintas.
   - El cuadrante que el registro no puede certificar va en vino.
   ========================================================================== */
.ins-quad {
  display: grid;
  grid-template-columns: minmax(4.5rem, auto) minmax(0, 1fr) minmax(4.5rem, auto);
  grid-template-rows: auto auto auto;
  align-items: center;
  gap: 0.7rem 0.9rem;
  width: 100%;
}

/* Los cuatro rotulos de eje. Arriba y abajo cruzan las tres columnas; los de
   los costados van en su columna, sin rotar: el texto vertical se lee mal y
   no aporta nada que el lugar no diga ya. */
.ins-quad__axis {
  font-size: 0.74rem;
  font-weight: 700;
  line-height: 1.25;
  color: var(--ink, var(--text-primary));
  text-align: center;
}

.ins-quad__axis[data-edge="top"]    { grid-area: 1 / 2 / 2 / 3; }
.ins-quad__axis[data-edge="bottom"] { grid-area: 3 / 2 / 4 / 3; }
.ins-quad__axis[data-edge="left"]   { grid-area: 2 / 1 / 3 / 2; }
.ins-quad__axis[data-edge="right"]  { grid-area: 2 / 3 / 3 / 4; }

.ins-quad__grid {
  position: relative;
  grid-area: 2 / 2 / 3 / 3;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.55rem;
}

/* Los ejes: dos lineas que se cruzan en el centro, con punta en los cuatro
   extremos. Van por encima de las cajas, en el canal del gap. */
.ins-quad__cross {
  position: absolute;
  inset: -0.9rem;
  pointer-events: none;
}

.ins-quad__cross::before,
.ins-quad__cross::after {
  content: '';
  position: absolute;
  background: color-mix(in srgb, var(--text-primary) 35%, transparent);
}

.ins-quad__cross::before { top: 50%; left: 0; right: 0; height: 1px; }

.ins-quad__cross::after  { left: 50%; top: 0; bottom: 0; width: 1px; }

.ins-quad__cell {
  display: grid;
  align-content: start;
  gap: 0.6rem;
  min-height: 9.5rem;
  padding: 1.1rem 1.3rem 1.3rem;
  background: color-mix(in srgb, var(--accent) calc(45% + var(--q) * 14%), var(--ins-paper, var(--bg-raised)));
  color: var(--bg-raised);
}

/* La esquina exterior redondeada, una por cuadrante. Es lo que hace que las
   cuatro cajas se lean como un solo tablero y no como cuatro tarjetas.

   Va por `data-q`, NO por `nth-child`: el primer hijo del tablero es la cruz
   de ejes, asi que el conteo posicional arrancaba corrido y cada cuadrante
   redondeaba la esquina del vecino. */
.ins-quad__cell[data-q="1"] { border-radius: 1.1rem 0 0 0; }
.ins-quad__cell[data-q="2"] { border-radius: 0 1.1rem 0 0; }
.ins-quad__cell[data-q="3"] { border-radius: 0 0 0 1.1rem; }
.ins-quad__cell[data-q="4"] { border-radius: 0 0 1.1rem 0; }

.ins-quad__cell[data-state="loss"] { background: var(--accent-alt); }

.ins-quad__name {
  padding-bottom: 0.55rem;
  border-bottom: 1px solid color-mix(in srgb, var(--bg-raised) 45%, transparent);
  font-size: 0.95rem;
  font-weight: 700;
  text-align: center;
}

.ins-quad__desc {
  max-width: none;
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.45;
  text-align: center;
  text-wrap: pretty;
}

.ins-quad__items {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.3rem;
}

.ins-quad__item {
  padding: 0.2rem 0.55rem;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--bg-raised) 55%, transparent);
  font-size: 0.72rem;
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-quad-in {
    from { opacity: 0; transform: scale(0.97); }
    to   { opacity: 1; transform: none; }
  }

  .ins-fig.is-in .ins-quad__cell {
    animation: ins-quad-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--q) - 1) * 0.09s);
  }
}

@media (max-width: 620px) {
  /* El tablero no se lee a 150px por celda. Se apila en cuatro y los ejes
     dejan de tener sentido como cruz, asi que se apagan: cada cuadrante ya
     lleva su nombre y su descripcion, y el orden reconstruye la matriz. */
  .ins-quad {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto auto;
  }

  .ins-quad__axis[data-edge="left"],
  .ins-quad__axis[data-edge="right"] { display: none; }

  .ins-quad__axis[data-edge="top"]    { grid-area: 1 / 1 / 2 / 2; }
  .ins-quad__grid                     { grid-area: 2 / 1 / 3 / 2; grid-template-columns: 1fr; }
  .ins-quad__axis[data-edge="bottom"] { grid-area: 3 / 1 / 4 / 2; }

  .ins-quad__cross { display: none; }

  .ins-quad__cell,
  .ins-quad__cell[data-q] { min-height: 0; border-radius: 0.9rem; }
}

/* ==========================================================================
   27 LAYERS  ·  .ins-layers
   Capas apiladas de un modelo, donde cada una DESCANSA sobre la anterior. Se
   usa cuando hay dependencia vertical: la de arriba necesita a la de abajo
   para existir. Si los elementos son pares sin jerarquia, va FIELDS.

   PROHIBIDA LA PIRAMIDE. Un apilado que se angosta hacia arriba dice que las
   capas superiores son mas chicas o menos importantes, y en un stack pasa lo
   contrario: la capa de arriba es la que el negocio ve. Ancho constante, y la
   dependencia se marca con la profundidad del color, no con el tamanio.

   La base va abajo y el numeral crece hacia arriba, como en cualquier plano
   de obra: se lee de abajo hacia arriba porque asi es como se construye.
   ========================================================================== */
.ins-layers { display: grid; gap: 0.4rem; width: 100%; }

.ins-layers__layer {
  display: grid;
  grid-template-columns: 2.6rem minmax(7rem, 0.32fr) minmax(0, 1fr);
  align-items: center;
  gap: 0.4rem 1rem;
  min-height: 4.2rem;
  padding: 0.85rem 1.1rem;
  /* La profundidad crece hacia la base: la capa de abajo es la que sostiene
     todo el resto, y por eso es la mas densa. */
  background: color-mix(in srgb, var(--accent) calc(18% + (var(--n, 4) - var(--i)) * 20%), var(--ins-paper, var(--bg-raised)));
  color: var(--ink, var(--text-primary));
}

/* Desde la mitad hacia abajo el fondo ya no aguanta tinta oscura. */
.ins-layers__layer[data-ink="light"] { color: var(--bg-raised); }

.ins-layers__layer[data-state="loss"] {
  background: color-mix(in srgb, var(--accent-alt) 16%, var(--ins-paper, var(--bg-raised)));
  box-shadow: inset 0 0 0 1.5px var(--accent-alt);
  color: var(--ink, var(--text-primary));
}

.ins-layers__n {
  font-size: 1.15rem;
  font-weight: 700;
  line-height: 1;
  color: var(--accent-alt);
  font-variant-numeric: tabular-nums;
}

.ins-layers__layer[data-ink="light"] .ins-layers__n { color: var(--bg-raised); }

.ins-layers__name { font-size: 0.92rem; font-weight: 700; }

.ins-layers__desc {
  max-width: none;
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.4;
  text-wrap: pretty;
}

/* Lo que cada capa aporta, como fichas. Opcional. */
.ins-layers__items { grid-column: 3; display: flex; flex-wrap: wrap; gap: 0.3rem; }

.ins-layers__item {
  padding: 0.15rem 0.5rem;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink, var(--text-primary)) 22%, transparent);
  font-size: 0.7rem;
}

.ins-layers__layer[data-ink="light"] .ins-layers__item {
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--bg-raised) 50%, transparent);
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-layers-in {
    from { opacity: 0; transform: translateY(0.4rem); }
    to   { opacity: 1; transform: none; }
  }

  /* Se apila DESDE LA BASE: el retardo mayor es para la capa de arriba,
     porque es la ultima que se puede construir. */
  .ins-fig.is-in .ins-layers__layer {
    animation: ins-layers-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--n, 4) - var(--i)) * 0.11s);
  }
}

@media (max-width: 620px) {
  .ins-layers__layer { grid-template-columns: 2.2rem minmax(0, 1fr); }

  .ins-layers__desc,
  .ins-layers__items { grid-column: 2; }
}

/* ==========================================================================
   33 SCORECARD  ·  .ins-score
   Opciones puntuadas contra un set de criterios. Dos a cuatro opciones, tres
   a seis criterios. Si la evaluacion es binaria va CRITERIA; una escala de
   1 a 5 donde todo termina siendo 4 o 5 es una tabla disfrazada.

   LA ESCALA SE DECLARA. Un puntaje sin escala no se lee: 4 puede ser
   excelente o mediocre segun donde termine la regla. Va en el pie, y ademas
   el maximo entra por `--max` para que la barra mida contra el de verdad.

   Cada celda lleva la cifra COMO TEXTO ademas de la barra. La barra da la
   comparacion de un vistazo; el numero es el que se puede citar.
   ========================================================================== */
.ins-score { display: grid; gap: 0.5rem; width: 100%; }

.ins-score__grid {
  display: grid;
  grid-template-columns: minmax(8rem, 0.7fr) repeat(var(--opts, 3), minmax(0, 1fr));
  gap: 0.4rem;
  align-items: stretch;
}

/* Encabezado: el nombre de cada opcion, lleno, como la clave de FIELDS. */
.ins-score__opt {
  display: grid;
  place-items: center;
  padding: 0.6rem 0.7rem;
  background: var(--accent);
  color: var(--bg-raised);
  font-size: 0.82rem;
  font-weight: 700;
  text-align: center;
}

.ins-score__corner { background: none; }

.ins-score__crit {
  display: flex;
  align-items: center;
  padding: 0.7rem 0.9rem;
  background: color-mix(in srgb, var(--line) 40%, var(--ins-paper, var(--bg-raised)));
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--text-primary);
}

/* La celda: barra corta arriba, cifra abajo. La barra mide contra --max. */
.ins-score__cell {
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 0.35rem;
  padding: 0.7rem 0.6rem;
  background: color-mix(in srgb, var(--accent) 7%, var(--ins-paper, var(--bg-raised)));
}

.ins-score__bar {
  width: 100%;
  height: 0.45rem;
  background: color-mix(in srgb, var(--accent) 18%, transparent);
}

.ins-score__bar span {
  display: block;
  width: calc(var(--v) / var(--max) * 100%);
  height: 100%;
  background: var(--accent);
}

.ins-score__n {
  font-size: 0.86rem;
  font-weight: 700;
  color: var(--ink, var(--text-primary));
  font-variant-numeric: tabular-nums;
}

/* El criterio que el registro no puede certificar: la fila entera queda
   marcada, porque el problema no es el puntaje sino que no se puede puntuar. */
.ins-score__crit[data-state="loss"],
.ins-score__cell[data-state="loss"] {
  background: color-mix(in srgb, var(--accent-alt) 9%, var(--ins-paper, var(--bg-raised)));
}

.ins-score__crit[data-state="loss"] { color: var(--accent-alt); }

.ins-score__cell[data-state="loss"] .ins-score__bar span { background: var(--accent-alt); }

.ins-score__cell[data-state="loss"] .ins-score__n { color: var(--accent-alt); }

/* El total: misma fila, tinta plena. */
.ins-score__crit--total,
.ins-score__cell--total { background: none; box-shadow: inset 0 2px 0 var(--ink, var(--text-primary)); }

.ins-score__cell--total .ins-score__n { font-size: 1.1rem; color: var(--accent); }

.ins-score__foot {
  max-width: none;
  margin: 0;
  font-size: 0.72rem;
  color: var(--text-muted);
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-score-fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }

  .ins-fig.is-in .ins-score__bar span {
    transform-origin: 0 50%;
    animation: ins-score-fill var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--r) - 1) * 0.1s);
  }
}

@media (max-width: 640px) {
  /* Cuatro columnas no entran. Se lee criterio por criterio, con las opciones
     apiladas debajo de cada uno y su nombre al lado de la cifra. */
  .ins-score__grid { grid-template-columns: 1fr; }

  .ins-score__opt { display: none; }

  .ins-score__crit { margin-top: 0.7rem; }

  .ins-score__cell {
    grid-template-columns: minmax(0, 1fr) auto auto;
    justify-items: stretch;
    align-items: center;
    gap: 0.6rem;
    padding: 0.5rem 0.9rem;
  }

  .ins-score__cell::before {
    content: attr(data-opt);
    font-size: 0.72rem;
    color: var(--text-muted);
  }
}

/* ==========================================================================
   44 BALANCED SCORECARD  ·  .ins-bsc
   Autorizado por Carlos el 2026-08-12 sobre una referencia suya. No estaba en
   el catalogo; se le abrio ficha en el mismo pase.

   Cuatro perspectivas alrededor de una estrategia, cada una con su tabla de
   objetivo contra actual. Es el unico componente del sistema que muestra
   CUATRO tablas a la vez, y por eso solo sirve a ancho completo: dentro de la
   placa de 44rem las columnas quedan en 60px y no se leen.

   Que compara: cada fila enfrenta un objetivo con lo que hay hoy. Cuando el
   actual queda por debajo del objetivo, la celda va en vino, por la regla de
   valores negativos: no es una opinion sobre la perspectiva, es que ese
   numero esta en contra.

   La pestania vertical es la excepcion a "no rotar texto" del sistema. Se
   permite porque es una PESTANIA de una palabra que identifica el bloque, no
   contenido que alguien tenga que leer en linea. Las cuatro se leen de abajo
   hacia arriba, como el lomo de un libro.

   El centro no flota sobre el contenido: las celdas de arriba reservan
   `--ins-bsc-clear` abajo y las de abajo arriba, asi el circulo cae siempre
   sobre papel vacio. Un z-index mas alto no alcanzaba, tapaba texto.
   ========================================================================== */
.ins-bsc {
  --ins-bsc-core: 8.5rem;
  --ins-bsc-clear: 4.75rem;
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.5rem;
  width: 100%;
}

.ins-bsc__cell {
  display: grid;
  grid-template-columns: 2.4rem minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr);
  gap: 1rem;
  background: var(--ins-paper, var(--bg-raised));
  box-shadow: inset 0 0 0 1px var(--line);
}

.ins-bsc__tab { grid-row: 1; grid-column: 1; }

.ins-bsc__body { grid-row: 1; grid-column: 2; }

/* Las dos de la derecha llevan la pestania del lado de afuera. */
.ins-bsc__cell[data-side="right"] { grid-template-columns: minmax(0, 1fr) 2.4rem; }

.ins-bsc__cell[data-side="right"] .ins-bsc__tab { grid-column: 2; }

.ins-bsc__cell[data-side="right"] .ins-bsc__body { grid-column: 1; }

.ins-bsc__tab {
  display: grid;
  place-items: center;
  /* Las cuatro del mismo azul. Una escala de intensidad diria que hay un
     orden entre las perspectivas, y no lo hay: son cuatro maneras de mirar
     lo mismo. La referencia usa cuatro colores por decoracion. */
  background: var(--accent);
  color: var(--bg-raised);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  writing-mode: vertical-rl;
  text-orientation: mixed;
  white-space: nowrap;
  transform: rotate(180deg);
}

.ins-bsc__body {
  display: grid;
  align-content: start;
  gap: 0.85rem;
  padding: 1.1rem 1.1rem 1.1rem 0;
}

.ins-bsc__cell[data-side="right"] .ins-bsc__body { padding: 1.1rem 0 1.1rem 1.1rem; }

/* Fila de arriba: el circulo entra por abajo. Fila de abajo: por arriba.
   El aire lo reserva el CUERPO, no la celda: la pestania va en el borde de
   afuera, donde el circulo no llega nunca, y tiene que correr el alto entero
   del bloque como en la referencia.

   Van DESPUES del padding del lado derecho a proposito. Las dos reglas pesan
   (0,3,0), y la de la derecha es un shorthand: si va ultima le devuelve el
   padding-top a 1.1rem y la celda de abajo a la derecha sube 58px sola. */
.ins-bsc__cell[data-row="top"] .ins-bsc__body { padding-bottom: var(--ins-bsc-clear); }

.ins-bsc__cell[data-row="bottom"] .ins-bsc__body { padding-top: var(--ins-bsc-clear); }

.ins-prose .ins-bsc__table {
  /* El core le da 2.28rem de margen vertical a toda tabla de la prosa. Aca el
     aire lo reparte el `gap` del cuerpo, y ese margen desalineaba las filas. */
  width: 100%;
  margin: 0;
  border-collapse: collapse;
}

/* El core estiliza `.ins-prose table tr:first-child th` con (0,2,3) y le pone
   mayusculas y bold a la primera fila del cuerpo, creyendo que es un encabezado.
   Esta regla es (0,3,3) y lo neutraliza. Ya paso tres veces. */
.ins-prose .ins-bsc__table th,
.ins-prose .ins-bsc__table td,
.ins-prose .ins-bsc__table tr:first-child th {
  padding: 0.55rem 0.65rem;
  border-bottom: 1px solid var(--line);
  font-size: 0.8rem;
  line-height: 1.3;
  text-align: left;
  text-transform: none;
  letter-spacing: 0;
  vertical-align: middle;
}

.ins-prose .ins-bsc__table { min-width: 0; }

.ins-prose .ins-bsc__table thead th,
.ins-prose .ins-bsc__table thead tr:first-child th {
  padding-block: 0.35rem;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
  border-bottom-color: color-mix(in srgb, var(--text-primary) 32%, transparent);
}

.ins-prose .ins-bsc__table tbody th,
.ins-prose .ins-bsc__table tbody tr:first-child th {
  width: 62%;
  font-weight: 400;
  color: var(--text-primary);
}

.ins-prose .ins-bsc__table td {
  font-weight: 700;
  color: var(--ink, var(--text-primary));
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* El actual que quedo por debajo del objetivo. */
.ins-prose .ins-bsc__table td[data-neg] {
  background: color-mix(in srgb, var(--accent-alt) 9%, transparent);
  color: var(--accent-alt);
}

.ins-bsc__note {
  max-width: none;
  margin: 0;
  font-size: 0.76rem;
  line-height: 1.45;
  color: var(--text-muted);
  text-wrap: pretty;
}

/* El centro. Cae en la interseccion, sobre el aire que las celdas reservaron. */
.ins-bsc__core {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 2;
  width: var(--ins-bsc-core);
  height: var(--ins-bsc-core);
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  padding: 0.5rem;
  border: 0.45rem solid var(--ins-paper, var(--bg-raised));
  border-radius: 50%;
  background: var(--accent);
  color: var(--bg-raised);
  font-size: 0.86rem;
  font-weight: 700;
  line-height: 1.25;
  text-align: center;
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes ins-bsc-in {
    from { opacity: 0; transform: scale(0.96); }
    to   { opacity: 1; transform: none; }
  }

  @keyframes ins-bsc-core-in {
    from { opacity: 0; transform: translate(-50%, -50%) scale(0.7); }
    to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  }

  .ins-fig.is-in .ins-bsc__cell {
    animation: ins-bsc-in var(--dur-base) var(--ease-out) both;
    animation-delay: calc((var(--i) - 1) * 0.1s);
  }

  .ins-fig.is-in .ins-bsc__core {
    animation: ins-bsc-core-in var(--dur-base) var(--ease-out) 0.45s both;
  }
}

@media (max-width: 900px) {
  /* Cuatro tablas en dos columnas dejan 150px por tabla. Se apilan, y el
     centro deja de tener una interseccion donde vivir: pasa a ser el titulo
     del conjunto, arriba de todo. */
  .ins-bsc { grid-template-columns: 1fr; }

  .ins-bsc__cell[data-row="top"] .ins-bsc__body,
  .ins-bsc__cell[data-row="bottom"] .ins-bsc__body { padding-block: 1.1rem; }

  /* La animacion del centro es (0,3,0) y le deja puesto translate(-50%,-50%).
     Un `animation: none` en (0,1,0) no la apaga: el centro se va media caja
     para arriba y para la izquierda, fuera de la placa. Hay que empatarle la
     especificidad. */
  .ins-fig.is-in .ins-bsc__core,
  .ins-bsc__core {
    position: static;
    order: -1;
    width: auto;
    height: auto;
    transform: none;
    border: 0;
    border-radius: 0;
    padding: 0.9rem 1.1rem;
    text-align: left;
    animation: none;
  }

  .ins-bsc__cell[data-side="right"] { grid-template-columns: 2.4rem minmax(0, 1fr); }

  .ins-bsc__cell[data-side="right"] .ins-bsc__tab { grid-column: 1; }

  .ins-bsc__cell[data-side="right"] .ins-bsc__body { grid-column: 2; padding: 1.1rem 1.1rem 1.1rem 0; }
}

/* El core convierte TODA tabla de la prosa en tarjetas bajo 640px: esconde el
   thead y apila cada celda. Aca eso deja tres renglones sueltos sin decir cual
   es el objetivo y cual el actual. Tres columnas cortas entran igual en 300px,
   asi que la tabla sigue siendo una tabla. */
@media (max-width: 640px) {
  .ins-prose .ins-bsc__table { display: table; }

  .ins-prose .ins-bsc__table thead {
    position: static;
    width: auto;
    height: auto;
    overflow: visible;
    clip-path: none;
  }

  .ins-prose .ins-bsc__table tbody { display: table-row-group; gap: 0; }

  .ins-prose .ins-bsc__table tbody tr {
    display: table-row;
    padding: 0;
    border: 0;
    background: none;
    box-shadow: none;
  }

  .ins-prose .ins-bsc__table tbody th,
  .ins-prose .ins-bsc__table tbody td {
    display: table-cell;
    padding: 0.5rem 0.5rem;
    border-bottom: 1px solid var(--line);
  }
}

@media (max-width: 460px) {
  .ins-prose .ins-bsc__table th,
  .ins-prose .ins-bsc__table td,
  .ins-prose .ins-bsc__table tr:first-child th { padding-inline: 0.4rem; font-size: 0.74rem; }

  .ins-bsc__cell { grid-template-columns: 1.9rem minmax(0, 1fr); gap: 0.7rem; }
}


/* ==========================================================================
   TRAMO  ·  .ins-stretch
   Envoltorio, no instrumento. Enmarca a otro componente entre dos extremos
   nombrados y le pone abajo cuanto dura el tramo.

   Existe porque en la Fig. 02 del articulo BANT los extremos y la duracion
   son parte del DATO: sin ellos la figura no dice entre que y que pasa todo
   eso, ni cuanto tarda. Sirve con cualquier componente adentro.

   Vive aca y no en el CSS de la pieza para no volver a duplicar: es
   exactamente la deuda que la libreria vino a terminar.
   ========================================================================== */
.ins-stretch { display: grid; gap: 1.1rem; }

.ins-stretch__ends {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  margin: 0;
  max-width: none;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}

.ins-stretch__span {
  margin: 0;
  max-width: none;
  font-size: 0.78rem;
  font-style: italic;
  text-align: center;
  color: var(--accent-alt);
}
