@ponchia/ui 0.6.4 → 0.6.5

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/docs/reference.md CHANGED
@@ -9,7 +9,7 @@ rendering of every class is the kitchen-sink demo:
9
9
  **<https://ponchia.github.io/bronto-ui/>**. Theming knobs and the token
10
10
  contract: [docs/theming.md](theming.md).
11
11
 
12
- - 540 classes across 167 component groups
12
+ - 593 classes across 171 component groups
13
13
  - Import the typed registry: `import { cls, ui, cx } from '@ponchia/ui/classes'`
14
14
  - Validate markup as data (no JS/TS): `@ponchia/ui/classes.json` — the same
15
15
  vocabulary as language-neutral JSON (`groups`, `classes`, `states`,
@@ -330,6 +330,24 @@ each one matches a real selector in the stylesheet.
330
330
  | `cls.citation` | `ui-citation` | base |
331
331
  | `cls.citationChip` | `ui-citation--chip` | modifier |
332
332
 
333
+ ### `.ui-claim`
334
+
335
+ | Registry key | Class | Kind |
336
+ | --- | --- | --- |
337
+ | `cls.claim` | `ui-claim` | base |
338
+ | `cls.claimBasis` | `ui-claim__basis` | part |
339
+ | `cls.claimCaveat` | `ui-claim__caveat` | part |
340
+ | `cls.claimLimits` | `ui-claim__limits` | part |
341
+ | `cls.claimRefs` | `ui-claim__refs` | part |
342
+ | `cls.claimScope` | `ui-claim__scope` | part |
343
+ | `cls.claimStatement` | `ui-claim__statement` | part |
344
+ | `cls.claimStatus` | `ui-claim__status` | part |
345
+ | `cls.claimDisputed` | `ui-claim--disputed` | modifier |
346
+ | `cls.claimPartial` | `ui-claim--partial` | modifier |
347
+ | `cls.claimSupported` | `ui-claim--supported` | modifier |
348
+ | `cls.claimUnknown` | `ui-claim--unknown` | modifier |
349
+ | `cls.claimUnsupported` | `ui-claim--unsupported` | modifier |
350
+
333
351
  ### `.ui-cluster`
334
352
 
335
353
  | Registry key | Class | Kind |
@@ -557,6 +575,33 @@ each one matches a real selector in the stylesheet.
557
575
  | `cls.errorSummaryList` | `ui-error-summary__list` | part |
558
576
  | `cls.errorSummaryTitle` | `ui-error-summary__title` | part |
559
577
 
578
+ ### `.ui-evidence-grid`
579
+
580
+ | Registry key | Class | Kind |
581
+ | --- | --- | --- |
582
+ | `cls.evidenceGrid` | `ui-evidence-grid` | base |
583
+
584
+ ### `.ui-evidence-item`
585
+
586
+ | Registry key | Class | Kind |
587
+ | --- | --- | --- |
588
+ | `cls.evidenceItem` | `ui-evidence-item` | base |
589
+ | `cls.evidenceItemBody` | `ui-evidence-item__body` | part |
590
+ | `cls.evidenceItemCaveat` | `ui-evidence-item__caveat` | part |
591
+ | `cls.evidenceItemKind` | `ui-evidence-item__kind` | part |
592
+ | `cls.evidenceItemMeta` | `ui-evidence-item__meta` | part |
593
+ | `cls.evidenceItemMethod` | `ui-evidence-item__method` | part |
594
+ | `cls.evidenceItemSource` | `ui-evidence-item__source` | part |
595
+ | `cls.evidenceItemTitle` | `ui-evidence-item__title` | part |
596
+ | `cls.evidenceItemValue` | `ui-evidence-item__value` | part |
597
+ | `cls.evidenceItemWindow` | `ui-evidence-item__window` | part |
598
+
599
+ ### `.ui-evidence-ledger`
600
+
601
+ | Registry key | Class | Kind |
602
+ | --- | --- | --- |
603
+ | `cls.evidenceLedger` | `ui-evidence-ledger` | base |
604
+
560
605
  ### `.ui-eyebrow`
561
606
 
562
607
  | Registry key | Class | Kind |
@@ -939,13 +984,41 @@ each one matches a real selector in the stylesheet.
939
984
  | Registry key | Class | Kind |
940
985
  | --- | --- | --- |
941
986
  | `cls.report` | `ui-report` | base |
987
+ | `cls.reportAction` | `ui-report__action` | part |
988
+ | `cls.reportActionCriteria` | `ui-report__action-criteria` | part |
989
+ | `cls.reportActionDue` | `ui-report__action-due` | part |
990
+ | `cls.reportActionOwner` | `ui-report__action-owner` | part |
991
+ | `cls.reportActionPriority` | `ui-report__action-priority` | part |
992
+ | `cls.reportActionSource` | `ui-report__action-source` | part |
993
+ | `cls.reportActionStatus` | `ui-report__action-status` | part |
994
+ | `cls.reportActionTitle` | `ui-report__action-title` | part |
995
+ | `cls.reportActions` | `ui-report__actions` | part |
942
996
  | `cls.reportAppendix` | `ui-report__appendix` | part |
943
997
  | `cls.reportCaption` | `ui-report__caption` | part |
944
998
  | `cls.reportCover` | `ui-report__cover` | part |
945
999
  | `cls.reportCoverCompact` | `ui-report__cover--compact` | modifier |
1000
+ | `cls.reportDecision` | `ui-report__decision` | part |
1001
+ | `cls.reportDecisionBody` | `ui-report__decision-body` | part |
1002
+ | `cls.reportDecisionGrid` | `ui-report__decision-grid` | part |
1003
+ | `cls.reportDecisionItem` | `ui-report__decision-item` | part |
1004
+ | `cls.reportDecisionKicker` | `ui-report__decision-kicker` | part |
1005
+ | `cls.reportDecisionLabel` | `ui-report__decision-label` | part |
1006
+ | `cls.reportDecisionMeta` | `ui-report__decision-meta` | part |
1007
+ | `cls.reportDecisionTitle` | `ui-report__decision-title` | part |
1008
+ | `cls.reportDecisionValue` | `ui-report__decision-value` | part |
946
1009
  | `cls.reportEvidence` | `ui-report__evidence` | part |
947
1010
  | `cls.reportFigure` | `ui-report__figure` | part |
948
1011
  | `cls.reportFinding` | `ui-report__finding` | part |
1012
+ | `cls.reportFindingCritical` | `ui-report__finding--critical` | modifier |
1013
+ | `cls.reportFindingMajor` | `ui-report__finding--major` | modifier |
1014
+ | `cls.reportFindingMinor` | `ui-report__finding--minor` | modifier |
1015
+ | `cls.reportFindingResolved` | `ui-report__finding--resolved` | modifier |
1016
+ | `cls.reportFindingCaveat` | `ui-report__finding-caveat` | part |
1017
+ | `cls.reportFindingClaim` | `ui-report__finding-claim` | part |
1018
+ | `cls.reportFindingEvidence` | `ui-report__finding-evidence` | part |
1019
+ | `cls.reportFindingImpact` | `ui-report__finding-impact` | part |
1020
+ | `cls.reportFindingRemediation` | `ui-report__finding-remediation` | part |
1021
+ | `cls.reportFindingTitle` | `ui-report__finding-title` | part |
949
1022
  | `cls.reportFootnotes` | `ui-report__footnotes` | part |
950
1023
  | `cls.reportHead` | `ui-report__head` | part |
951
1024
  | `cls.reportMeta` | `ui-report__meta` | part |
package/docs/reporting.md CHANGED
@@ -37,11 +37,11 @@ No install? Link the same files from a CDN. Pin the version — pre-1.0, breakin
37
37
  changes ship in the minor (see [stability.md](./stability.md)):
38
38
 
39
39
  ```html
40
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.4/dist/bronto.css" />
41
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.4/dist/css/report.css" />
42
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.4/dist/css/dataviz.css" />
43
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.4/dist/css/annotations.css" />
44
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.4/dist/css/legend.css" />
40
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.5/dist/bronto.css" />
41
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.5/dist/css/report.css" />
42
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.5/dist/css/dataviz.css" />
43
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.5/dist/css/annotations.css" />
44
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.5/dist/css/legend.css" />
45
45
  ```
46
46
 
47
47
  The CDN serves the package's own `fonts/` next to the CSS, so font URLs resolve
@@ -106,6 +106,24 @@ they are all safe in the static, PDF-first report path.
106
106
  <div class="ui-report__summary">
107
107
  <p>The summary block is for the decision-level conclusion.</p>
108
108
  </div>
109
+ <aside class="ui-report__decision" aria-labelledby="decision-title">
110
+ <p class="ui-report__decision-kicker">Decision</p>
111
+ <h3 class="ui-report__decision-title" id="decision-title">Ship the low-risk path</h3>
112
+ <p class="ui-report__decision-body">
113
+ State the operator-facing call first, then list the evidence below it.
114
+ </p>
115
+ <dl class="ui-report__decision-grid">
116
+ <div class="ui-report__decision-item">
117
+ <dt class="ui-report__decision-label">Basis</dt>
118
+ <dd class="ui-report__decision-value">Two verified sources support the call.</dd>
119
+ </div>
120
+ <div class="ui-report__decision-item">
121
+ <dt class="ui-report__decision-label">Next action</dt>
122
+ <dd class="ui-report__decision-value">Owner rechecks the remaining caveat by Jun 8.</dd>
123
+ </div>
124
+ </dl>
125
+ <p class="ui-report__decision-meta">Evidence state: supported · Checked: 2026-06-01</p>
126
+ </aside>
109
127
  <div class="ui-statgrid">
110
128
  <div class="ui-stat">
111
129
  <span class="ui-stat__label">Open risks</span>
@@ -127,6 +145,147 @@ they are all safe in the static, PDF-first report path.
127
145
  </main>
128
146
  ```
129
147
 
148
+ ## Report-specific primitives
149
+
150
+ Use these report-layer primitives before inventing custom card layouts. They are
151
+ generic, static, and PDF-safe; the host still owns the content, scoring, source
152
+ fetching, and claim wording.
153
+
154
+ - `ui-report__decision` is the above-the-fold call. Pair it with
155
+ `ui-report__decision-kicker`, `ui-report__decision-title`,
156
+ `ui-report__decision-body`, optional `ui-report__decision-grid` /
157
+ `ui-report__decision-item` detail rows, and optional
158
+ `ui-report__decision-meta`. It should answer "what should the reader do or
159
+ believe now?" before the deep evidence. Good rows are basis, impact, next
160
+ action, owner, recheck date, and evidence state.
161
+ - `ui-report__finding` is the repeated finding block. Add
162
+ `ui-report__finding--critical`, `--major`, `--minor`, or `--resolved` only
163
+ when the written finding label also states the severity/status. The colour
164
+ band is a scanning aid, not the data of record. For dense reports, use
165
+ `ui-report__finding-title`, `ui-report__finding-claim`,
166
+ `ui-report__finding-impact`, `ui-report__finding-remediation`,
167
+ `ui-report__finding-evidence`, and `ui-report__finding-caveat` so impact,
168
+ evidence, caveat, and remediation do not collapse into one paragraph.
169
+ - `ui-claim` is the smallest claim/evidence contract. Use
170
+ `ui-claim--supported`, `--partial`, `--disputed`, `--unsupported`, or
171
+ `--unknown` only when the written `ui-claim__status` says the same thing.
172
+ Use `ui-claim__statement`, `__scope`, `__basis`, `__limits`, `__refs`, and
173
+ `__caveat` to show what the report asserts, where it applies, what supports
174
+ it, what would limit or change it, and which sources/evidence entries it maps
175
+ to.
176
+ - `ui-evidence-grid` and `ui-evidence-item` are for compact evidence packets:
177
+ one source, check, observation, counterexample, or assumption per item. Use
178
+ `ui-evidence-item__title`, `__meta`, and `__body` for simple cards; add
179
+ `__kind`, `__method`, `__window`, `__value`, `__source`, and `__caveat` when
180
+ the evidence needs to say how it was gathered. Link to source cards or a table
181
+ when the evidence is more than a sentence.
182
+ - `ui-evidence-ledger` is a wrapper for a claim/evidence/source matrix. Put a
183
+ normal `ui-table` inside it with columns such as claim, evidence, source,
184
+ trust, freshness, relation, and caveat.
185
+ - `ui-report__actions`, `ui-report__action`, and
186
+ `ui-report__action-status` are for follow-up rows in status, incident, and
187
+ audit reports. Add `ui-report__action-title`, `__action-owner`,
188
+ `__action-due`, `__action-priority`, `__action-criteria`, and
189
+ `__action-source` when the action is a real workflow item. The status text
190
+ must be written out; do not rely on tone alone.
191
+
192
+ Decision brief pattern:
193
+
194
+ ```html
195
+ <aside class="ui-report__decision" aria-labelledby="decision-title">
196
+ <p class="ui-report__decision-kicker">Decision</p>
197
+ <h3 class="ui-report__decision-title" id="decision-title">Adopt the safer option</h3>
198
+ <p class="ui-report__decision-body">
199
+ The current evidence supports the lower-risk path while the disputed source is rechecked.
200
+ </p>
201
+ <dl class="ui-report__decision-grid">
202
+ <div class="ui-report__decision-item">
203
+ <dt class="ui-report__decision-label">Basis</dt>
204
+ <dd class="ui-report__decision-value">Verified metrics support the call; one source is stale.</dd>
205
+ </div>
206
+ <div class="ui-report__decision-item">
207
+ <dt class="ui-report__decision-label">Recheck</dt>
208
+ <dd class="ui-report__decision-value"><time datetime="2026-06-08">2026-06-08</time></dd>
209
+ </div>
210
+ </dl>
211
+ <p class="ui-report__decision-meta">Evidence state: partial · Sources: 4 · Checked: 2026-06-01</p>
212
+ </aside>
213
+ ```
214
+
215
+ Finding + evidence pattern:
216
+
217
+ ```html
218
+ <article class="ui-report__finding ui-report__finding--major" aria-labelledby="finding-cache">
219
+ <p class="ui-eyebrow" id="finding-cache">Major finding — cache pressure is rising</p>
220
+ <p class="ui-report__finding-claim">
221
+ Claim: cache pressure is rising during the refresh window.
222
+ </p>
223
+ <p class="ui-report__finding-impact">Impact: p95 latency is likely to breach target if volume rises.</p>
224
+ <p class="ui-report__finding-remediation">Remediation: lower the refresh batch size before the next rollout.</p>
225
+ <p class="ui-report__finding-caveat">
226
+ Caveat: the conclusion assumes comparable traffic shape in the next window.
227
+ </p>
228
+ </article>
229
+ <div class="ui-evidence-grid" aria-label="Evidence summary">
230
+ <article class="ui-evidence-item">
231
+ <h3 class="ui-evidence-item__title">Metric trend</h3>
232
+ <p class="ui-evidence-item__kind">Observation</p>
233
+ <p class="ui-evidence-item__meta">Prometheus · 24 h window</p>
234
+ <p class="ui-evidence-item__body">p95 latency rose 18% while request volume stayed flat.</p>
235
+ </article>
236
+ <article class="ui-evidence-item">
237
+ <h3 class="ui-evidence-item__title">Log sample</h3>
238
+ <p class="ui-evidence-item__meta">Application logs · reviewed</p>
239
+ <p class="ui-evidence-item__body">Timeouts cluster around cache refresh intervals.</p>
240
+ </article>
241
+ </div>
242
+ ```
243
+
244
+ Claim block pattern:
245
+
246
+ ```html
247
+ <article class="ui-claim ui-claim--partial" id="claim-latency">
248
+ <p class="ui-claim__statement">The migration improved latency without reducing availability.</p>
249
+ <p class="ui-claim__status">Evidence state: partial</p>
250
+ <p class="ui-claim__scope">Scope: last 7 days, production traffic only</p>
251
+ <p class="ui-claim__basis">Basis: metrics export S1 and incident note S2 support the claim.</p>
252
+ <p class="ui-claim__limits">Limit: retry volume still needs a separate review.</p>
253
+ <p class="ui-claim__refs">Sources: <a class="ui-citation" href="#source-metrics">S1</a></p>
254
+ </article>
255
+ ```
256
+
257
+ Evidence ledger pattern:
258
+
259
+ ```html
260
+ <div class="ui-evidence-ledger">
261
+ <div class="ui-table-wrap">
262
+ <table class="ui-table ui-table--dense">
263
+ <caption>Claim, evidence, and caveat ledger</caption>
264
+ <thead>
265
+ <tr>
266
+ <th>Claim</th>
267
+ <th>Evidence</th>
268
+ <th>Source</th>
269
+ <th>Trust</th>
270
+ <th>Relation</th>
271
+ <th>Caveat</th>
272
+ </tr>
273
+ </thead>
274
+ <tbody>
275
+ <tr>
276
+ <td><a href="#claim-latency">Latency improved</a></td>
277
+ <td>p95 fell 48 ms</td>
278
+ <td><a class="ui-citation" href="#source-metrics">S1</a></td>
279
+ <td>Verified</td>
280
+ <td>Supports</td>
281
+ <td>Last 7 days only</td>
282
+ </tr>
283
+ </tbody>
284
+ </table>
285
+ </div>
286
+ </div>
287
+ ```
288
+
130
289
  ## Composition rules
131
290
 
132
291
  - Use `ui-report` as the page-level wrapper. Add `ui-report--numbered` when
@@ -150,6 +309,12 @@ they are all safe in the static, PDF-first report path.
150
309
  `ui-alert` for persistent notices, `ui-table` for structured evidence,
151
310
  `ui-timeline` for events, `ui-meter` for measured values, and `ui-num` for
152
311
  non-table numeric values.
312
+ - Put a `ui-report__decision` near the start of decision reports, audits, and
313
+ incident reviews. If the report is intentionally exploratory and has no
314
+ decision yet, say so in the summary instead of leaving the reader to infer it.
315
+ - Use severity modifiers on `ui-report__finding` only for scanability. The
316
+ label should still include the severity/status in text, for example
317
+ "Major finding — …" or "Resolved finding — …".
153
318
  - In alerts, put the readable message in `<p class="ui-alert__body">…</p>`
154
319
  and use `ui-alert__title` only for a separate title line. `ui-alert` is a
155
320
  grid with a leading status dot; raw text or loose inline children such as
@@ -579,14 +744,100 @@ the target theme, or use the frozen inline `<svg>` route, which has no runtime.
579
744
 
580
745
  ## Common templates
581
746
 
582
- - Executive brief: compact cover, one summary block, KPI `ui-statgrid`, short
583
- findings, and sources.
584
- - Research brief: compact header, decision frame, evidence table, quotes or
585
- prose excerpts, and sources.
586
- - Incident review: compact cover, summary, `ui-timeline`, corrective-action
587
- evidence table, and footnotes.
588
- - Project status: compact header, KPI `ui-statgrid`, chart figure with fallback
589
- data, print-only notes, and unnumbered appendix.
747
+ - Executive brief: compact cover, above-fold reader outcome, KPI
748
+ `ui-statgrid`, short findings, evidence-state disclosure, and sources.
749
+ - Decision report: decision frame, options considered, chosen option, rationale,
750
+ tradeoffs, revisit trigger, next actions, evidence ledger, and sources.
751
+ - Research brief: compact header, scope/method block, claim cards, evidence
752
+ table, quotes or prose excerpts, limitations, and sources.
753
+ - Incident review: compact cover, impact summary, `ui-timeline`, root-cause
754
+ claim, corrective-action register, evidence ledger, and footnotes.
755
+ - Audit: summary, finding cards with severity in text, evidence/caveat rows,
756
+ remediation owner/due dates, accepted risk, and sources.
757
+ - Project status: compact header, KPI `ui-statgrid`, current state, blocked
758
+ decisions, action register, chart figure with fallback data, print-only notes,
759
+ and unnumbered appendix.
760
+
761
+ Minimum blocks by report type:
762
+
763
+ | Type | Required shape |
764
+ | --- | --- |
765
+ | Executive | Summary, above-fold outcome, evidence-state disclosure, source cards. |
766
+ | Decision | Decision frame, options/tradeoffs, claim cards, evidence ledger, next actions, sources. |
767
+ | Research | Scope/method, explicit claims, evidence table, limitations, sources. |
768
+ | Primer | Scope, teaching sequence, key claims, examples, caveats, sources. |
769
+ | Incident | Impact, root-cause claim, timeline, evidence ledger, corrective actions, footnotes. |
770
+ | Audit | Severity-labelled findings, evidence/caveat rows, remediation owners/dates, accepted risk, sources. |
771
+ | Status | Current state, risks/blockers, decision requests, action register, recheck timing, sources. |
772
+
773
+ ## Semantic contract
774
+
775
+ The report layer is not a fact checker, but it should make a report's reasoning
776
+ auditable. A useful report separates:
777
+
778
+ - **Reader outcome** — what the reader should do or believe now.
779
+ - **Claim** — the actual assertion, with scope and evidence state.
780
+ - **Evidence** — observation, metric, log, quote, sample, method, assumption,
781
+ counterevidence, or limitation.
782
+ - **Source** — where the evidence came from, with trust/freshness written in
783
+ text.
784
+ - **Action** — who does what next, by when, and how completion is checked.
785
+
786
+ Use inline citations and stable IDs to connect those layers:
787
+
788
+ ```html
789
+ <article class="ui-claim ui-claim--supported" id="claim-1" data-source-ids="source-metrics">
790
+ <p class="ui-claim__statement">Availability remained above target.</p>
791
+ <p class="ui-claim__status">Evidence state: supported</p>
792
+ <p class="ui-claim__refs">Source: <a class="ui-citation" href="#source-metrics">S1</a></p>
793
+ </article>
794
+
795
+ <article class="ui-source-card ui-src--verified" id="source-metrics">
796
+ <h3 class="ui-source-card__title">Metrics export</h3>
797
+ <p class="ui-source-card__origin">Verified operational export</p>
798
+ </article>
799
+ ```
800
+
801
+ If a claim is generated, inferred, stale, disputed, or uncited, say so near the
802
+ claim, not only in the source appendix. Do not use a numeric confidence widget
803
+ unless the number has a real model, sample, or scoring method behind it.
804
+
805
+ Generator-side tools should keep a machine-readable claim/source sidecar beside
806
+ important reports. The HTML stays the readable artifact; the sidecar lets a
807
+ checker prove that claim IDs, source IDs, trust states, retrieval dates and
808
+ high-risk decisions still line up after editing.
809
+
810
+ ```json
811
+ {
812
+ "schemaVersion": "bronto-report-claims.v1",
813
+ "report": { "title": "Decision readiness", "type": "decision" },
814
+ "claims": [
815
+ {
816
+ "id": "claim-primary",
817
+ "status": "supported",
818
+ "risk": "medium",
819
+ "statement": "The guarded option reduces operational risk.",
820
+ "scope": "Current release window",
821
+ "sourceIds": ["source-primary"]
822
+ }
823
+ ],
824
+ "sources": [
825
+ {
826
+ "id": "source-primary",
827
+ "state": "verified",
828
+ "title": "Release metrics export",
829
+ "origin": "Verified operational export",
830
+ "retrievedAt": "2026-06-08T10:00:00Z",
831
+ "supports": ["claim-primary"]
832
+ }
833
+ ]
834
+ }
835
+ ```
836
+
837
+ For source archives, keep the same source IDs and add any available immutable
838
+ handles: URL, artifact path, content hash, retrieval timestamp, collection
839
+ method and caveats. A report is more useful when the source appendix, inline
840
+ citations, evidence ledger and sidecar all name the same IDs.
590
841
 
591
842
  ## Print and PDF
592
843
 
@@ -594,6 +845,11 @@ The supported export target is modern Chromium print/PDF. A bronto report is
594
845
  static and zero-JS, so producing the PDF is just _load → print_ — you do not
595
846
  need a full automatable browser, only a Chromium-class layout+print pass.
596
847
 
848
+ Chromium's generated PDF is a visual/export artifact, not a tagged accessible
849
+ PDF. Keep the HTML report as the accessible artifact unless the host application
850
+ adds a separate tagged-PDF pipeline and verifies it with PDF accessibility
851
+ tooling.
852
+
597
853
  - **By hand:** open the report in Chrome/Edge → Print (Cmd/Ctrl+P) → "Save as
598
854
  PDF". In **More settings**, enable **Background graphics** (the dialog's
599
855
  equivalent of `printBackground` — without it chart fills and swatches drop
@@ -666,6 +922,19 @@ Before returning a report, an LLM should verify:
666
922
  cells and `.ui-stat` deltas, `is-open`/`is-active`) are valid but live
667
923
  outside `cls` by design — keep them.
668
924
  - The document has one `h1`, ordered headings, and a single main report region.
925
+ - The report type is clear: executive, decision, research, incident, audit,
926
+ primer, or status. The above-fold block answers what the reader should do or
927
+ believe now, unless the report explicitly says it is exploratory.
928
+ - Every decision, major finding, quantitative claim, and recommendation has a
929
+ nearby citation, claim block, evidence packet, evidence ledger row, or an
930
+ explicit assumption/uncited/generated label.
931
+ - Claim/source sidecars, when present, resolve every claim ID and source ID back
932
+ to visible HTML. High-risk claims have at least one verified or reviewed
933
+ source.
934
+ - Stale, conflicting, unverified, or generated inputs are surfaced near the
935
+ affected claim or decision, not buried only in the source appendix.
936
+ - Actions that represent real follow-up include owner, due/recheck date, status,
937
+ and success criteria, or explicitly say why those fields are unassigned.
669
938
  - Tables have captions and header cells.
670
939
  - Charts have captions, direct labels or legends, and fallback data.
671
940
  - No raw chromatic colors appear in inline styles.
package/docs/sources.md CHANGED
@@ -102,6 +102,35 @@ A references section: a reset list of source cards (or rows).
102
102
  </ol>
103
103
  ```
104
104
 
105
+ ## Optional behavior — `initSources`
106
+
107
+ When you want citations to jump back to their source cards with a visible focus
108
+ cue, wrap the report or article in `data-bronto-sources` and initialize the
109
+ behavior:
110
+
111
+ ```html
112
+ <main data-bronto-sources>
113
+ <p>Latency fell 38%<a class="ui-citation" href="#s1" aria-label="Source 1">[1]</a>.</p>
114
+ <article id="s1" class="ui-source-card ui-src--verified">…</article>
115
+ </main>
116
+
117
+ <script type="module">
118
+ import { initSources } from '@ponchia/ui/behaviors';
119
+ const stop = initSources();
120
+ </script>
121
+ ```
122
+
123
+ `initSources()` is progressive enhancement over authored IDs. It resolves
124
+ `.ui-citation[href^="#"]` and `[data-bronto-source-ref]` controls inside each
125
+ `[data-bronto-sources]` island, adds preview metadata (`title` and
126
+ `aria-describedby`) when the author did not already provide it, and activation
127
+ focuses the matching source card with a temporary `.is-source-active` highlight.
128
+ It emits `bronto:source:focus` with `{ id, citation, source }`.
129
+
130
+ The host still owns fetching, numbering, permission checks, trust decisions, and
131
+ any rich preview popover. Generated/static reports can stay behavior-free:
132
+ hash-link navigation and `.ui-source-card:target` still provide a CSS-only cue.
133
+
105
134
  ## Provenance — `.ui-provenance`
106
135
 
107
136
  A compact metadata row beside generated content — each `__item` carries a trust
@@ -130,6 +159,9 @@ ui.provenance({ state: 'reviewed' }); // "ui-provenance ui-src--reviewed"
130
159
 
131
160
  - A citation must be a real link or button with a stable accessible name; the
132
161
  bracketed index alone is not enough.
162
+ - `initSources()` is optional. Initialize it only on trusted markup; the
163
+ delegated `data-bronto-source-ref` / `href="#…"` relationships focus elements
164
+ inside the source island.
133
165
  - The trust state must be readable as text — the tone dot/border is decorative
134
166
  reinforcement. Under `forced-colors`, dots and borders fall back to
135
167
  `CanvasText`, so the label remains the channel.
package/docs/stability.md CHANGED
@@ -1,12 +1,15 @@
1
1
  # Public API Stability
2
2
 
3
3
  `@ponchia/ui` is pre-1.0. Breaking changes ship in the minor (`0.x.0`), and
4
- patches are non-breaking. In practical terms: **PATCH releases (`0.5.x`) are
4
+ patches are non-breaking. In practical terms: **PATCH releases (`0.6.x`) are
5
5
  non-breaking bug-fixes and additive changes — safe to upgrade without review;
6
6
  MINOR releases (`0.x.0`) may include breaking changes and consumers should
7
7
  review the CHANGELOG before upgrading.** Pin `~0.x` (tilde) to accept only
8
8
  patches, or `^0.x` only if you accept minor-level churn. This policy holds
9
9
  until `1.0.0` is tagged. This matrix defines what counts as public API.
10
+ For the exhaustive package-manifest inventory — every `exports` key, every
11
+ shipped `files` entry, and the generated artifact provenance map — see
12
+ [package-contract.md](./package-contract.md).
10
13
 
11
14
  | Surface | Stability | Contract |
12
15
  | --- | --- | --- |
@@ -18,7 +21,7 @@ until `1.0.0` is tagged. This matrix defines what counts as public API.
18
21
  | Design tokens | Stable names/roles | Token names and documented roles are public. Exact values and generated colour math outputs may change for visual tuning before 1.0. |
19
22
  | `--accent-1..6` | Stable names/roles | A subtle-to-bold accent ramp derived from `--accent`. Exact resolved values are visual tuning; algorithm changes require release-note visibility and resolver/browser checks. |
20
23
  | Tokens as data (`tokens.json`, `tokens.dtcg.json`, `tokens/resolved.json`) | Stable additive | The JSON shapes are public for non-CSS/non-JS consumers. `resolved.json` exposes `light`/`dark` (resolved colours) and `scale` (resolved non-colour scales). Token names/roles are stable; exact resolved values are visual tuning (pin `~0.x`). |
21
- | Theme axes | Mixed | `data-theme` (light/dark) is the **contractual** base. `data-surface="oled"`, `data-density`, and `data-contrast` are **convenience presets** — best-effort visual variants, **not** part of the stability contract; their presence and exact values may change for tuning. (A computed-style smoke test guards the OLED `--bg` flip; the others are unverified.) |
24
+ | Theme axes | Mixed | `data-theme` (light/dark) is the **contractual** base. `data-surface="oled"`, `data-density`, and `data-contrast` are **convenience presets** — best-effort visual variants, **not** part of the stability contract; their presence and exact values may change for tuning. Computed-style smoke tests guard that the presets apply to their intended token families. |
22
25
  | Behavior attributes (`data-bronto-*`) | Stable | Attribute names and documented markup relationships are public. Behavior internals are not. |
23
26
  | Behavior functions (`@ponchia/ui/behaviors`) | Stable | Exported function names, option names, custom events, SSR no-op behavior, idempotency, and cleanup-returning contract are public. |
24
27
  | Glyph registry/renderers (`@ponchia/ui/glyphs`) | Stable additive | Existing glyph names stay valid. New glyphs are additive. Renderer option names and accessibility defaults are public. |
@@ -35,7 +38,7 @@ until `1.0.0` is tagged. This matrix defines what counts as public API.
35
38
  | Crosshair (`css/crosshair.css`, `.ui-crosshair*`, `.ui-readout`, `initCrosshair`) | Stable additive | Crosshair/readout class names, the `--crosshair-x/y` properties, the `data-bronto-crosshair` attribute, and the `bronto:crosshair:move`/`:leave` event contract are public. Opt-in. Reports pointer position only — no data mapping. |
36
39
  | Selection states (`css/selection.css`, `.ui-sel*`) | Stable additive | The `.ui-sel`/`--on`/`--off`/`--maybe` emphasis classes and recipe options are public. Opt-in, cross-cutting. The host owns selection logic; Bronto only styles the states. |
37
40
  | Analytical roll-up (`css/analytical.css`) | Stable additive | A convenience `@import` of the seven analytical leaves (annotations, legend, marks, connectors, spotlight, crosshair, selection). The set of leaves it bundles may grow additively; each leaf also stays individually exported. Opt-in, not in the default bundle. |
38
- | Sources / provenance (`css/sources.css`, `.ui-citation*`, `.ui-source-card*`, `.ui-source-list*`, `.ui-provenance*`, `.ui-src--*`) | Stable additive | Citation/source/provenance class names, the cross-cutting `.ui-src--*` trust-state modifiers (always paired with an author label), and the `ui.citation`/`ui.source`/`ui.provenance` recipes + `cls.sourceList` are public. Opt-in, not in the default bundle. |
41
+ | Sources / provenance (`css/sources.css`, `.ui-citation*`, `.ui-source-card*`, `.ui-source-list*`, `.ui-provenance*`, `.ui-src--*`, `initSources`) | Stable additive | Citation/source/provenance class names, the cross-cutting `.ui-src--*` trust-state modifiers (always paired with an author label), the optional `data-bronto-sources` / `data-bronto-source-ref` behavior contract, `bronto:source:focus`, and the `ui.citation`/`ui.source`/`ui.provenance` recipes + `cls.sourceList` are public. Opt-in, not in the default bundle. |
39
42
  | Lifecycle state (`css/state.css`, `.ui-state*`, `.ui-syncbar`) | Stable additive | The `.ui-state`/`__label`/`__detail`/`--busy` classes, the canonical lifecycle state modifiers, `.ui-syncbar`, and the `ui.state` recipe are public. Opt-in, not in the default bundle. |
40
43
  | Generated / AI-trust (`css/generated.css`, `.ui-generated*`, `.ui-origin-label*`, `.ui-reasoning*`, `.ui-tool-log`, `.ui-tool-call*`) | Stable additive | The generated-content, origin-label (incl. `--ai`), reasoning-trace and tool-log/tool-call class names and the `ui.originLabel` recipe are public. Opt-in, not in the default bundle. Not a chat kit; no confidence widget. |
41
44
  | Workbench (`css/workbench.css`, `.ui-inspector*`, `.ui-property*`, `.ui-selectionbar*`) | Stable additive | Inspector, property-row and selection-bar class + BEM part names are public (class-only — no recipe). Opt-in, not in the default bundle. Splitters/drag handles are out of scope. |