@orkestrel/scaffold 0.0.64 → 0.0.66

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.
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  npm install --save-dev @orkestrel/scaffold
10
10
  ```
11
11
 
12
- The executable needs Node 22.12 or later. Run it without installing anything:
12
+ The executable needs Node 22.18.0 or later. Run it without installing anything:
13
13
 
14
14
  ```sh
15
15
  npx @orkestrel/scaffold --help
@@ -58,6 +58,16 @@ vendored data root, and the generated file set.
58
58
 
59
59
  ## Notes
60
60
 
61
+ The `scaffold new` command generates a workspace that declares an npm floor of 11.6.0 in its
62
+ `devEngines` record. An npm at 10.9.0 or later and earlier than 11.6.0 refuses the `npm install`
63
+ command there with the `EBADDEVENGINES` code, before resolving the dependency graph.
64
+ npm 10.5.0 and npm 10.8.3, the releases measured earlier than 10.9.0, ignore the record and fail
65
+ inside dependency resolution instead.
66
+ No Node release the executable supports bundles an npm earlier than 10.9.0. Read the ambient
67
+ version with the `npm --version` command. Raise it with the `npm install --global npm@11.6.0`
68
+ command before the first install.
69
+ These readings come from a Linux host, on 2026-09-13.
70
+
61
71
  On Windows, run the executable as `npx scaffold …` or `node ./dist/bin/main.js …`. PowerShell
62
72
  mangles npm's `--` passthrough, so avoid `npm run scaffold -- …` there.
63
73
 
@@ -1,225 +1,243 @@
1
1
  ---
2
2
  name: enterprise-bootstrap
3
3
  description: >-
4
- Design and build distinctive, production-grade user interfaces with Bootstrap
5
- 5.3 and intentional frontend craft, in any host project and on any stack. Use
6
- for Bootstrap user-interface work — creating, restyling, or
4
+ Design and build distinctive, production-grade UI with Bootstrap 5.3 on any
5
+ stack. Use for any Bootstrap interface work — creating, restyling, or
7
6
  extending pages, screens, components, layouts, app shells, dashboards, admin
8
7
  panels, SaaS tools, data tables, filter bars, forms, wizards, navigation,
9
8
  modals, empty/loading/error states, dark mode, marketing surfaces — whenever
10
9
  the task touches HTML/CSS/visual design, mentions Bootstrap or its components,
11
- or must look professional and avoid templated defaults. Covers aesthetics,
12
- typography, color modes, design tokens, accessibility (WCAG 2.2 AA),
13
- responsive layout, and enterprise app patterns. The `orkestrel-polish-surface`
14
- skill owns a requested verdict, round, or campaign over a surface that already
15
- renders, including a review that changes nothing. In that campaign's fix
16
- units, use this skill for Bootstrap craft.
10
+ asks for visual hierarchy, polish, a design system, or spacing/type/color
11
+ scales, or must look professional rather than like stock Bootstrap. Covers
12
+ aesthetics, typography, color modes, design tokens, elevation, finishing
13
+ details, accessibility (WCAG 2.2 AA), responsive layout, and enterprise app
14
+ patterns. The `orkestrel-polish-surface` skill owns a requested verdict,
15
+ round, or campaign over a surface that already renders, including a review
16
+ that changes nothing; in that campaign's fix units, use this skill for
17
+ Bootstrap craft.
17
18
  ---
18
19
 
19
20
  # Enterprise Bootstrap
20
21
 
21
- Set a deliberate visual direction, build it from Bootstrap 5.3 components and utilities, and settle
22
- every claim about the result from what renders.
23
-
24
- Open the reference that owns a subject before writing markup. Never guess a class name: an invented
25
- utility (`.vw-50`, `.pointer-events-none`) has no rule in the shipped CSS and fails silently. Pick
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). 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.
33
-
34
- | Layer | File | Holds |
35
- | -------------- | ----------------------------------------------------------- | --------------------------------------------------------------------------------- |
36
- | Operate | `SKILL.md` | Process, decision rules, checklist |
37
- | Design craft | [frontend-design.md](references/frontend-design.md) | Aesthetic, typography, signature, interface copy, anti-defaults |
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 |
40
- | Utilities | [utilities.md](references/utilities.md) | Class index, helpers, composition notes |
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 |
22
+ Start with the person's task, give it a deliberate visual hierarchy, and build it from Bootstrap
23
+ 5.3 components and utilities. Settle claims about the result from what renders.
24
+
25
+ Open the reference that owns the decision before writing markup. Pick components and their
26
+ structure from [components.md](references/components.md), input affordances from
27
+ [inputs.md](references/inputs.md), and fine layout from [utilities.md](references/utilities.md). Take narrow composition and breakpoint
28
+ behavior from [responsive-layout.md](references/responsive-layout.md) before building the shell.
29
+ Never guess a class name: an invented utility has no shipped rule and fails silently. Where
30
+ Bootstrap ships no component — combobox, date picker, tags input, data grid, tree — work the
31
+ native-first ladder in [bootstrap-reference.md](references/bootstrap-reference.md) → When not to
32
+ hand-roll before building one.
33
+
34
+ | Layer | File | Holds |
35
+ | -------------- | ----------------------------------------------------------- | ------------------------------------------------------------------ |
36
+ | Operate | `SKILL.md` | Process, styling ladder, contrast bars, action rank, checklist |
37
+ | Design craft | [frontend-design.md](references/frontend-design.md) | Hierarchy, spacing, type, color, depth, imagery, signature, copy |
38
+ | Components | [components.md](references/components.md) | Bootstrap markup and enterprise selection notes |
39
+ | Inputs | [inputs.md](references/inputs.md) | Affordance, alternates, styling rung, and states per category |
40
+ | Responsive | [responsive-layout.md](references/responsive-layout.md) | Narrow-first layout, task parity, containers, overlays, proof |
41
+ | Color modes | [color-modes.md](references/color-modes.md) | Inheritance, surface ownership, nested modes, component exceptions |
42
+ | Utilities | [utilities.md](references/utilities.md) | Class index, helpers, composition |
43
+ | Bootstrap deep | [bootstrap-reference.md](references/bootstrap-reference.md) | Theming, forms, lifecycle, accessibility, enterprise patterns |
44
+ | Instruments | [inspection.md](references/inspection.md) | Mechanical evidence contracts and rendered review criteria |
45
+
46
+ Take the operating rules here over a lookup example. Adapt example heading levels, action rank,
47
+ labels, and paint to the host surface. Move an illustrative inline declaration through the styling
48
+ ladder before shipping; its presence in a lookup is not an exemption. A declaration a lookup names
49
+ as a runtime producer is the exception, and only for the property that lookup names.
43
50
 
44
51
  ---
45
52
 
46
53
  ## Portability
47
54
 
48
55
  1. **Assume no stack.** Infer it from the workspace. Do not assume Vue, React, a skin library, a folder layout, or a named product.
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.
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.
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).
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.
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).
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.
56
+ 2. **Target Bootstrap 5.3.x** class names and behaviors. Hold a compatible skin to the same component contracts.
57
+ 3. **Follow the project's code law.** Take language, layout, and forbidden patterns from `AGENTS.md`, lint rules, and the design system. Take UI craft and Bootstrap usage from here, never language law. Preserve existing tokens and identity unless the brief authorizes changing them.
58
+ 4. **Write framework-neutral markup** — semantic HTML plus Bootstrap classes. Wire behavior with the project's stack; in an SPA prefer framework-native Bootstrap wrappers over competing DOM ownership ([bootstrap-reference.md](references/bootstrap-reference.md) → JavaScript lifecycle).
59
+ 5. **Keep this folder intact** so its relative links resolve. Install or vendor it wherever the tooling looks for skills; the paths are tooling-specific, the content is not.
60
+ 6. **Use the installed Bootstrap.** Otherwise take the pinned CDN example from [bootstrap-reference.md](references/bootstrap-reference.md) → Quick start. Do not upgrade dependencies as a side effect of a visual pass.
61
+ 7. **Apply this skill** to the work in its frontmatter. For a requested verdict, round, or campaign over an already rendering surface, use `orkestrel-polish-surface`; use this skill for the campaign's Bootstrap fixes.
55
62
 
56
63
  ---
57
64
 
58
65
  ## The mandate
59
66
 
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.
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.
67
+ 1. **Design direction** — ground hierarchy and character in the subject, audience, and job. Preserve an existing signature or introduce a coherent one when the brief calls for it; spend aesthetic risk only where the brief leaves room.
68
+ 2. **Bootstrap execution** — take components and utilities first, extend the system only for a real gap, and preserve Bootstrap's adaptive surfaces and component-owned foregrounds. Take color decisions from [color-modes.md](references/color-modes.md); a `--bs-*` prefix alone does not establish mode support.
62
69
 
63
- Match the density to the context: a marketing page can open with a thesis-hero, an authenticated
64
- tool opens with clarity and scan paths. In product UI put the signature in the chrome, never in the
65
- data ([frontend-design.md](references/frontend-design.md) → Where the signature lives).
70
+ A marketing page may lead with a thesis-hero; an authenticated tool leads with the work. Keep its
71
+ signature in the frame and its data conventional enough to scan. A distinctive shell never excuses
72
+ a confusing feature ([frontend-design.md](references/frontend-design.md) → Where the signature lives).
66
73
 
67
74
  ---
68
75
 
69
76
  ## Process
70
77
 
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:
74
-
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.
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).
77
- 3. **Critique the plan** — if swapping the logo would make it "any SaaS", revise. Avoid the clustered AI defaults unless the brief asks for them: cream + #F4F1EA + serif + terracotta; near-black + acid green or vermilion; broadsheet hairlines, zero radius, dense columns. The brief wins when it pins a direction.
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.
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.
80
-
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).
83
-
84
- **Rendered proof.** Settle every claim about a screen from a capture, never from source alone;
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
88
- `orkestrel-polish-surface` skill instead of improvising one here.
89
-
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.
78
+ Read [frontend-design.md](references/frontend-design.md) before setting a direction. It owns the
79
+ visual decisions; the loop here owns their order.
80
+
81
+ 1. **Ground** — state the subject, audience, single job, primary action, and existing constraints. Use real content; mark fixture data as such. Start with a feature, not a navigation shell.
82
+ 2. **Plan** — record each region's narrow layout, expansion threshold, content/action parity, and overflow policy in a responsive contract. Render the primary task at 320 and 390 CSS px before expanding the shell. Settle reading order and grouping in low fidelity before paint, and hold color until the arrangement reads in grayscale (body surfaces, inherited text, weight, and spacing only). Reuse or define a compact system: **color families and surface ownership**, **type roles and scale**, **spacing and width roles**, **radius and elevation**, **a coherent signature where the brief calls for one**. Set personality through these levers — typeface, primary color, radius family, and copy register — and hold each on every screen. Record changes, not a parallel system. Take each scale's Bootstrap source, shipped steps, and gaps from [bootstrap-reference.md](references/bootstrap-reference.md) → Define the working scales. State the settled layout in prose or a small wireframe before building it.
83
+ 3. **Critique the plan** — reject unclear hierarchy, invented functionality, and interchangeable styling. Follow a pinned brief; otherwise take character from the subject rather than clustered AI defaults. Do not manufacture novelty inside an established product.
84
+ 4. **Build** — implement the smallest useful flow and its data states, then refine the working feature. Use documented components and shipped utilities; map shared tokens once. Fix conflicting declarations rather than adding specificity. Revise the recorded plan when the render disproves it. Extend the next feature after this one works.
85
+ 5. **Critique the render** — complete the primary flow at narrow width first; then read task, hierarchy, grouping, type, contrast, states, and signature in order. Fix the earliest failure first, then re-read the earlier criteria against the fixed render. Remove a needless accessory if one exists; never remove useful information to meet a quota.
86
+
87
+ Keep exploratory drafts private. Deliver the selected direction, the changes, and their evidence
88
+ limits, not every discarded variation.
89
+
90
+ **Rendered proof.** Capture the declared viewports, themes, and states, plus an accessibility
91
+ snapshot. Use captures for visual claims and source to explain mechanisms; use interaction tests
92
+ for behavior. `.agents/orchestration.md` owns this law where present. Name the coverage and any
93
+ unverified state. Without a render-capable environment, report visual verification as open, never
94
+ as passed.
95
+
96
+ **Mechanical proof.** Run applicable instruments in [inspection.md](references/inspection.md) with
97
+ their negative controls. Report population, reading, control result, and coverage. A control the
98
+ reader misses invalidates the run; an expected but empty population fails. Record a genuinely
99
+ absent feature as not applicable with a reason, not as a pass. `.claude/rules/quality.md` owns this
100
+ law where present. Keep qualitative design review separate from instrument results: named criteria
101
+ and captures are evidence, not fabricated mechanical tests or a beauty score.
98
102
 
99
103
  ---
100
104
 
101
105
  ## Bootstrap operating principles
102
106
 
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.
106
- 4. **Test every breakpoint you claim.**
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).
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).
107
+ 1. **Mobile first** — unprefixed classes define a complete narrow task; breakpoint classes enhance it when its container has room. Use the contract in [responsive-layout.md](references/responsive-layout.md), not a desktop composition with wrapping added later.
108
+ 2. **Semantic HTML** — use landmarks and hold heading order; choose visual size independently of heading level.
109
+ 3. **Work down the styling ladder** — component classes, utilities, then Bootstrap's extension points.
110
+ 4. **Test behavior, not class presence.** Check 320 and 390 CSS px, a wide view, and immediately below/at/above each used threshold. Drive state and theme transitions; enlarge text and use long content. Distinguish viewport reflow, browser zoom, and text-resize tests.
111
+ 5. **Take Bootstrap's transitions first.** Use custom motion only where it serves the task or signature, and respect `prefers-reduced-motion` ([bootstrap-reference.md](references/bootstrap-reference.md) → Reduced motion).
112
+ 6. **Resolve treatments in the shipped cascade** — Bootstrap, skins, and dependency stylesheets. A token name or class recipe is not a contrast guarantee. Measure foregrounds, surfaces, and translucent layers in each declared theme and state.
109
113
 
110
114
  ### The styling ladder
111
115
 
112
- Work down these rungs in order. Reach a rung only when the preceding one cannot express the need.
116
+ Reach a rung only when the preceding one cannot express the need. Cite a rung by its name, never by
117
+ its position.
113
118
 
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.
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).
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.
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.
119
+ 1. **Component rung — documented component structure.** Keep required elements, nesting, modifiers, behavior, and ARIA. Use optional headers, titles, and footers only when the content needs them; a component example is not a mandate to add empty chrome.
120
+ 2. **Utility rung — shipped utilities.** Compose spacing, flex, sizing, text, border, and color classes from [utilities.md](references/utilities.md). Verify extensions exist in the loaded build before authoring them.
121
+ 3. **Extension rung — Bootstrap extension points.** Use component `--bs-{component}-*` variables or the Sass utilities API for a recurring system gap. Declare the role once, compile where required, and verify the emitted rule.
122
+ 4. **Authored rung — developer-authorized custom CSS.** Propose what Bootstrap cannot express and why. Take this rung unasked only under [inspection.md](references/inspection.md) → When an authored rule is already earned.
118
123
 
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:
124
+ Resolve a conflict at the rung that owns it. Utilities may carry `!important`, so read the winning
125
+ declaration in the shipped cascade and remove the conflicting class before escalating selector
126
+ specificity. A class selector stays a class selector whatever its name.
121
127
 
122
- - a `style="..."` attribute;
123
- - a `<style>` block in a page or component;
124
- - a new stylesheet rule for something a utility already does.
128
+ **Where an authored rule lives.** Put every authored rule in the project's stylesheet and token
129
+ layer. A standalone HTML deliverable carries that stylesheet as one `<style>` block in `<head>` —
130
+ tokens and declared roles, before any markup. That block is the project stylesheet.
125
131
 
126
- ### Hierarchy & actions
127
-
128
- | Intent | Typical choice |
129
- | ----------- | ------------------------------------------------------------------- |
130
- | Primary | `btn btn-primary` — **one** clear primary per region |
131
- | Secondary | `btn-secondary` — solid, so the surface underneath cannot change it |
132
- | Destructive | `btn-danger` + the confirmation ladder |
133
- | Tertiary | `btn-link` or text links |
134
- | Status | `badge` / `alert` / `*-emphasis` — **icon + color + word** |
132
+ Never write a `style` attribute on authored markup, and never open a second `<style>` block beside
133
+ a component or scoped to one. This rule fixes a location and nothing else: inline CSS and authored
134
+ rules participate in the cascade normally, and a runtime producer named in
135
+ [inspection.md](references/inspection.md) → Style escapes writes its own declaration.
135
136
 
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.
137
+ **What an authored rule may contain** is a separate rule, and the styling ladder owns it. Reach the
138
+ authored rung only when the component, utility, and extension rungs cannot express the need. Do not
139
+ duplicate a shipped utility, and keep raw values in declared primitive definitions rather than in
140
+ component paint.
140
141
 
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.
142
+ ### Hierarchy & actions
143
143
 
144
- Draw a status mark with **no text** as an icon glyph, never as a `badge`
144
+ | Rank or meaning | Typical choice |
145
+ | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
146
+ | Primary | `btn btn-primary` — at most one dominant action per active task region |
147
+ | Secondary | `btn-outline-secondary` with `--bs-btn-color: var(--bs-emphasis-color)` set once at the theme root (the stock label is 3.3:1 on the dark body), or `btn-secondary` |
148
+ | Tertiary | `btn btn-link` for an action; a real link for navigation |
149
+ | Destructive | Rank first; strong `btn-danger` for the final destructive commit |
150
+ | Status | Quiet badge or alert treatment; icon + color + word |
151
+
152
+ Choose rank before hue. Do not make every action solid or every destructive action dominant.
153
+ Outline and link-style controls are allowed only when their text, boundary or state cue, and focus
154
+ meet the applicable bars across actual surfaces and states. Use a measured solid variant when the
155
+ quieter one cannot pass. Never use an inert button as decoration.
156
+
157
+ Re-measure fills under opacity, overlays, or a skin. Keep the destructive confirmation ladder from
158
+ [bootstrap-reference.md](references/bootstrap-reference.md) → Destructive actions; visual rank does
159
+ not lower the required friction. Draw a textless status mark as an icon glyph, not an empty badge
145
160
  ([components.md](references/components.md) → Badge).
146
161
 
147
162
  ### Surfaces, color, contrast
148
163
 
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.
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.
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.
164
+ - **Hold these bars — this section owns them.** ≥ 4.5:1 for all information-bearing text, including large text, captions, and metadata; ≥ 3:1 for meaningful textless marks and state/focus chrome. The text floor is deliberately stricter than WCAG's large-text exception. Measure every declared theme and reached state; do not generalize one reading to all surfaces. A ratio quoted anywhere in this skill is a stock Bootstrap reading and bounds that stock theme alone — the bars are the policy, the readings are not.
165
+ - **Inherit ordinary text.** When content owns no background, add no foreground override. Prefer `bg-body`, `bg-body-secondary`, `bg-body-tertiary`, and `bg-*-subtle` for quiet surfaces; do not automatically add a text-color utility to them. Follow [color-modes.md](references/color-modes.md) for exceptions and component-owned colors.
166
+ - **Pair like with like.** Adaptive text on adaptive surfaces (`text-body*` and `text-*-emphasis` on `bg-body*` and `bg-*-subtle`); fixed text on fixed fills (`text-bg-*`, a component's own foreground, or a `data-bs-theme` scope that also carries `text-body` — a scope changes variables only, and plain text inherits the outer mode's painted color). Treat a mixed pair as unproven and measure it in each declared mode: `bg-light` with inherited text, `text-white` on `bg-body`, `text-primary` on the dark body, and a stock `btn-outline-secondary` label in dark mode each fail one stock mode, while inherited text on `bg-primary` fails light and dark alike. Replace `bg-light`, `bg-white`, and `text-dark` on adaptive surfaces because they are fixed ([color-modes.md](references/color-modes.md) → Fixed and adaptive classes).
167
+ - **Clear a deprecated class on its deprecation, not on a contrast reading.** 5.3 deprecates `text-muted`, `navbar-light`, `navbar-dark`, `dropdown-menu-dark`, `btn-close-white`, and `carousel-dark`. `text-muted` still resolves through the adaptive secondary color, so it pairs correctly and is a deprecation to clear; the `navbar-*`, `dropdown-menu-dark`, `btn-close-white`, and `carousel-dark` classes give way to a `data-bs-theme` scope.
168
+ - **Keep supporting text readable.** Start with inherited color, spacing, and weight. Use `text-body-secondary` for a deliberate secondary tier — it clears 4.5:1 on every stock body surface in light and dark — not for every caption. `text-body-tertiary` is body color at 50 % alpha and measures 3.0–4.1:1 on those stock surfaces: decoration or disabled only, never a caption someone reads. Any further readable tier is a declared opaque token, measured on the surface it sits on. Never quiet text with opacity, and do not carry a neutral secondary tier blindly onto a colored fill; inherit its tested foreground first, using a scoped opaque same-hue tier only when needed ([color-modes.md](references/color-modes.md) → Text tiers).
169
+ - **Pair intentional solid surfaces; preserve selected foregrounds.** Let the owning component set its foreground and background, or use a tested solid pair. Do not recolor ordinary children. Keep status encoded by icon and word and capture the selected state.
170
+ - **Inside subtle fills, measure the children against that fill.** Badge, button, and caption recipes need their own readings; a page-background result does not transfer into a card or alert.
171
+ - **Exempt disabled controls from the contrast bars**, but visibly neutralize an unavailable destructive action and explain why with `aria-describedby`; `title` may supplement, never replace, the explanation.
172
+ - **Verify mode transitions and boundaries.** Take adaptive-versus-fixed utilities, nested `data-bs-theme` scopes, badges, tables, and overlay mounts from [color-modes.md](references/color-modes.md). An attribute or variable name is not proof of painted adaptation.
173
+ - **Bound variable backgrounds.** For text over imagery, gradients, or overlays, measure the actual painted background under the text. A flat-color reader or an average image sample cannot settle that claim.
159
174
 
160
175
  ### Density, layout, responsive
161
176
 
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.
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.
164
- - Take `.card` where grouping earns it; otherwise carry the grouping with spacing and type.
165
- - Swap conditional chrome in place. A bulk-action bar or an alert that shoves the toolbar down shifts the layout mid-task.
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.
177
+ Take [responsive-layout.md](references/responsive-layout.md) as the layout contract. Preserve the
178
+ primary task, reading order, and access to information at every width. A contained horizontal
179
+ table can pass document-overflow checks and still fail the task; inspect both.
180
+
181
+ - Choose density for the task. Start each gap one step too large, render, and step down; compress where throughput or comparison requires it, not because the default felt cramped. Hold every target to the floor in [bootstrap-reference.md](references/bootstrap-reference.md) → WCAG 2.2 requirements for app UI, which owns the target dimensions.
182
+ - Take compact controls together across a row: `btn-sm`, `form-control-sm`, `form-select-sm`, and `input-group-sm`. Do not shrink body text or targets to force one-row layouts.
183
+ - Keep inter-group gaps larger than internal gaps. Bound forms, rails, and prose by content with a maximum width; let comparison tables use the width they need. Use percentage columns only where elements must scale together — a `col-*` login card or `col-3` sidebar changes width at every breakpoint ([bootstrap-reference.md](references/bootstrap-reference.md) → Breakpoints & layout).
184
+ - Use `.card` where an independent group earns containment. Try spacing and type before more borders, fills, or shadows. Keep elevation tied to layering, not every available box.
185
+ - Stack search, controls, and action groups at the base; expand them only when they fit. Reserve horizontal scrolling for named two-dimensional content, not ordinary toolbars.
186
+ - Reflow before truncating task-critical information. Scale large headings and outer space independently of body text and controls. Swap conditional chrome in place so selection or feedback does not shift the task.
187
+ - Take layout, wide-data strategies, and frame mechanics from [bootstrap-reference.md](references/bootstrap-reference.md) → Enterprise patterns, and class composition from [utilities.md](references/utilities.md) → Composition habits.
167
188
 
168
189
  ### States & feedback
169
190
 
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.
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.
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.
191
+ - **Ship ideal, empty, loading, partial, and error states on each data surface.** Build them within the feature cycle, not after the polished populated screen. Take the detailed contracts and feedback channels from [bootstrap-reference.md](references/bootstrap-reference.md) → The data states, Feedback discipline.
192
+ - **Distinguish first-use from filtered-empty.** First-use offers a useful create/import action and drops inert chrome; filtered-empty preserves active filters and the clear path. Errors preserve context and offer recovery. Never invent progress or success.
193
+ - **Build a blocking decision on native `<dialog>`** unless the project already uses Bootstrap modals. Preserve platform focus, dismissal, and top-layer behavior; dress the interior with Bootstrap components ([components.md](references/components.md) → Modal).
194
+ - **Prefer undo for reversible actions.** Take interruption and confirmation rules from [bootstrap-reference.md](references/bootstrap-reference.md) → Destructive actions.
173
195
 
174
196
  ### Forms
175
197
 
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.
177
- - Give every field a visible label (top-aligned by default) or `.form-floating` — never placeholder-only.
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.
179
- - Pair a focusable error summary with inline `.invalid-feedback` per field (`aria-describedby`, `aria-invalid`).
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.
198
+ - Choose the affordance by what the person is asked for in [inputs.md](references/inputs.md), and draw its fixed state set. Keep read-only/edit geometry stable and preserve the non-drag path for uploads.
199
+ - Give every field a visible label or `.form-floating`, never placeholder-only. Removing redundant labels on displayed data does not apply to inputs. Naming a form does not name its individual controls.
200
+ - Keep label, control, help, and error closer to each other than to the next field group. Use extra columns for genuinely related fields or supporting explanation, not to fill a wide canvas.
201
+ - Validate on blur, re-validate error fields on input, and re-check on submit. Keep submit enabled while fields are invalid; a disabled submit hides what is wrong. While a submit is in flight, mark the control busy and refuse a second submit — that pending block is a different state, and this rule does not bar it. Show a focusable error summary and linked inline feedback (`aria-describedby`, `aria-invalid`).
202
+ - Take validation mechanics, autosave, and multi-step rules from [bootstrap-reference.md](references/bootstrap-reference.md) → Forms in production, Wizards & multi-step forms.
181
203
 
182
204
  ### When custom CSS is justified
183
205
 
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).
206
+ Exhaust the component, utility, and extension rungs before proposing a custom rule. Name the unmet
207
+ requirement and the smallest rule that would satisfy it. A desire for a signature does not waive the
208
+ styling ladder.
189
209
 
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.
210
+ Wait for developer authorization. [inspection.md](references/inspection.md) → When an authored rule
211
+ is already earned owns the one exception and every condition that opens it; read that section rather
212
+ than judging a shorter copy here. An unavailable Sass build is not permission to silently invent a
213
+ second CSS system.
195
214
 
196
- When the developer authorizes it, or that exception opens:
215
+ When authorized, or when that exception opens:
197
216
 
198
- - Name it in Bootstrap vocabulary.
199
- - Take colors from `var(--bs-…)` and theme tokens so light and dark both work.
200
- - Use logical properties (`margin-inline-start`, not `margin-left`) so RTL works.
201
- - Keep the surface area minimal and document why.
202
- - Write a stylesheet rule, never a `style` attribute or a `<style>` block.
217
+ - Name the rule in Bootstrap vocabulary and document the gap.
218
+ - Use `var(--bs-…)` for paint and declared scales for type, spacing, radius, and elevation.
219
+ - Use logical properties so RTL survives.
220
+ - Keep the rule in the project's stylesheet, with the smallest scope and no utility duplication.
203
221
 
204
222
  ---
205
223
 
206
224
  ## Accessibility baseline
207
225
 
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
222
- [bootstrap-reference.md](references/bootstrap-reference.md) → Accessibility.
226
+ - Give the page a skip link, landmarks, and ordered headings; visual size does not dictate heading level.
227
+ - Name icon-only controls and hold every target to the floor in [bootstrap-reference.md](references/bootstrap-reference.md) → WCAG 2.2 requirements for app UI. Preserve visible labels within accessible names.
228
+ - Use `aria-current` for the current navigation item, `aria-selected` for selectable tabs, and native checked state for checkboxes/radios. Do not apply one selection attribute to every widget.
229
+ - Wire disclosures with `aria-expanded` and `aria-controls`; wire help/errors with `aria-describedby` and invalid fields with `aria-invalid`.
230
+ - Match announcements to urgency: polite status for routine async results, alerts for urgent failures. Do not infer urgency solely from an alert's visual styling.
231
+ - Associate a form with its existing visible name through `aria-labelledby` where useful; keep each field's own visible label.
232
+ - Preserve visible focus, clear of sticky chrome. Manage focus on SPA route change, failed submit, and row deletion; use the platform or existing dialog implementation for containment and restoration.
233
+ - Never encode meaning by color alone. Measure contrast, including state cues, against actual surfaces.
234
+ - Preserve content and operation under enlarged text and narrow reflow; do not hide essential content to pass a viewport check.
235
+ - Give drag interactions a non-drag alternative. Respect reduced motion. Give images alternatives appropriate to their role.
236
+ - Dispose Bootstrap instances on SPA unmount, or use the framework-native wrapper's lifecycle.
237
+
238
+ Take WCAG 2.2 details, APG contracts, and focus recipes from
239
+ [bootstrap-reference.md](references/bootstrap-reference.md) → Accessibility. A passing subset of
240
+ these checks is not a claim of full accessibility conformance.
223
241
 
224
242
  ---
225
243
 
@@ -227,24 +245,33 @@ Take WCAG 2.2 deltas, APG pattern contracts, reduced motion, and SPA focus recip
227
245
 
228
246
  ```
229
247
  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
231
- - [ ] Project code law followed; no wrong-stack assumptions
232
- - [ ] Subject, audience, single job stated
233
- - [ ] Design plan critiqued against the AI defaults: palette, type, layout, one signature
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
236
- - [ ] Styling ladder held: no `style` attribute, no `<style>` block, no custom rule doing a utility's job
237
- - [ ] Plan tokens mapped to theme / --bs-* (no hex scatter); light and dark both shipped where both are offered
238
- - [ ] Copy in user language, verbs consistent, empty/error/loading text useful
239
- - [ ] Every state per data surface: ideal / empty / loading / partial / error
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
241
- - [ ] Tiers held: `-emphasis` for information-bearing status, solid buttons for real actions, no tone class inside a filled surface
242
- - [ ] Every treatment resolved in the shipped cascade, not from docs memory
243
- - [ ] Keyboard: focus visible, not obscured, targets ≥ 24px, icon controls named
244
- - [ ] Reduced motion respected; every drag has a non-drag path
245
- - [ ] Forms: labels visible, blur validation, error summary + inline, submit enabled
246
- - [ ] Claimed breakpoints spot-checked; RTL-safe (start/end only)
247
- - [ ] States present: hover / focus / disabled / invalid / active
248
- - [ ] SPA hygiene: JS instances disposed on unmount, or framework wrappers used
249
- - [ ] Rendered proof: captures at every viewport and every theme the surface declares + an accessibility snapshot
248
+ - [ ] Project code law, installed stack, existing identity, and scope held
249
+ - [ ] Subject, audience, single job, primary action, and real/fixture content identified
250
+ - [ ] Feature hierarchy settled before shell/detail; plan specific to the brief
251
+ - [ ] Color families and surface ownership, type, spacing/width, radius, elevation, and signature declared or reused
252
+ - [ ] Typeface, primary color, radius family, and copy register set once and held; arrangement read in grayscale before hue
253
+ - [ ] Type sizes in `rem` from the scale or its generated steps; no `em` sizes, nested `.small`, or off-scale spacing
254
+ - [ ] Components and utilities resolved in the shipped build; input affordances and states taken from their references
255
+ - [ ] Styling ladder held; no `style` attribute, no component-scoped `<style>` block, no unearned utility duplication; a standalone HTML deliverable carries its one project stylesheet in `<head>`
256
+ - [ ] Tokens mapped through semantics to components; literals confined to declared primitives
257
+ - [ ] Ordinary/subtle content inherits; solid exceptions own their pair; no fixed leaf color conceals a mode failure
258
+ - [ ] Every text/background pair is adaptive-on-adaptive or fixed-on-fixed; fixed fills carry `text-bg-*`, their component's foreground, or a `data-bs-theme` scope with `text-body` on the same element; no `bg-light`, `bg-white`, or `text-dark` on adaptive surfaces
259
+ - [ ] Deprecated classes cleared on their deprecation: `text-muted`, `navbar-light`, `navbar-dark`, `dropdown-menu-dark`, `btn-close-white`, `carousel-dark`
260
+ - [ ] Secondary tier is `text-body-secondary` or a declared opaque token; no opacity or unreadable tertiary tone; secondary text on colored surfaces measured rather than assumed
261
+ - [ ] Every declared mode transition, supported nested scopes, and overlay mounts tested without rebuilding the UI
262
+ - [ ] Primary action clear; supporting content readable; destructive rank and friction both correct
263
+ - [ ] Group spacing unambiguous; widths content-led; type/baseline/line length suitable
264
+ - [ ] All data states built; first-use and filtered-empty distinct; errors recoverable; no invented progress
265
+ - [ ] Images bounded and legible; depth serves layering; accents, tints, and shadows each earn their place; no needless accessories
266
+ - [ ] Contrast measured in every declared theme and reached state against the bars in § Surfaces, color, contrast
267
+ - [ ] Keyboard, labels, announcements, targets, reduced motion, and non-drag paths checked
268
+ - [ ] Forms retain visible labels, blur/submit validation, and summary + inline errors
269
+ - [ ] Responsive contract recorded; primary task works at 320/390 CSS px before wide-screen enhancement
270
+ - [ ] Used breakpoint boundaries, actual container widths, long content, enlarged text, and short-height overlays checked
271
+ - [ ] Essential fields/actions remain reachable; local data scrolling is named, keyboard-operable, and not used to mask page overflow
272
+ - [ ] Navigation open/close/resize and selection/filter preservation tested; RTL covered when claimed
273
+ - [ ] Runtime behavior and SPA lifecycle tested where changed
274
+ - [ ] Rendered review names criteria and captures at declared widths/themes/states, plus accessibility snapshot
275
+ - [ ] Mechanical results name population, negative controls, and coverage; absent features marked not applicable with reason
276
+ - [ ] Untested, unsupported, or failed verification listed as open; no source-only visual pass or full-conformance claim
250
277
  ```