---
title: "Arquitectura de construcción de la plataforma: lo que decidimos y en qué se sostiene."
seo_title: "Arquitectura de plataforma: decisiones y referencias | SazAI"
description: "Cómo construye SazAI: motores agnósticos de formato, linaje, decisiones versionadas, validación con método."
tags: [marketing]
icon: book
---

> **Conclusión: el acelerador es el dominio del equipo sobre el sustrato; y ninguna decisión aquí es cuestión de gusto: la elección está escrita, con lo que se desechó y por qué.** La pirámide de abajo es el mapa; el vacío queda fuera de ella, enunciado.

<div class="chap">

<div class="ico-col"><span class="ico"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:36px;height:36px"><path d="M24 8l16 8-16 8-16-8z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M8 24l16 8 16-8" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M8 32l16 8 16-8" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>

## Qué es SazAI

<h3 class="sub">Motores, componentes y documentación, dominados por quien los construyó</h3>

SazAI es la plataforma: el sustrato de inteligencia y prueba sobre el que se construyen los productos. Multi-inquilino, autenticación, linaje, orquestación, capa de agentes, medición exacta y decisiones versionadas, construidas una sola vez. SazAI Corpus, la bóveda y el design system son los productos que ya han salido de ella, y cada uno usa el mismo motor en lugar de reconstruirlo.

Los paneles descienden por fortaleza de anclaje, y cada uno cierra con sus referencias en un bloque expandible, para quien quiera verificar. Las citas siguen el estándar ABNT NBR 6023, 2018.

<figure class="viz" role="group" aria-label="La pirámide de esta página: cuatro fortalezas de anclaje, desde dependencia de ejecución hasta posicionamiento, y el vacío en el exterior">
<div class="duo" style="grid-template-columns:auto 1fr">
<div class="mid"><svg viewBox="0 0 220 170" aria-hidden="true" style="width:200px">
<polygon points="110,10 150,50 70,50" fill="var(--hue-analysis)" opacity=".85"/>
<polygon points="64,58 156,58 176,92 44,92" fill="var(--hue-output)" opacity=".65"/>
<polygon points="38,100 182,100 198,130 22,130" fill="var(--hue-upload)" opacity=".5"/>
<polygon points="16,138 204,138 214,160 6,160" fill="var(--hue-reprocess)" opacity=".35"/>
<rect x="180" y="8" width="34" height="34" rx="4" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none" stroke-dasharray="4 3" style="color:var(--gray)"/>
</svg></div>
<div class="side" style="text-align:left">
<b style="color:var(--hue-analysis)">dependencia de ejecución</b><span>el motor no funciona sin el estándar · paso 1</span>
<b style="color:var(--hue-output);margin-top:.5rem">estándar aplicado y medido</b><span>ley en el esquema, criterio en el componente, contraste por token · pasos 2 a 4</span>
<b style="color:var(--hue-upload);margin-top:.5rem">decisión registrada</b><span>elección escrita, con lo que se desechó y por qué · pasos 5 y 6</span>
<b style="color:var(--hue-reprocess);margin-top:.5rem">posicionamiento</b><span>estudios con la salvedad adjunta · paso 7</span>
<b style="color:var(--gray);margin-top:.5rem">el vacío</b><span>fuera de la pirámide, y enunciado · último panel</span>
</div>
</div>
<figcaption>La fortaleza del anclaje decide la altura. Lo que no sostiene nada queda fuera del dibujo, punteado, con su propio panel.</figcaption>
</figure>

No es plug and play para alguien que llega de afuera. **El acelerador no es el sustrato; es el dominio del equipo sobre él.** Quien conoce los motores, los componentes y la documentación construye un producto SaaS nuevo a partir de lo que ya existe, y el resto de esta página es la medida de cuánto eso acorta el camino.

<figure class="viz duo" role="group" aria-label="Motores, componentes y documentación; el dominio del equipo en el medio; los productos que salen">
<div class="side" style="color:var(--hue-analysis)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:48px;height:48px"><rect x="10" y="10" width="28" height="28" rx="4" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="24" cy="24" r="6" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="24" y1="4" x2="24" y2="10" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="24" y1="38" x2="24" y2="44" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="4" y1="24" x2="10" y2="24" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="38" y1="24" x2="44" y2="24" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>el sustrato</b>motores, componentes, documentación</div>
<div class="mid" style="color:var(--hue-upload)"><svg viewBox="0 0 120 72" aria-hidden="true"><line x1="6" y1="36" x2="40" y2="36" stroke="currentColor" stroke-width="1.5"/><path d="M34 31l6 5-6 5" fill="none" stroke="currentColor" stroke-width="1.5"/><circle cx="60" cy="36" r="14" fill="currentColor" opacity=".12" stroke="currentColor" stroke-width="1.5"/><path d="M54 36l4 4 8-8" fill="none" stroke="currentColor" stroke-width="1.5"/><line x1="80" y1="36" x2="114" y2="36" stroke="var(--hue-output)" stroke-width="1.5"/><path d="M108 31l6 5-6 5" fill="none" stroke="var(--hue-output)" stroke-width="1.5"/></svg><b>el dominio del equipo</b>es lo que acelera</div>
<div class="side" style="color:var(--hue-output)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:48px;height:48px"><rect x="8" y="12" width="32" height="24" rx="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="8" y1="20" x2="40" y2="20" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="13" cy="16" r="1.4" fill="currentColor"/><circle cx="18" cy="16" r="1.4" fill="currentColor"/></svg><b>los productos</b>Corpus, bóveda, design system</div>
</figure>

El marco para esta idea no es nuevo, y no viene de esta página: es el octavo de los nueve pilares con los que SazAI se describe a sí misma, *plataforma antes que producto*. Lo que sigue es su evidencia.

</div>

<div class="chap">

<div class="ico-col"><sz-icon style="color:var(--hue-analysis)" name="file" size="36"></sz-icon></div>

## El motor depende de estándares de formato para existir

<h3 class="sub">Paso 1 · dependencia de ejecución, el anclaje más fuerte que hay</h3>

Si el estándar fuera incorrecto en el código, el motor no funcionaría. La referencia no se menciona; se depende de ella, y el determinismo sale de eso.

**Datos y hechos:**

- Espacio de nombres OOXML en el motor: 237 apariciones en 37 formas distintas (2026-09-01).
- Dublin Core como dependencia: 22 espacios de nombres. ISO 8601: el estándar más citado en la base de datos, 60 apariciones.
- La cadena verificable: cláusula publicada → comentario DDL → mapa de datos → columna. Paráfrasis prohibida por regla escrita; DDL y mapa llevan la misma cláusula, textualmente.

<figure class="viz duo four" role="group" aria-label="La cadena del determinismo: cláusula publicada, comentario DDL, capa de mapa, columna relacional">
<div class="side" style="color:var(--hue-analysis)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:40px;height:40px"><path d="M12 6h18l8 8v28H12z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M30 6v8h8" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="18" y1="24" x2="32" y2="24" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>cláusula publicada</b>el estándar, por número</div>
<div class="side" style="color:var(--hue-analysis)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:40px;height:40px"><rect x="8" y="10" width="32" height="28" rx="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="14" y1="18" x2="34" y2="18" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none" stroke-dasharray="3 2"/><line x1="14" y1="25" x2="30" y2="25" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="14" y1="31" x2="30" y2="31" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>comentario DDL</b>la misma cláusula, textualmente</div>
<div class="side" style="color:var(--hue-analysis)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:40px;height:40px"><circle cx="14" cy="14" r="5" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="34" cy="18" r="5" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="22" cy="34" r="5" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="17" y1="17" x2="31" y2="16" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="16" y1="18" x2="20" y2="30" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>capa de mapa</b>sin paráfrasis, por regla</div>
<div class="side" style="color:var(--hue-analysis)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:40px;height:40px"><rect x="8" y="8" width="32" height="32" rx="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="20" y1="8" x2="20" y2="40" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="8" y1="20" x2="40" y2="20" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>columna relacional</b>existe porque la cláusula existe</div>
</figure>


### Y el siguiente formato cuesta menos

El primer formato fue PowerPoint, y costó el motor completo: leer, medir, traducir, escribir de vuelta, comparar, todo por primera vez. El segundo, el documento Word, costó un orden de magnitud menos. El tercero, la hoja de cálculo, uno más. Y el cuarto, PDF, costó lo mismo que el tercero: la curva se estabilizó. No es una lista de logros; es una curva, y la curva es el argumento.

<figure class="viz curve" role="group" aria-label="Costo de cada formato en el ciclo completo, en escala logarítmica: el primero costó el motor completo, cada siguiente un orden de magnitud menos, y el cuarto se estabiliza al mismo costo que el tercero">
<div class="row ooxml"><b>PPTX</b><span class="track"><span class="bar" style="width:100%"></span></span><em>el motor completo</em></div>
<div class="row ooxml"><b>DOCX</b><span class="track"><span class="bar" style="width:46%"></span></span><em>un orden menos</em></div>
<div class="row ooxml"><b>XLSX</b><span class="track"><span class="bar" style="width:16%"></span></span><em>uno más</em></div>
<div class="row other"><b>PDF</b><span class="track"><span class="bar" style="width:15%"></span></span><em>se estabiliza</em></div>
<figcaption>Escala logarítmica: cada paso es un orden de magnitud. El cuarto punto no es solo el más pequeño: es de una naturaleza diferente, y costó lo mismo que el tercero.</figcaption>
</figure>

<p class="claim">El <b>PDF es el primer sustrato que no es Office</b>: un grafo binario de objetos en lugar de zip más XML. Si el motor solo hubiera mejorado en PowerPoint, el cuarto formato habría costado como el primero. Costó como el tercero. <b>El motor no se hizo más rápido en PowerPoint; se hizo agnóstico de formato</b>, y los <a href="documents">cuatro formatos</a> se ejecutan hoy en la misma arquitectura, cada uno con su garantía declarada. Por eso el quinto costará lo que costó el cuarto, y eso es lo que esta página llama aceleración.</p>

<div class="bound">
<p><b>Dónde esto está registrado, enunciado antes de que preguntes.</b> En git, no en el diario institucional: la curva descansa en decisiones fechadas y en commits, que son la fuente correcta para un intervalo, y eso es lo que se verifica en una evaluación. Los tiempos absolutos para cada formato viven en el documento técnico, con el comando que los deriva junto a él.</p>
</div>
<details class="refs"><summary>Referencias y decisiones registradas</summary>
<div>
<p><b>Lo que está escrito, y lo que se desechó</b></p><ul><li>Leer cada formato por el estándar, cláusula por cláusula; la heurística se desechó porque no sobrevive una auditoría.</li><li>Fechas en ISO 8601 en todo el sistema; metadatos por Dublin Core.</li><li>PDF aceptado como el primer sustrato que no es Office, citado por su propio estándar.</li></ul><p><b>Referencias (ABNT NBR 6023:2018)</b></p><ul><li>ECMA INTERNATIONAL. <b>ECMA-376</b>: Office Open XML File Formats. Disponible en: https://ecma-international.org/publications-and-standards/standards/ecma-376/.</li><li>ISO/IEC. <b>ISO/IEC 29500</b>: Office Open XML File Formats.</li><li>ISO. <b>ISO 32000-1</b>: Portable Document Format. · ISO. <b>ISO 19005</b>: PDF/A.</li><li>ISO. <b>ISO 15836-1</b>: Dublin Core. · ISO. <b>ISO 8601</b>: Date and time.</li><li>IETF. <b>RFC 5646</b>: Tags for Identifying Languages.</li><li>MICROSOFT. <b>MS-PPTX · MS-DOCX · MS-OE376 · MS-ODRAWXML · MS-OFFCRYPTO</b>: implementation notes.</li><li>UNICODE CONSORTIUM. <b>Unicode CMap</b> specifications.</li></ul>
</div>
</details>

</div>

<div class="chap">

<div class="ico-col"><span class="ico"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:36px;height:36px"><circle cx="24" cy="24" r="5" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="10" cy="12" r="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="38" cy="10" r="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="12" cy="38" r="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="38" cy="36" r="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="13" y1="14" x2="20" y2="21" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="35" y1="12" x2="28" y2="21" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="14" y1="36" x2="20" y2="27" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="35" y1="34" x2="28" y2="27" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>

## El cuerpo de conocimiento

<h3 class="sub">Todo lo que decidimos, medimos y escribimos, ligado, y navegable por el equipo y por agentes</h3>

El dominio del equipo sobre el sustrato tiene un lugar donde vive: una bóveda Obsidian que refleja el repositorio. Decisiones, el mapa de datos, contratos de agentes, personas, estrategia, sesiones de trabajo: cada nota se enlaza con las otras, y los hubs son las puertas por donde entra una persona o un agente. Es el mismo grafo que el producto entrega al cliente en su propia bóveda, usado primero en nosotros mismos. Abajo, el nuestro, en movimiento; pasa sobre un hub para ver a qué se enlaza, y haz clic para abrirlo completo.

<figure class="viz graph" id="vault-graph" role="group" tabindex="0" aria-label="El grafo de la bóveda de SazAI: los hubs para decisiones, agentes, mapa de datos, producto, estrategia, operaciones, personas, pitch y personas, enlazados entre sí y con sus notas">
<div class="stage"><svg viewBox="0 0 800 520" aria-hidden="true"><g class="edges"></g><g class="nodes"></g></svg><div class="labels" aria-hidden="true"></div></div>
<figcaption>La bóveda de SazAI, como el equipo la ve cada día. Cada punto es una nota; cada línea, un enlace que alguien escribió. Los hubs tienen nombres; el resto es lo que enlazan. Conjunto de nodos fotografiado a mano el 2026-08-28; cuando llegue la derivación automática de la bóveda, esta línea se va.</figcaption>
</figure>

<div class="bound">
<p><b>Hasta dónde llega el mapa, medido, y es la parte que más vale.</b> El grafo de la bóveda llega a 55 de las 158 tablas del mapa de datos y a uno de los cinco mapas de formato; el repositorio llega a 158 de 158. Una figura que mostrara todo conectado sería el único reclamo de esta página sin recibo detrás, en una página cuyo tema completo es que nuestros reclamos llevan recibos. Lo que se valida no es que todo se conecte: es que sabemos exactamente qué se conecta y qué no. Donde el mapa es silencioso, el repositorio responde.</p>
</div>

</div>

<div class="chap">

<div class="ico-col"><sz-icon style="color:var(--hue-reprocess)" name="info" size="36"></sz-icon></div>

## La protección de datos es diseño, y el diseño se audita

<h3 class="sub">Paso 2 · la ley se convirtió en esquema, y el esquema se puede verificar</h3>

Lo que la ley pide por escrito, la base de datos lo cumple a través de la estructura. La verificación no es leer nuestra política; es auditar el esquema.

**Datos y hechos:**

- El almacenamiento permanente no lleva contenido de documentos; el contenido vive en una base de datos separada, sensible y borrable.
- Aislamiento por inquilino como columna, no como promesa: las divisiones nunca cruzan inquilinos.
- Certificación hoy: ninguna. Controles diseñados para servir como evidencia cuando se busquen.

<figure class="viz duo" role="group" aria-label="Dos bases de datos: la permanente sin contenido, y la sensible, separada y borrable">
<div class="side" style="color:var(--hue-analysis)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:48px;height:48px"><ellipse cx="24" cy="12" rx="14" ry="5" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M10 12v24c0 3 6 5 14 5s14-2 14-5V12" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="16" y1="22" x2="32" y2="22" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="16" y1="29" x2="28" y2="29" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>permanente</b>estructura, medición, linaje; contenido, nunca</div>
<div class="mid" style="color:var(--gray)"><svg viewBox="0 0 120 72" aria-hidden="true"><line x1="60" y1="10" x2="60" y2="62" stroke="currentColor" stroke-width="1.5" stroke-dasharray="4 3"/></svg><b>separado por diseño</b>audita el esquema</div>
<div class="side" style="color:var(--hue-reprocess)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:48px;height:48px"><ellipse cx="24" cy="12" rx="14" ry="5" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M10 12v24c0 3 6 5 14 5s14-2 14-5V12" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none" stroke-dasharray="4 3"/><line x1="18" y1="26" x2="30" y2="34" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="30" y1="26" x2="18" y2="34" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>sensible</b>el contenido, verdaderamente borrable</div>
</figure>

<details class="refs"><summary>Referencias y decisiones registradas</summary>
<div>
<p><b>Lo que está escrito, y lo que se desechó</b></p><ul><li>Privacidad por diseño y por defecto como arquitectura; una capa de cumplimiento sobre una base de datos compartida se desechó.</li><li>La remoción se llama <b>retiro</b>, no eliminación: la palabra más fuerte se desechó porque prometía un alcance que las copias de seguridad no sostienen.</li></ul><p><b>Referencias (ABNT NBR 6023:2018)</b></p><ul><li>EUROPEAN UNION. <b>Regulation (EU) 2016/679</b> (GDPR), art. 25.</li><li>BRAZIL. <b>Law No. 13,709, of August 14, 2018</b> (LGPD).</li><li>CAVOUKIAN, Ann. <b>Privacy by Design</b>: the 7 foundational principles. Toronto: IPC, 2009.</li><li>ISO/IEC. <b>ISO/IEC 27001</b>. · OWASP FOUNDATION. Disponible en: https://owasp.org/.</li></ul>
</div>
</details>

</div>

<div class="chap">

<div class="ico-col"><sz-icon style="color:var(--hue-output)" name="eye" size="36"></sz-icon></div>

## La accesibilidad se mide, no se declara

<h3 class="sub">Paso 3 · un estándar citado es cumplimiento; un número medido es diseño</h3>

El criterio vive en el componente, con el número junto al código, y el contraste se mide antes de que un color entre en el sistema.

**Datos y hechos:**

- WCAG 2.2 AA en 51 archivos del design system, con criterios citados por número (1.4.1, 3.1) (2026-09-01).
- Contraste medido por token: `--hue-linaje` en 4.00:1 con la nota *guía, nunca texto* escrita dentro del token mismo; `--text-faint` **falló** por medir 2.56:1 en blanco, y el fallo registrado.
- Ceguera al color medida: el púrpura evaluado bajo deuteranopía, distancia de color ΔE 29.1.
- Cero decisiones de arquitectura registran WCAG; el anclaje de accesibilidad más fuerte de la casa es invisible en el registro de decisiones, y registrarlo es trabajo aún por hacer.

<figure class="viz" role="group" aria-label="Tres medidas de color: un token aprobado como guía, uno fallido, y el púrpura medido bajo deuteranopía">
<div class="duo" style="grid-template-columns:1fr 1fr 1fr">
<div class="side"><div class="ev proof" style="margin:0"><span class="n">4.00:1</span><span class="t"><b>aprobado como guía</b>con la nota <i>guía, nunca texto</i> escrita dentro del token mismo</span></div></div>
<div class="side"><div class="ev open" style="margin:0"><span class="n">2.56:1</span><span class="t"><b>falló</b>medido en blanco, y el fallo registrado</span></div></div>
<div class="side"><div class="ev proof" style="margin:0"><span class="n">ΔE 29.1</span><span class="t"><b>deuteranopía</b>el púrpura medido bajo la deficiencia de color más común</span></div></div>
</div>
<figcaption>Un estándar citado es cumplimiento; un número medido es diseño. Los tres números viven en los tokens, no en una política.</figcaption>
</figure>

### El design system es un producto, construido sobre un estándar abierto

<h3 class="sub">Paso 4 · el acelerador para las otras superficies, en estándar W3C</h3>

El design system es un producto SazAI por ratificación (2026-08-26), con la función de acelerar los otros: los componentes que sirven marketing, la bóveda y la vitrina son los mismos, y son estándar abierto, no un marco propietario.

**Datos y hechos:**

- Componentes construidos en W3C Custom Elements y CSS Custom Properties; sin dependencia de marco.
- Una biblioteca, tres superficies servidas; temas claro y oscuro y skins blanco etiquetados a través del mismo mecanismo de tokens.
- Los tokens llevan sus propias mediciones y notas de uso (paso 3), así que la regla viaja con el color.

<figure class="viz duo" role="group" aria-label="Una biblioteca de componentes sirviendo tres superficies">
<div class="side" style="color:var(--verb-see)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:48px;height:48px"><rect x="8" y="8" width="14" height="14" rx="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><rect x="26" y="8" width="14" height="14" rx="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><rect x="8" y="26" width="14" height="14" rx="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><rect x="26" y="26" width="14" height="14" rx="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>una biblioteca</b>componentes, tokens, skins</div>
<div class="mid" style="color:var(--gray)"><svg viewBox="0 0 120 72" aria-hidden="true"><line x1="10" y1="36" x2="55" y2="36" stroke="currentColor" stroke-width="1.5"/><line x1="55" y1="36" x2="105" y2="14" stroke="currentColor" stroke-width="1.5"/><line x1="55" y1="36" x2="105" y2="36" stroke="currentColor" stroke-width="1.5"/><line x1="55" y1="36" x2="105" y2="58" stroke="currentColor" stroke-width="1.5"/></svg><b>el mismo mecanismo</b>temas y blanco etiquetado por token</div>
<div class="side" style="color:var(--hue-output)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:48px;height:48px"><rect x="6" y="8" width="36" height="10" rx="2" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><rect x="6" y="22" width="36" height="10" rx="2" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><rect x="6" y="36" width="36" height="6" rx="2" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>tres superficies</b>marketing, bóveda, vitrina</div>
</figure>


<details class="refs"><summary>Referencias y decisiones registradas</summary>
<div><p><b>Lo que está escrito, y lo que se desechó</b></p><ul><li>Criterio por número en el componente que lo cumple; la página de política central se desechó.</li><li>Palabra fuera del diseño: texto en HTML, geometría en SVG.</li></ul><p><b>Referencias (ABNT NBR 6023:2018)</b></p><ul><li>W3C. <b>WCAG 2.2</b>: Web Content Accessibility Guidelines, nivel AA. Recomendación, 2023. Disponible en: https://www.w3.org/TR/WCAG22/.</li></ul><p><b>Lo que está escrito, y lo que se desechó</b></p><ul><li>Web Components estándar; el marco propietario se desechó para que el etiquetado blanco no dependa de una licencia nuestra.</li><li>Sostenido al mismo estándar que cualquier superficie: una suite que se ejecuta, guardias que rechazan en la compilación.</li></ul><p><b>Referencias (ABNT NBR 6023:2018)</b></p><ul><li>W3C. <b>Custom Elements</b> (HTML Living Standard). · W3C. <b>CSS Custom Properties for Cascading Variables</b>.</li></ul></div>
</details>

</div>

<div class="chap">

<div class="ico-col"><sz-icon style="color:var(--hue-analysis)" name="globe" size="36"></sz-icon></div>

## Los canales son capacidad: API y MCP cambian lo que el producto puede ser

<h3 class="sub">Paso 5 · estándares abiertos en la puerta, y lo que habilitan</h3>

API abierta y MCP no son fontanería: es lo que permite que otras interfaces y conexiones se construyan sobre el mismo sustrato, sin nosotros en la sala. Un agente de terceros, un panel de los tuyos, una integración de flujo de trabajo: el producto se vuelve capaz de ser esas cosas porque los canales existen.

**Datos y hechos:**

- El canal del agente es un servidor de recursos OAuth estándar: 401 sin credencial, descubrimiento publicado.
- Paridad como contrato: **MCP ⊆ OpenAPI**, todo lo que MCP expone existe en la API abierta. Un sustrato, varios lectores.
- Orquestación por una herramienta de ejecución de flujo de trabajo durable, adoptada por lo que garantiza, y la garantía se mide: el trabajo muerto no deja estado parcial; la sobrecarga degrada en una cola, no se rompe; nada falla silenciosamente.

<figure class="viz duo" role="group" aria-label="Un sustrato, dos canales, y las interfaces que habilitan">
<div class="side" style="color:var(--hue-analysis)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:48px;height:48px"><rect x="10" y="10" width="28" height="28" rx="4" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="24" cy="24" r="6" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>un sustrato</b>el motor y la bóveda</div>
<div class="mid" style="color:var(--hue-upload)"><svg viewBox="0 0 120 72" aria-hidden="true"><rect x="38" y="14" width="44" height="18" rx="9" stroke="currentColor" stroke-width="1.5" fill="currentColor" opacity=".12"/><rect x="38" y="40" width="44" height="18" rx="9" stroke="currentColor" stroke-width="1.5" fill="none"/><line x1="10" y1="36" x2="38" y2="24" stroke="currentColor" stroke-width="1.5"/><line x1="10" y1="36" x2="38" y2="48" stroke="currentColor" stroke-width="1.5"/><line x1="82" y1="24" x2="110" y2="16" stroke="var(--hue-output)" stroke-width="1.5"/><line x1="82" y1="48" x2="110" y2="40" stroke="var(--hue-output)" stroke-width="1.5"/><line x1="82" y1="36" x2="110" y2="60" stroke="var(--hue-output)" stroke-width="1.5"/></svg><b>API y MCP</b>MCP ⊆ OpenAPI, por contrato</div>
<div class="side" style="color:var(--hue-output)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:48px;height:48px"><path d="M24 6l4 12 12 4-12 4-4 12-4-12-12-4 12-4z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>lo que puede ser</b>agentes tuyos, paneles tuyos, flujos de trabajo tuyos</div>
</figure>

<details class="refs"><summary>Referencias y decisiones registradas</summary>
<div><p><b>Lo que está escrito, y lo que se desechó</b></p><ul><li>Código abierto ante la bóveda, API RESTful con descobrimiento OpenAPI; el modelo de distribución propietario se desechó.</li><li>Observabilidad por la misma bóveda: registros de trabajos y la bóveda del usuario son la instrumentación, no un servicio aparte.</li></ul><p><b>Referencias (ABNT NBR 6023:2018)</b></p><ul><li>OPENAPIS INITIATIVE. <b>OpenAPI 3.1.0 Specification</b>. Disponible en: https://spec.openapis.org/oas/v3.1.0.</li><li>ANTHROPIC. <b>Model Context Protocol</b> (MCP). Disponible en: https://modelcontextprotocol.io/.</li><li>OASIS. <b>OpenData Protocol</b> (OData). · IETF. <b>RFC 6749</b>: The OAuth 2.0 Authorization Framework.</li></ul></div>
</details>

</div>

<div class="chap">

<div class="ico-col"><span class="ico"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:36px;height:36px"><path d="M12 6h18l8 8v28H12z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M30 6v8h8" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="24" cy="28" r="6" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="24" y1="25" x2="24" y2="29" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="24" cy="31.5" r=".9" fill="currentColor"/></svg></span></div>

## Cómo validamos

<h3 class="sub">Pruebas que rechazan, auditoría con método, y defectos publicados junto a lo que pasó</h3>

La validación tiene cuatro capas, y el orden importa. **Pruebas:** 505 archivos de prueba en el repositorio, con la suite del design system ejecutándose en cada compilación. **Guardias:** verificaciones que rechazan en tiempo de compilación en lugar de solo reportar; una compilación que viola una regla no se entrega. **Carga:** la prueba del 2026-07-20, en una réplica fiel de producción, con 50 lecturas concurrentes respondidas en 0.77 s, un trabajo pesado llegando a 4.71 GiB contra un techo de 5, y ondas de cinco y diez trabajos con cero fallos, cero desbordamientos de memoria, cero corrupción. Bajo sobrecarga el sistema entra en una cola; no se rompe. **Auditoría interna:** reportes fechados de estrés, destrucción y seguridad, con un veredicto por elemento.

<figure class="viz duo four" role="group" aria-label="Cuatro capas de validación: pruebas, guardias que rechazan, auditoría con método, defectos publicados">
<div class="side" style="color:var(--hue-output)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:44px;height:44px"><rect x="8" y="8" width="32" height="32" rx="3" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M15 24l6 6 12-12" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>505 pruebas</b>la suite se ejecuta en cada compilación</div>
<div class="side" style="color:var(--hue-output)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:44px;height:44px"><path d="M8 12h32v10H8z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M8 26h32v10H8z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="30" y1="14" x2="36" y2="20" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="36" y1="14" x2="30" y2="20" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M28 31l3 3 5-6" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>guardias que rechazan</b>una compilación violada no se entrega</div>
<div class="side" style="color:var(--hue-output)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:44px;height:44px"><circle cx="21" cy="21" r="11" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="29" y1="29" x2="40" y2="40" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="16" y1="19" x2="26" y2="19" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="16" y1="24" x2="23" y2="24" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>auditoría con método</b>estrés, destrucción, seguridad</div>
<div class="side" style="color:var(--hue-output)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:44px;height:44px"><path d="M12 6h18l8 8v28H12z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M30 6v8h8" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="24" cy="28" r="6" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="24" y1="25" x2="24" y2="29" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><circle cx="24" cy="31.5" r=".9" fill="currentColor"/></svg><b>defectos publicados</b>junto a lo que pasó</div>
</figure>

<p class="claim">No estamos certificados en SOC2 ni ISO. Lo que tenemos es <b>auditoría interna documentada, con un método declarado y con los defectos que encontró publicados junto a los que pasó</b>. Uno de nuestros reportes lleva, como sus propias secciones, <i>defectos encontrados</i>, <i>un falso positivo que casi publico</i>, e <i>lo que no pude establecer</i>. Un sello es la palabra de un tercero; un método declarado, el lector técnico juzga solo. Y las decisiones escritas están diseñadas para servir como evidencia de control cuando se busque certificación.</p>

<div class="bound">
<p><b>Lo que esta página cita y lo que no cita.</b> Aquí está la existencia de los reportes y su método. Los veredictos elemento por elemento viven en el documento técnico que acompaña una evaluación, porque publicar la lista de sondas con resultados en el tope del embudo entrega un mapa a quien no debería tener uno. La frase que la prueba de carga <i>no</i> autoriza: <i>cincuenta concurrentes</i>. Son cincuenta asientos y un trabajo pesado a la vez; confundir los dos es el error que esta página existe para no cometer.</p>
</div>

<details class="refs"><summary>Referencias y decisiones registradas</summary>
<div><p><b>Metodología externa declarada para el eje de pruebas: ninguna.</b> Práctica fuerte, guardias que rechazan en compilación, reportes fechados; la fuente del método es interna, y decirlo es parte del método.</p></div>
</details>

</div>

<div class="chap">

<div class="ico-col"><span class="ico"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:36px;height:36px"><path d="M12 6h18l8 8v28H12z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M30 6v8h8" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="18" y1="22" x2="32" y2="22" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="18" y1="28" x2="32" y2="28" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="18" y1="34" x2="26" y2="34" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="15" y1="25" x2="35" y2="25" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none" stroke-width="2"/></svg></span></div>

## Cómo decidimos

<h3 class="sub">Decisiones escritas y fechadas, y una supersesión que tacha dos frases y nada más</h3>

Toda decisión de arquitectura de SazAI es un documento fechado, con el contexto, la alternativa rechazada y la razón. Hay 61 en la fecha de esta página, y el número entra fechado porque crece; el comando que lo deriva está en las referencias de este panel. Lo que hace esto un recibo y no un archivo muerto es la supersesión: cuando una nueva decisión contradice una antigua, enuncia exactamente qué frase de la antigua deja de valer, y la antigua recibe la marca en su propio cuerpo, en la frase, y no en el título.

El ejemplo más reciente es de ayer. Decisión 023 fijó, entre otras cosas, el vocabulario con que el usuario nombra las capacidades del producto. Decisión 061 superó **dos frases** de ella, ambas sobre vocabulario, y dejó todo lo del motor intacto, incluyendo la cláusula creída violada que no lo era. Tres lectores competentes habían leído esa cláusula de la misma manera equivocada, y la decisión registra los tres nombres, porque una decisión que mantiene solo la conclusión pierde la razón de por qué tres personas se equivocaron juntas.

<figure class="viz duo" role="group" aria-label="Una decisión antigua con dos frases tachadas y el resto intacto, enlazada a la nueva decisión">
<div class="side" style="color:var(--hue-reprocess)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:52px;height:52px"><path d="M12 6h18l8 8v28H12z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M30 6v8h8" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="18" y1="22" x2="32" y2="22" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="18" y1="28" x2="32" y2="28" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="18" y1="34" x2="26" y2="34" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><line x1="15" y1="25" x2="35" y2="25" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none" stroke-width="2"/></svg><b>la decisión antigua</b>dos frases tachadas, el resto intacto</div>
<div class="mid" style="color:var(--hue-reprocess)"><svg viewBox="0 0 120 72" aria-hidden="true"><line x1="10" y1="36" x2="106" y2="36" stroke="currentColor" stroke-width="1.5"/><path d="M100 31l6 5-6 5" fill="none" stroke="currentColor" stroke-width="1.5"/><rect x="42" y="26" width="36" height="20" rx="10" fill="currentColor" opacity=".12" stroke="currentColor" stroke-width="1.5"/></svg><b>supersede</b>nombra la frase, y solo ella</div>
<div class="side" style="color:var(--hue-output)"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:52px;height:52px"><path d="M12 6h18l8 8v28H12z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M30 6v8h8" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M18 28l4 4 8-8" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg><b>la decisión nueva</b>con los tres nombres que se equivocaron juntos</div>
</figure>

<div class="bound">
<p><b>Un número que esta página no publica.</b> Cuántas de estas decisiones son <i>aceptadas</i> depende de cuáles palabras el contador admite en el campo de estado, y cinco contadores competentes llegaron a cinco números diferentes esta semana. Nadie se equivocó: el campo nunca declaró su propio vocabulario. Publicamos el conteo fechado, con el comando junto a él; el conteo de aceptadas solo va a público cuando viene con el comando que lo produce junto a él, de la manera que las 158 tablas ya lo hacen.</p>
</div>

### Y cómo escribimos: un contrato interno, un paso abajo por honestidad

<h3 class="sub">Paso 6 · coherencia interna registrada, un paso bajo estándar externo</h3>

Estilo de escritura, nombres y convenciones de la casa viven en un contrato versionado que los agentes citan. Su anclaje es coherencia interna con una decisión registrada, no un estándar externo numerado; eso es un paso bajo los anteriores, y bajar de un paso prueba que la jerarquía de esta página se aplica incluso cuando cuesta algo.

**Datos y hechos:**

- Un estándar de escritura único, versionado por revisión, citado por decisiones y por agentes como contrato.
- Nombres y convenciones de nombres uniformes en todo el sistema; un estándar citado nunca se parafrasea.
- Formato, lint y escaneo secreto automatizados, declarados en el estándar con la fuente junto a ellos.

<figure class="viz" role="group" aria-label="Coherencia interna registrada: un paso bajo un estándar externo, dibujado punteado a propósito">
<div class="ev open"><span class="n">coherencia interna</span><span class="t"><b>Un paso abajo, y dibujado así</b>El anclaje de este panel es una decisión registrada, no un estándar numerado. El marco punteado es el mismo que la casa usa para todo lo que no es un recibo, y un panel que baja de un paso prueba que la jerarquía se aplica incluso cuando cuesta algo.</span></div>
</figure>


<details class="refs"><summary>Referencias y decisiones registradas</summary>
<div>
<p><b>Lo que está escrito, y lo que se desechó</b></p><ul>
<li>El conteo: <code>ls docs/corpus/pptx/tech_specs/ADR | grep -c '^ADR-'</code> devuelve 61 el 2026-09-01. El número crece; el comando no.</li><li>Las alternativas de nombres fueron rechazadas por convergencia en tres superficies, y el rechazo se registra con la razón.</li></ul><p><b>Referencias</b></p><p>el contrato interno (<i>code_standards</i>, versionado) nombra sus propias fuentes; esta página no lo parafrasea.</p>
</div>
</details>

</div>

<div class="chap">

<div class="ico-col"><sz-icon style="color:var(--hue-output)" name="check" size="36"></sz-icon></div>

## Qué es un recibo, y qué aún es práctica

<h3 class="sub">Cuatro capacidades con evidencia; tres declaradas, sin verbo en tiempo presente</h3>

Cada capacidad en esta plataforma fue sometida a tres preguntas: ¿hay una decisión escrita que la gobierna? ¿hay una medición? ¿o solo funciona, sin que nadie haya escrito por qué? Lo que pasa las dos primeras lo llamamos <dfn data-hint="Una capacidad con una decisión escrita y una medición que cualquiera puede reproducir: no una promesa, un registro.">recibo</dfn>. El resto es práctica, y se mantiene declarado como dirección, de la misma manera que la [hoja de ruta](#roadmap) de abajo declara lo que aún no existe. Una página que presenta siete capacidades donde tres son recibos es más débil que una que presenta cuatro.

<figure class="viz ledger" role="group" aria-label="Cuatro recibos con su evidencia y tres prácticas declaradas como dirección">
<div class="col receipts">
<h4>Recibo</h4>
<div class="item"><b>Plug and play</b><span>4 ADRs y la receta · la curva de cuatro puntos · la partición de 158 tablas, re-derivable</span></div>
<div class="item"><b>Control de colas</b><span>5 ADRs · prueba de carga con cero fallos, cero OOM, cero corrupción</span></div>
<div class="item"><b>Arquitectura · linaje · multi-inquilino</b><span>con la frontera del proveedor declarada como agujero nombrado</span></div>
<div class="item"><b>Versionamiento de decisión</b><span>decisiones fechadas, supersesión quirúrgica</span></div>
</div>
<div class="col practices">
<h4>Práctica declarada</h4>
<div class="item"><b>Versionamiento de esquema</b><span>dirección declarada</span></div>
<div class="item"><b>Versionamiento de artefacto</b><span>dirección declarada</span></div>
<div class="item"><b>Comunicación entre agentes</b><span>dirección declarada, con modos de fallo medidos</span></div>
</div>
</figure>
<p class="claim">Los cuatro de la izquierda tienen dónde verificarse, y los capítulos siguientes dicen dónde. Los tres de la derecha son hacia dónde va la plataforma, y ninguno de sus verbos está en tiempo presente.</p>

### Y el mercado: estudios con las salvedades adjuntas

<h3 class="sub">Paso 7 · anclajes donde jugamos, no cómo construimos</h3>

Este paso sostiene posicionamiento, no ingeniería, y por eso está al final: es el anclaje más débil de la página, y se etiqueta como tal.

**Datos y hechos:**

- Siete casas: Gartner, BCG, McKinsey, Deloitte, Menlo Ventures, MIT NANDA, Stanford HAI.
- Salvedades incorporadas en las entradas mismas: preliminar llamado preliminar (MIT NANDA, n=52); republicado llamado republicado (Stanford/McKinsey); un corte regional llamado regional (Deloitte, EMEA).
- El 79% de BCG demuestra el obstáculo, datos no estructurados ingobernados; no demuestra el puente.
- La investigación de encuestas ejecutivas es percepción, no finanzas auditadas.


<details class="refs"><summary>Referencias y decisiones registradas</summary>
<div>
<p><b>Lo que está escrito, y lo que se desechó</b></p><ul><li>Plataforma antes que producto; compra antes que construcción.</li><li>En IA Sombra, solo la forma citable: reducción a través de un camino corporativo gobernado. "SazAI resuelve IA Sombra" se desechó por no tener medición que lo apoye.</li></ul><p><b>Referencias</b></p><p>las entradas completas en forma ABNT NBR 6023:2018 están en los bloques de esta página; de las 25 en el inventario, las consultadas en línea llevan <i>Acceso el</i>, como el estándar requiere, y el resto no, como el estándar permite.</p>
</div>
</details>

</div>

<div class="chap">

<div class="ico-col"><span class="ico"><svg viewBox="0 0 48 48" aria-hidden="true" style="width:36px;height:36px"><circle cx="24" cy="24" r="16" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M31 17l-4 10-10 4 4-10z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>

<a id="roadmap"></a>

## Hoja de ruta: lo que estamos construyendo

La hoja de ruta contiene las grandes direcciones, las que la plataforma señala y aún no ha construido. Cuando algo sale de aquí, desaparece de esta lista y aparece en la página de la capacidad correspondiente, con la fecha. Una hoja de ruta que se mueve es la única prueba de ritmo que no puede escribirse con un adjetivo. Nada de abajo ha llegado a producción, y ningún elemento aquí debería influir en tu decisión hoy.
Nada en esta página ha llegado a producción. Ningún elemento aquí debería influir en tu decisión hoy, y nadie de nuestro equipo debería presentar ninguno de ellos en tiempo presente. Lo que ha llegado está en la [página de demostración del producto](/) con lo que garantiza, y los límites de lo que existe están en [confianza](trust).

## Redacción y negociación con inteligencia

Comparar un borrador contra las revisiones de las partes, mostrar qué cambió cada lado, dónde se desplazó el riesgo, y qué intención revela el texto. El motor de comparación que sustenta esto ya existe y se ejecuta hoy sobre versiones de documentos. Lo que falta es la capa legal: entender que una cláusula alterada no es solo un párrafo diferente.

**Por qué está en la hoja de ruta y no en la carretera:** es la dirección con el mayor potencial para crear su propia categoría, y eso es exactamente por qué es la más fácil de vender demasiado pronto. No existe.

## Agentes especializados sobre tu corpus

Agentes con su propio alcance, construidos sobre el conocimiento que ya está en tu bóveda: un tutor que enseña de material real de tu empresa, un compañero de adopción para un nuevo proceso, un evaluador que verifica competencia citando la fuente que usó.

**Lo que ya se sostiene debajo:** el corpus, linaje, el agente conversacional, y cita de fuentes. **Lo que falta:** especialización a nivel de tarea, con sus propios límites y reglas por agente.

## Sustrato para una flota de agentes gobernados

El siguiente paso desde el anterior, y el de mayor alcance. Cada parte de la empresa alimenta la bóveda con sus propios documentos, y los agentes que esa parte ya usa consultan esa bóveda en tiempo de ejecución, por archivo o por protocolo, para cualquier pregunta sobre la empresa. Una fuente gobernada única debajo de toda una flota, en lugar de herramientas de IA sueltas que nadie audita.

**Por qué esto es hoja de ruta y no una promesa vaga:** el mecanismo de adopción es concreto y ya existe en parte, porque la bóveda es portátil y consumible desde afuera. Lo que falta es gobernanza de flota, y no está construido.

## Cosas que existen y que aún no podemos mostrarte

Estas son brechas de evidencia, no características faltantes. La capacidad existe; la prueba pública no, y hasta que exista preferimos listar la brecha que hablar alrededor de ella.

- **Exportación de bóveda demostrada.** La bóveda existe y es texto plano con enlaces; lo que falta es una demostración publicada que cualquiera pueda reproducir sin hablarnos. Hasta entonces, es una conversación de debida diligencia, no un elemento de página.
- **Suficiencia del registro para auditoría formal.** El registro existe y sirve como evidencia de control. Si cierra un requisito de auditoría específico en tu sector es una pregunta que respondemos caso a caso, no un reclamo de página.
- **Escala por encima de lo que medimos.** Volúmenes en cientos de miles o millones de documentos no han sido ejercitados. Eso es un proyecto de dimensionamiento antes de ser una compra.

## Cosas que aún no existen

Estas son características faltantes, y archivarlas en cualquier lugar más suave te diría que están ahí y simplemente no podemos mostrarlas. No están ahí.

- **Verificación visual fiel.** El sistema mide estructura y cuenta elementos; no mira la página final. Un verificador visual dentro del producto no existe.
- **Eliminación que alcance copias de seguridad.** Hoy la eliminación es completa en sistemas en vivo y no alcanza copias de seguridad dentro de la ventana de retención. La ruta técnica está definida y aún no está construida. El alcance exacto está en [privacidad y soberanía](privacy).
- **Quitar el contenido y desactivar la cuenta, en una acción a través de la interfaz.** Hoy existe eliminación de documentos y toma derivados con ella; hacer esto todo de una vez no existe aún, y el cierre se maneja bajo solicitud. El nombre es deliberado: borra el contenido y desactiva la cuenta, porque el rastro de quién accedió al sistema permanece.

## Cómo se mantiene esta página

Un elemento sale de aquí cuando existe y ha sido medido, no cuando está casi listo. Cuando sale, entra en la página de capacidad con lo que garantiza y dónde se detiene. Si sigues SazAI por un tiempo, esta página es donde se muestra el ritmo.

### Lo que esta pirámide no sostiene

Una pirámide honesta dice qué queda fuera de ella.

**Datos y hechos:**

- Cinco referencias de doctrina en cero artefactos de ingeniería: W3C **PROV** · ZAHARIA et al., **compound AI systems** (BAIR, 2024) · XU et al., **GraphRAG** (SIGIR, 2024) · literatura de **model routing** · **CommonMark/GFM**. Formaron el pensamiento; ninguna decisión registrada salió de ellas.
- Pruebas: práctica fuerte, guardias que rechazan en compilación, reportes fechados; metodología externa declarada: ninguna. Dicho en esas palabras, sin vecino plausible.
- Y el hallazgo que sostiene toda la conclusión, medido en todas las decisiones con una alternativa en el encabezado: en once de once, lo que decidió fue un principio de ingeniería, no una referencia externa. El estándar apoya; la elección es nuestra, y está escrita.

*Figuras medidas el 2026-09-01 sobre conjuntos que crecen: quien repita la medición mañana debería esperar números más grandes, no los mismos.*

## Donde pasa la frontera

<h3 class="sub">Tres límites que un lector técnico prueba primero, dichos antes de la prueba</h3>

**La frontera del proveedor.** El linaje acompaña cada fragmento de texto hasta que sale hacia el modelo de lenguaje y comienza de nuevo cuando vuelve. Ninguna tabla nuestra registra lo que pasó al otro lado; quien pregunta *demuestra que hicieron con mi texto dentro del modelo* recibe los términos de retención del proveedor que contrataste, y en una instalación tuya el proveedor es tu elección. La página de [soberanía](privacy) dice dónde termina esto.

**La exclusión de licencias copyleft.** Ninguna biblioteca AGPL entra en el motor, y está escrito en el archivo de dependencias como decisión de proyecto documentada. Es un comentario, no una puerta: nada quiebra la compilación si alguien la ignora. Decir esto es más fuerte que fingir que es puerta, porque quien abre el archivo lo ve en diez segundos.

**Los agentes.** Este sistema está construido por un equipo de agentes con alcance declarado y una cadena de revisión, y la comunicación entre ellos es práctica, no recibo: no hay decisión escrita que gobierne el canal, y los modos de fallo de él fueron medidos por nosotros esta semana. Está en el lado derecho del libro-razón, y es para allá que va.

Todo lo que esta página afirma tiene un comando o un documento detrás, y lo que no lo tiene está dicho como dirección. Si algo aquí no puede ser reproducido en una evaluación tuya, eso es un defecto nuestro y queremos saberlo antes que tú. El producto que salió primero de esta plataforma es lo que [ves cuando un documento entra](see).

</div>

<script type="module">
// IF THE #stars CANVAS EVER MORPHS INTO THIS GRAPH (Dev UX / Dev CO), REMOVE THIS FIGURE: two
// objects doing one job on one page is how a surface rots, quietly, because both look right.
// THE VAULT GRAPH, BORN AS STARS. Geometry in SVG, words in HTML. The layout is seeded, so the
// same picture renders every time; hubs are the real hubs of sazai.vault; satellites are counted
// per section, not drawn one to one. First reveal on intersection: points scatter like the
// starfield, then settle into the graph and the labels fade in. Hover lights a hub's edges;
// click (or Enter) opens the same scene full-screen; Escape closes. Reduced motion: no drift.
const fig=document.getElementById('vault-graph'); if(fig){
const svg=fig.querySelector('svg'),E=fig.querySelector('.edges'),N=fig.querySelector('.nodes'),L=fig.querySelector('.labels');
// no namespace literal: the house serves zero external references, and insertAdjacentHTML inside the <svg> inherits the SVG namespace on its own
const el=(t,a,parent)=>{parent.insertAdjacentHTML('beforeend','<'+t+' '+Object.entries(a).map(([k,v])=>k+'="'+v+'"').join(' ')+'/>');return parent.lastElementChild};
let seed=20260828; const rnd=()=>{seed=(seed*1664525+1013904223)%4294967296;return seed/4294967296};
const H=[ // real hubs of sazai.vault; n = satellites drawn, proportional, not exact
 {id:'index',l:'00-INDEX',x:400,y:250,c:'var(--dark)',r:9,n:6},
 {id:'adrs',l:'ADRs Hub',x:300,y:120,c:'var(--hue-reprocess)',r:8,n:59},
 {id:'agents',l:'Agents Hub',x:250,y:330,c:'var(--hue-analysis)',r:8,n:30},
 {id:'km',l:'Knowledge Map',x:560,y:130,c:'var(--hue-output)',r:7,n:18},
 {id:'product',l:'MOC-Product',x:600,y:300,c:'var(--hue-output)',r:7,n:26},
 {id:'strategy',l:'MOC-Strategy',x:520,y:410,c:'var(--hue-upload)',r:7,n:28},
 {id:'ops',l:'MOC-Operations',x:130,y:200,c:'var(--gray)',r:6,n:14},
 {id:'people',l:'MOC-People',x:150,y:440,c:'var(--hue-analysis)',r:6,n:10},
 {id:'pitch',l:'MOC-Pitch',x:690,y:440,c:'var(--hue-upload)',r:6,n:12},
 {id:'personas',l:'Personas',x:410,y:470,c:'var(--hue-reprocess)',r:6,n:7},
 {id:'sessions',l:'Sessions',x:700,y:200,c:'var(--gray)',r:5,n:9},
];
const X=[['index','adrs'],['index','agents'],['index','km'],['index','product'],['index','strategy'],['index','ops'],['index','people'],['index','pitch'],['index','personas'],['index','sessions'],['adrs','km'],['adrs','agents'],['agents','ops'],['agents','people'],['product','km'],['product','strategy'],['strategy','pitch'],['strategy','personas'],['pitch','personas'],['sessions','agents'],['sessions','adrs']];
const nodes=[],edges=[];
for(const h of H){const hub={...h,hub:true,sx:h.x,sy:h.y,ph:rnd()*6.28};nodes.push(hub);
  for(let i=0;i<h.n;i++){const a=rnd()*6.28,d=34+rnd()*(h.n>20?110:70);const s={id:h.id+i,x:h.x+Math.cos(a)*d,y:h.y+Math.sin(a)*d,c:h.c,r:1.6+rnd()*1.6,hub:false,of:hub,ph:rnd()*6.28};s.sx=s.x;s.sy=s.y;nodes.push(s);edges.push([hub,s]);
    if(rnd()<.12){const o=nodes[Math.floor(rnd()*nodes.length)];if(o&&o!==s)edges.push([s,o]);}}}
const byId=Object.fromEntries(nodes.filter(n=>n.hub).map(n=>[n.id,n]));
for(const [a,b] of X)edges.push([byId[a],byId[b]]);
for(const n of nodes){n.el=el('circle',{r:n.r,fill:n.c,opacity:n.hub?1:.75},N);n.el.style.color=n.c;
  n.rx=rnd()*800;n.ry=rnd()*520;n.t=0; // scatter origin, for the reveal
  if(n.hub){const sp=document.createElement('span');sp.textContent=n.l;sp.dataset.hub=n.id;L.appendChild(sp);n.lab=sp;
    n.el.classList.add('hub');n.el.dataset.hub=n.id;}}
for(const e of edges){e.el=el('line',{stroke:'var(--lightgray)','stroke-width':e[0].hub&&e[1].hub?1:.6,opacity:.55},E);}
const reduce=matchMedia('(prefers-reduced-motion: reduce)').matches;
let t0=null,revealed=false,lit=null;
function place(){const now=performance.now();for(const n of nodes){
  const k=reduce?1:Math.min(1,(now-(t0||now))/1600),ease=1-Math.pow(1-k,3);
  const dx=reduce?0:Math.sin(now/1900+n.ph)*(n.hub?2.2:3.6),dy=reduce?0:Math.cos(now/2300+n.ph)*(n.hub?2.2:3.6);
  n.x=n.rx+(n.sx-n.rx)*ease+dx;n.y=n.ry+(n.sy-n.ry)*ease+dy;
  n.el.setAttribute('cx',n.x);n.el.setAttribute('cy',n.y);
  if(n.hub){const pulse=reduce?1:1+Math.sin(now/1400+n.ph)*.08;n.el.setAttribute('r',n.r*pulse*ease+ .5);
    n.lab.style.left=(n.x/800*100)+'%';n.lab.style.top=(n.y/520*100)+'%';}else n.el.setAttribute('r',n.r*(.4+.6*ease));}
  for(const e of edges){e.el.setAttribute('x1',e[0].x);e.el.setAttribute('y1',e[0].y);e.el.setAttribute('x2',e[1].x);e.el.setAttribute('y2',e[1].y);}
  if(!revealed&&(reduce||now-t0>1500)){revealed=true;fig.classList.add('ready');}
  if(!reduce||!revealed)requestAnimationFrame(place);}
function light(id){lit=id;fig.classList.toggle('lit',!!id);
  for(const e of edges){const on=id&&(e[0].id===id||e[1].id===id||(e[0].of&&e[0].of.id===id&&e[1].hub===false&&e[1].of===e[0].of));
    e.el.setAttribute('opacity',id?(on?1:.12):.55);e.el.setAttribute('stroke',on?byId[id].c:'var(--lightgray)');}
  for(const n of nodes){const on=!id||n.id===id||(n.of&&n.of.id===id);n.el.setAttribute('opacity',on?(n.hub?1:.85):.18);}}
fig.addEventListener('mouseover',e=>{const h=e.target.closest('[data-hub]');if(h)light(h.dataset.hub)});
fig.addEventListener('mouseout',e=>{if(e.target.closest('[data-hub]'))light(null)});
// THE EXPANDED SCENE IS A MODAL (ADR-047 A10.4 #15): the figure moves into an sz-modal beside it, inside the same
// chapter so the .chap .graph.full rules still match, and comes back on close. The dialog brings the top layer, the
// blurred page behind (A10.2) and Esc; moved BEFORE open, the figure is inside the modal, so no hole is cut for it.
const ph=document.createElement('div');let modal=null;
const restore=()=>{if(!fig.classList.contains('full'))return;fig.classList.remove('full');ph.replaceWith(fig);document.body.style.overflow='';fig.focus({preventScroll:true})};
const expand=()=>{if(!modal){modal=document.createElement('sz-modal');modal.setAttribute('size','full');modal.setAttribute('bare','');modal.setAttribute('label',fig.getAttribute('aria-label')||'');modal.addEventListener('sz-close',restore)}
  ph.style.height=fig.offsetHeight+'px';fig.replaceWith(ph);ph.after(modal);modal.appendChild(fig);fig.classList.add('full');document.body.style.overflow='hidden';modal.open();fig.focus({preventScroll:true})};
const toggle=()=>{if(fig.classList.contains('full')){modal.close();return}customElements.whenDefined('sz-modal').then(expand)};
fig.addEventListener('click',e=>{if(!e.target.closest('[data-hub]')||fig.classList.contains('full'))toggle()});
fig.addEventListener('keydown',e=>{if(e.key==='Enter'||e.key===' '){e.preventDefault();toggle()}});
// START ON SIGHT. IntersectionObserver is the primary trigger; a geometry check on load and on the
// first scroll is the fallback, so a viewport that never reports intersection (measured: an
// automated background tab delivers neither IO nor rAF) still gets the reveal on the next paint.
let started=false;const start=()=>{if(started)return;started=true;t0=performance.now();requestAnimationFrame(place)};
const inView=()=>{const r=fig.getBoundingClientRect();return r.top<innerHeight*.8&&r.bottom>innerHeight*.2};
const io=new IntersectionObserver((en)=>{if(en.some(x=>x.isIntersecting)){start();io.disconnect()}},{threshold:.35});io.observe(fig);
if(inView())start();else addEventListener('scroll',()=>{if(inView())start()},{passive:true});
}
</script>

<style>

/* CHAPTER NUMERALS, EDITORIAL. The number is the chapter's mark, not a KPI: it enters large,
   in the domain hue, beside an uppercase kicker that says what it counts. The house h2 follows
   untouched. These rules move to marketing.css (and the connectome port) when the page lands;
   they live in the body for the refine loop. */
/* ICON COLUMN (Ramés, 2026-08-28): the chapter icon sits left of the title AND its subtitle; the
   subtitle takes the old kicker voice: small, uppercase, quiet. */
/* THE ICON IS A SIBLING OF THE H2, NEVER INSIDE IT, AND THAT IS AN ANCHOR DECISION RATHER THAN
   A STYLE ONE. Quartz slugs a heading from its TEXT CONTENT, and any inline element in the
   heading contributes an empty token. Measured on a probe page, all six forms: `<sz-icon>`
   before the words gives `id="-forma-a-inline-antes"`, a `<span>` behaves identically, the icon
   AFTER the words gives a TRAILING hyphen, and the `{#explicit-id}` syntax is NOT supported
   here: it is slugged as literal text. Only a heading with no markup at all comes out clean.
   AN ANCHOR IS A URL AND A WRONG URL IS PERMANENT, so the icon leaves the heading. The visual
   is unchanged: `.ch` is zero-height and the icon is absolutely placed into the padding column
   the h2 already reserves. */
/* ============================================================================
   THE CHAPTER IS A PANEL, AND THAT ALSO RETIRES THREE MAGIC NUMBERS.

   THE DIAGNOSIS WAS AN INVERTED HIERARCHY, not a missing divider. Rendered, the page read
   heading / floating prose / CONTAINED FIGURE / floating prose: the figure carried a border,
   a fill and a blur while the chapter that owns it carried nothing, so the strongest container
   on the page was a child of the section rather than the section. Prose did not read loose so
   much as OUT-RANKED.

   Now each chapter is a real element, which fixes the ranking AND the alignment at once:

   1. THE CHAPTER IS THE SURFACE. Soft ground, hairline border, radius, generous padding.
   2. THE FIGURE GIVES BACK ITS FILL and keeps only its outline, so it reads as an object
      INSIDE the panel instead of a competing surface. The blur goes with the fill: a backdrop
      filter over a transparent box is cost with no picture.
   3. THE ICON SITS IN ITS OWN GRID COLUMN, vertically centred on the title block by the
      layout rather than by an offset. Everything before this was a magic number chasing a
      MARGIN COLLAPSE: `.ch` was a zero-height div and the h2's top margin collapsed through
      it, so the icon's 18px raise was EMERGENT, and every spacing change moved it. Measured,
      three times: padding opened a 2.4rem gap; a margin dropped it 19px; a margin on the
      previous paragraph did the same. The wrapper removes the collapse from the problem.
   ============================================================================ */
article .chap{position:relative;display:grid;grid-template-columns:3.4rem 1fr;
  gap:0 0;align-items:start;
  border:1px solid color-mix(in srgb,var(--lightgray) 85%,transparent);border-radius:14px;
  background:transparent;
  padding:1.7rem 1.9rem 1.5rem;margin:1.6rem 0}
/* THE GLASS IS A VEIL, NOT A FILTER ON THE PANEL, AND THAT IS A MEASURED CORRECTION.
   `blur(4px)` is the house's own value, read off the served page from `div.search-container`
   and `div.global-graph-outer`, the only two elements that already carry a backdrop filter.
   PUT IT ON `.chap` DIRECTLY AND THE COMPARE MODAL BREAKS: `backdrop-filter` makes the element
   a containing block for `position:fixed` DESCENDANTS, and the modal lives inside this panel.
   Measured before and after: the scrim went from the viewport (1440x757) to the panel's own box
   (788x569). So the veil goes on a pseudo-element at `z-index:-1`, which blurs what is behind
   the panel while leaving `.chap` an ordinary containing block. IT IS THE HOUSE'S OWN ANSWER
   TOO: `sz-search-field` solves the identical problem with a `.veil` behind its pill. */
article .chap::before{content:"";position:absolute;inset:0;z-index:-1;border-radius:inherit;
  /* `--surface` AND NOT `--light`, MEASURED RATHER THAN CHOSEN BY NAME. In the dark theme
     `--light` resolves to #09090b, which is EXACTLY the body background: a 40% mix of the
     background over the background is the background, and the panel measured invisible on the
     rendered pixels (inside 9,9,10 against outside 9,9,11: a delta of zero). Blur cannot
     rescue it either, because a backdrop filter over a flat surface has nothing to blur: THE
     FILL IS WHAT MAKES A PANEL EXIST and the blur is only its texture. `--surface` is #18181b,
     the house's own raised colour, the one `sz-search-field` puts behind its pill. */
  background:color-mix(in srgb,var(--surface) 72%,transparent);
  backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);pointer-events:none}
article .chap .ico-col{grid-column:1;grid-row:1 / span 2;align-self:center;
  display:flex;align-items:center;justify-content:flex-start;padding-top:.15rem}
article .chap .ico-col sz-icon,article .chap .ico-col .ico{display:inline-flex}
article .chap .ico-col .ico svg{width:36px;height:36px}
article .chap > h2{grid-column:2;grid-row:1;padding-left:0;margin:0}
article .chap > h3.sub{grid-column:2;grid-row:2;padding-left:0;margin:2px 0 0;line-height:1.15}
/* THE ANCHOR ICON WAS INFLATING THE LINE BOX, AND MY OWN CHANGE PUT IT THERE. Promoting the
   subtitle from `<p>` to `<h3>` for the SEO reading also gave it the `a[role=anchor]` Quartz
   adds to every heading: 15px tall, inline, on the baseline. Measured, the h3 box went to 26px
   for a 16px line, and that surplus is what read as too much air between title and subtitle.
   Capping the anchor to the text's own em takes the inflation out without removing the anchor,
   so the heading keeps the link it earned by being a heading. */
article .chap h2 a[role=anchor],article .chap h3.sub a[role=anchor]{
  display:inline-flex;align-items:center;height:1em;line-height:1;vertical-align:middle}
article .chap > *:not(.ico-col):not(h2):not(h3.sub){grid-column:1 / -1}
/* THE SPACE BELONGS TO THE FIRST PROSE PARAGRAPH, AND `:first-of-type` GAVE IT TO THE SUBTITLE.
   The first `<p>` inside a panel is `p.sub`, so this rule matched the subtitle instead of the
   prose: same specificity as the `.sub` rule and later in the block, so it won, and the
   subtitle inherited a 16px top margin nobody wrote for it. @rames spotted it on the rendered
   page before any probe did. Targeting the paragraph that FOLLOWS the subtitle says what was
   meant and cannot drift onto a sibling again. */
article .chap > h3.sub + p{margin-top:1rem}
article .chap > *:last-child{margin-bottom:0}
/* the figure is an object inside the panel, never a second surface */
article .chap .viz{background:transparent;backdrop-filter:none;-webkit-backdrop-filter:none;
  border-color:color-mix(in srgb,var(--lightgray) 65%,transparent)}
/* ============================================================================
   HINT TEXT ON A TERM, AND THE RULE IT KEEPS: THE HOVER IS NEVER THE ONLY COPY.

   @copy-chief's rule applied literally: the explanation lives in the SENTENCE, where all three
   readers reach it (the person, the buyer's research agent, our agent reading the .md). The
   attribute is the SHORT FORM of that same sentence, so the hover adds convenience and never
   carries meaning the prose lacks. His measured reason is this page's own defect: the
   aria-label versus <text> divergence came from two copies of the same words in two encodings,
   and only one of them ever got translated.

   NO SCRIPT. Hover, keyboard focus and tap all resolve through :hover and :focus-visible, so
   there is nothing to upgrade, nothing that can trap focus, and it works before any module
   loads. `tabindex=0` makes the term reachable by keyboard and gives a tap somewhere to land.
   The term is marked as a TERM and not as a link: dotted underline, body colour, no pointer,
   because the page carries four real links and a fifth affordance that looked the same
   would lie.
   ============================================================================ */
article dfn[data-hint]{font-style:italic;position:relative;border-bottom:1px dotted var(--gray);
  cursor:help;outline:none}
article dfn[data-hint]::after{content:attr(data-hint);position:absolute;left:0;top:calc(100% + .5rem);
  z-index:30;width:min(30rem,72vw);padding:.7rem .85rem;border:1px solid var(--lightgray);
  border-radius:10px;background:var(--light);color:var(--darkgray);
  font-style:normal;font-size:var(--fs-xs,.76rem);line-height:1.45;letter-spacing:0;
  box-shadow:0 8px 24px rgb(0 0 0 / .28);opacity:0;visibility:hidden;transition:opacity .12s ease}
article dfn[data-hint]:hover::after,article dfn[data-hint]:focus-visible::after{opacity:1;visibility:visible}
article dfn[data-hint]:focus-visible{border-bottom-color:var(--secondary)}
/* THE SUBTITLE IS AN h3 AND ITS LOOK IS UNCHANGED. @sophia's SEO reading: the H2s lost their
   keywords when they became short labels, and the sentences that carry them became a styled
   paragraph with no heading weight. Promoting the element gives the weight back without moving
   a pixel: every typographic value below is the one the `<p>` already had. */
article h3.sub{font-size:var(--fs-xs,.74rem);font-weight:var(--fw-normal,400);letter-spacing:.08em;text-transform:uppercase;color:var(--gray);line-height:1.15}
/* COMPARE, in the vault's vocabulary: original, the declared relation, the edition; the button opens the component. */
article .duo .act{grid-column:1/-1;text-align:center;margin-top:.4rem}
article .duo sz-compare{display:block;height:0;overflow:hidden}
/* THE SAME BLUR THE SEARCH OVERLAY USES (Quartz .search-container: backdrop-filter blur(4px)),
   applied to the content boxes over a translucent ground so the starfield lifts them. Moves to
   marketing.css .viz when the page lands. */
article .duo.four{grid-template-columns:repeat(4,1fr)}
article .duo.strip{grid-template-columns:auto auto 1fr}
article .duo .out4{display:grid;grid-template-columns:repeat(4,1fr);gap:.5rem}
article .duo .out4 span{display:block}
article .duo .out4 svg{width:40px;height:40px;margin:0 auto .3rem}
article .duo.four .side svg{width:44px;color:var(--hue-analysis)}
article .duo.xray .side svg{color:var(--hue-upload)}
@media (max-width:640px){article .duo.four{grid-template-columns:1fr 1fr}}
/* THE MODAL MUST BE ABOVE THE PAGE CHROME, AND THE HOUSE HAS NO LAYER SCALE TO SAY SO. Measured
   on the served page: the compare scrim is z-index 50 (sz-compare), the consent notice 60
   (sz-consent), the search field host 10000 (chrome CSS). A dialog the reader opened that
   renders UNDER the search bar is a defect; this lifts it through the part the component
   exposes for exactly that. 10001 is a magic number chasing another one, declared as such:
   the durable fix is NOT a z-scale: sz-modal already solved this in-house by building on the
   native <dialog> and its top layer, which no z-index can sit above. sz-compare following it
   onto <dialog> retires this rule; that is a component change, not a page style. */
article sz-compare::part(modal){z-index:10001}
@media (max-width:640px){article .duo.strip{grid-template-columns:1fr}article .duo .out4{grid-template-columns:1fr 1fr}}
/* THE CLOSE MIRRORS THE OPEN: one vault in the middle, two readers on the sides. Geometry only;
   every word is HTML. */
article .duo{display:grid;grid-template-columns:1fr auto 1fr;gap:1rem;align-items:center;text-align:center;font-size:var(--fs-xs,.74rem);color:var(--gray)}
article .duo svg{display:block;height:auto;margin:0 auto .3rem}
article .duo .side svg{width:56px}
article .duo .mid svg{width:96px}
article .duo b{display:block;color:var(--dark);font-size:var(--fs-sm,.86rem)}
@media (max-width:640px){article .duo{grid-template-columns:1fr}}

/* ============================================================================
   TWO OBJECTS THIS PAGE NEEDED AND `see` DID NOT.

   1. THE CURVE, ON A LOG SCALE, BECAUSE A LINEAR ONE HIDES THE ARGUMENT. The claim is one
      order of magnitude per format: 3600h, 48h, 4h, one session. Drawn linearly the last
      three bars are invisible and the fourth point, THE ONE CARRYING THE STRONGEST PROOF,
      reads as merely small. Log widths make the collapse legible, and the caption says the
      scale out loud so nobody reads it as linear.

      AND THE FOURTH ROW BREAKS THE VISUAL FAMILY ON PURPOSE. The three OOXML formats share a
      hue and a solid bar; PDF gets a different hue and an outlined bar. **THE BREAK IS THE
      ARGUMENT**: the engine did not get faster at PowerPoint, it became format-agnostic, and
      a fourth bar in the same family would have said the opposite.

   2. RECEIPT AND PRACTICE MUST NOT LOOK ALIKE, and that is a composition rule rather than a
      label. A receipt is a thing already true and carries its evidence on the same line, so
      it is solid, filled, and reads as closed. A practice is declared direction with no
      present-tense verb, so it is outlined, muted, and reads as open. A reader who never
      gets to the words should still be able to see which column is which.

   3. THE BOUNDS ARE IN THE FLOW, NOT IN SMALL PRINT. `see` had none of these. A bound that
      has to be read as a footnote is a bound that gets skipped, and both of this page's
      bounds are the kind a competent reader tests FIRST. So they sit inside the chapter, at
      the same measure as the prose, in a treatment that is quieter than the claim but not
      smaller than it.
   ============================================================================ */
article .curve{display:flex;flex-direction:column;gap:.55rem}
article .curve .row{display:grid;grid-template-columns:4.2rem 1fr 7.5rem;align-items:center;gap:.8rem}
article .curve .row b{font-size:var(--fs-sm,.86rem);color:var(--text)}
article .curve .track{display:block;height:10px;border-radius:5px;background:color-mix(in srgb,var(--lightgray) 45%,transparent)}
article .curve .bar{display:block;height:100%;border-radius:5px}
article .curve .ooxml .bar{background:var(--hue-analysis)}
article .curve .other .bar{background:transparent;border:1.5px solid var(--hue-output)}
article .curve .other b{color:var(--hue-output)}
article .curve em{font-style:normal;font-size:var(--fs-xs,.76rem);color:var(--gray);text-align:right}
article .curve .other em{color:var(--hue-output)}
article .ledger{display:grid;grid-template-columns:1fr 1fr;gap:1.4rem}
article .ledger h4{margin:0 0 .6rem;font-size:var(--fs-xs,.74rem);letter-spacing:.08em;text-transform:uppercase;font-weight:var(--fw-normal,400);color:var(--gray)}
article .ledger .item{margin-bottom:.7rem}
article .ledger .item b{display:block;font-size:var(--fs-sm,.88rem)}
article .ledger .item span{display:block;font-size:var(--fs-xs,.76rem);color:var(--gray);line-height:1.4;margin-top:.1rem}
article .ledger .receipts .item{border-left:2px solid var(--hue-output);padding-left:.7rem}
article .ledger .practices .item{border-left:2px dashed color-mix(in srgb,var(--gray) 55%,transparent);padding-left:.7rem}
article .ledger .practices .item b{color:var(--gray);font-weight:var(--fw-normal,400)}
article p.claim{margin:1rem 0 0;color:var(--text);font-size:var(--fs-sm,.95rem);line-height:1.55}
article .bound{margin:1.1rem 0 0;padding:.85rem 1rem;border-left:2px solid color-mix(in srgb,var(--gray) 40%,transparent);
  background:color-mix(in srgb,var(--surface) 45%,transparent);border-radius:0 8px 8px 0}
article .bound p{margin:0 0 .5rem;font-size:var(--fs-xs,.82rem);line-height:1.5;color:var(--gray)}
article .bound p:last-child{margin-bottom:0}
@media (max-width:640px){article .ledger{grid-template-columns:1fr}article .curve .row{grid-template-columns:3.4rem 1fr}article .curve em{grid-column:1/-1;text-align:left}}

/* THE VAULT GRAPH: born as stars, settles into the map. Geometry in SVG, words in HTML spans over
   it; `.stage` binds the two so labels track the drawing in both modes. Placed LAST so it wins
   over the panel's `.chap .viz` reset, and scoped to `.chap` so its specificity matches hers. */
article .chap .graph{position:relative;padding:.6rem;cursor:zoom-in;outline:none}
article .chap .graph .stage{position:relative;width:100%;aspect-ratio:800/520}
article .chap .graph .stage svg{display:block;width:100%;height:100%}
article .chap .graph .labels{position:absolute;inset:0;pointer-events:none}
article .chap .graph .labels span{position:absolute;transform:translate(-50%,10px);font-size:var(--fs-xs,.72rem);color:var(--dark);white-space:nowrap;opacity:0;transition:opacity .7s ease;text-shadow:0 0 6px var(--light),0 0 2px var(--light);pointer-events:auto}
article .chap .graph.ready .labels span{opacity:1}
article .chap .graph .nodes .hub{cursor:pointer;transition:opacity .25s}
article .chap .graph .edges line{transition:opacity .25s,stroke .25s}
article .chap .graph figcaption{margin-top:.4rem}
article .chap .graph:focus-visible{box-shadow:0 0 0 2px var(--secondary)}
article .chap .graph.full{flex:1;min-width:0;margin:0;border:0;border-radius:0;padding:3vh 4vw;background:transparent;cursor:zoom-out;display:flex;flex-direction:column;align-items:center;justify-content:center}
article .chap .graph.full .stage{width:min(92vw,calc(84vh * 800 / 520))}
article .chap .graph.full .labels span{font-size:1rem}
article .chap .graph.full figcaption{text-align:center;margin-top:1rem;max-width:70ch}
</style>
