@orkestrel/scaffold 0.0.58 → 0.0.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/dist/host/agents/skills/enterprise-bootstrap/SKILL.md +91 -82
  2. package/dist/host/agents/skills/enterprise-bootstrap/references/bootstrap-reference.md +5 -5
  3. package/dist/host/agents/skills/enterprise-bootstrap/references/components.md +10 -10
  4. package/dist/host/agents/skills/enterprise-bootstrap/references/inputs.md +501 -0
  5. package/dist/host/agents/skills/enterprise-bootstrap/references/inspection.md +167 -0
  6. package/dist/host/agents/skills/enterprise-bootstrap/references/utilities.md +2 -2
  7. package/dist/host/agents/skills/orkestrel-polish-surface/SKILL.md +4 -1
  8. package/dist/host/agents/skills/orkestrel-polish-surface/references/capture-harness.md +71 -50
  9. package/dist/host/agents/skills/orkestrel-prove-journey/SKILL.md +93 -29
  10. package/dist/host/agents/skills/orkestrel-prove-journey/agents/openai.yaml +1 -1
  11. package/dist/host/agents/skills/orkestrel-prove-journey/references/captures.md +62 -38
  12. package/dist/host/agents/skills/orkestrel-prove-journey/references/decide.md +68 -0
  13. package/dist/host/agents/skills/orkestrel-prove-journey/references/layer.md +107 -79
  14. package/dist/host/agents/skills/orkestrel-prove-journey/references/statechart.md +84 -0
  15. package/dist/host/agents/skills/orkestrel-prove-journey/references/styles.md +87 -0
  16. package/dist/host/claude/agents/orkestrel.md +11 -10
  17. package/dist/host/claude/skills/orkestrel-prove-journey/SKILL.md +1 -1
  18. package/dist/host/manifest.json +43 -13
  19. package/dist/host/scripts/codex.sh +0 -0
  20. package/dist/host/scripts/cursor.sh +0 -0
  21. package/dist/host/scripts/deps.sh +0 -0
  22. package/dist/host/scripts/ollama.sh +0 -0
  23. package/dist/src/core/index.cjs +5 -5
  24. package/dist/src/core/index.cjs.map +1 -1
  25. package/dist/src/core/index.js +5 -5
  26. package/dist/src/core/index.js.map +1 -1
  27. package/package.json +5 -5
@@ -24,18 +24,22 @@ every claim about the result from what renders.
24
24
  Open the reference that owns a subject before writing markup. Never guess a class name: an invented
25
25
  utility (`.vw-50`, `.pointer-events-none`) has no rule in the shipped CSS and fails silently. Pick
26
26
  components from [components.md](references/components.md) → Choosing components, take their markup
27
- from the same file, and take fine layout from [utilities.md](references/utilities.md). Where
28
- Bootstrap ships no component for the need — combobox, date picker, tags input, data grid, tree —
29
- work the native-first ladder in [bootstrap-reference.md](references/bootstrap-reference.md) → When
30
- not to hand-roll before building one.
27
+ from the same file, and take fine layout from [utilities.md](references/utilities.md). Pick an
28
+ input's affordance from [inputs.md](references/inputs.md) by what the person is asked for, not by
29
+ what a schema calls the field. Where Bootstrap ships no component for the need — combobox, date
30
+ picker, tags input, data grid, tree — work the native-first ladder in
31
+ [bootstrap-reference.md](references/bootstrap-reference.md) → When not to hand-roll before building
32
+ one.
31
33
 
32
34
  | Layer | File | Holds |
33
35
  | -------------- | ----------------------------------------------------------- | --------------------------------------------------------------------------------- |
34
- | Operate | `SKILL.md` (this file) | Process, decision rules, checklist |
36
+ | Operate | `SKILL.md` | Process, decision rules, checklist |
35
37
  | Design craft | [frontend-design.md](references/frontend-design.md) | Aesthetic, typography, signature, interface copy, anti-defaults |
36
38
  | Components | [components.md](references/components.md) | Bootstrap component markup + enterprise selection notes |
39
+ | Inputs | [inputs.md](references/inputs.md) | Affordance per input category, its alternates, its rung, its states |
37
40
  | Utilities | [utilities.md](references/utilities.md) | Class index, helpers, composition notes |
38
41
  | Bootstrap deep | [bootstrap-reference.md](references/bootstrap-reference.md) | Color modes, theming/tokens, forms, JS lifecycle, a11y depth, enterprise patterns |
42
+ | Instruments | [inspection.md](references/inspection.md) | Property, population, reading, negative control, and coverage per instrument |
39
43
 
40
44
  ---
41
45
 
@@ -43,20 +47,20 @@ not to hand-roll before building one.
43
47
 
44
48
  1. **Assume no stack.** Infer it from the workspace. Do not assume Vue, React, a skin library, a folder layout, or a named product.
45
49
  2. **Target Bootstrap 5.3.x** class names and behaviors. Hold a compatible skin that keeps `.btn`, `.card`, `.form-control`, and `data-bs-*` to the same contracts.
46
- 3. **Follow the project's code law.** Its `AGENTS.md`, lint rules, and design system decide language, layout, and forbidden patterns. This package owns UI craft and Bootstrap usage, not language law.
50
+ 3. **Follow the project's code law.** Take language, layout, and forbidden patterns from its `AGENTS.md` file, its lint rules, and its design system. Take UI craft and Bootstrap usage from here, and never language law.
47
51
  4. **Write framework-neutral markup** — semantic HTML plus Bootstrap classes. Wire behavior with what the project already uses; in an SPA prefer the framework-native Bootstrap wrappers over raw `bootstrap.*` JS ([bootstrap-reference.md](references/bootstrap-reference.md) → JavaScript lifecycle).
48
52
  5. **Keep this folder intact** so the relative links between its files resolve. Install or vendor it wherever the tooling looks for skills; the paths are tooling-specific, the content is not.
49
53
  6. **Use the project's installed Bootstrap** when it has one; otherwise take the CDN snippet from [bootstrap-reference.md](references/bootstrap-reference.md) → Quick start (5.3.8).
50
- 7. **Apply this package** to UI, Bootstrap, and visual-design work matching the description above. When the user points at it, treat it as authoritative for the visual pass.
54
+ 7. **Apply this package** to UI, Bootstrap, and visual-design work matching the frontmatter description. When the user points at it, treat it as authoritative for the visual pass.
51
55
 
52
56
  ---
53
57
 
54
58
  ## The mandate
55
59
 
56
60
  1. **Design direction** — take a point of view rooted in the _subject_ (audience, job-to-be-done, vernacular). Take one justified aesthetic risk, in one place.
57
- 2. **Bootstrap execution** — components and utilities first; custom CSS only when the system cannot express the need; paint through `--bs-*` so light and dark both survive.
61
+ 2. **Bootstrap execution** — take components and utilities first, custom CSS only when the system cannot express the need, and paint through `--bs-*` so light and dark both survive.
58
62
 
59
- Match the density to the context: a marketing page may open with a thesis-hero, an authenticated
63
+ Match the density to the context: a marketing page can open with a thesis-hero, an authenticated
60
64
  tool opens with clarity and scan paths. In product UI put the signature in the chrome, never in the
61
65
  data ([frontend-design.md](references/frontend-design.md) → Where the signature lives).
62
66
 
@@ -64,9 +68,9 @@ data ([frontend-design.md](references/frontend-design.md) → Where the signatur
64
68
 
65
69
  ## Process
66
70
 
67
- Design craft — subject grounding, hero and thesis, typography, structure, motion, restraint, and
68
- interface copy — lives in [frontend-design.md](references/frontend-design.md). Read it before
69
- setting a direction. The loop:
71
+ Read [frontend-design.md](references/frontend-design.md) before setting a direction; it owns subject
72
+ grounding, hero and thesis, typography, structure, motion, restraint, and interface copy. Then work
73
+ this loop:
70
74
 
71
75
  1. **Ground** — name the subject, the audience, and the screen's single job, and state them. Use known user preferences and prior designs as hints, not templates.
72
76
  2. **Plan** — build a token system: **color** (4–6 named values), **type** (display / body / utility), **layout** (prose plus ASCII if useful), **signature** (one memorable element).
@@ -74,53 +78,51 @@ setting a direction. The loop:
74
78
  4. **Build** — compose Bootstrap components and utilities; map the plan's tokens onto theme variables or a thin skin, with no scattered one-off hex ([bootstrap-reference.md](references/bootstrap-reference.md) → Theming & design tokens). Watch selector specificity: a utility and a custom rule that cancel each other show up as padding and margin bugs.
75
79
  5. **Critique the render** — remove one accessory. Check contrast, focus, `prefers-reduced-motion`, mobile, and every data state. Critique what rendered, not the markup.
76
80
 
77
- Brainstorm privately; show a direction only once it satisfies the brief and the quality floor
78
- ([frontend-design.md](references/frontend-design.md) → Process).
81
+ Show a direction only after it satisfies the brief and the quality floor, and keep every earlier
82
+ draft private ([frontend-design.md](references/frontend-design.md) → Process).
79
83
 
80
84
  **Rendered proof.** Settle every claim about a screen from a capture, never from source alone;
81
- `.agents/orchestration.md` owns this law where it is present. The review input here is captures at
82
- both viewports and both themes plus an accessibility snapshot; source only corroborates the
83
- mechanism. For a full review-round campaign built on that evidence, use the
85
+ `.agents/orchestration.md` owns this law where it is present. Take captures at every viewport and
86
+ every theme the surface declares, plus an accessibility snapshot, as the review input, and use source only to corroborate
87
+ the mechanism. For a full review-round campaign built on that evidence, use the
84
88
  `orkestrel-polish-surface` skill instead of improvising one here.
85
89
 
86
- **Mechanical proof.** These instruments settle what a capture cannot. Pair each one with a negative
87
- control drawn from outside the population it covers, and treat an instrument whose control passes as
88
- broken; `.claude/rules/quality.md` owns this law where it is present:
89
-
90
- - **Contrast, composited.** Read every pairing through a reader that composites the painted layers, in both themes ([bootstrap-reference.md](references/bootstrap-reference.md) → Measuring the bars).
91
- - **Authored classes against the shipped cascade.** Extract every class authored in the templates and components, and fail the run on one that has no rule in the compiled CSS the page loads. Assert a population floor so an extractor that quietly matched nothing cannot pass, and control it with a class you know is absent.
92
- - **One glyph, one meaning.** Register each status glyph against the meaning it carries. No meaning takes more than one glyph, no glyph serves more than one meaning, and every registered glyph resolves in the icon set actually shipped.
90
+ **Mechanical proof.** Run every instrument in [inspection.md](references/inspection.md) with the
91
+ negative control it names, and treat an instrument whose negative control passes as broken;
92
+ `.claude/rules/quality.md` owns that law where it is present. Those instruments settle what a capture
93
+ cannot: composited contrast, authored classes against the shipped cascade, declared class
94
+ combinations, style escapes, token discipline, a custom rule doing a utility's job, and one glyph per
95
+ meaning. Hold every check the deliverable lists to that shape, whether or not inspection.md names
96
+ it: each states its population, its negative control, and its coverage, and a check that cannot
97
+ name a negative control is recorded as open rather than listed as a check.
93
98
 
94
99
  ---
95
100
 
96
101
  ## Bootstrap operating principles
97
102
 
98
- 1. **Mobile first** — smallest screen first, then `sm` / `md` / `lg` / `xl` / `xxl`.
99
- 2. **Semantic HTML** — `nav`, `main`, `section`, heading order.
100
- 3. **Work down the styling ladder below** — component classes, then utilities, then Bootstrap's own extension points.
103
+ 1. **Mobile first** — build the smallest screen first, then `sm` / `md` / `lg` / `xl` / `xxl`.
104
+ 2. **Semantic HTML** — use `nav`, `main`, and `section`, and hold the heading order.
105
+ 3. **Work down the styling ladder that follows** — component classes, then utilities, then Bootstrap's own extension points.
101
106
  4. **Test every breakpoint you claim.**
102
107
  5. **Reach for Bootstrap's own transitions before writing custom animation**, spend one orchestrated moment at most, and wrap any custom animation in `prefers-reduced-motion: no-preference` ([bootstrap-reference.md](references/bootstrap-reference.md) → Reduced motion).
103
- 6. **Resolve every treatment in the shipped cascade** — Bootstrap plus every skin and dependency stylesheet the page pulls in — never from docs memory. A class with no rule of its own may still inherit one, and a token pair that passes in stock Bootstrap can fail under a compatible skin. Measure the `*-subtle` / `*-emphasis` recipes too, once per theme, with a reader that composites the translucent layers ([bootstrap-reference.md](references/bootstrap-reference.md) → Measuring the bars).
108
+ 6. **Resolve every treatment in the shipped cascade** — Bootstrap plus every skin and dependency stylesheet the page pulls in — never from docs memory. A class with no rule of its own can still inherit one, and a token pair that passes in stock Bootstrap can fail under a compatible skin. Measure the `*-subtle` / `*-emphasis` recipes too, once per theme, with a reader that composites the translucent layers ([bootstrap-reference.md](references/bootstrap-reference.md) → Measuring the bars).
104
109
 
105
110
  ### The styling ladder
106
111
 
107
- Work down these rungs in order. Reach a lower rung only when the one above genuinely cannot express
108
- the need.
112
+ Work down these rungs in order. Reach a rung only when the preceding one cannot express the need.
109
113
 
110
- 1. **The component's own classes, in its documented structure.** Use the right elements, nesting, class names, and required ARIA: a card is `.card` wrapping `.card-body` wrapping `.card-title`, not a `div` with borrowed padding. Variants, states, color modes, and responsive behavior all hang off that structure.
114
+ 1. **The component's own classes, in its documented structure.** Use the right elements, nesting, class names, and required ARIA: a card is `.card` wrapping `.card-body` wrapping `.card-title`, not a `div` with borrowed padding. Modifier classes, affordance states, color modes, and responsive behavior all hang off that structure.
111
115
  2. **Bootstrap utilities, for refinement.** Spacing, flex, display, sizing, text, borders, color. Compose utilities rather than reaching past them, and use only classes that exist in [utilities.md](references/utilities.md).
112
116
  3. **Bootstrap's own extension points.** Component `--bs-{component}-*` variables and the utilities API, when a real gap remains after the component-class and utility tiers.
113
- 4. **Anything beyond Bootstrap's conventions is the developer's call, not yours.** Stop at rung 3 and say plainly what rung 4 would require.
117
+ 4. **Leave anything beyond Bootstrap's conventions to the developer.** Stop at rung 3 and say plainly what rung 4 would require. Take rung 4 unasked only where [inspection.md](references/inspection.md) → When an authored rule is already earned opens it.
114
118
 
115
- Never open at rung 4. Specifically, do not reach first for:
119
+ Never reach first for any of these, because each ends the cascade for that element and then survives
120
+ no `--bs-*` retheming, no breakpoint change, and no color-mode change:
116
121
 
117
122
  - a `style="..."` attribute;
118
123
  - a `<style>` block in a page or component;
119
124
  - a new stylesheet rule for something a utility already does.
120
125
 
121
- Each ends the cascade for that element: it outranks the utilities, it ignores `--bs-*` retheming, and
122
- it does not change across breakpoints or color modes.
123
-
124
126
  ### Hierarchy & actions
125
127
 
126
128
  | Intent | Typical choice |
@@ -131,61 +133,67 @@ it does not change across breakpoints or color modes.
131
133
  | Tertiary | `btn-link` or text links |
132
134
  | Status | `badge` / `alert` / `*-emphasis` — **icon + color + word** |
133
135
 
134
- **Outline buttons are the decorative tier.** They paint no background of their own, so they borrow
135
- whatever surface they sit on and their contrast is surface- and theme-dependent by construction:
136
- against stock Bootstrap the whole `btn-outline-*` family misses 4.5:1 across the dark theme and on
137
- light tinted surfaces — cards, subtle alerts. Give any action that carries information or
138
- consequence the solid variant. Solid variants paint their own background and measure identically on
139
- every surface, and the stock fills sit at the 4.5:1 bar with nothing to spare. Re-measure a solid
140
- variant whenever anything layers over it — an `opacity-*` utility, a translucent overlay, a skin's
141
- own tint.
136
+ **Give any action that carries information or consequence a solid `btn-*` class, and keep outline
137
+ buttons decorative.** Against stock Bootstrap the whole `btn-outline-*` family misses 4.5:1 across
138
+ the dark theme and on light tinted surfaces — cards, subtle alerts — because an outline button
139
+ paints no background of its own and borrows the surface it sits on.
142
140
 
143
- A status mark with **no text** is an icon glyph, never a `badge`
141
+ **Re-measure a solid fill whenever anything layers over it** — an `opacity-*` utility, a translucent
142
+ overlay, a skin's own tint — because the stock fills sit at the 4.5:1 bar with nothing to spare.
143
+
144
+ Draw a status mark with **no text** as an icon glyph, never as a `badge`
144
145
  ([components.md](references/components.md) → Badge).
145
146
 
146
147
  ### Surfaces, color, contrast
147
148
 
148
- - **Contrast bars, measured in both themes:** **≥ 4.5:1** for anything information-bearing — `small`, captions, and meta text included — and **≥ 3:1** for textless marks, state indicators, and the hover/focus chrome that carries state. Verify Bootstrap's own palette too; the docs admit some defaults fall short. Read both themes — a pairing that passes light routinely fails dark.
149
- - **Information-bearing status text takes the `-emphasis` pair.** Plain `text-success` and `text-danger` miss the bar across the dark theme and on light tinted surfaces, and `text-warning` is theme-asymmetric — unreadable on light, comfortable on dark. Never make a plain semantic color the encoding; use it only as decoration beside an encoding that already passes.
150
- - `text-body-tertiary` carries no information anywhere: it measures under 4.5:1 on every surface in both themes. Tier text a user must read `text-body-secondary` or better, and keep tertiary for genuinely decorative marks.
151
- - **A subtle fill degrades everything inside it one notch.** Inside `alert-*` and the `*-subtle` backgrounds, outline buttons and plain semantic text fail even in light — so information-bearing text there is `-emphasis` and every button is solid.
152
- - **A primary fill destroys every semantic color.** On `.active`, `.bg-primary`, and `text-bg-*` surfaces every tone class measured lands under the bar in both themes, the `-emphasis` family included, because the fill supplies its own contrast color and the tone class overrides it with one tuned for a different background. Carry no tone class inside such a fill; let the surface's contrast color take the text, keep the status encoded by icon and word, and verify by capturing the selected state ([components.md](references/components.md) → Selection fills).
153
- - Disabled controls are exempt from the bars, but a disabled **destructive** control must not keep full danger saturation — at full strength it still reads as armed. Neutralize the variant while it is disabled and carry the reason on the control with `aria-describedby` (plus `title` for pointer users), never `title` alone.
149
+ - **Measure these contrast bars in both themes:** **≥ 4.5:1** for anything information-bearing — `small`, captions, and meta text included — and **≥ 3:1** for textless marks, state indicators, and the hover/focus chrome that carries state. Verify Bootstrap's own palette too; the docs admit some defaults fall short. Read both themes — a pairing that passes light routinely fails dark.
150
+ - **Take the `-emphasis` pair for information-bearing status text.** Plain `text-success` and `text-danger` miss the bar across the dark theme and on light tinted surfaces, and `text-warning` is theme-asymmetric — unreadable on light, comfortable on dark. Never make a plain semantic color the encoding; use it only as decoration beside an encoding that already passes.
151
+ - **Tier text a person must read `text-body-secondary` or better**, and keep `text-body-tertiary` for decorative marks: tertiary measures under 4.5:1 on every surface in both themes, so it carries no information anywhere.
152
+ - **Inside `alert-*` and the `*-subtle` backgrounds, take `-emphasis` for information-bearing text and a solid `btn-*` class for every button.** A subtle fill degrades everything inside it one notch, so outline buttons and plain semantic text fail there even in light.
153
+ - **Carry no tone class inside a primary fill.** On `.active`, `.bg-primary`, and `text-bg-*` surfaces every tone class measured lands under the bar in both themes, the `-emphasis` family included, because the fill supplies its own contrast color and the tone class overrides it with one tuned for a different background. Let the surface's contrast color take the text, keep the status encoded by icon and word, and verify by capturing the selected state ([components.md](references/components.md) → Selection fills).
154
+ - Exempt a disabled control from the bars, but never leave a disabled **destructive** control at full danger saturation — at full strength it still reads as armed. Neutralize the danger tone while the control is disabled and carry the reason on the control with `aria-describedby` (plus `title` for pointer users), never `title` alone.
154
155
  - Prefer `bg-body`, `bg-body-secondary`, `bg-body-tertiary` over raw `bg-white` / `bg-light`, and drive custom paint from `var(--bs-…)` — they track `data-bs-theme`, a hard-coded hex does not.
155
- - Pairings: `text-bg-*`, `*-subtle`, `*-emphasis`, `text-body` / `text-body-secondary`. `text-muted` is deprecated — use `text-body-secondary`.
156
- - On **dark surfaces**, scope `data-bs-theme="dark"` rather than the deprecated component variants `navbar-dark`, `dropdown-menu-dark`, `btn-close-white`, and `carousel-dark`; gray-on-dark outlines often fail contrast.
157
- - Support `data-bs-theme="light"` and `dark` when the product offers both. Mechanics: [bootstrap-reference.md](references/bootstrap-reference.md) → Color modes.
156
+ - Take pairings from `text-bg-*`, `*-subtle`, `*-emphasis`, and `text-body` / `text-body-secondary`. `text-muted` is deprecated — use `text-body-secondary`.
157
+ - On **dark surfaces**, scope `data-bs-theme="dark"` rather than the deprecated `*-dark` component classes `navbar-dark`, `dropdown-menu-dark`, `btn-close-white`, and `carousel-dark`; gray-on-dark outlines often fail contrast.
158
+ - Support `data-bs-theme="light"` and `dark` when the product offers both, and take the mechanics from [bootstrap-reference.md](references/bootstrap-reference.md) → Color modes.
158
159
 
159
160
  ### Density, layout, responsive
160
161
 
161
- - Enterprise density: `table-sm`, `btn-sm` / `btn-group-sm`, compact toolbars — but keep every interactive target **≥ 24×24px**, measured on the rendered box rather than assumed from the class (WCAG 2.2); pad hit areas rather than shrinking them.
162
+ - Take enterprise density from `table-sm`, `btn-sm` / `btn-group-sm`, and compact toolbars, but keep every interactive target **≥ 24×24px**, measured on the rendered box rather than assumed from the class (WCAG 2.2); pad hit areas rather than shrinking them.
162
163
  - Where information density is the screen's job, take the `-sm` family across a control row together — `btn-sm` with `form-control-sm`, `form-select-sm`, `input-group-sm` — so the row shares one height. Never mix control sizes within one row.
163
- - Cards earn their keep: `.card` when grouping helps; otherwise spacing and type.
164
+ - Take `.card` where grouping earns it; otherwise carry the grouping with spacing and type.
164
165
  - Swap conditional chrome in place. A bulk-action bar or an alert that shoves the toolbar down shifts the layout mid-task.
165
- - App shell, dense tables, filter bars, and the ranked responsive strategies for wide data: [bootstrap-reference.md](references/bootstrap-reference.md) → Enterprise patterns. Spacing, toolbar, truncation, and print composition: [utilities.md](references/utilities.md) → Composition habits.
166
+ - Take the app shell, dense tables, filter bars, and the ranked responsive strategies for wide data from [bootstrap-reference.md](references/bootstrap-reference.md) → Enterprise patterns, and spacing, toolbar, truncation, and print composition from [utilities.md](references/utilities.md) → Composition habits.
166
167
 
167
168
  ### States & feedback
168
169
 
169
- - **Every data surface ships these states:** ideal, empty, loading, partial, error. It is not done until every one exists. Loading thresholds, empty and error specifics, and the channel matrix for toast / inline alert / banner / modal: [bootstrap-reference.md](references/bootstrap-reference.md) → The data states, Feedback discipline.
170
+ - **Ship every one of these states on every data surface:** ideal, empty, loading, partial, error. Treat the surface as unfinished until every one exists. Take loading thresholds, empty and error specifics, and the channel matrix for toast / inline alert / banner / modal from [bootstrap-reference.md](references/bootstrap-reference.md) → The data states, Feedback discipline.
170
171
  - **Build a blocking decision on the native `<dialog>`.** `showModal()` brings focus containment, Esc, an inert background, and top-layer stacking from the platform, with no instance to construct and none to leak on unmount. Dress it with Bootstrap chrome inside ([components.md](references/components.md) → Modal). Reach for `.modal` and its JS only when the project already drives its dialogs that way.
171
- - **Destructive actions:** prefer undoable over interrupting. Ladder and confirmation contracts: [bootstrap-reference.md](references/bootstrap-reference.md) → Destructive actions.
172
+ - **Make a destructive action undoable rather than interrupting**, and take the ladder and the confirmation contracts from [bootstrap-reference.md](references/bootstrap-reference.md) → Destructive actions.
172
173
 
173
174
  ### Forms
174
175
 
176
+ - Choose each field's affordance in [inputs.md](references/inputs.md) → The catalog by what the person is asked for, draw every state in that file's fixed set, and obey its cross-category rules — read-only chrome, the locked select, the chosen filter's accent tone, the non-drag path for a file drop.
175
177
  - Give every field a visible label (top-aligned by default) or `.form-floating` — never placeholder-only.
176
178
  - Validate on **blur**, re-validate error fields on input, re-check everything on submit, and keep submit **enabled**. Never disable submit as a validation strategy.
177
179
  - Pair a focusable error summary with inline `.invalid-feedback` per field (`aria-describedby`, `aria-invalid`).
178
- - Layout, validation mechanics and their assistive-tech limitation, input groups, autosave, and multi-step rules: [bootstrap-reference.md](references/bootstrap-reference.md) → Forms in production, Wizards & multi-step forms.
180
+ - Take layout, validation mechanics and their assistive-technology limitation, input groups, autosave, and multi-step rules from [bootstrap-reference.md](references/bootstrap-reference.md) → Forms in production, Wizards & multi-step forms.
179
181
 
180
182
  ### When custom CSS is justified
181
183
 
182
- This is rung 4 of the styling ladder, so it is the developer's decision. Propose it, name what it
183
- buys, and do not take it unprompted. Exhaust rungs 1–3 first: correct component structure, then
184
- utilities, then the extension points — component `--bs-{component}-*` variables for restyling, the
185
- utilities API for missing utility steps ([bootstrap-reference.md](references/bootstrap-reference.md)
186
- → Theming).
184
+ Treat custom CSS as rung 4 and the developer's decision: propose it, name what it buys, and take it
185
+ unprompted only under the exception that follows. Exhaust rungs 1–3 first — correct component
186
+ structure, then utilities, then the extension points: component `--bs-{component}-*` variables for
187
+ restyling, the utilities API for missing utility steps
188
+ ([bootstrap-reference.md](references/bootstrap-reference.md) → Theming).
189
+
190
+ Take an authored rule without asking only where an instrument in
191
+ [inspection.md](references/inspection.md) reports the vendor cascade failing a stated bar, the rule
192
+ cites that reading, the rule restores the bar and does nothing else, and the rule is written over
193
+ tokens. [inspection.md](references/inspection.md) → When an authored rule is already earned states
194
+ the whole condition. Treat anything wider as a proposal.
187
195
 
188
- When the developer authorizes it:
196
+ When the developer authorizes it, or that exception opens:
189
197
 
190
198
  - Name it in Bootstrap vocabulary.
191
199
  - Take colors from `var(--bs-…)` and theme tokens so light and dark both work.
@@ -197,20 +205,20 @@ When the developer authorizes it:
197
205
 
198
206
  ## Accessibility baseline
199
207
 
200
- - Skip link to main; landmarks; `h1` → `h2` order.
201
- - `aria-label` on icon-only controls; targets ≥ 24×24px.
202
- - `aria-current` / `aria-selected` on active nav and tabs — exactly one `aria-current` per selection.
203
- - `aria-expanded` / `aria-controls` for disclosure.
204
- - `aria-describedby` for help and errors; `aria-invalid` on failed fields.
205
- - Live regions match the message: an async status mark is `role="status"`; an alert-styled notice is `role="alert"`.
206
- - A form whose host already names the request associates with that name (`aria-labelledby`) instead of repeating the prompt as its own label.
207
- - Visible focus — keep the Bootstrap rings, use the `.focus-ring` helper for custom elements, and never write `outline: none`.
208
- - Focus not obscured by sticky chrome (`scroll-margin-top`); focus moved deliberately on SPA route change, failed submit, and row delete.
209
- - Meaning never by color alone; contrast verified.
210
- - Every drag interaction has a non-drag alternative.
211
- - Dialogs carry `aria-labelledby`; let the platform or Bootstrap trap and restore focus rather than scripting it; dispose Bootstrap instances in SPAs on unmount.
212
-
213
- WCAG 2.2 deltas, APG pattern contracts, reduced motion, and SPA focus recipes:
208
+ - Give the page a skip link to main, landmarks, and `h1` → `h2` heading order.
209
+ - Name every icon-only control with `aria-label`, and keep every target ≥ 24×24px.
210
+ - Mark active nav and tabs with `aria-current` / `aria-selected` — exactly one `aria-current` per selection.
211
+ - Wire every disclosure with `aria-expanded` and `aria-controls`.
212
+ - Wire help and errors with `aria-describedby`, and mark a failed field `aria-invalid`.
213
+ - Match the live region to the message: `role="status"` for an async status mark, `role="alert"` for an alert-styled notice.
214
+ - Associate a form with the name its host already gives the request (`aria-labelledby`) rather than repeating the prompt as its own label.
215
+ - Keep focus visible: keep the Bootstrap rings, use the `.focus-ring` helper for custom elements, and never write `outline: none`.
216
+ - Keep focus clear of sticky chrome (`scroll-margin-top`), and move focus deliberately on SPA route change, failed submit, and row delete.
217
+ - Never carry meaning by color alone, and verify the contrast.
218
+ - Give every drag interaction a non-drag alternative.
219
+ - Give every dialog `aria-labelledby`, let the platform or Bootstrap trap and restore focus rather than scripting it, and dispose Bootstrap instances in an SPA on unmount.
220
+
221
+ Take WCAG 2.2 deltas, APG pattern contracts, reduced motion, and SPA focus recipes from
214
222
  [bootstrap-reference.md](references/bootstrap-reference.md) → Accessibility.
215
223
 
216
224
  ---
@@ -219,10 +227,12 @@ WCAG 2.2 deltas, APG pattern contracts, reduced motion, and SPA focus recipes:
219
227
 
220
228
  ```
221
229
  Progress:
230
+ - [ ] Every check that follows, inspection.md instrument or not, reports its population, names the negative control that failed, and states its coverage; a check that can name no negative control is listed as open instead
222
231
  - [ ] Project code law followed; no wrong-stack assumptions
223
232
  - [ ] Subject, audience, single job stated
224
233
  - [ ] Design plan critiqued against the AI defaults: palette, type, layout, one signature
225
234
  - [ ] Shell from components.md, utilities from utilities.md; no invented class
235
+ - [ ] Input affordances from inputs.md; every state in its fixed set drawn, per field
226
236
  - [ ] Styling ladder held: no `style` attribute, no `<style>` block, no custom rule doing a utility's job
227
237
  - [ ] Plan tokens mapped to theme / --bs-* (no hex scatter); light and dark both shipped where both are offered
228
238
  - [ ] Copy in user language, verbs consistent, empty/error/loading text useful
@@ -230,12 +240,11 @@ Progress:
230
240
  - [ ] Contrast composited and measured in both themes: ≥ 4.5:1 information-bearing (small included), ≥ 3:1 marks and state chrome; meaning not color-alone
231
241
  - [ ] Tiers held: `-emphasis` for information-bearing status, solid buttons for real actions, no tone class inside a filled surface
232
242
  - [ ] Every treatment resolved in the shipped cascade, not from docs memory
233
- - [ ] Authored classes checked against that cascade; one glyph per meaning; every instrument's control failed
234
243
  - [ ] Keyboard: focus visible, not obscured, targets ≥ 24px, icon controls named
235
244
  - [ ] Reduced motion respected; every drag has a non-drag path
236
245
  - [ ] Forms: labels visible, blur validation, error summary + inline, submit enabled
237
246
  - [ ] Claimed breakpoints spot-checked; RTL-safe (start/end only)
238
247
  - [ ] States present: hover / focus / disabled / invalid / active
239
248
  - [ ] SPA hygiene: JS instances disposed on unmount, or framework wrappers used
240
- - [ ] Rendered proof: captures at both viewports and both themes + an accessibility snapshot
249
+ - [ ] Rendered proof: captures at every viewport and every theme the surface declares + an accessibility snapshot
241
250
  ```
@@ -81,7 +81,7 @@ CDN (5.3.8 is the current — and final — 5.3.x patch before 5.4):
81
81
 
82
82
  ## Color Modes (light / dark / custom)
83
83
 
84
- The 5.3 color-mode system replaces the old per-component dark variants.
84
+ The 5.3 color-mode system replaces the old per-component `*-dark` classes.
85
85
 
86
86
  ### Mechanics
87
87
 
@@ -290,7 +290,7 @@ Client-side, the documented pattern:
290
290
  </div>
291
291
  ```
292
292
 
293
- Details: input groups with feedback need `.has-validation` on the group (border-radius fix). `.valid/invalid-tooltip` variants need a `position-relative` parent. Validation colors are mode-adaptive via `--bs-form-valid-color`, `--bs-form-valid-border-color`, `--bs-form-invalid-color`, `--bs-form-invalid-border-color`.
293
+ Details: input groups with feedback need `.has-validation` on the group (border-radius fix). `.valid-tooltip` and `.invalid-tooltip` need a `position-relative` parent. Validation colors are mode-adaptive via `--bs-form-valid-color`, `--bs-form-valid-border-color`, `--bs-form-invalid-color`, `--bs-form-invalid-border-color`.
294
294
 
295
295
  ### Autosave vs explicit save
296
296
 
@@ -354,7 +354,7 @@ Hold the baseline in [SKILL.md](../SKILL.md) → Accessibility baseline. Its Boo
354
354
  - collects every painted layer from the element upward to the first opaque one, then composites them top over bottom (Porter-Duff `over`) onto that opaque base;
355
355
  - composites a translucent foreground over that result before taking the ratio, rather than reading the declared color;
356
356
  - measures both themes in one run, since the theme swap re-points the tokens under every layer;
357
- - carries a negative control drawn from outside the population it covers — a pairing known to fail — and voids the run if that control passes.
357
+ - carries a negative control drawn from outside the population it covers — a pairing known to fail — and voids the run if that negative control passes.
358
358
 
359
359
  Wire the reader into the suite once it has settled a question.
360
360
 
@@ -485,7 +485,7 @@ The Bootstrap implementation — a responsive offcanvas that renders inline abov
485
485
  </div>
486
486
  ```
487
487
 
488
- Give header cells an **opaque background** (`bg-body-secondary` or a table variant) — table backgrounds are transparent by default, so rows show through a sticky header otherwise. Sticky chrome is the prime Focus-Not-Obscured offender: add `scroll-margin-top` on row focusables equal to the header height. Sticky first column only when row identity is lost on horizontal scroll — it costs paint and complexity.
488
+ Give header cells an **opaque background** (`bg-body-secondary` or a `.table-*` tone class) — table backgrounds are transparent by default, so rows show through a sticky header otherwise. Sticky chrome is the prime Focus-Not-Obscured offender: add `scroll-margin-top` on row focusables equal to the header height. Sticky first column only when row identity is lost on horizontal scroll — it costs paint and complexity.
489
489
 
490
490
  - **Sorting:** the whole header is a button (not a bare caret), with a visible direction indicator, and `aria-sort="ascending|descending"` on the active `<th>` only:
491
491
 
@@ -551,7 +551,7 @@ Match friction to reversibility × blast radius:
551
551
 
552
552
  Do not type-gate a single-row delete; do not one-tap a tenant wipe. Confirm only where this ladder calls for it — a confirmation on every action gets clicked through.
553
553
 
554
- **Neutralize a disabled destructive control.** `btn-danger` at full saturation reads as armed whatever the `disabled` attribute says, and the contrast exemption for disabled controls does not excuse it. While the action is unavailable, drop to the neutral or outline variant (or let the disabled state mute the fill) so the color stops promising an action, and say _why_ it is unavailable in text the assistive layer reaches: `aria-describedby` pointing at the reason, with `title` only as the pointer-user convenience on top. Never use `title` alone — it never reaches a keyboard or screen-reader user, and it disappears on touch.
554
+ **Neutralize a disabled destructive control.** `btn-danger` at full saturation reads as armed whatever the `disabled` attribute says, and the contrast exemption for disabled controls does not excuse it. While the action is unavailable, drop to the neutral or outline `btn-*` class (or let the disabled state mute the fill) so the color stops promising an action, and say _why_ it is unavailable in text the assistive layer reaches: `aria-describedby` pointing at the reason, with `title` only as the pointer-user convenience on top. Never use `title` alone — it never reaches a keyboard or screen-reader user, and it disappears on touch.
555
555
 
556
556
  ## RTL
557
557
 
@@ -24,7 +24,7 @@
24
24
 
25
25
  - Typography: `.h1`–`.h6`, `.display-1`–`.display-6`, `.lead`, `.small`
26
26
  - Images: `.img-fluid`, `.img-thumbnail`, `.figure`
27
- - Tables: `.table` + variants — see [Tables](#tables)
27
+ - Tables: `.table` plus its `.table-*` tone classes — see [Tables](#tables)
28
28
  - Figures: `.figure`, `.figure-img`, `.figure-caption`
29
29
 
30
30
  ### Form Components
@@ -86,7 +86,7 @@ Full form patterns and validation JS: [bootstrap-reference.md](bootstrap-referen
86
86
  </div>
87
87
  ```
88
88
 
89
- Variants: `.accordion-flush` (edge-to-edge, no outer borders); omit `data-bs-parent` to allow multiple items open.
89
+ Modifier classes: `.accordion-flush` (edge-to-edge, no outer borders); omit `data-bs-parent` to allow multiple items open.
90
90
 
91
91
  ### Alerts
92
92
 
@@ -188,7 +188,7 @@ The current page is `aria-current="page"` and not a link. Use breadcrumbs only f
188
188
 
189
189
  Icon-only buttons need `aria-label` and a ≥24×24 px target (WCAG 2.2) — `btn-sm` icon clusters in toolbars are the common violation; pad rather than shrink.
190
190
 
191
- Choose the variant by contrast rather than by taste ([SKILL.md](../SKILL.md) → Hierarchy & actions).
191
+ Choose the `btn-*` class by contrast rather than by taste ([SKILL.md](../SKILL.md) → Hierarchy & actions).
192
192
 
193
193
  ### Button Group
194
194
 
@@ -525,7 +525,7 @@ Bootstrap's modal enforces focus, adds `role="dialog"`/`aria-modal="true"`, clos
525
525
  <ul class="nav nav-underline">
526
526
  …
527
527
  </ul>
528
- <!-- 5.3: understated bottom-border variant -->
528
+ <!-- 5.3: understated bottom-border style -->
529
529
  <ul class="nav nav-pills nav-fill">
530
530
  …
531
531
  </ul>
@@ -858,13 +858,13 @@ Modifiers (combine freely):
858
858
  .table-active /* highlight a row/cell */
859
859
  .table-group-divider /* thicker rule between <tbody> groups */
860
860
  .caption-top /* caption above the table */
861
- .table-primary … .table-dark /* variants, on table/tr/td */
861
+ .table-primary … .table-dark /* tone classes, on table/tr/td */
862
862
  .align-middle /* vertical alignment, on table/tr/td */
863
863
  ```
864
864
 
865
865
  - **Responsive:** wrap in `.table-responsive{-sm|-md|-lg|-xl|-xxl}` for horizontal scroll. Caveat: the wrapper clips overflowing content — dropdown menus inside a responsive table get cut off.
866
- - **Dark tables:** `data-bs-theme="dark"` on the `<table>` (the `.table-dark` variant approach is superseded).
867
- - **Theming:** variants set CSS variables, not fixed colors — `--bs-table-bg`, `--bs-table-color`, `--bs-table-striped-bg`, `--bs-table-hover-bg`, `--bs-table-active-bg`, `--bs-table-border-color`. `--bs-table-bg` is transparent by default so striping/hover layer through.
866
+ - **Dark tables:** `data-bs-theme="dark"` on the `<table>` (the `.table-dark` class approach is superseded).
867
+ - **Theming:** the `.table-*` tone classes set CSS variables, not fixed colors — `--bs-table-bg`, `--bs-table-color`, `--bs-table-striped-bg`, `--bs-table-hover-bg`, `--bs-table-active-bg`, `--bs-table-border-color`. `--bs-table-bg` is transparent by default so striping/hover layer through.
868
868
  - **Sticky headers are NOT built in.** Bootstrap ships no sticky-header feature; the pattern needs a few lines of custom CSS. That, plus selection columns, `aria-sort` sorting, bulk-action bars, and responsive strategies: [bootstrap-reference.md](bootstrap-reference.md) → Dense data tables.
869
869
 
870
870
  ### Toasts
@@ -881,7 +881,7 @@ Modifiers (combine freely):
881
881
 
882
882
  <div class="toast align-items-center text-bg-primary border-0" role="status" aria-live="polite">
883
883
  <div class="d-flex">
884
- <div class="toast-body">Color variant</div>
884
+ <div class="toast-body">Color tone</div>
885
885
  <button
886
886
  type="button"
887
887
  class="btn-close me-2 m-auto"
@@ -1005,7 +1005,7 @@ The textless mark that survives both themes — dots, ticks, rings, pulses — i
1005
1005
  A selected row, pill, or filter chip repaints everything inside it — marks included. These traps stay invisible until the selected state is captured in both themes:
1006
1006
 
1007
1007
  - **A mark on an active fill of the same family disappears.** `.active` on a `list-group-item`, `nav-pill`, or `page-item` sets the item's own color, and a `text-bg-primary`-family mark inside it inherits or loses to that fill — present in the markup, gone on screen. Carry no tone class inside the fill ([SKILL.md](../SKILL.md) → Surfaces, color, contrast). Verify by capturing the selected row, not by reading the class list.
1008
- - **`btn-check` filter labels invert in dark.** A `btn-outline-secondary` label reads as "chosen" in light and as "muted" in dark, because the checked fill and the surface swap relative weight. Give chosen filters an accent variant (a real theme color) rather than the neutral outline, so "chosen" reads the same way in both modes.
1008
+ - **`btn-check` filter labels invert in dark.** A `btn-outline-secondary` label reads as "chosen" in light and as "muted" in dark, because the checked fill and the surface swap relative weight. Give chosen filters an accent tone class (a real theme color) rather than the neutral outline, so "chosen" reads the same way in both modes.
1009
1009
 
1010
1010
  Exactly one item in a selection carries `aria-current` — the visual fill and the announced state must be the same item.
1011
1011
 
@@ -1017,5 +1017,5 @@ Exactly one item in a selection carries `aria-current` — the visual fill and t
1017
1017
 
1018
1018
  ### Theming
1019
1019
 
1020
- - Components consume CSS variables — favor `text-bg-*`, `*-subtle`, and `data-bs-theme` over one-off colors; the deprecated `*-dark` component variants (`navbar-dark`, `dropdown-menu-dark`, `btn-close-white`, `carousel-dark`) all map to `data-bs-theme="dark"`.
1020
+ - Components consume CSS variables — favor `text-bg-*`, `*-subtle`, and `data-bs-theme` over one-off colors; the deprecated `*-dark` component classes (`navbar-dark`, `dropdown-menu-dark`, `btn-close-white`, `carousel-dark`) all map to `data-bs-theme="dark"`.
1021
1021
  - To restyle a component, override its `--bs-{component}-*` variables in your own scope instead of writing high-specificity rules — see [bootstrap-reference.md](bootstrap-reference.md) → Theming & design tokens.