[verified] add semantic patterns and accessible motion
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
# Optional animation
|
||||
|
||||
Animation explains a complete static diagram; it never supplies missing meaning. Load this reference only when motion is explicitly requested or materially clarifies order, accumulation, evaluation, containment, or propagation. Otherwise use mode `none` and ship static HTML.
|
||||
|
||||
## Modes
|
||||
|
||||
Choose one mode per figure with `data-motion-mode="none|reveal|step|loop"`.
|
||||
|
||||
| Mode | Behavior | Controls / implementation | Use |
|
||||
|---|---|---|---|
|
||||
| `none` | Complete stable figure | No JavaScript | Default, print, screenshot, export, reduced-motion fallback with playback controls unavailable |
|
||||
| `reveal` | One deterministic run ending complete | CSS-only for ≤5s; otherwise use the scoped controller | Short ordered explanation; never auto-replay |
|
||||
| `step` | Paused semantic states | Minimal inline JS for Play, Pause, Replay, Previous, Next | Teaching, comparison, policy traces |
|
||||
| `loop` | One decorative token repeats without changing meaning | CSS-only default | Quiet flow hint; ≥3s cycle |
|
||||
|
||||
Only `loop` repeats. Queue state, typing, field values, policy outcomes, containment, and audit entries use `reveal` or `step` and finish complete.
|
||||
|
||||
## Static-first enhancement contract
|
||||
|
||||
1. **Source is complete.** Every semantic node, label, connector, status, and outcome is visible in the HTML/SVG before enhancement. Only selectors below `.motion-ready` may hide or transform them.
|
||||
2. **Stable capture.** Initial `data-frame="static"`, `?motion=static`, print, no-JS, and standalone SVG export expose the complete frame and hide controls/decorative tokens. Do not capture after an arbitrary delay.
|
||||
3. **CSS owns presentation.** Use CSS transitions/keyframes for appearance and travel. Minimal inline JavaScript is allowed only to bind explicit controls, update step/state attributes, schedule deterministic steps, and update the dedicated live-status region. No fetches, markup injection, path measurement, or mutation of semantic diagram labels or values.
|
||||
4. **One clock.** Use `--motion-fast: 160ms`, `--motion-step: 480ms`, `--motion-hold: 720ms`, and `--motion-total` ≤ `8000ms`; derive delays from integer steps. No randomness, springs, or transition-event timing.
|
||||
5. **Explicit order.** Mark items `data-motion-item data-step="N"` for integer steps 1–8. DOM order follows narrative order. At most two items enter per step.
|
||||
6. **Stable end.** Completion exposes all items and sets `data-frame="end"`. Replay resets to step 0 first. Pause clears the pending timer and resume continues from the same step.
|
||||
7. **Scoped state.** Controls operate on their nearest `[data-motion-root]`; IDs, timers, live regions, and step state never cross figure boundaries.
|
||||
8. **Failure-safe startup.** JavaScript adds `.motion-ready` only after controls are bound. A script error before that point leaves the complete source visible.
|
||||
|
||||
## Semantic primitives
|
||||
|
||||
Every primitive has text, count, symbol, pattern, or outline in addition to color.
|
||||
|
||||
| Primitive | Mechanism | Static / reduced-motion result | Limit |
|
||||
|---|---|---|---|
|
||||
| **Path draw** | Decorative duplicate path with `pathLength="1"` and animated dash offset | Base labeled connector remains visible | ≤2 paths; one active |
|
||||
| **Staggered reveal** (stage reveal) | `data-motion-item` + opacity/translate ≤8px | All stages visible | ≤8 steps, 12 items |
|
||||
| **Queue counter** (queue accumulation) | Stable slots; item reveal plus visible numeric count | Final queue and count visible | ≤5 items; no reorder |
|
||||
| **Typing / field population** | Full accessible string; clipped decorative overlay or labeled row reveal | Complete text/fields visible once | ≤32 typed chars or 6 fields |
|
||||
| **Policy evaluation** (rule evaluation) | Ordered rule rows with text statuses and a current-row outline | Every state and outcome visible | 3–6 rules; 2 traces |
|
||||
| **Flow token** | `aria-hidden` token on a fixed path | Token hidden; connector remains | One token; loop ≥3s |
|
||||
| **Containment** | Reveal children, then persistent labeled boundary | Children and boundary visible | One boundary transition |
|
||||
| **Audit append** | Chronological rows revealed; stable timestamp/sequence | Complete ordered log visible | ≤5 appended rows |
|
||||
|
||||
Do not animate layout coordinates, connector routes, `viewBox`, node dimensions, or semantic text. Avoid zoom, parallax, bounce, shake, glow, particles, and indefinite blinking.
|
||||
|
||||
```css
|
||||
:root {
|
||||
--motion-fast: 160ms;
|
||||
--motion-step: 480ms;
|
||||
--motion-hold: 720ms;
|
||||
--motion-ease: cubic-bezier(.2,.8,.2,1);
|
||||
}
|
||||
.motion-ready [data-motion-item] {
|
||||
opacity: 0;
|
||||
transform: translateY(8px);
|
||||
transition: opacity var(--motion-step) var(--motion-ease),
|
||||
transform var(--motion-step) var(--motion-ease);
|
||||
}
|
||||
.motion-ready [data-motion-item].is-visible,
|
||||
.motion-ready[data-frame="end"] [data-motion-item] {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
}
|
||||
[data-motion-controls][hidden] { display: none !important; }
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*, *::before, *::after {
|
||||
animation-duration: 0.001ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.001ms !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
[data-motion-item] { opacity: 1 !important; transform: none !important; }
|
||||
[data-motion-decorative] { display: none !important; }
|
||||
[data-motion-controls] { display: none !important; }
|
||||
}
|
||||
@media print {
|
||||
[data-motion-controls], [data-motion-decorative] { display: none !important; }
|
||||
[data-motion-item] { opacity: 1 !important; transform: none !important; }
|
||||
}
|
||||
```
|
||||
|
||||
## Interactive controls and keyboard
|
||||
|
||||
Every interactive `step` figure provides native buttons for **Play, Pause, Replay, Previous, and Next**, outside the SVG. Use `data-motion-action="play|pause|replay|prev|next"`, ≥44×44px targets, visible focus, disabled state for unavailable actions, and `aria-pressed` for play/pause state.
|
||||
|
||||
When focus is within the motion root: `ArrowRight` advances, `ArrowLeft` goes back, `Home` resets, `End` completes, and `Space` toggles play/pause when focus is not already on a native control. Do not capture keys from inputs, links, or unrelated regions. Never move focus as the frame changes.
|
||||
|
||||
Provide visible instructions and a scoped `role="status" aria-live="polite" aria-atomic="true"`. Announce user actions such as “Step 3 of 5: first divergence”; do not announce every autoplay frame. Controls operate only on their nearest `[data-motion-root]`.
|
||||
|
||||
Use [`assets/template-motion.html`](../assets/template-motion.html) rather than inventing another controller. Its inline controller is the executable implementation contract: copy that script body verbatim. The skin linter rejects modified or additional controllers, even when they carry `data-diagram-controls`. Replace diagram content and slug-prefixed IDs, but preserve the controller and its state/control attributes.
|
||||
|
||||
## Reduced motion, color, and accessibility
|
||||
|
||||
- `prefers-reduced-motion: reduce` initializes at the complete static frame, disables and hides every playback control, hides decorative movement, and exposes `data-motion-state="reduced"` plus status text that playback is unavailable. It never presents partial-step announcements beside a complete frame.
|
||||
- The SVG's `<title>` and `<desc>` describe the complete meaning, not the animation. Interaction instructions remain visible HTML text.
|
||||
- Decorative overlays carry `aria-hidden="true" focusable="false"`. Semantic text exists once in the accessibility tree.
|
||||
- State is never color-only: policy uses symbol + `PASS/FAIL/SKIPPED/NOT REACHED`; queues show counts; active stages use number/label/outline.
|
||||
- Nothing flashes or changes luminance more than three times per second.
|
||||
|
||||
## Complexity and deterministic timing
|
||||
|
||||
Motion does not raise the static diagram budget: ≤8 semantic steps (target 3–6), ≤12 marked items, ≤2 simultaneous reveals, ≤2 drawn paths, one flow-token loop, 160–600ms transitions, 400–1200ms holds, ≤24px translation, and 3–8s total autoplay.
|
||||
|
||||
Declare `data-step-count`; do not infer steps from transition events. Use one `setTimeout` chain per root, clear it on Pause/Replay/page hide and immediately after rendering the final step, and never use `setInterval` for semantic playback. Pause when `document.visibilityState` becomes hidden and do not catch up later. `?motion=step&step=N` may expose an exact zero-duration frame for visual regression only when `N` is a non-negative base-10 integer from 0 through `data-step-count`; missing, fractional, negative, and over-budget values leave normal playback in place.
|
||||
|
||||
The final-state capture contract is synchronous: `?motion=static`, `<html data-motion="static">`, or mode `none` exposes every semantic item, hides controls and decorative overlays, and sets `data-frame="static"`. Wait for `document.fonts.ready` before capture. Two captures from the same URL, viewport, fonts, and device scale must be pixel-identical; random delays, generated IDs, clocks, and runtime path measurement are forbidden.
|
||||
|
||||
## Export and verification
|
||||
|
||||
PNG and SVG exports are static final-state artifacts unless the user explicitly requests a named step. Before capture, open `?motion=static`, await `document.fonts.ready`, and assert `data-frame="static"`. SVG extraction omits HTML controls and scripts; source-visible semantic markup keeps the result complete.
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
python3 scripts/verify-motion.py path/to/animated-diagram.html
|
||||
python3 scripts/test-verify-motion.py
|
||||
python3 scripts/lint-skin.py path/to/animated-diagram.html
|
||||
```
|
||||
|
||||
The verifier checks mode/state declarations, contiguous steps, motion budgets, complete SVG naming, no-JS source visibility, decorative accessibility, the full control set, live status, reduced-motion/print CSS, keyboard handling, page-hide pause, bounded static/test overrides, immediate final-step stop, and exact canonical-controller identity. Its adversarial tests mutate the canonical template to prove each failure is rejected.
|
||||
|
||||
Then verify in a browser:
|
||||
|
||||
1. Disable JavaScript: the complete diagram remains visible and meaningful.
|
||||
2. Emulate `prefers-reduced-motion: reduce`: the final state is complete, playback controls are hidden and disabled, and the DOM status says playback is unavailable.
|
||||
3. Use keyboard only: Tab reaches each native control; Enter/Space operate it; Left/Right/Home/End step without moving focus.
|
||||
4. Pause, resume, and replay twice: ordering and final state are identical.
|
||||
5. Capture `?motion=static` twice after `document.fonts.ready`: pixels are stable.
|
||||
6. Print preview plus PNG/SVG export: controls and decorative tokens are absent, while all semantic labels and relationships remain.
|
||||
|
||||
## Anti-patterns
|
||||
|
||||
- Autoplay on load, viewport re-entry, or an endless semantic loop.
|
||||
- A blank/partial no-JS or reduced-motion frame.
|
||||
- Motion that rescues an over-dense or unlabeled static diagram.
|
||||
- Pass/fail, queue fullness, or outcome encoded only by hue.
|
||||
- Remote scripts, general application logic, runtime geometry, or duplicated semantic text.
|
||||
- Capturing at wall-clock delay instead of the explicit static override.
|
||||
@@ -48,7 +48,7 @@ Tools that don't fetch remote fonts at import time (offline Illustrator, some Fi
|
||||
|
||||
## PNG export procedure
|
||||
|
||||
Render **the original HTML** (not the extracted SVG) and screenshot only the `<svg>` element's bounding box. This keeps font loading reliable (already wired in the source HTML) while satisfying the "diagram only" rule. The PNG always has a **transparent background** (`omit_background=True`) so it can be placed on any slide or doc colour without a white halo.
|
||||
Render **the original HTML** (not the extracted SVG) and screenshot only the `<svg>` element's bounding box. This keeps font loading reliable (already wired in the source HTML) while satisfying the "diagram only" rule. The PNG always has a **transparent background** (`omit_background=True`) so it can be placed on any slide or doc colour without a white halo. For motion-enabled HTML, append `?motion=static`, await `document.fonts.ready`, and assert the motion root has `data-frame="static"` before capture; never export at an arbitrary wall-clock delay.
|
||||
|
||||
### Detection
|
||||
|
||||
@@ -131,6 +131,6 @@ If the target aspect ratio doesn't match the `viewBox` aspect ratio, say so and
|
||||
## What this command never does
|
||||
|
||||
- Modifies the source HTML.
|
||||
- Adds export buttons or `<script>` tags to generated diagrams (the "no JS in deliverables" rule in §11 still stands).
|
||||
- Adds export buttons or `<script>` tags. Static diagrams remain script-free; an already motion-enabled source may retain the scoped controller from [`animation.md`](animation.md), but export never injects another controller.
|
||||
- Auto-emits `.svg` or `.png` alongside HTML generation. Manual on every call.
|
||||
- Embeds an HTML wrapper (cards, headers) into the SVG via `foreignObject`. Too fragile across renderers.
|
||||
|
||||
@@ -77,6 +77,18 @@ Read the rendered `font-family` stack of:
|
||||
|
||||
If the site has only one family, keep the schematic defaults for the missing roles (Instrument Serif for title, Geist Mono for mono). Don't force-pick a mono font that isn't on the site.
|
||||
|
||||
### Exact-font gate for brand-matched output
|
||||
|
||||
Do not replace a detected brand family with `serif`, `system-ui`, or `ui-monospace` merely to make the file dependency-free. A public font is part of the visual system.
|
||||
|
||||
1. Record the computed family and weight used by the sampled heading, body, and technical-label elements.
|
||||
2. Trace each family to its source: an existing Google Fonts stylesheet, an installed/system stack, or a custom-hosted `@font-face`.
|
||||
3. If it is available through Google Fonts, carry the exact family name, weights, and approved stylesheet into the style guide and generated HTML. The single-file allowlist accepts only a parsed HTTPS URL whose hostname is exactly `fonts.googleapis.com` and whose path is exactly `/css2`; prefix/lookalike hosts and other paths fail. Preserve an intentional system stack in order and verify the resolved family on the target machine.
|
||||
4. A custom-hosted or paid font is not compatible with the default single-file allowlist. Label that role `fallback` unless the user separately approves and packages the font; never silently add a remote font URL or claim an exact match.
|
||||
5. Verify the rendered output with `getComputedStyle`; a declared family that failed to load does not pass.
|
||||
|
||||
For a page containing bespoke diagrams or editorial figures, inspect their rendered font roles as well as the surrounding article. A figure-specific stylesheet may intentionally differ from the site's global heading/body stack.
|
||||
|
||||
---
|
||||
|
||||
## Step 3 — map to semantic roles
|
||||
@@ -120,6 +132,16 @@ Show the user what will change in `style-guide.md`. Only the tokens table — ev
|
||||
|
||||
Also regenerate the dark variant via the inversion rule (`rgba(11,13,11, X)` → `rgba(ink-rgb, X)`).
|
||||
|
||||
Include a compact **brand fidelity receipt** with the preview:
|
||||
|
||||
- sampled URLs;
|
||||
- detected paper, ink, muted, accent, surface, and rule values;
|
||||
- title, body, and technical-label families with weights and source URLs;
|
||||
- `exact` or `fallback` for each font role;
|
||||
- any page-specific figure styling that should override the global site skin.
|
||||
|
||||
The receipt is required when the user says “match this site,” “use their branding,” or provides a page as the visual reference.
|
||||
|
||||
---
|
||||
|
||||
## Step 5 — apply
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
# Semantic patterns
|
||||
|
||||
Semantic patterns describe **what a system does**; the 27 visual types describe **how information is arranged**. Choose a pattern first when behavior, state, enforcement, or risk is load-bearing, then use its nearest visual type as the layout grammar. If no pattern matches, choose a visual type directly.
|
||||
|
||||
Use one primary pattern per figure. A second pattern may supply at most one supporting primitive; if both need full treatment, split overview and detail. Labels and outcomes must remain complete in a static frame.
|
||||
|
||||
## Routing table
|
||||
|
||||
| The reader must understand… | Semantic pattern | Nearest visual type |
|
||||
|---|---|---|
|
||||
| Many arrivals competing for finite service capacity | **Fan-in queue / bottleneck** | Data flow |
|
||||
| Repeated questions, inputs, controls, and outputs across stages | **Stage framework with semantic slots** | Process |
|
||||
| A loose conversation becoming a durable structured record | **Unstructured input → structured artifact** | Data flow |
|
||||
| Why two policy decisions differ and where they first diverge | **Paired policy-evaluation traces** | Flowchart |
|
||||
| Which routes cross a trust boundary and which routes are blocked | **Secure paved road** | Architecture |
|
||||
| Which controls apply at each enforcement surface | **Governance / control catalog** | Layer stack |
|
||||
| How defenses reduce risk and what risk remains | **Compensating security layers** | Layer stack |
|
||||
|
||||
## 1. Fan-in queue / bottleneck
|
||||
|
||||
**Selection triggers:** Several producers converge on one reviewer, service, gate, or constrained resource; the story depends on arrival rate, queue depth, wait, capacity, or backpressure.
|
||||
|
||||
**Required primitives:** Distinct sources; fanned ingress; an ordered queue with visible slots and count; a capacity/service-rate label; one constrained service point; admitted and deferred/rejected outcomes. Label units (`8/hour`, `3 slots`), not just “high.”
|
||||
|
||||
**Complexity budget:** ≤5 sources, ≤5 queue slots, one bottleneck, two outcomes, and ≤9 primary nodes. Aggregate excess sources as a named cohort.
|
||||
|
||||
**Anti-patterns:** Equal-width pipeline that hides contention; arrows merged before they can be traced; capacity implied only by box size; decorative pile-up; animation that changes item order; red alone meaning overloaded.
|
||||
|
||||
**Static fallback:** Show the representative final queue, numeric count/capacity, bottleneck label, and both outcome paths. A still must reveal why work waits.
|
||||
|
||||
**Nearest visual type:** **Data flow** by default; use **Process** when service stages, rather than sources, dominate.
|
||||
|
||||
## 2. Stage framework with semantic slots
|
||||
|
||||
**Selection triggers:** A lifecycle or operating model repeats the same semantic questions across stages, commonly Question, Input, Governance, and Output. Cross-stage comparability matters more than message timing.
|
||||
|
||||
**Required primitives:** Ordered stage headers; a consistent slot grid; explicit empty/not-applicable slots; stage-to-stage handoff; stable slot labels; one primary output per stage. Preserve slot order in every stage.
|
||||
|
||||
**Complexity budget:** 3–6 stages, 3–4 slot kinds, ≤20 populated cells, ≤2 lines per cell. Split detail when a cell needs prose.
|
||||
|
||||
**Anti-patterns:** Each stage invents a different internal layout; slot meaning encoded by position with no labels; fake precision from dozens of cells; confusing stage order with ownership lanes; shrinking text to keep one canvas.
|
||||
|
||||
**Static fallback:** Render the full stage × slot matrix with handoffs and explicit `—` or `Not applicable` entries. Do not depend on staged reveal to teach the schema.
|
||||
|
||||
**Nearest visual type:** **Process**; use **Swimlane** only when the repeated rows represent owners rather than semantic slots.
|
||||
|
||||
## 3. Unstructured input → structured artifact
|
||||
|
||||
**Selection triggers:** Dialogue, notes, prompts, or a rambling request are elicited, normalized, and written into a durable brief, ticket, record, schema, or other structured artifact.
|
||||
|
||||
**Required primitives:** Source utterance(s); clarifying questions; extracted field/value pairs; a named transformation; the durable artifact boundary; provenance links from representative statements to fields; missing/unknown state.
|
||||
|
||||
**Complexity budget:** ≤4 exchanges, ≤6 artifact fields, one transformation, and ≤3 provenance links. Show representative content, not a transcript.
|
||||
|
||||
**Anti-patterns:** “AI magic” sparkle between two boxes; artifact shown as another chat bubble; fields appearing without sources; inventing certainty for missing facts; typing animation as the only readable copy.
|
||||
|
||||
**Static fallback:** Show a short source excerpt beside the completed labeled artifact, with at least one provenance mapping and any unknown fields visible.
|
||||
|
||||
**Nearest visual type:** **Data flow**; use **Process** when elicitation has several ordered gates.
|
||||
|
||||
## 4. Paired policy-evaluation traces
|
||||
|
||||
**Selection triggers:** Two otherwise similar requests reach different outcomes; the reader needs rule-by-rule `PASS`, `FAIL`, `SKIPPED`, or `NOT REACHED` state and the first divergence.
|
||||
|
||||
**Required primitives:** The same ordered rules on both traces; explicit status text plus symbol/shape; inputs that differ; final outcomes; a labeled first-divergence marker; a distinction between `SKIPPED` (applicable flow intentionally bypassed) and `NOT REACHED` (evaluation stopped earlier).
|
||||
|
||||
**Complexity budget:** Exactly 2 traces, 3–6 rules, one first divergence, ≤12 status cells, and one outcome per trace. Move rule prose to notes if labels exceed one line.
|
||||
|
||||
**Anti-patterns:** Comparing two independently ordered flows; green/red dots without words; treating skipped and not-reached as synonyms; highlighting every difference; continuing a denied trace as if downstream rules ran.
|
||||
|
||||
**Static fallback:** Show all rule states and both outcomes at once; use a persistent bracket/line and label for the first divergence.
|
||||
|
||||
**Nearest visual type:** **Flowchart** for ordered decision logic; use **Sequence** only when messages between actors and time are also load-bearing.
|
||||
|
||||
## 5. Secure paved road
|
||||
|
||||
**Selection triggers:** A supported architecture creates a bounded route from intake/build to deployment; trust boundaries, privileged moments, permitted ingress, forbidden ingress, and approved versus blocked deploy paths are the point.
|
||||
|
||||
**Required primitives:** Labeled trust boundaries; actors and identities; permitted ingress with a positive text label; forbidden ingress terminating at the boundary; approved deployment path; blocked bypass path; privileged gate; isolated runtime; audit destination. Use different line styles and stop symbols in addition to color.
|
||||
|
||||
**Complexity budget:** ≤3 trust zones, ≤8 components, ≤10 paths, ≤2 forbidden paths, and one privileged gate. Split control detail into a catalog figure.
|
||||
|
||||
**Anti-patterns:** Dashed box called “security” with no route semantics; forbidden arrow crossing into the protected zone; secrets or identity implied but unlabeled; every component styled as trusted; a bypass path that visually rejoins the approved route.
|
||||
|
||||
**Static fallback:** Render every boundary and both permitted/forbidden routes. Blocked paths must visibly stop before entry or deployment.
|
||||
|
||||
**Nearest visual type:** **Architecture**.
|
||||
|
||||
## 6. Governance / control catalog
|
||||
|
||||
**Selection triggers:** A control inventory must be understood by where it is enforced: authoring, workspace, merge/CI, deploy/runtime, or another named surface. A single checklist would hide those enforcement points.
|
||||
|
||||
**Required primitives:** Enforcement-surface groups; named controls; enforcement actor (`code`, `platform`, `human`); timing (`write`, `merge`, `deploy`, `run`); bypassability or exception route; coverage/gap notation.
|
||||
|
||||
**Complexity budget:** 3–5 surfaces, 3–7 controls per surface, ≤24 controls total, and ≤3 attributes per control. Summarize counts only when the item list exists elsewhere.
|
||||
|
||||
**Anti-patterns:** 35 tiny pills; grouping by vague themes instead of enforcement point; mixing aspirations with enforced controls; icons without control names; claiming defense-in-depth without showing surface coverage.
|
||||
|
||||
**Static fallback:** Show the complete grouped catalog with surface headers and text labels for actor and enforcement timing; preserve gaps and exceptions.
|
||||
|
||||
**Nearest visual type:** **Layer stack**; use **DP security matrix** when role permissions, not enforcement surfaces, are the dominant comparison.
|
||||
|
||||
## 7. Compensating security layers
|
||||
|
||||
**Selection triggers:** No layer is perfect; each defense covers a failure left by the previous layer, and residual risk must visibly narrow, transfer, or remain through the stack.
|
||||
|
||||
**Required primitives:** Ordered threat/risk input; named defensive layers; each layer's mitigation; explicit limitation or escape; residual-risk carrier between layers; final residual risk and consequence/response. Use labels or decreasing measures, never area alone.
|
||||
|
||||
**Complexity budget:** 3–5 layers, one primary risk thread, ≤2 mitigations per layer, and one final residual-risk statement. Split multiple unrelated threats into separate figures.
|
||||
|
||||
**Anti-patterns:** Implying the final layer makes risk zero; equal opaque slabs with no propagation; treating audit as prevention; shrinking shapes without numeric or verbal meaning; reversing prevention/detection/recovery order without explanation.
|
||||
|
||||
**Static fallback:** Show the complete propagation chain: initial risk → mitigation → escaped risk at every layer → final residual risk and response.
|
||||
|
||||
**Nearest visual type:** **Layer stack**; use **Nested** when containment boundaries, rather than ordered compensation, carry the meaning.
|
||||
|
||||
## Composition rules
|
||||
|
||||
- The semantic pattern may specialize status, boundary, queue, or propagation primitives; the selected type still owns page axis, connector grammar, spacing, and type-specific limits.
|
||||
- Apply the stricter of the pattern budget and visual-type budget. Semantic cells/statuses are not permission to exceed the nine-node overview target.
|
||||
- Use stable text for states and outcomes. Color, motion, and position reinforce meaning but never carry it alone.
|
||||
- Optional animation is a presentation layer, not another pattern. Load [`animation.md`](animation.md) only when motion is requested or materially clarifies ordered change.
|
||||
Reference in New Issue
Block a user