@orkestrel/scaffold 0.0.63 → 0.0.65

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 (57) hide show
  1. package/README.md +29 -104
  2. package/dist/bin/main.js +95 -27
  3. package/dist/bin/main.js.map +1 -1
  4. package/dist/host/AGENTS.md +2 -2
  5. package/dist/host/CLAUDE.md +6 -0
  6. package/dist/host/agents/orchestration.md +23 -15
  7. package/dist/host/agents/skills/enterprise-bootstrap/SKILL.md +184 -177
  8. package/dist/host/agents/skills/enterprise-bootstrap/references/bootstrap-reference.md +314 -91
  9. package/dist/host/agents/skills/enterprise-bootstrap/references/color-modes.md +241 -0
  10. package/dist/host/agents/skills/enterprise-bootstrap/references/components.md +83 -36
  11. package/dist/host/agents/skills/enterprise-bootstrap/references/frontend-design.md +297 -98
  12. package/dist/host/agents/skills/enterprise-bootstrap/references/inputs.md +25 -14
  13. package/dist/host/agents/skills/enterprise-bootstrap/references/inspection.md +216 -128
  14. package/dist/host/agents/skills/enterprise-bootstrap/references/responsive-layout.md +187 -0
  15. package/dist/host/agents/skills/enterprise-bootstrap/references/utilities.md +109 -20
  16. package/dist/host/agents/skills/orkestrel-debrief/references/field-testing.md +5 -5
  17. package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +1 -1
  18. package/dist/host/agents/skills/orkestrel-publish/SKILL.md +15 -15
  19. package/dist/host/agents/skills/orkestrel-publish/references/wave.md +43 -17
  20. package/dist/host/agents/skills/orkestrel-publish/references/window.md +41 -16
  21. package/dist/host/claude/agents/orkestrel.md +56 -56
  22. package/dist/host/claude/agents/reviewer.md +13 -0
  23. package/dist/host/claude/rules/architecture.md +51 -45
  24. package/dist/host/claude/rules/documentation.md +18 -1
  25. package/dist/host/claude/rules/portability.md +2 -0
  26. package/dist/host/claude/rules/quality.md +1 -1
  27. package/dist/host/claude/rules/tests.md +12 -11
  28. package/dist/host/claude/rules/typescript.md +5 -0
  29. package/dist/host/claude/rules/workspace.md +25 -20
  30. package/dist/host/claude/rules/writing.md +4 -0
  31. package/dist/host/claude/settings.json +1 -1
  32. package/dist/host/claude/skills/enterprise-bootstrap/SKILL.md +10 -9
  33. package/dist/host/codex/agents/orkestrel.toml +3 -3
  34. package/dist/host/codex/agents/reviewer.toml +4 -2
  35. package/dist/host/configs/helpers.ts +311 -2
  36. package/dist/host/configs/policy.ts +1100 -51
  37. package/dist/host/dotfiles/oxlintrc.json +72 -1
  38. package/dist/host/guides/guide.md +749 -222
  39. package/dist/host/guides/scaffold.md +529 -394
  40. package/dist/host/manifest.json +53 -40
  41. package/dist/host/scripts/ollama.sh +322 -13
  42. package/dist/host/tests/config.test.ts +1200 -16
  43. package/dist/host/tests/policy.test.ts +157 -173
  44. package/dist/host/tests/setupPolicy.ts +522 -1007
  45. package/dist/src/core/index.cjs +402 -287
  46. package/dist/src/core/index.cjs.map +1 -1
  47. package/dist/src/core/index.d.cts +160 -128
  48. package/dist/src/core/index.d.ts +160 -128
  49. package/dist/src/core/index.js +400 -286
  50. package/dist/src/core/index.js.map +1 -1
  51. package/dist/src/server/index.cjs +28 -21
  52. package/dist/src/server/index.cjs.map +1 -1
  53. package/dist/src/server/index.d.cts +38 -33
  54. package/dist/src/server/index.d.ts +38 -33
  55. package/dist/src/server/index.js +28 -21
  56. package/dist/src/server/index.js.map +1 -1
  57. package/package.json +18 -19
@@ -0,0 +1,241 @@
1
+ # Color modes and inheritance
2
+
3
+ > Part of the `enterprise-bootstrap` package. Use for foreground ownership, adaptive surfaces,
4
+ > nested themes, and color-mode repairs. Take the contrast bars from [SKILL.md](../SKILL.md).
5
+
6
+ ## Contents
7
+
8
+ - [Choose the surface](#choose-the-surface)
9
+ - [Text tiers](#text-tiers)
10
+ - [Preserve the cascade](#preserve-the-cascade)
11
+ - [Scope the mode](#scope-the-mode)
12
+ - [Respect component ownership](#respect-component-ownership)
13
+ - [Extend the theme](#extend-the-theme)
14
+ - [Verify the result](#verify-the-result)
15
+
16
+ ## Choose the surface
17
+
18
+ Default to inherited text. When ordinary content owns no background, add no foreground override.
19
+ For quiet containers and status, prefer adaptive backgrounds without an added text-color class.
20
+ Treat this as the package default, not a claim that Bootstrap forbids its documented emphasis pairs.
21
+
22
+ | Context | Use | Refuse by default |
23
+ | -------------------------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
24
+ | Ordinary content | Inherited body or component text | A leaf `color` declaration or `text-*` color chosen without a surface contract |
25
+ | Neutral separation | `bg-body`, `bg-body-secondary`, or `bg-body-tertiary`; inherit text | `bg-white`, `bg-light`, or `bg-dark` as an adaptive surface |
26
+ | Quiet semantic status | `bg-*-subtle`; inherit text and state the meaning in words | Automatically matching the fill with `text-*` or `text-*-emphasis` |
27
+ | Intentional solid or inverse treatment | A component-owned pair, or a measured `text-bg-*` helper | A solid `bg-*` with an unrelated inherited foreground |
28
+ | Selected control | The component's checked/active treatment and foreground | Descendant text or icon colors that override the selected foreground |
29
+ | Secondary information | Spacing and weight first; `text-body-secondary` for a deliberate tier ([Text tiers](#text-tiers)) | Opacity, `text-body-tertiary`, or a neutral grey on a colored fill |
30
+
31
+ Use these quiet treatments inside an ordinary body-color context:
32
+
33
+ ```html
34
+ <section class="bg-body-tertiary rounded p-3" aria-labelledby="sync-heading">
35
+ <h2 id="sync-heading" class="h6">Synchronization</h2>
36
+ <p class="mb-0">Updates appear after the next sync.</p>
37
+ </section>
38
+ <span class="d-inline-flex rounded-pill bg-success-subtle px-2 py-1 small fw-semibold">Paid</span>
39
+ ```
40
+
41
+ Measure the inherited result on its actual background. A subtle fill changes only the background;
42
+ it cannot repair a fixed, translucent, or inverse foreground inherited from an ancestor. Remove
43
+ that conflict or establish an owned surface boundary before adding a leaf override.
44
+
45
+ ## Text tiers
46
+
47
+ Stock Bootstrap ships two readable text tiers, not three. `--bs-secondary-color` is the body color
48
+ at 75 % alpha and `--bs-tertiary-color` at 50 % alpha, so both composite against whatever sits
49
+ beneath them. Measured on the three stock body surfaces (`bg-body` / `bg-body-tertiary` /
50
+ `bg-body-secondary`) in 5.3.8:
51
+
52
+ | Tier | Light | Dark | 4.5:1 bar |
53
+ | --------------------- | ------------------ | ----------------- | ---------------- |
54
+ | Inherited body | 15.4 / 14.6 / 13.0 | 11.9 / 10.2 / 8.8 | Passes |
55
+ | `text-body-secondary` | 6.8 / 6.6 / 6.2 | 7.3 / 6.5 / 5.8 | Passes |
56
+ | `text-body-tertiary` | 3.1 / 3.1 / 3.0 | 4.1 / 3.8 / 3.5 | Fails everywhere |
57
+
58
+ - Use `text-body-secondary` as the one shipped quiet tier. Use `text-body-tertiary` for decoration
59
+ or disabled chrome only; it never carries a caption, timestamp, or count someone reads.
60
+ - Declare a third readable tier as an opaque token — override `$body-tertiary-color` and
61
+ `$body-tertiary-color-dark`, or add a semantic token — and measure it on each surface it sits on.
62
+ The opaque `text-secondary` (`$gray-600`) clears 4.5:1 only on pure white and does not adapt.
63
+ - More than a dozen component variables consume the translucent secondary color — placeholders,
64
+ `.form-text`, table captions, breadcrumb dividers and the active crumb, toast headers, figure
65
+ captions, list-group action text, several disabled states — and inherit this table.
66
+ - On a colored fill, `text-body-secondary` composites the body color over the hue — grey on color —
67
+ and `text-white-50` or `text-opacity-*` let the fill show through the glyphs. The quiet tone on a
68
+ fill is the same hue at lower contrast: keep the owning component's foreground and quiet a line
69
+ with weight or size, or declare a same-hue token (for the stock blue, the `$blue-200`–`$blue-300`
70
+ region in light mode) through the component's own variable and measure it.
71
+ - For a tinted region, use the shipped same-hue pair: `text-*-emphasis` on `bg-*-subtle` (about
72
+ 10:1 for primary in the stock light theme), adapting in both modes. Keep `text-bg-*` solids for
73
+ the primary element.
74
+
75
+ When checking utility behavior, see Bootstrap's [Background](https://getbootstrap.com/docs/5.3/utilities/background/)
76
+ and [Colors](https://getbootstrap.com/docs/5.3/utilities/colors/) references. Distinguish the
77
+ adaptive families from the original contextual families:
78
+
79
+ - Use `bg-*-subtle`, `border-*-subtle`, and body-role variables for mode-aware surfaces and boundaries.
80
+ Measure a required control boundary separately; a subtle border is not a focus treatment.
81
+ - Treat original contextual `bg-primary`, `text-primary`, and their semantic siblings as
82
+ non-adaptive in stock 5.3. Treat `bg-light`, `bg-dark`, `text-light`, and `text-dark` the same way.
83
+ Do not confuse `bg-secondary` with `bg-body-secondary`.
84
+ - Treat `text-*-emphasis` as adaptive but optional. Use it only for a deliberate semantic foreground
85
+ on a known, measured surface, not merely because that surface has a subtle fill.
86
+ - Reserve `text-bg-*` for a deliberate solid pair. Bootstrap selects its foreground with Sass at
87
+ build time, not through runtime contrast calculation. Recheck after theme-variable changes;
88
+ see [Color and background](https://getbootstrap.com/docs/5.3/helpers/color-background/).
89
+ - Do not invent `text-bg-*-subtle`; stock Bootstrap does not ship that helper.
90
+
91
+ ## Preserve the cascade
92
+
93
+ Inspect the winning declaration before changing a color. Remove a conflicting utility or local
94
+ rule before adding specificity. A literal moved into an unchanging `--bs-*` variable remains an
95
+ unchanging color; the prefix does not prove adaptation.
96
+
97
+ Keep native component foregrounds and states. Do not apply `color: inherit` to all descendants or
98
+ strip every text utility: alerts, validation feedback, links, and selected controls own meaningful
99
+ foreground behavior. Override only the element that violates its surface contract.
100
+
101
+ Use `text-reset` only to restore inheritance where a component or utility has replaced it. The
102
+ helper sets `color: inherit`, not a chosen palette color. Use `text-body` only when the element
103
+ must establish the active mode's body foreground on an owned surface, not as a universal reset.
104
+ Neither helper repairs an inappropriate ancestor by itself.
105
+
106
+ Keep links on Bootstrap's link rules. For a deliberate high-contrast neutral link, use
107
+ `link-body-emphasis`; among stock 5.3 colored-link helpers, only that helper adapts to color modes.
108
+ Do not override a link with a text utility and lose its hover/focus treatment; see
109
+ [Colored links](https://getbootstrap.com/docs/5.3/helpers/colored-links/).
110
+
111
+ Use opacity utilities only where the painted rule consumes their variable. Stock `bg-*-subtle`
112
+ rules do not consume `--bs-bg-opacity`; adding `bg-opacity-*` does not tint them. Check the same
113
+ relationship for emphasis text and subtle borders. Do not use whole-element opacity to create a
114
+ quiet panel with information-bearing children.
115
+
116
+ ## Scope the mode
117
+
118
+ Use the host's mode controller. With Bootstrap's attribute strategy, set the resolved `light` or
119
+ `dark` value on `<html>`; scope an intentional exception with `data-bs-theme` on its boundary.
120
+ Do not pin components to dark merely because the page happens to be dark during development.
121
+
122
+ On a generic nested region, establish its surface as well as its variables:
123
+
124
+ ```html
125
+ <section data-bs-theme="dark" class="bg-body text-body p-3" aria-labelledby="preview-heading">
126
+ <h2 id="preview-heading" class="h6">Preview</h2>
127
+ <div class="bg-primary-subtle rounded p-3">This text inherits from the preview.</div>
128
+ </section>
129
+ ```
130
+
131
+ Keep the body foreground at that owned boundary; add no text-color classes to its ordinary
132
+ children. A component that already consumes its mode's foreground and background, such as a
133
+ `.dropdown-menu`, can establish its own pair without these utilities.
134
+
135
+ Do not treat `data-bs-theme` as paint. Changing variables on a plain element does not recompute a
136
+ `color` already inherited from outside the scope. Check the boundary guidance in Bootstrap's
137
+ [5.3.0 color-mode notes](https://blog.getbootstrap.com/2023/05/30/bootstrap-5-3-0/).
138
+
139
+ Resolve a portal, teleport, or `container: 'body'` overlay at its actual DOM mount point. Carry an
140
+ intentional local mode to that mount point; do not assume the trigger's ancestry follows it.
141
+
142
+ Avoid mode-sensitive aliases declared only at the root, such as `--app-text: var(--bs-body-color)`,
143
+ then inherited into a different local mode. Consume the Bootstrap variable at the component, or
144
+ rebind the alias at every supported mode boundary. Custom properties resolve their references
145
+ before inheritance; see [CSS Custom Properties](https://www.w3.org/TR/css-variables-1/).
146
+
147
+ When implementing a picker, validate persisted values, tolerate unavailable storage, and resolve
148
+ `auto` through `prefers-color-scheme` before setting the attribute. Follow system changes only
149
+ while the preference is automatic. Apply the resolved mode before first paint, keep server/client
150
+ initial state consistent, and update the picker's accessible state. Do not write
151
+ `data-bs-theme="auto"` without an explicitly implemented custom mode. Take the integration details
152
+ from [Bootstrap color modes](https://getbootstrap.com/docs/5.3/customize/color-modes/).
153
+
154
+ ## Respect component ownership
155
+
156
+ ### Badges and removable tags
157
+
158
+ For quiet status, prefer the utility-composed span in [Choose the surface](#choose-the-surface).
159
+ When preserving `.badge`, restore inheritance explicitly:
160
+
161
+ ```html
162
+ <span class="badge bg-success-subtle text-reset">Paid</span>
163
+ ```
164
+
165
+ Do not use `.badge bg-success-subtle` alone: stock `.badge` supplies a white foreground, not
166
+ inherited body text. Do not mistake the absence of a `text-*` class for the absence of a color
167
+ rule. Confirm the skin's badge rule; see [Badges](https://getbootstrap.com/docs/5.3/components/badge/).
168
+ Keep a removable tag's close button in the same mode and measure its hit area; a badge's small
169
+ font must not shrink the control below the package target floor.
170
+
171
+ ### Alerts, buttons, and selection
172
+
173
+ Leave `.alert-*` on its native foreground, subtle background, border, and `.alert-link` treatment.
174
+ Do not add `text-reset` to an alert merely to enforce inheritance. Choose its announcement role
175
+ by urgency, not by the color or visual component.
176
+
177
+ Choose button rank before color. Keep `.btn-*` state rules; do not add `bg-*-subtle` to a button
178
+ and override its hover/active backgrounds with a utility's `!important`. For a custom variant,
179
+ map the full state contract through component variables and test it. Do not assume an outline
180
+ variant is safe or that a solid variant automatically passes.
181
+
182
+ Within an active row, tab, or filter, let ordinary labels and glyphs follow its tested foreground.
183
+ Remove a competing status tint before changing the selected fill. Keep a genuinely independent
184
+ nested badge on its own measured surface, or remove its fill and restore inheritance.
185
+
186
+ ### Tables and overlays
187
+
188
+ Prefer the uncolored `.table` for automatic light/dark behavior. Treat `.table-primary` and the
189
+ other `.table-*` color variants as non-adaptive in stock 5.3 even though they expose CSS variables.
190
+ Do not describe their Sass-generated values as runtime color-mode mappings.
191
+
192
+ Inspect cells, not only the table or row. The base `--bs-table-bg` uses the body background; the
193
+ transparent default belongs to `--bs-table-accent-bg`. Striping, hover, and active states paint
194
+ cell overlays. Use the table's component variables for a required custom treatment rather than
195
+ stacking generic background utilities on a row; see
196
+ [Tables](https://getbootstrap.com/docs/5.3/content/tables/).
197
+
198
+ Let neutral cards, dropdowns, modals, offcanvas panels, and toasts retain their component-owned
199
+ surfaces. For an intentional local dark region, use `data-bs-theme` rather than the deprecated
200
+ `navbar-dark`, `dropdown-menu-dark`, `btn-close-white`, or `carousel-dark` classes. Check close
201
+ icons and overlay content after every supported mode transition.
202
+
203
+ ## Extend the theme
204
+
205
+ Reuse the installed theme before introducing a palette. Keep primitives in the token source and
206
+ map only the required semantics and component states. Define light and dark as deliberate
207
+ hierarchies; do not mechanically invert every shade or increase decoration in dark mode.
208
+
209
+ Keep RGB companions aligned when a consumer reads them. Changing `--bs-primary` alone does not
210
+ update a utility reading `--bs-primary-rgb`, rebuild `.btn-primary`, or recompute a `text-bg-*`
211
+ foreground. Use the actual consumer's extension point and inspect the emitted rule.
212
+
213
+ Stock ramps are mechanical: `$blue-100…400` are `tint-color` mixes with white and `$blue-600…900`
214
+ are `shade-color` mixes with black, and the `-text-emphasis` / `-bg-subtle` / `-border-subtle`
215
+ triads are the same mixes. Hue stays fixed and saturation can only fall, so any brand base short
216
+ of full saturation washes out at the light end and goes muddy at the dark end; stock blue survives
217
+ only because its base is 98 % saturated. For a brand color, override the nine `$brand-100…900`
218
+ variables and the six triad variables (`$brand-text-emphasis`, `-bg-subtle`, `-border-subtle`,
219
+ each with its `-dark` twin) with hand-picked values before `variables` is imported; every
220
+ `.alert-brand`, `bg-brand-subtle`, `text-brand-emphasis`, and `table-brand` then consumes them.
221
+ Stock greys sit at hue 210° with 7–17 % saturation — cool, matched to the stock blue. For a warm
222
+ brand, override `$gray-100…900` as a complete set of nine with one hue and temperature; never drop
223
+ one warm grey into the cool set. Take the picking method from
224
+ [frontend-design.md](frontend-design.md) → Color as a constrained system.
225
+
226
+ With Sass, complete the light and dark emphasis/subtle maps for an added theme color. Inspect the
227
+ utility-value maps and extend the generated utilities when the build requires it. A variable's
228
+ presence does not prove that its expected class exists. Follow
229
+ [Theming & design tokens](bootstrap-reference.md#theming--design-tokens) for import order and
230
+ extension points. Add no custom color mode without a brief that requires it.
231
+
232
+ ## Verify the result
233
+
234
+ Cross theme changes with narrow/wide layout states from [responsive-layout.md](responsive-layout.md).
235
+ Check a light page with its local dark hero, an opened mobile drawer, and any root-mounted dialog.
236
+ Do not infer their foregrounds from a desktop capture or from the theme attribute alone.
237
+
238
+ Run [Color-mode inheritance](inspection.md#color-mode-inheritance) and the applicable contrast,
239
+ target, and rendered-review checks against the loaded Bootstrap build and skin. Exercise the
240
+ existing mounted UI through light, dark, and back, including supported local scopes and overlays.
241
+ Report actual coverage; do not claim a host application pass from documentation or a stock fixture.
@@ -22,7 +22,8 @@
22
22
 
23
23
  ### Content Components
24
24
 
25
- - Typography: `.h1`–`.h6`, `.display-1`–`.display-6`, `.lead`, `.small`
25
+ - Typography: `.h1`–`.h6`, `.display-1`–`.display-6`, `.lead`, `.small` (sizes, weights, and the `.small` `em` trap: [utilities.md](utilities.md) → Text)
26
+ - Lists and quotes: `.list-unstyled`, `.list-inline`, `.blockquote`, `.blockquote-footer` — icon bullets and promoted quotes per [utilities.md](utilities.md) → Composition habits
26
27
  - Images: `.img-fluid`, `.img-thumbnail`, `.figure`
27
28
  - Tables: `.table` plus its `.table-*` tone classes — see [Tables](#tables)
28
29
  - Figures: `.figure`, `.figure-img`, `.figure-caption`
@@ -41,6 +42,10 @@ Full form patterns and validation JS: [bootstrap-reference.md](bootstrap-referen
41
42
 
42
43
  ## Component Markup
43
44
 
45
+ Preserve the component's native foreground and state rules. For quiet custom surfaces, inherit text
46
+ and use adaptive fills; take exceptions from [color-modes.md](color-modes.md). Do not copy a solid
47
+ variant merely because it appears in this catalog.
48
+
44
49
  ### Accordion
45
50
 
46
51
  ```html
@@ -91,17 +96,17 @@ Modifier classes: `.accordion-flush` (edge-to-edge, no outer borders); omit `dat
91
96
  ### Alerts
92
97
 
93
98
  ```html
94
- <div class="alert alert-primary" role="alert">Primary alert</div>
95
- <div class="alert alert-success" role="alert">Success alert</div>
99
+ <div class="alert alert-primary" role="status">Sync complete</div>
100
+ <div class="alert alert-success" role="status">Changes saved</div>
96
101
  <div class="alert alert-danger" role="alert">Danger alert</div>
97
102
  <div class="alert alert-warning" role="alert">Warning alert</div>
98
103
 
99
- <div class="alert alert-primary d-flex align-items-center" role="alert">
104
+ <div class="alert alert-primary d-flex align-items-center" role="status">
100
105
  <svg class="bi flex-shrink-0 me-2" role="img" aria-label="Info:">...</svg>
101
106
  <div>Alert with icon</div>
102
107
  </div>
103
108
 
104
- <div class="alert alert-success alert-dismissible fade show" role="alert">
109
+ <div class="alert alert-success alert-dismissible fade show" role="status">
105
110
  <h4 class="alert-heading">Well done!</h4>
106
111
  <p>Content here.</p>
107
112
  <hr />
@@ -110,12 +115,24 @@ Modifier classes: `.accordion-flush` (edge-to-edge, no outer borders); omit `dat
110
115
  </div>
111
116
  ```
112
117
 
113
- `role="alert"` announces immediately when the element is injected into the DOM — right for errors and warnings. For calm status messages injected dynamically, prefer a polite live region (`role="status"`). Anything that _looks_ like an alert carries the alert role: styling and semantics disagree the moment a notice wears `.alert` chrome with no role, and an accessibility snapshot is what catches it. When to use alert vs toast vs banner: [bootstrap-reference.md](bootstrap-reference.md) → Feedback discipline.
118
+ Choose the announcement by urgency: `role="status"` for routine asynchronous results, `role="alert"` for urgent failures. Do not make every warning assertive or infer urgency from `.alert` styling. A static advisory does not require a live region merely because it has alert chrome. Take channel selection from [bootstrap-reference.md](bootstrap-reference.md) → Feedback discipline.
119
+
120
+ Keep the native `.alert-*` foreground, subtle background, and `.alert-link` states. Do not add blanket `text-reset` or text-color utilities to alerts. Measure their children on the actual fill; see [color-modes.md](color-modes.md) → Alerts, buttons, and selection.
114
121
 
115
- An alert is a subtle fill — apply the subtle-fill degradation rule to everything inside it ([SKILL.md](../SKILL.md) → Surfaces, color, contrast).
122
+ A side accent is an accessory, one per region: `alert alert-warning border-0 border-start border-4 border-warning`. Zero the alert's own border first — `border-4` alone widens all four sides — and check the fixed `border-warning` against the dark `bg-warning-subtle` ([utilities.md](utilities.md) → Borders).
116
123
 
117
124
  ### Badge
118
125
 
126
+ Start quiet status with inherited text on a subtle fill. Use a plain span to avoid the badge's
127
+ built-in white foreground; when retaining `.badge`, use `text-reset` to restore inheritance:
128
+
129
+ ```html
130
+ <span class="d-inline-flex rounded-pill bg-success-subtle px-2 py-1 small fw-semibold">Paid</span>
131
+ <span class="badge bg-success-subtle text-reset">Paid</span>
132
+ ```
133
+
134
+ Reserve the solid variants for intentional prominence or a counter with its own paired surface:
135
+
119
136
  ```html
120
137
  <span class="badge text-bg-primary">Primary</span>
121
138
  <span class="badge text-bg-secondary">Secondary</span>
@@ -139,13 +156,13 @@ An alert is a subtle fill — apply the subtle-fill degradation rule to everythi
139
156
  </button>
140
157
  ```
141
158
 
142
- Use `text-bg-*` (auto-contrasting text) rather than `bg-*` alone. A badge is never the only carrier of meaning — pair color with text or a visually-hidden label.
159
+ For an intentional solid badge, use a measured `text-bg-*` pair rather than a solid background alone. Its foreground is selected at Sass build time, not recalculated on a runtime theme change. Never make color the only carrier of meaning; keep visible text or an accessible label.
143
160
 
144
161
  **A badge is never a textless mark.** Stock Bootstrap ships `.badge:empty { display: none }`, so an empty `<span class="badge">` used as a status dot renders nothing at all — the surface silently loses the state it claimed to show, and source review never sees it. A textless status mark is an **icon glyph** (see [Icons](#icons) → Status glyph marks), not a stripped badge.
145
162
 
146
- **A badge's fill is never assumed.** Stock `.badge` carries no background of its own, but compatible skins may give it one, so an "unfilled" badge can arrive painted and land at a contrast the design never intended. State the fill explicitly — `bg-*-subtle` for a muted badge, `bg-transparent` when the surface behind it must show through — and measure the result in both themes against the cascade the page actually loads.
163
+ State a badge's intended fill and inspect the skin. For a quiet badge use `bg-*-subtle text-reset`; for an unfilled badge use `bg-transparent text-reset`. Verify the inherited foreground on that actual surface in light and dark. A fill-only utility does not remove `.badge`'s white text; see [color-modes.md](color-modes.md) → Badges and removable tags.
147
164
 
148
- A badge reporting an in-flight request is a live region: `role="status"` on the badge (or on the small wrapper that holds it) announces the settled state politely without stealing focus. Reserve `role="alert"` for alert-styled notices ([Alerts](#alerts)).
165
+ A badge reporting an in-flight request is a live region: `role="status"` on the badge (or on the small wrapper that holds it) announces the settled state politely without stealing focus. Reserve `role="alert"` for urgent results ([Alerts](#alerts)).
149
166
 
150
167
  ### Breadcrumb
151
168
 
@@ -188,10 +205,16 @@ The current page is `aria-current="page"` and not a link. Use breadcrumbs only f
188
205
 
189
206
  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
207
 
191
- Choose the `btn-*` class by contrast rather than by taste ([SKILL.md](../SKILL.md) → Hierarchy & actions).
208
+ The three sizes scale padding faster than font — `btn-sm` 4/8 px at 14 px, `btn` 6/12 at 16 px, `btn-lg` 8/16 at 20 px — so a large button reads as larger, not zoomed. Use them as shipped; do not derive a fourth size with `em` padding. Weight is `$font-weight-normal`; `fw-semibold` on a button is a deliberate emphasis choice, not a default.
209
+
210
+ Choose action rank, then a variant whose rest, hover, focus, active/checked, and disabled treatment works on its actual surface ([SKILL.md](../SKILL.md) → Hierarchy & actions). Do not override native button states with background or text utilities.
192
211
 
193
212
  ### Button Group
194
213
 
214
+ Keep joined groups on one line only while their labels and targets fit. For narrow filters or
215
+ review controls, use a select or independently spaced wrapping buttons; `flex-wrap` alone does
216
+ not make joined corners and shared borders into a coherent multiline group.
217
+
195
218
  ```html
196
219
  <div class="btn-group" role="group" aria-label="Basic example">
197
220
  <button type="button" class="btn btn-primary">Left</button>
@@ -219,7 +242,7 @@ Choose the `btn-*` class by contrast rather than by taste ([SKILL.md](../SKILL.m
219
242
  <img src="..." class="card-img-top" alt="..." />
220
243
  <div class="card-body">
221
244
  <h5 class="card-title">Title</h5>
222
- <h6 class="card-subtitle mb-2 text-body-secondary">Subtitle</h6>
245
+ <h6 class="card-subtitle mb-2">Subtitle</h6>
223
246
  <p class="card-text">Text content.</p>
224
247
  <a href="#" class="card-link">Link</a>
225
248
  <a href="#" class="btn btn-primary">Button</a>
@@ -227,15 +250,23 @@ Choose the `btn-*` class by contrast rather than by taste ([SKILL.md](../SKILL.m
227
250
  <ul class="list-group list-group-flush">
228
251
  <li class="list-group-item">Item</li>
229
252
  </ul>
230
- <div class="card-footer text-body-secondary">Footer</div>
253
+ <div class="card-footer">Footer</div>
231
254
  </div>
232
255
 
233
- <div class="card text-bg-primary">Colored card</div>
234
- <div class="card border-primary">Bordered card</div>
256
+ <div class="card bg-primary-subtle">Quiet tinted card</div>
257
+ <div class="card border-primary-subtle">Quiet bordered card</div>
258
+ <div class="card border-0 shadow-sm">
259
+ Borderless raised card — page surface must differ from the card's
260
+ </div>
261
+ <div class="card border-0 border-top border-4 border-primary">
262
+ Top accent — border-0 first, or border-4 widens every side
263
+ </div>
235
264
  <div class="card-group">Card group</div>
236
265
  <div class="row row-cols-1 row-cols-md-3 g-4">Card grid (with h-100 on cards)</div>
237
266
  ```
238
267
 
268
+ Use `card` only where a group earns containment; try spacing and a surface change first. Card headers and footers are a 3 % tint of the body color, so `border-0` on `card-header` often reads cleaner than the shipped rule. One accent per region ([utilities.md](utilities.md) → Borders).
269
+
239
270
  ### Carousel
240
271
 
241
272
  ```html
@@ -356,6 +387,8 @@ Multiple targets: give each panel `.multi-collapse` and point separate triggers
356
387
 
357
388
  `.dropdown-menu-dark` is deprecated — use `data-bs-theme="dark"` on the menu or an ancestor. Dropdowns have full keyboard support (arrows, Esc) built in. A dropdown is a **command menu** — for choosing a form value use `.form-select`, never a styled dropdown pretending to be an input.
358
389
 
390
+ A menu is a floating surface, not only a list of links: give it `dropdown-header` sections, a `dropdown-divider`, an icon, and a `small text-body-secondary` line under a `fw-semibold` label inside each `dropdown-item`, or a `row` of columns in a `p-3` menu, while keeping `dropdown-item` semantics on every choice.
391
+
359
392
  ### List Group
360
393
 
361
394
  ```html
@@ -404,6 +437,10 @@ Multiple targets: give each panel `.multi-collapse` and point separate triggers
404
437
 
405
438
  ### Modal
406
439
 
440
+ Keep width bounded and all actions vertically reachable on short viewports and enlarged text.
441
+ Use `modal-fullscreen-*-down` only with Bootstrap modal markup; a native `<dialog>` needs its own
442
+ measured sizing contract. Keep row-action dialogs outside table overflow ancestors.
443
+
407
444
  **Build a blocking dialog on the native `<dialog>`.** `showModal()` brings focus containment, Esc, an inert background, and top-layer stacking from the platform — nothing to construct, nothing to dispose when the view unmounts, and no JS instance for a virtual-DOM framework to fight with over the same nodes. Leave the element itself unpainted and put Bootstrap chrome inside it:
408
445
 
409
446
  ```html
@@ -504,7 +541,9 @@ Bootstrap's modal enforces focus, adds `role="dialog"`/`aria-modal="true"`, clos
504
541
  <nav class="navbar bg-body-tertiary sticky-top">Sticky top</nav>
505
542
 
506
543
  <!-- Dark navbar: .navbar-dark is DEPRECATED — scope the theme instead -->
507
- <nav class="navbar bg-primary" data-bs-theme="dark">Dark-themed navbar</nav>
544
+ <nav class="navbar bg-body-tertiary" data-bs-theme="dark">
545
+ <a class="navbar-brand" href="#">Dark-themed navbar</a>
546
+ </nav>
508
547
  ```
509
548
 
510
549
  ### Navs & Tabs
@@ -592,6 +631,10 @@ Real switchable tab panels (JS-driven — buttons, not scroll anchors):
592
631
 
593
632
  ### Offcanvas
594
633
 
634
+ Take narrow/inline thresholds, trigger parity, and open-resize-close tests from
635
+ [responsive-layout.md](responsive-layout.md#handle-navigation-and-overlays). Match trigger and panel
636
+ breakpoints; do not leave a hidden focus trap or scroll lock after expansion.
637
+
595
638
  ```html
596
639
  <button
597
640
  class="btn btn-primary"
@@ -629,6 +672,10 @@ Real switchable tab panels (JS-driven — buttons, not scroll anchors):
629
672
 
630
673
  ### Pagination
631
674
 
675
+ On narrow screens, retain the current page and previous/next controls; reduce numbered links
676
+ before shrinking targets. Keep pagination outside the table scroller and preserve page state
677
+ when the presentation changes.
678
+
632
679
  ```html
633
680
  <nav aria-label="Search results pages">
634
681
  <ul class="pagination">
@@ -807,11 +854,11 @@ Gotcha: the spied element must be a scroll container (height/overflow, or focusa
807
854
  ### Spinners
808
855
 
809
856
  ```html
810
- <div class="spinner-border text-primary" role="status">
857
+ <div class="spinner-border" role="status">
811
858
  <span class="visually-hidden">Loading...</span>
812
859
  </div>
813
860
 
814
- <div class="spinner-grow text-primary" role="status">
861
+ <div class="spinner-grow" role="status">
815
862
  <span class="visually-hidden">Loading...</span>
816
863
  </div>
817
864
 
@@ -841,14 +888,14 @@ Gotcha: the spied element must be a scroll container (height/overflow, or focusa
841
888
  <tbody>
842
889
  <tr>
843
890
  <th scope="row">INV-1042</th>
844
- <td><span class="badge text-bg-success">Paid</span></td>
891
+ <td><span class="badge bg-success-subtle text-reset">Paid</span></td>
845
892
  <td class="text-end">$1,280.00</td>
846
893
  </tr>
847
894
  </tbody>
848
895
  </table>
849
896
  ```
850
897
 
851
- Modifiers (combine freely):
898
+ Combine structural modifiers as needed; choose color variants separately:
852
899
 
853
900
  ```css
854
901
  .table-sm /* half padding — dense screens */
@@ -863,8 +910,8 @@ Modifiers (combine freely):
863
910
  ```
864
911
 
865
912
  - **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` 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.
913
+ - **Color modes:** let the uncolored `.table` follow the page. Use `data-bs-theme="dark"` only for an intentional local mode, not as a permanent setting on a table that must follow the toggle.
914
+ - **Theming:** treat `.table-*` color variants as non-adaptive in stock 5.3; their CSS variables contain Sass-generated colors. The base table background uses the body background; the transparent default belongs to `--bs-table-accent-bg`. Inspect painted cells and their state overlays; see [color-modes.md](color-modes.md) → Tables and overlays.
868
915
  - **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
916
 
870
917
  ### Toasts
@@ -879,13 +926,12 @@ Modifiers (combine freely):
879
926
  <div class="toast-body">Changes published.</div>
880
927
  </div>
881
928
 
882
- <div class="toast align-items-center text-bg-primary border-0" role="status" aria-live="polite">
929
+ <div class="toast align-items-center bg-primary-subtle border-0" role="status" aria-live="polite">
883
930
  <div class="d-flex">
884
931
  <div class="toast-body">Color tone</div>
885
932
  <button
886
933
  type="button"
887
934
  class="btn-close me-2 m-auto"
888
- data-bs-theme="dark"
889
935
  data-bs-dismiss="toast"
890
936
  aria-label="Close"
891
937
  ></button>
@@ -960,15 +1006,11 @@ Bootstrap's core CSS ships **no icons**. The `.bi` SVGs in examples come from th
960
1006
  The textless mark that survives both themes — dots, ticks, rings, pulses — is a glyph, not a badge ([Badge](#badge)). Inline SVG or icon font, the composition rules are the same:
961
1007
 
962
1008
  ```html
963
- <span
964
- class="bi bi-circle-fill fs-6 lh-1 text-success-emphasis"
965
- role="img"
966
- aria-label="Healthy"
967
- ></span>
968
- <span class="bi bi-circle fs-6 lh-1 text-body-secondary" role="img" aria-label="Not started"></span>
1009
+ <span class="bi bi-circle-fill fs-6 lh-1" role="img" aria-label="Healthy"></span>
1010
+ <span class="bi bi-circle fs-6 lh-1" role="img" aria-label="Not started"></span>
969
1011
  ```
970
1012
 
971
- - **Color from the emphasis tokens.** `text-*-emphasis` is the mode-adaptive tier built for marks on subtle surfaces; the plain `text-*` colors are tuned for light and thin out in dark. On a filled surface — `.active`, `.bg-primary`, `text-bg-*` — drop the tone class instead and let the fill's contrast color take the glyph ([Selection fills](#selection-fills)). Measure every mark at **≥ 3:1** against the surface it sits on, **in both themes**, against the compiled cascade — a skin's token values are its own.
1013
+ - **Inherit the owning foreground.** Keep ordinary glyphs on body or component text, including selected fills. Add `text-*-emphasis` only for a deliberate semantic tint on a known, measured surface; never apply it to every mark on a subtle fill. Measure meaningful marks at **≥ 3:1** in light and dark. Take cascade exceptions from [color-modes.md](color-modes.md).
972
1014
  - **Filled and hollow say different things** — done vs pending, live vs idle — so pair glyphs that share one advance width (a filled/hollow pair from the same icon family). Mixed widths make a column of marks jitter row to row.
973
1015
  - **Size with `fs-*` _and_ `lh-1`.** A glyph inherits the row's line-height, so an `fs-*` bump without `lh-1` grows the line box and pushes the row taller than its neighbors.
974
1016
  - Give the mark an accessible name (`role="img"` + `aria-label`, or a `.visually-hidden` word next to an `aria-hidden` glyph) — a mark whose only meaning is its color and shape is color-only status.
@@ -1002,12 +1044,17 @@ The textless mark that survives both themes — dots, ticks, rings, pulses — i
1002
1044
 
1003
1045
  ### Selection fills
1004
1046
 
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:
1047
+ Keep the component's selected foreground on ordinary labels and glyphs. Remove a competing
1048
+ semantic tint before changing its active fill; handle an independently filled badge through
1049
+ [color-modes.md](color-modes.md) → Alerts, buttons, and selection.
1006
1050
 
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 tone class (a real theme color) rather than the neutral outline, so "chosen" reads the same way in both modes.
1051
+ Verify that chosen and unchosen filters remain distinguishable in light and dark. Do not assume
1052
+ that a neutral outline always inverts meaning or that an accent hue repairs it. Preserve the
1053
+ checked/pressed state and add a visible non-color cue when the fill alone is ambiguous.
1009
1054
 
1010
- Exactly one item in a selection carries `aria-current` — the visual fill and the announced state must be the same item.
1055
+ Use `aria-current` for current navigation, `aria-selected` for tabs, and native checked state for
1056
+ checkboxes/radios. Match the visual state to the applicable pattern; do not apply `aria-current`
1057
+ to every selection widget.
1011
1058
 
1012
1059
  ### Navigation & overlays
1013
1060
 
@@ -1017,5 +1064,5 @@ Exactly one item in a selection carries `aria-current` — the visual fill and t
1017
1064
 
1018
1065
  ### Theming
1019
1066
 
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"`.
1067
+ - Preserve native component colors and prefer adaptive quiet surfaces. Take ownership, solid exceptions, nested modes, and deprecated-class replacements from [color-modes.md](color-modes.md). Do not assume every component variable adapts.
1021
1068
  - 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.