---
title: "플랫폼 아키텍처: 우리가 결정한 것과 그것이 기초한 것"
seo_title: "플랫폼 아키텍처: 의사결정과 참고자료 | SazAI"
description: "SazAI의 구축 방식: 포맷에 무관한 엔진, 리니지, 버전 관리되는 의사결정, 방법론을 갖춘 검증"
tags: [marketing]
icon: book
---

> **결론: 가속기는 팀의 기판에 대한 통제력이다. 여기서 의사결정은 취향이 아니다. 선택지는 기록되어 있고, 버린 것과 그 이유도 함께 있다.** 아래의 피라미드가 지도다. 빈 공간은 그 밖에 있고, 명시되어 있다.

<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>

## SazAI는 무엇인가

<h3 class="sub">엔진, 컴포넌트, 문서화. 그것을 만든 사람들이 통제한다</h3>

SazAI는 플랫폼이다. 제품들이 구축되는 지능 및 증빙 기판이다. 다중 테넌시, 인증, 리니지, 오케스트레이션, 에이전트 계층, 정확한 계측, 버전 관리되는 의사결정. 한 번만 만든다. SazAI Corpus, 금고, 디자인 시스템은 이미 나온 제품들이고, 각각 같은 엔진을 사용한다. 다시 만들지 않는다.

패널들은 앵커 강도로 내려간다. 각각은 전개 가능 블록에서 참고자료로 닫힌다. 누구든 확인하려 하는 사람 말이다. 인용은 ABNT NBR 6023 표준 2018을 따른다.

<figure class="viz" role="group" aria-label="이 페이지의 피라미드: 실행 의존성부터 포지셔닝까지 네 가지 앵커 강도, 그 밖의 빈 공간">
<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)">실행 의존성</b><span>엔진은 표준 없이 실행되지 않는다 · 스텝 1</span>
<b style="color:var(--hue-output);margin-top:.5rem">표준 적용 및 측정</b><span>스키마의 법칙, 컴포넌트의 기준, 토큰별 대비 · 스텝 2~4</span>
<b style="color:var(--hue-upload);margin-top:.5rem">기록된 의사결정</b><span>선택지는 기록되고, 버린 것과 그 이유도 함께 · 스텝 5~6</span>
<b style="color:var(--hue-reprocess);margin-top:.5rem">포지셔닝</b><span>주의사항이 첨부된 연구 · 스텝 7</span>
<b style="color:var(--gray);margin-top:.5rem">빈 공간</b><span>피라미드 밖에 있고, 명시되어 있다 · 마지막 패널</span>
</div>
</div>
<figcaption>앵커 강도가 높이를 결정한다. 아무것도 지탱하지 않는 것은 드래시처리된 선으로 그려져 있고, 밖에 있으며, 자신의 패널을 가지고 있다.</figcaption>
</figure>

밖에서 오는 사람에게는 플러그-앤-플레이가 아니다. **가속기는 기판이 아니다. 가속기는 팀의 기판에 대한 통제력이다.** 엔진, 컴포넌트, 문서화를 아는 사람은 이미 존재하는 것으로부터 새로운 SaaS 제품을 만든다. 이 페이지의 나머지는 그것이 경로를 얼마나 단축하는지를 측정한다.

<figure class="viz duo" role="group" aria-label="엔진, 컴포넌트, 문서화. 중간의 팀의 통제력. 나오는 제품들">
<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>기판</b>엔진, 컴포넌트, 문서화</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>팀의 통제력</b>가속을 만드는 것</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>제품들</b>Corpus, 금고, 디자인 시스템</div>
</figure>

이 아이디어의 프레임은 새로운 것이 아니고, 이 페이지의 것도 아니다. SazAI가 자신을 설명하는 아홉 가지 기둥 중 여덟 번째다. *제품 전에 플랫폼*. 다음이 그 증거다.

</div>

<div class="chap">

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

## 엔진은 포맷 표준에 의존한다

<h3 class="sub">스텝 1 · 실행 의존성, 가장 강한 앵커</h3>

표준이 코드에서 틀렸다면 엔진은 실행되지 않는다. 참고자료는 언급되지 않는다. 의존된다. 거기서 결정론이 나온다.

**데이터와 사실:**

- 엔진의 OOXML 네임스페이스: 37개의 서로 다른 형태에 걸쳐 237개 (2026-09-01).
- 의존성으로서의 Dublin Core: 22개 네임스페이스. ISO 8601: 데이터베이스에서 가장 인용된 표준, 60개 사용.
- 확인 가능한 체인: 게시 절 → DDL 열 주석 → 데이터 맵 → 열. 패러프레이즈 금지. DDL과 맵이 같은 절을 문자 그대로 담는다.

<figure class="viz duo four" role="group" aria-label="결정론의 체인: 게시된 절, DDL 주석, 맵 계층, 관계형 열">
<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>게시된 절</b>표준, 번호로</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>DDL 주석</b>같은 절, 문자 그대로</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>맵 계층</b>패러프레이즈 없음, 규칙으로</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>관계형 열</b>절이 있어서 존재한다</div>
</figure>

### 다음 포맷은 비용이 더 낮다

첫 번째 포맷은 PowerPoint였고, 엔진 전체 비용이 들었다. 읽기, 측정, 번역, 다시 쓰기, 비교. 모두 처음으로. 두 번째 Word 문서는 한 자리 수 적게 들었다. 세 번째 스프레드시트는 또 한 자리 수 적게 들었다. 네 번째 PDF는 세 번째와 같은 비용이다. 곡선이 안정화되었다. 성취의 목록이 아니다. 곡선이고, 곡선이 주장이다.

<figure class="viz curve" role="group" aria-label="각 포맷의 전체 사이클 비용, 로그 스케일에서: 첫 번째는 엔진 비용, 각 다음은 한 자리 수 적게, 네 번째는 세 번째와 같은 비용에서 안정화">
<div class="row ooxml"><b>PPTX</b><span class="track"><span class="bar" style="width:100%"></span></span><em>엔진 전체</em></div>
<div class="row ooxml"><b>DOCX</b><span class="track"><span class="bar" style="width:46%"></span></span><em>한 자리 적게</em></div>
<div class="row ooxml"><b>XLSX</b><span class="track"><span class="bar" style="width:16%"></span></span><em>또 한 자리</em></div>
<div class="row other"><b>PDF</b><span class="track"><span class="bar" style="width:15%"></span></span><em>안정화</em></div>
<figcaption>로그 스케일: 각 단계는 한 자리 수다. 네 번째 점은 가장 작은 것뿐만 아니라. 다른 특성이고, 세 번째와 같은 비용이었다.</figcaption>
</figure>

<p class="claim"><b>PDF는 Office가 아닌 첫 번째 기판이다</b>. 객체의 바이너리 그래프. zip과 XML이 아니라. 엔진이 PowerPoint에서만 좋아졌다면, 네 번째 포맷은 첫 번째처럼 비용이 들었을 것이다. 세 번째처럼 들었다. <b>엔진은 PowerPoint에서 더 빨라지지 않았다. 포맷에 무관해졌다</b>. <a href="documents">네 개 포맷</a>이 오늘 같은 아키텍처에서 실행된다. 각각 자신의 선언된 보장을 가지고. 그래서 다섯 번째는 네 번째 비용이 들 것이다. 이것이 이 페이지가 가속이라고 부르는 것이다.</p>

<div class="bound">
<p><b>이것이 기록된 곳, 당신이 묻기 전에 말해진다.</b> git에. 제도적 일지가 아니라. 곡선은 날짜 지정 의사결정과 커밋에 기초한다. 간격의 올바른 소스다. 평가에서 확인된다. 각 포맷의 절대 시간은 기술 문서에 있다. 그것을 도출하는 명령 옆에.</p>
</div>

<details class="refs"><summary>참고자료 및 기록된 의사결정</summary>
<div>
<p><b>기록된 것과 버려진 것</b></p><ul><li>표준별로 각 포맷을 읽는다. 절 단위로. 휴리스틱은 감사를 견디지 못해서 버려졌다.</li><li>전체 시스템에 걸친 ISO 8601 날짜. Dublin Core의 메타데이터.</li><li>PDF는 Office가 아닌 첫 번째 기판으로 인정된다. 자신의 표준으로 인용된다.</li></ul><p><b>참고자료 (ABNT NBR 6023:2018)</b></p><ul><li>ECMA INTERNATIONAL. <b>ECMA-376</b>: Office Open XML 파일 포맷. Available at: https://ecma-international.org/publications-and-standards/standards/ecma-376/.</li><li>ISO/IEC. <b>ISO/IEC 29500</b>: Office Open XML 파일 포맷.</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>: 날짜 및 시간.</li><li>IETF. <b>RFC 5646</b>: 언어 식별 태그.</li><li>MICROSOFT. <b>MS-PPTX · MS-DOCX · MS-OE376 · MS-ODRAWXML · MS-OFFCRYPTO</b>: 구현 노트.</li><li>UNICODE CONSORTIUM. <b>Unicode CMap</b> 사양.</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>

## 지식의 본체

<h3 class="sub">우리가 결정하고 측정하고 기록한 모든 것. 연결되어 있고 팀과 에이전트가 탐색할 수 있다</h3>

팀의 기판에 대한 통제력은 살아가는 장소가 있다. 저장소를 미러링하는 Obsidian 금고다. 의사결정, 데이터 맵, 에이전트 계약, 페르소나, 전략, 작업 세션. 각 노트가 다른 것에 연결된다. 허브가 문이다. 사람이나 에이전트가 들어오는 문.

같은 그래프를 제품이 고객의 금고에서 전달한다. 먼저 우리 자신에게 사용된다. 아래, 우리의 것, 움직이고 있다. 허브 위로 마우스를 놓으면 그것이 연결된 것을 본다. 클릭하면 전체를 연다.

<figure class="viz graph" id="vault-graph" role="group" tabindex="0" aria-label="SazAI 금고의 그래프: 의사결정, 에이전트, 데이터 맵, 제품, 전략, 운영, 사람, 피치, 페르소나 허브, 서로 연결되어 있고 자신의 노트에 연결되어 있다">
<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>SazAI 금고, 팀이 매일 보는 것처럼. 각 점은 노트다. 각 선은 누군가 쓴 연결이다. 허브에는 이름이 있다. 나머지는 그것들이 연결하는 것이다. 2026-08-28에 손으로 촬영한 노드 세트. 금고의 자동 도출이 나타나면, 이 줄은 나간다.</figcaption>
</figure>

<div class="bound">
<p><b>맵이 도달하는 곳, 측정되고, 그것이 가장 가치 있는 부분이다.</b> 금고 그래프가 158개 데이터맵 테이블 중 55개와 5개 포맷 맵 중 1개에 도달한다. 저장소는 158개 중 158개에 도달한다. 모든 것이 연결되어 있는 것을 보여주는 그림은 이 페이지의 유일한 증빙 없는 주장이었을 것이다. 페이지 전체의 주제가 우리 주장에 증빙이 있다는 것인 페이지에서. 검증된 것은 모든 것이 연결된다는 것이 아니다. 정확히 무엇이 연결되고 무엇이 아닌지를 안다는 것이다. 맵이 침묵하는 곳, 저장소가 대답한다.</p>
</div>

</div>

<div class="chap">

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

## 데이터 보호는 설계이고, 설계는 감사된다

<h3 class="sub">스텝 2 · 법칙이 스키마가 되었고, 스키마는 확인 가능하다</h3>

법칙이 기록에서 요청하는 것, 데이터베이스가 구조를 통해 충족한다. 검증은 우리 정책을 읽는 것이 아니다. 스키마를 감사하는 것이다.

**데이터와 사실:**

- 영구 저장소에는 문서 콘텐츠가 없다. 콘텐츠는 별도의 데이터베이스에 산다. 민감하고 지워질 수 있다.
- 테넌트별 격리. 열로. 슬라이스는 테넌트 간 교차하지 않는다.
- 오늘의 인증: 없음. 제어는 그것이 구하는 증거로 기능하도록 설계되어 있다.

<figure class="viz duo" role="group" aria-label="두 개의 데이터베이스: 콘텐츠 없는 영구적인 것, 민감한 것은 별도로 지워질 수 있다">
<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>영구적</b>구조, 측정, 리니지. 콘텐츠, 절대 아니다</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>설계로 분리됨</b>스키마를 감사한다</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>민감한</b>콘텐츠, 정말로 지워질 수 있다</div>
</figure>

<details class="refs"><summary>참고자료 및 기록된 의사결정</summary>
<div>
<p><b>기록된 것과 버려진 것</b></p><ul><li>기본값으로 설계에 의한 개인정보 보호 및 기본값으로 설계. 공유 데이터베이스 위의 규정 준수 계층이 버려졌다.</li><li>제거는 <b>철수</b>라고 불린다, 삭제가 아니다. 더 강한 단어가 백업이 지탱하지 않는 도달을 약속해서 버려졌다.</li></ul><p><b>참고자료 (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>: 7가지 기초 원칙. Toronto: IPC, 2009.</li><li>ISO/IEC. <b>ISO/IEC 27001</b>. · OWASP FOUNDATION. Available at: 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>

## 접근성은 선언되지 않고 측정된다

<h3 class="sub">스텝 3 · 인용된 표준은 규정 준수. 측정된 숫자는 설계</h3>

기준은 컴포넌트에 산다. 코드 옆에 숫자가 있다. 색상이 시스템에 들어오기 전에 대비가 측정된다.

**데이터와 사실:**

- 51개 디자인시스템 파일에 걸친 WCAG 2.2 AA. 숫자로 인용된 기준 (1.4.1, 3.1) (2026-09-01).
- 토큰당 측정된 대비: `--hue-lineage` 4.00:1, *가이드, 절대 텍스트* 노트가 토큰 자신 안에 쓰여 있다. `--text-faint` **실패함** 흰색에서 2.56:1을 측정, 그리고 실패가 기록됨.
- 색맹이 측정됨: 자주색이 색약증 아래에서 평가됨, 색 거리 ΔE 29.1.
- 0개 아키텍처 의사결정이 WCAG를 기록한다. 집의 가장 강한 접근성 앵커는 의사결정 기록에서 보이지 않는다. 기록하는 것은 아직 할 일이다.

<figure class="viz" role="group" aria-label="세 가지 색 측정: 한 토큰은 가이드로 승인, 한 토큰은 실패함, 자주색은 색약증 아래에서 측정됨">
<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>가이드로 승인됨</b>토큰 자신 안에 쓰인 노트 <i>가이드, 절대 텍스트</i></span></div></div>
<div class="side"><div class="ev open" style="margin:0"><span class="n">2.56:1</span><span class="t"><b>실패함</b>흰색에서 측정, 그리고 실패가 기록됨</span></div></div>
<div class="side"><div class="ev proof" style="margin:0"><span class="n">ΔE 29.1</span><span class="t"><b>색약증</b>자주색이 가장 흔한 색 결핍 아래에서 측정됨</span></div></div>
</div>
<figcaption>인용된 표준은 규정 준수다. 측정된 숫자는 설계다. 세 숫자는 정책이 아니라 토큰에 산다.</figcaption>
</figure>

### 디자인 시스템은 제품이고, 열린 표준에 구축된다

<h3 class="sub">스텝 4 · 다른 표면들을 가속하는 것, W3C 표준에서</h3>

디자인 시스템은 SazAI 제품이다. 정하기로 (2026-08-26), 다른 것들을 가속하는 기능을 가지고. 마케팅, 금고, 쇼케이스를 제공하는 컴포넌트는 같은 것들이고, 오픈 표준이다. 독점 프레임워크가 아니다.

**데이터와 사실:**

- W3C Custom Elements와 CSS Custom Properties에 구축된 컴포넌트. 프레임워크 의존성 없음.
- 한 라이브러리, 세 표면. 밝은 테마와 어두운 테마, 같은 토큰 메커니즘을 통한 화이트레이블 스킨.
- 토큰은 자신의 측정과 사용 노트를 담는다 (스텝 3), 그래서 규칙이 색과 함께 이동한다.

<figure class="viz duo" role="group" aria-label="세 표면을 제공하는 한 컴포넌트 라이브러리">
<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>한 라이브러리</b>컴포넌트, 토큰, 스킨</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>같은 메커니즘</b>토큰으로 테마와 화이트레이블</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>세 표면</b>마케팅, 금고, 쇼케이스</div>
</figure>

<details class="refs"><summary>참고자료 및 기록된 의사결정</summary>
<div><p><b>기록된 것과 버려진 것</b></p><ul><li>그것을 충족하는 컴포넌트에서 번호로 기준. 중앙 정책 페이지가 버려졌다.</li><li>설계에서 단어가 나간다. HTML의 텍스트, SVG의 기하학.</li></ul><p><b>참고자료 (ABNT NBR 6023:2018)</b></p><ul><li>W3C. <b>WCAG 2.2</b>: 웹 콘텐츠 접근성 지침, 레벨 AA. 권장사항, 2023. Available at: https://www.w3.org/TR/WCAG22/.</li></ul><p><b>기록된 것과 버려진 것</b></p><ul><li>표준 웹 컴포넌트. 독점 프레임워크가 버려졌다. 화이트레이블이 우리의 라이선스에 의존하지 않도록.</li><li>모든 표면과 같은 표준으로 유지된다. 실행되는 스위트, 거부하는 보호.</li></ul><p><b>참고자료 (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>

## 채널은 능력이다. API와 MCP가 제품이 될 수 있는 것을 바꾼다

<h3 class="sub">스텝 5 · 문에서 열린 표준, 그리고 그들이 활성화하는 것</h3>

열린 API와 MCP는 배관이 아니다. 우리 없이 방에 같은 기판 위에 다른 인터페이스와 연결을 구축되도록 허락한다. 제3자 에이전트, 자신의 대시보드, 워크플로우 통합. 채널이 존재해서 제품이 그런 것들이 될 수 있다.

**데이터와 사실:**

- 에이전트 채널은 표준 OAuth 자원 서버다. 증명 없이 401. 발견이 게시됨.
- 계약으로서의 동등성: **MCP ⊆ OpenAPI**, MCP가 노출하는 모든 것이 열린 API에 존재한다. 한 기판, 여러 독자.
- 지속 가능한 워크플로우 실행 도구로 오케스트레이션. 보장하는 것으로 채택됨. 보장이 측정됨. 죽은 일은 부분 상태를 남기지 않는다. 과부하는 큐에 떨어진다. 그것은 부러지지 않는다. 아무것도 침묵히 실패하지 않는다.

<figure class="viz duo" role="group" aria-label="한 기판, 두 채널, 그들이 활성화하는 인터페이스">
<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>한 기판</b>엔진과 금고</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와 MCP</b>MCP ⊆ OpenAPI, 계약으로</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>될 수 있는 것</b>자신의 에이전트, 자신의 대시보드, 자신의 워크플로우</div>
</figure>

<details class="refs"><summary>참고자료 및 기록된 의사결정</summary>
<div>
<p><b>기록된 것과 버려진 것</b></p><ul><li>RFC별 인증과 발견. 사용자 정의 협약이 버려졌다.</li><li>새로운 채널이 새로운 표면을 발명하지 않는다. 동등성 규칙이 MCP가 두 번째 API가 되지 않도록 유지한다.</li></ul><p><b>참고자료 (ABNT NBR 6023:2018)</b></p><ul><li>IETF. <b>RFC 8414</b>: OAuth 2.0 인증 서버 메타데이터. 2018.</li><li>IETF. <b>RFC 9728</b>: OAuth 2.0 보호된 자원 메타데이터. 2025.</li><li>IETF. <b>RFC 8707</b>: OAuth 2.0 자원 지표. 2020.</li><li>OPENAPI INITIATIVE. <b>OpenAPI 사양</b>. Available at: https://spec.openapis.org/.</li><li>ANTHROPIC. <b>Model Context Protocol</b> (MCP). Available at: https://modelcontextprotocol.io/.</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="M24 6l14 5v12c0 9-6 15-14 19-8-4-14-10-14-19V11z" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M17 24l5 5 9-10" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none"/></svg></span></div>

## 우리가 검증하는 방법

<h3 class="sub">거부하는 테스트, 방법론이 있는 감사, 통과한 것 옆에 게시된 결함</h3>

검증은 네 가지 계층을 가지고, 순서가 중요하다. **테스트:** 저장소에서 505개 테스트 파일, 디자인시스템 스위트가 모든 빌드에서 실행된다. **보호:** 보고만 하는 대신 빌드 시간에 거부하는 확인. 규칙을 위반하는 빌드는 배포되지 않는다. **로드:** 2026-07-20의 테스트, 충실한 프로덕션 복제에서, 50개 동시 읽기가 0.77초에 답변되고, 무거운 일이 5에 대해 4.71 GiB의 피크, 그리고 5개와 10개 작업의 파도가 0개 실패, 0개 메모리 오버런, 0개 손상. 과부하에서 시스템은 큐에 들어간다. 부러지지 않는다. **내부 감사:** 날짜 지정된 스트레스, 파괴, 보안 보고서, 각 항목당 판정.

<figure class="viz duo four" role="group" aria-label="네 가지 검증 계층: 테스트, 거부하는 보호, 방법론이 있는 감사, 게시된 결함">
<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개 테스트</b>스위트가 모든 빌드에서 실행된다</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>거부하는 보호</b>위반된 빌드는 배포되지 않는다</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>방법론이 있는 감사</b>스트레스, 파괴, 보안</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>게시된 결함</b>통과한 것 옆에</div>
</figure>

<p class="claim">우리는 SOC2 또는 ISO 인증을 받지 않았다. 우리가 가진 것은 <b>문서화된 내부 감사, 선언된 방법론, 그것이 발견한 결함이 통과한 것 옆에 게시되어 있다</b>. 우리의 한 보고서는 자신의 섹션으로 <i>발견한 결함</i>, <i>거의 게시했을 거짓 양성</i>, <i>설정할 수 없었던 것</i>을 가진다. 인장은 제3자의 말이다. 선언된 방법론, 기술적 독자가 혼자 판단한다. 그리고 기록된 의사결정은 인증이 추구할 때 제어 증거로 기능하도록 설계되어 있다.</p>

<div class="bound">
<p><b>이 페이지가 인용하는 것과 인용하지 않는 것.</b> 여기 보고서의 존재와 그들의 방법론이다. 항목별 판정은 평가와 동반하는 기술 문서에 산다. 프로브 목록을 결과로 계획의 맨 위에 게시하는 것은 그렇지 않아야 할 사람에게 지도를 전달하기 때문. 로드 테스트가 <i>인증하지 않는</i> 구절: <i>50개 동시</i>. 50개 좌석과 한 번에 한 개의 무거운 작업이다. 둘을 혼동하는 것은 이 페이지가 존재하지 않도록 하기 위한 오류다.</p>
</div>

</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>

## 우리가 결정하는 방법

<h3 class="sub">기록된 날짜 지정 의사결정, 그리고 두 문장을 삭제하고 다른 것 없음</h3>

모든 SazAI 아키텍처 의사결정은 날짜 지정 문서다. 문맥, 거부된 대안, 이유. 61개가 이 페이지의 날짜 기준이다. 이것을 죽은 파일이 아닌 증빙으로 만드는 것은 대체: 새 의사결정이 오래된 것과 충돌할 때, 오래된 것의 정확히 어떤 문장이 더 이상 유지되지 않는지를 명시한다. 오래된 것이 그 자신의 본체에서, 제목이 아니라 문장에서 마크를 얻는다.

가장 최근 예는 어제부터다. 결정 023은 다른 것들 중에서 사용자가 제품의 능력을 이름 짓는 어휘를 고정했다. 결정 061은 **두 문장**을 대체했다. 엔진에 대한 모든 것을 그대로 두고, 위반된다고 믿어진 절을 포함해서. 그런데 그것이 아니었다. 세 명의 유능한 독자가 그 절을 같은 잘못된 방식으로 읽었고, 의사결정이 모든 세 이름을 기록한다. 결론만을 유지하는 의사결정은 세 사람이 함께 잘못된 이유를 잃는다.

<figure class="viz duo" role="group" aria-label="두 문장이 삭제되고 나머지는 그대로인 오래된 의사결정, 새로운 의사결정에 연결됨">
<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>오래된 의사결정</b>두 문장이 삭제됨, 나머지는 그대로</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>대체</b>문장을 이름 짓는다, 그것뿐</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>새 의사결정</b>함께 잘못된 세 이름</div>
</figure>

<div class="bound">
<p><b>이 페이지가 게시하지 않는 숫자.</b> 이 61개 중 몇 개가 <i>수용됨</i>인지는 카운터가 상태 필드에 허용하는 단어에 달려 있고, 다섯 명의 유능한 카운터는 이번 주에 다섯 개의 다른 숫자에 도달했다. 아무도 틀리지 않았다. 필드가 자신의 어휘를 선언한 적이 없다. 우리는 61개를 게시한다. 그것은 안정적이다. 수용된 개수는 그것을 생산하는 명령 옆에 올 때만 공개 간다. 158개 테이블처럼 이미 한다.</p>
</div>

### 그리고 우리가 기록하는 방법: 내부 계약, 정직을 위해 한 단계 아래

<h3 class="sub">스텝 6 · 기록된 내부 일관성, 외부 표준 아래 한 단계</h3>

작문 스타일, 이름 지정, 집 규약은 에이전트가 인용하는 버전 관리 계약에서 산다. 그것의 앵커는 번호 있는 외부 표준이 아니라 기록된 의사결정이다. 이것이 이전 것들 아래 한 단계이고, 내려가는 것이 비용이 들 때도 이 페이지의 계층이 적용됨을 증명한다.

**데이터와 사실:**

- 한 개의 작문 표준, 개정별로 버전 관리됨, 의사결정과 에이전트에 의해 계약으로 인용됨.
- 전체 시스템에 걸친 이름 지정과 이름 규약이 균일함. 인용된 표준은 절대 패러프레이즈되지 않는다.
- 자동화된 포맷 지정, 린트, 비밀 스캔. 표준에 선언됨, 그 옆에 소스가 있음.

<figure class="viz" role="group" aria-label="기록된 내부 일관성: 외부 표준 아래 한 단계, 의도적으로 드래시처리됨">
<div class="ev open"><span class="n">내부 일관성</span><span class="t"><b>한 단계 아래, 그렇게 그려짐</b>이 패널의 앵커는 번호 있는 표준이 아니라 기록된 의사결정이다. 드래시 프레임은 집이 증빙이 아닌 모든 것에 사용하는 것과 같다. 그리고 내려가는 패널은 비용이 들 때도 계층이 적용됨을 증명한다.</span></div>
</figure>

<details class="refs"><summary>참고자료 및 기록된 의사결정</summary>
<div>
<p><b>기록된 것과 버려진 것</b></p><ul>
<li>개수: <code>ls docs/corpus/pptx/tech_specs/ADR | grep -c '^ADR-'</code> 는 2026-09-01에 61을 반환한다. 개수는 증가한다. 명령은 그렇지 않다.</li><li>이름 지정 대안은 세 표면 전역 수렴으로 거부되었고, 거부가 이유와 함께 기록되었다.</li></ul><p><b>참고자료</b></p><p>내부 계약 (`code_standards`, 버전 관리됨)은 자신의 소스를 이름 짓는다. 이 페이지는 그것을 패러프레이즈하지 않는다.</p><p>내부 계약 (<i>code_standards</i>, 버전 관리됨)은 자신의 소스를 이름 짓는다. 이 페이지는 그것을 패러프레이즈하지 않는다.</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>

## 증빙이 무엇이고, 아직 실행은 무엇인가

<h3 class="sub">증거가 있는 네 가지 능력. 세 개 선언됨, 현재 시제의 동사 없이</h3>

이 플랫폼의 모든 능력은 세 가지 질문을 받았다. 그것을 통제하는 기록된 의사결정이 있는가. 측정이 있는가. 또는 그냥 작동하는가, 아무도 왜를 기록하지 않았는가. 처음 두 개를 통과하는 것을 <dfn data-hint="기록된 의사결정과 누구나 재현할 수 있는 측정을 가진 능력. 약속이 아니라, 기록.">증빙</dfn>이라고 부른다. 나머지는 실행이고, 방향으로 선언된 상태로 남는다. [로드맵](#roadmap) 아래가 아직 존재하지 않는 것을 선언하는 것과 같은 방식으로. 세 가지가 증빙인 일곱 가지 능력을 제공하는 페이지는 네 가지가 증빙인 페이지보다 약하다.

<figure class="viz ledger" role="group" aria-label="네 가지 증빙과 그들의 증거, 그리고 세 가지 실행이 방향으로 선언됨">
<div class="col receipts">
<h4>증빙</h4>
<div class="item"><b>플러그 앤 플레이</b><span>4개 ADR과 레시피 · 4개 포인트 곡선 · 158개 테이블 분할, 재도출 가능</span></div>
<div class="item"><b>큐 제어</b><span>5개 ADR · 0개 실패, 0개 OOM, 0개 손상의 로드 테스트</span></div>
<div class="item"><b>아키텍처 · 리니지 · 테넌시</b><span>공급자 경계가 이름 있는 구멍으로 선언됨</span></div>
<div class="item"><b>의사결정 버전 관리</b><span>기록된 의사결정, 수술적 대체</span></div>
</div>
<div class="col practices">
<h4>선언된 실행</h4>
<div class="item"><b>스키마 버전 관리</b><span>선언된 방향</span></div>
<div class="item"><b>아티팩트 버전 관리</b><span>선언된 방향</span></div>
<div class="item"><b>에이전트 간 통신</b><span>선언된 방향, 측정된 실패 모드</span></div>
</div>
</figure>
<p class="claim">왼쪽의 네 가지는 확인할 곳이 있고, 다음 장이 말한다. 오른쪽의 세 가지는 플랫폼이 가는 곳이고, 그들의 동사는 어느 것도 현재 시제에 없다.</p>

</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>

## 로드맵: 우리가 구축하는 것

로드맵은 큰 방향을 유지한다. 플랫폼이 가리키고 아직 구축하지 않은 것들. 한 조각이 여기를 떠날 때, 그것은 이 목록에서 사라지고 일치하는 능력에 대한 페이지에 나타난다. 날짜와 함께. 움직이는 로드맵은 형용사로 쓸 수 없는 속도의 유일한 증거다. 아래는 아무것도 배포되지 않았다. 여기의 어느 항목도 오늘의 당신의 결정에 무게를 두어야 하지 않는다. 이 페이지에서 배포된 것은 [제품 전망](/), 그것이 보장하는 것과 함께, 그리고 [신뢰](trust)에서 기존하는 것의 한계가 있다.

## 원라인과 협상 지능

초안과 당사자들의 수정본 비교. 각 측이 변경한 것을 보여 준다. 위험이 옮겨진 곳. 텍스트가 드러내는 의도. 이것을 기초하는 비교 엔진은 이미 존재하고 문서 버전 위에서 오늘 실행된다. 누락된 것은 법적 계층이다. 변경된 절이 다른 단락일뿐만 아니라는 것을 이해하는 것.

**그것이 도로가 아니라 로드맵에 있는 이유:** 그것은 자신의 범주를 만들 가능성이 가장 큰 방향이고, 정확히 그래서 그것이 너무 일찍 팔기가 가장 쉽다. 그것은 존재하지 않는다.

## 당신의 말뭉치에 대한 전문화된 에이전트

자신의 범위를 가진 에이전트. 이미 당신의 금고에 있는 지식 위에 구축됨. 당신의 회사의 실제 자료에서 가르치는 튜터. 새 프로세스를 위한 도입 동반자. 출처를 인용하면서 능력을 확인하는 평가자.

**이미 아래에 서 있는 것:** 말뭉치, 리니지, 대화 에이전트, 출처 인용. **누락된 것:** 작업 수준 전문화, 각 에이전트당 자신의 한계 및 규칙.

## 통제된 에이전트 함대를 위한 기판

이전 것에서 다음 단계, 그리고 가장 광범위. 회사의 각 부분은 자신의 문서로 금고를 공급한다. 그 부분이 이미 사용하는 에이전트는 런타임에서 그 금고를 참조한다. 파일별로 또는 프로토콜로. 회사에 대한 어떤 질문이든. 한 개의 통제된 소스는 전체 함대 아래. 아무도 감사하는 느슨한 AI 도구가 아니라.

**이것이 모호한 약속이 아니라 로드맵인 이유:** 도입 메커니즘은 구체적이고 이미 부분적으로 존재한다. 금고는 휴대 가능하고 밖에서 소비 가능하기 때문. 누락된 것은 함대 통제. 그것은 구축되지 않았다.

## 존재하는 것과 당신에게 아직 보일 수 없는 것

이것들은 기능 누락이 아니다. 증거 간격이다. 능력이 있다. 공개 증거는 없고, 그때까지 우리는 그 주변에 말하기보다는 간격을 목록에 나열하는 것을 선호한다.

- **금고 내보내기 시연.** 금고가 존재하고 평문이고 링크가 있다. 누락된 것은 누구나 우리와 대화하지 않고 재현할 수 있는 게시된 시연이다. 그때까지 그것은 실사 대화고, 페이지 항목이 아니다.
- **공식 감사에 대한 기록의 충분성.** 기록이 존재하고 제어 증거로 작동한다. 당신의 산업에서 특정 감사 요구사항을 닫는지는 우리가 사례별로 대답하는 질문이고, 페이지 청구가 아니다.
- **우리가 측정한 것 위의 규모.** 수백만 또는 수백만 개 문서의 량은 연습되지 않았다. 그것은 구매 전에 크기 조정 프로젝트다.

## 아직 존재하지 않는 것

이것들은 기능이 누락되고, 파일링하는 어디든 부드럽게 그들이 있고 우리는 단지 보여줄 수 없다고 말할 것이다. 그들은 없다.

- **충실한 시각적 검증.** 시스템이 구조를 측정하고 요소를 센다. 최종 페이지를 보지 않는다. 제품 내부 시각적 검사자는 없다.
- **백업 사본에 도달하는 삭제.** 오늘 삭제는 실제 시스템에서 완료되고 보존 윈도우 내 백업에 도달하지 않는다. 기술적 경로가 정의되고 아직 구축되지 않았다. 정확한 범위는 [개인정보 보호 및 주권](privacy)에 있다.
- **콘텐츠를 제거하고 계정을 비활성화하고, 인터페이스를 통해 한 동작에서.** 오늘 문서 삭제가 존재하고 유도물을 가지고 간다. 이 모든 것을 한번에 하는 것은 존재하지 않고, 폐쇄는 요청 시 처리된다. 이름이 의도적이다. 콘텐츠를 지우고 계정을 비활성화한다. 누가 시스템에 접근했는지의 추적은 남아 있기 때문이다.

## 이 페이지가 유지되는 방법

한 항목이 거의 준비되었을 때가 아니라 존재하고 측정되었을 때 여기를 떠난다. 떠날 때, 그것이 보장하는 것과 멈추는 곳을 가진 능력 페이지에 들어간다. 당신이 SazAI를 한동안 따르면, 이 페이지가 속도를 보여준다.

## 경계가 통과하는 곳

<h3 class="sub">기술적 독자가 먼저 테스트하는 세 가지 한계. 테스트 전에 명시됨</h3>

**공급자 경계.** 리니지가 각 텍스트 조각을 언어 모델을 떠나는 것까지 따르고 돌아올 때 다시 시작한다. 우리의 테이블 중 어느 것도 다른 쪽에서 일어난 것을 기록하지 않는다. 누가 *내 텍스트가 모델 내부에서 어떻게 되었는지 증명한다*고 묻는 사람은 그들이 계약한 공급자의 보존 조건을 받고, 당신 자신의 설치에서 공급자는 당신의 선택이다. [주권](privacy) 페이지가 그것이 멈추는 곳을 말한다.

**카피레프트 라이선스 배제.** AGPL 라이브러리는 엔진에 들어오지 않고, 그것은 의존성 파일에 문서화된 프로젝트 결정으로 기록된다. 그것은 주석이고, 관문이 아니다. 누군가 그것을 무시하면 아무것도 빌드를 깨지 않는다. 그렇게 말하는 것은 관문인 척하는 것보다 더 강하다. 파일을 여는 누구든지 10초 안에 본다.

**에이전트.** 이 시스템은 선언된 범위와 검토 체인을 가진 에이전트 팀으로 구축된다. 그들 사이의 통신은 실행이고, 증빙이 아니다. 채널을 통제하는 기록된 의사결정이 없다. 그 실패 모드는 우리에 의해 이번 주에 측정되었다. 그것은 원장의 오른쪽에 있고, 그곳이 그것이 가는 곳이다.

이 페이지가 주장하는 모든 것은 그 뒤에 명령이나 문서를 가진다. 그리고 그렇지 않은 것은 방향으로 말해진다. 여기서 무엇도 자신의 평가에서 재현될 수 없다면, 그것은 우리의 결함이고 우리는 당신이 하기 전에 알고 싶다. 이 플랫폼에서 나온 첫 번째 제품은 [문서가 들어올 때 당신이 보는 것](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;
  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()}});
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>