@ponchia/ui 0.6.3 → 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.
Files changed (51) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/README.md +7 -7
  3. package/behaviors/glyph.d.ts +7 -0
  4. package/behaviors/glyph.d.ts.map +1 -1
  5. package/behaviors/glyph.js +58 -4
  6. package/behaviors/index.d.ts +2 -0
  7. package/behaviors/index.d.ts.map +1 -1
  8. package/behaviors/index.js +2 -0
  9. package/behaviors/sources.d.ts +28 -0
  10. package/behaviors/sources.d.ts.map +1 -0
  11. package/behaviors/sources.js +158 -0
  12. package/classes/classes.json +210 -4
  13. package/classes/index.d.ts +75 -1
  14. package/classes/index.js +95 -1
  15. package/css/dots.css +210 -3
  16. package/css/report.css +359 -7
  17. package/css/skins.css +9 -0
  18. package/css/sources.css +18 -0
  19. package/css/spark.css +14 -0
  20. package/css/table.css +7 -1
  21. package/css/tokens.css +8 -1
  22. package/dist/bronto.css +1 -1
  23. package/dist/css/dots.css +1 -1
  24. package/dist/css/report.css +1 -1
  25. package/dist/css/skins.css +1 -1
  26. package/dist/css/sources.css +1 -1
  27. package/dist/css/spark.css +1 -1
  28. package/dist/css/table.css +1 -1
  29. package/dist/css/tokens.css +1 -1
  30. package/docs/dots.md +146 -0
  31. package/docs/frontier-primitives.md +262 -0
  32. package/docs/glyphs.md +114 -0
  33. package/docs/package-contract.md +263 -0
  34. package/docs/reference.md +115 -1
  35. package/docs/reporting.md +296 -16
  36. package/docs/sources.md +32 -0
  37. package/docs/stability.md +6 -3
  38. package/glyphs/glyphs.d.ts +61 -0
  39. package/glyphs/glyphs.js +593 -30
  40. package/llms.txt +79 -25
  41. package/package.json +13 -3
  42. package/qwik/index.d.ts +1 -0
  43. package/qwik/index.d.ts.map +1 -1
  44. package/qwik/index.js +5 -0
  45. package/react/index.d.ts +1 -0
  46. package/react/index.d.ts.map +1 -1
  47. package/react/index.js +3 -0
  48. package/solid/index.d.ts +2 -0
  49. package/solid/index.d.ts.map +1 -1
  50. package/solid/index.js +3 -0
  51. package/tokens/skins.js +22 -9
package/css/dots.css CHANGED
@@ -348,6 +348,177 @@
348
348
  animation-delay: 0.63s;
349
349
  }
350
350
 
351
+ /* ==========================================================================
352
+ Data-bound dot surfaces — the reporting/dashboard family. Each is a thin,
353
+ token-driven leaf over the same lit/dim/accent dot vocabulary: the HOST
354
+ normalises the data (lights `is-on`, sets `data-level`, or writes `--v`
355
+ 0..1) and the leaf only lays out + tones. None compute a scale, bin, or
356
+ threshold — that stays with the host (the spark/meter boundary).
357
+
358
+ a11y: every one is opaque to assistive tech, so the container MUST carry a
359
+ host-written `role="img"` + `aria-label` with the exact value/meaning
360
+ (rounding to whole cells is presentation-only; keep the figure in the label).
361
+ ========================================================================== */
362
+
363
+ /* Waffle / unit chart — part-to-whole as an N×N field of lit dots ("73 of
364
+ 100"). Host marks the lit cells with `is-on`. */
365
+ .ui-waffle {
366
+ display: grid;
367
+ gap: var(--waffle-gap, 0.18em);
368
+ grid-template-columns: repeat(var(--waffle-cols, 10), 1fr);
369
+ inline-size: var(--waffle-size, 7em);
370
+ }
371
+
372
+ .ui-waffle i {
373
+ aspect-ratio: 1;
374
+ background: var(--field-dot);
375
+ border-radius: var(--dotmatrix-dot-radius, 50%);
376
+ }
377
+
378
+ .ui-waffle i.is-on {
379
+ background: var(--field-dot-accent);
380
+ box-shadow: 0 0 var(--dotmatrix-glow, 0) var(--field-dot-accent);
381
+ }
382
+
383
+ /* Activity / contribution grid — density-over-time. A flat list of day cells
384
+ flows down each weekday column via grid-auto-flow; intensity is a 5-step
385
+ ramp on `data-level="0..4"` (the host bins data → level). */
386
+ .ui-activity {
387
+ display: grid;
388
+ gap: var(--activity-gap, 0.18em);
389
+ grid-auto-columns: var(--activity-cell, 0.82em);
390
+ grid-auto-flow: column;
391
+ grid-template-rows: repeat(var(--activity-rows, 7), 1fr);
392
+ }
393
+
394
+ .ui-activity i {
395
+ aspect-ratio: 1;
396
+ background: var(--field-dot);
397
+ border-radius: var(--dotmatrix-dot-radius, 2px);
398
+ }
399
+
400
+ .ui-activity i[data-level='1'] {
401
+ background: color-mix(in oklab, var(--field-dot-accent) 30%, var(--field-dot));
402
+ }
403
+
404
+ .ui-activity i[data-level='2'] {
405
+ background: color-mix(in oklab, var(--field-dot-accent) 55%, var(--field-dot));
406
+ }
407
+
408
+ .ui-activity i[data-level='3'] {
409
+ background: color-mix(in oklab, var(--field-dot-accent) 78%, var(--field-dot));
410
+ }
411
+
412
+ .ui-activity i[data-level='4'] {
413
+ background: var(--field-dot-accent);
414
+ }
415
+
416
+ /* LED level meter — a column of discrete segments lit to a threshold (signal /
417
+ load / VU). Fills from the bottom; host marks lit segments with `is-on`.
418
+ `--warn`/`--danger` re-point the lit colour for the whole meter when the host
419
+ crosses a threshold (the host owns the threshold, not the leaf). */
420
+ .ui-level {
421
+ block-size: var(--level-height, 4em);
422
+ display: flex;
423
+ flex-direction: column-reverse;
424
+ gap: var(--level-gap, 2px);
425
+ inline-size: var(--level-size, 0.7em);
426
+ }
427
+
428
+ .ui-level i {
429
+ background: var(--field-dot);
430
+ border-radius: var(--radius-sm);
431
+ flex: 1;
432
+ }
433
+
434
+ .ui-level i.is-on {
435
+ background: var(--accent);
436
+ box-shadow: 0 0 var(--dotmatrix-glow, 0) var(--accent);
437
+ }
438
+
439
+ .ui-level--warn i.is-on {
440
+ background: var(--warning);
441
+ }
442
+
443
+ .ui-level--danger i.is-on {
444
+ background: var(--danger);
445
+ }
446
+
447
+ /* Dot gauge — a 0..1 reading (`--v`) as a ring of dots filling along an arc.
448
+ A conic-gradient sweep (accent up to --v, dim beyond) intersected with a
449
+ donut-ring × dot-pattern mask, so the lit arc reads as discrete dots. */
450
+ .ui-dotgauge {
451
+ --_v: var(--v, 0);
452
+ --_sweep: var(--gauge-sweep, 270deg);
453
+
454
+ aspect-ratio: 1;
455
+ background: conic-gradient(
456
+ from var(--gauge-from, 135deg),
457
+ var(--field-dot-accent) calc(var(--_v) * var(--_sweep)),
458
+ var(--field-dot) calc(var(--_v) * var(--_sweep)) var(--_sweep),
459
+ transparent var(--_sweep)
460
+ );
461
+ border-radius: 50%;
462
+ inline-size: var(--gauge-size, 5em);
463
+
464
+ /* ring (donut) ∩ dot lattice → a ring of dots */
465
+ /* stylelint-disable property-no-vendor-prefix -- Safari still needs the prefixed mask props. */
466
+ -webkit-mask:
467
+ radial-gradient(closest-side, transparent 58%, #000 59%),
468
+ radial-gradient(circle, #000 34%, transparent 36%) 0 0 / var(--gauge-dot, 0.5em) var(--gauge-dot, 0.5em);
469
+ -webkit-mask-composite: source-in;
470
+ /* stylelint-enable property-no-vendor-prefix */
471
+ mask:
472
+ radial-gradient(closest-side, transparent 58%, #000 59%),
473
+ radial-gradient(circle, #000 34%, transparent 36%) 0 0 / var(--gauge-dot, 0.5em) var(--gauge-dot, 0.5em);
474
+ mask-composite: intersect;
475
+ }
476
+
477
+ /* Readout — a row of dot-matrix glyphs forming a big numeric (renderReadout).
478
+ The glyphs are decorative; the row carries role=img + the value as its name. */
479
+ .ui-readout {
480
+ align-items: flex-end;
481
+ display: inline-flex;
482
+ gap: var(--readout-gap, 0.12em);
483
+ }
484
+
485
+ .ui-readout__spacer {
486
+ display: inline-block;
487
+ inline-size: var(--readout-space, 0.5em);
488
+ }
489
+
490
+ /* Halftone — render host content (an <img> or a box with its own background)
491
+ through a dot lattice so a thumbnail/cover takes on the dot look. A style
492
+ filter, NOT a data viz: the dots are a fixed lattice, not value-modulated. */
493
+ .ui-halftone {
494
+ /* stylelint-disable-next-line property-no-vendor-prefix -- Safari still needs the prefixed mask property. */
495
+ -webkit-mask: radial-gradient(circle, #000 var(--halftone-dot, 38%), transparent calc(var(--halftone-dot, 38%) + 1%)) 0 0 /
496
+ var(--halftone-gap, 0.5em) var(--halftone-gap, 0.5em);
497
+ mask: radial-gradient(circle, #000 var(--halftone-dot, 38%), transparent calc(var(--halftone-dot, 38%) + 1%)) 0 0 /
498
+ var(--halftone-gap, 0.5em) var(--halftone-gap, 0.5em);
499
+ }
500
+
501
+ /* Density wrapper — make any dot surface inside respond to the CARD it sits in,
502
+ not the viewport, so the same component reads well in a wide hero and a
503
+ narrow tile. Opt-in: wrap the surface and the breakpoint below densifies it. */
504
+ .ui-dotfit {
505
+ container: dotfit / inline-size;
506
+ }
507
+
508
+ @container dotfit (width < 18rem) {
509
+ .ui-dotfit .ui-dotgrid {
510
+ --dot-gap: 8px;
511
+ }
512
+
513
+ .ui-dotfit .ui-activity {
514
+ --activity-cell: 0.6em;
515
+ }
516
+
517
+ .ui-dotfit .ui-waffle {
518
+ --waffle-size: 5em;
519
+ }
520
+ }
521
+
351
522
  /* Matrix-reveal wrapper — content wipes in left→right on .is-in. Gate the
352
523
  clipped from-state on `scripting: enabled`: with JS off, `.is-in` is never
353
524
  toggled, so without the gate the content stays permanently clipped away and
@@ -443,16 +614,52 @@
443
614
  forced-color-adjust: none;
444
615
  background: LinkText;
445
616
  }
617
+
618
+ /* The data-bound dot surfaces encode their value via background-color, which
619
+ HCM flattens. Opt out and pin the lit state to a system colour so the
620
+ reading survives. The activity ramp's 5 steps can't all stay distinct under
621
+ HCM — collapse to present (CanvasText) vs absent (the unstyled track). */
622
+ .ui-waffle i.is-on,
623
+ .ui-level i.is-on {
624
+ forced-color-adjust: none;
625
+ background: LinkText;
626
+ }
627
+
628
+ .ui-level--warn i.is-on {
629
+ background: Mark;
630
+ }
631
+
632
+ .ui-level--danger i.is-on {
633
+ background: Highlight;
634
+ }
635
+
636
+ .ui-activity i[data-level='1'],
637
+ .ui-activity i[data-level='2'],
638
+ .ui-activity i[data-level='3'],
639
+ .ui-activity i[data-level='4'] {
640
+ forced-color-adjust: none;
641
+ background: CanvasText;
642
+ }
643
+
644
+ /* The gauge is a masked gradient; keep its paint rather than let HCM drop it. */
645
+ .ui-dotgauge {
646
+ forced-color-adjust: none;
647
+ }
446
648
  }
447
649
 
448
650
  /* Print: the dot surfaces carry data (heatmap cells, the segmented meter, the
449
- status dot, the masked glyph), so their painted fills must survive the print
450
- "economy" default that drops backgrounds. */
651
+ status dot, the masked glyph, the waffle/activity/level/gauge readings), so
652
+ their painted fills must survive the print "economy" default that drops
653
+ backgrounds. */
451
654
  @media print {
452
655
  .ui-dotmatrix__cell,
453
656
  .ui-dotbar i,
454
657
  .ui-dot,
455
- .ui-icon {
658
+ .ui-icon,
659
+ .ui-waffle i,
660
+ .ui-activity i,
661
+ .ui-level i,
662
+ .ui-dotgauge {
456
663
  -webkit-print-color-adjust: exact;
457
664
  print-color-adjust: exact;
458
665
  }
package/css/report.css CHANGED
@@ -12,7 +12,6 @@
12
12
  --report-padding-block: var(--space-2xl);
13
13
  --report-gap: var(--space-lg);
14
14
  --report-measure: 74ch;
15
- --report-page-margin: 18mm;
16
15
 
17
16
  color: var(--text-soft);
18
17
  display: grid;
@@ -31,6 +30,24 @@
31
30
  counter-reset: report-section;
32
31
  }
33
32
 
33
+ .ui-report > *,
34
+ .ui-report__cover > *,
35
+ .ui-report__head > *,
36
+ .ui-report__toc > *,
37
+ .ui-report__summary > *,
38
+ .ui-report__decision > *,
39
+ .ui-report__finding > *,
40
+ .ui-report__evidence > *,
41
+ .ui-report__section > *,
42
+ .ui-report__figure > *,
43
+ .ui-claim > *,
44
+ .ui-evidence-grid > *,
45
+ .ui-evidence-ledger > *,
46
+ .ui-compare > *,
47
+ .ui-compare__col > * {
48
+ min-inline-size: 0;
49
+ }
50
+
34
51
  .ui-report__cover {
35
52
  align-content: end;
36
53
  border-block-end: 1px solid var(--line);
@@ -143,8 +160,204 @@
143
160
  border-inline-start: 2px solid var(--accent);
144
161
  }
145
162
 
163
+ .ui-report__decision {
164
+ background: var(--panel);
165
+ border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--line));
166
+ border-inline-start: 3px solid var(--accent);
167
+ border-radius: var(--radius-md);
168
+ display: grid;
169
+ gap: var(--space-sm);
170
+ padding: var(--space-md);
171
+ }
172
+
173
+ .ui-report__decision-kicker {
174
+ color: var(--accent-text);
175
+ font-family: var(--mono);
176
+ font-size: var(--text-2xs);
177
+ letter-spacing: var(--tracking-wide);
178
+ margin: 0;
179
+ text-transform: uppercase;
180
+ }
181
+
182
+ .ui-report__decision-title {
183
+ color: var(--text);
184
+ font-family: var(--display);
185
+ font-size: var(--text-lg);
186
+ font-weight: var(--display-weight);
187
+ letter-spacing: 0;
188
+ line-height: 1.18;
189
+ margin: 0;
190
+ text-transform: uppercase;
191
+ text-wrap: balance;
192
+ }
193
+
194
+ .ui-report__decision-body {
195
+ color: var(--text-soft);
196
+ line-height: 1.6;
197
+ margin: 0;
198
+ max-inline-size: var(--report-measure);
199
+ }
200
+
201
+ .ui-report__decision-meta {
202
+ color: var(--text-dim);
203
+ display: flex;
204
+ flex-wrap: wrap;
205
+ font-family: var(--mono);
206
+ font-size: var(--text-2xs);
207
+ gap: 0.45rem 0.75rem;
208
+ letter-spacing: 0;
209
+ }
210
+
211
+ .ui-report__decision-grid {
212
+ border-block-start: 1px solid var(--line);
213
+ display: grid;
214
+ gap: 0;
215
+ }
216
+
217
+ .ui-report__decision-item {
218
+ align-items: start;
219
+ border-block-end: 1px solid var(--line);
220
+ display: grid;
221
+ gap: var(--space-xs);
222
+ grid-template-columns: minmax(8rem, 14rem) minmax(0, 1fr);
223
+ padding-block: var(--space-xs);
224
+ }
225
+
226
+ .ui-report__decision-label,
227
+ .ui-report__decision-value {
228
+ margin: 0;
229
+ }
230
+
231
+ .ui-report__decision-label {
232
+ color: var(--text-dim);
233
+ font-family: var(--mono);
234
+ font-size: var(--text-2xs);
235
+ letter-spacing: var(--tracking-wide);
236
+ text-transform: uppercase;
237
+ }
238
+
239
+ .ui-report__decision-value {
240
+ color: var(--text-soft);
241
+ line-height: 1.5;
242
+ }
243
+
146
244
  .ui-report__finding {
147
- border-inline-start: 2px solid var(--line-strong);
245
+ --report-finding-tone: var(--line-strong);
246
+
247
+ border-inline-start: 2px solid var(--report-finding-tone);
248
+ }
249
+
250
+ .ui-report__finding--critical {
251
+ --report-finding-tone: var(--danger);
252
+ }
253
+
254
+ .ui-report__finding--major {
255
+ --report-finding-tone: var(--warning);
256
+ }
257
+
258
+ .ui-report__finding--minor {
259
+ --report-finding-tone: var(--info);
260
+ }
261
+
262
+ .ui-report__finding--resolved {
263
+ --report-finding-tone: var(--success);
264
+ }
265
+
266
+ .ui-report__finding-title,
267
+ .ui-report__finding-claim,
268
+ .ui-report__finding-impact,
269
+ .ui-report__finding-remediation,
270
+ .ui-report__finding-evidence,
271
+ .ui-report__finding-caveat {
272
+ margin: 0;
273
+ }
274
+
275
+ .ui-report__finding-title {
276
+ color: var(--text);
277
+ font-size: var(--text-md);
278
+ font-weight: 650;
279
+ line-height: 1.25;
280
+ }
281
+
282
+ .ui-report__finding-claim {
283
+ color: var(--text);
284
+ line-height: 1.6;
285
+ }
286
+
287
+ .ui-report__finding-impact,
288
+ .ui-report__finding-remediation,
289
+ .ui-report__finding-evidence {
290
+ color: var(--text-soft);
291
+ line-height: 1.55;
292
+ }
293
+
294
+ .ui-report__finding-caveat {
295
+ color: var(--text-dim);
296
+ font-size: var(--text-sm);
297
+ line-height: 1.55;
298
+ }
299
+
300
+ .ui-claim {
301
+ --claim-tone: var(--accent);
302
+
303
+ background: var(--panel-soft);
304
+ border: 1px solid var(--line);
305
+ border-inline-start: 2px solid var(--claim-tone);
306
+ border-radius: var(--radius-md);
307
+ display: grid;
308
+ gap: var(--space-xs);
309
+ padding: var(--space-sm);
310
+ }
311
+
312
+ .ui-claim--supported {
313
+ --claim-tone: var(--success);
314
+ }
315
+
316
+ .ui-claim--partial {
317
+ --claim-tone: var(--warning);
318
+ }
319
+
320
+ .ui-claim--disputed,
321
+ .ui-claim--unsupported {
322
+ --claim-tone: var(--danger);
323
+ }
324
+
325
+ .ui-claim--unknown {
326
+ --claim-tone: var(--info);
327
+ }
328
+
329
+ .ui-claim__statement,
330
+ .ui-claim__status,
331
+ .ui-claim__scope,
332
+ .ui-claim__basis,
333
+ .ui-claim__limits,
334
+ .ui-claim__refs,
335
+ .ui-claim__caveat {
336
+ margin: 0;
337
+ }
338
+
339
+ .ui-claim__statement {
340
+ color: var(--text);
341
+ font-weight: 650;
342
+ line-height: 1.45;
343
+ }
344
+
345
+ .ui-claim__status,
346
+ .ui-claim__scope,
347
+ .ui-claim__refs {
348
+ color: var(--text-dim);
349
+ font-family: var(--mono);
350
+ font-size: var(--text-2xs);
351
+ letter-spacing: 0;
352
+ text-transform: uppercase;
353
+ }
354
+
355
+ .ui-claim__basis,
356
+ .ui-claim__limits,
357
+ .ui-claim__caveat {
358
+ color: var(--text-soft);
359
+ font-size: var(--text-sm);
360
+ line-height: 1.55;
148
361
  }
149
362
 
150
363
  .ui-report__evidence {
@@ -209,6 +422,142 @@
209
422
  text-transform: uppercase;
210
423
  }
211
424
 
425
+ .ui-evidence-grid {
426
+ display: grid;
427
+ gap: var(--space-sm);
428
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
429
+ }
430
+
431
+ .ui-evidence-item {
432
+ background: var(--panel-soft);
433
+ border: 1px solid var(--line);
434
+ border-radius: var(--radius-md);
435
+ display: grid;
436
+ gap: 0.35rem;
437
+ padding: var(--space-sm);
438
+ }
439
+
440
+ .ui-evidence-item__title {
441
+ color: var(--text);
442
+ font-size: var(--text-sm);
443
+ font-weight: 600;
444
+ margin: 0;
445
+ }
446
+
447
+ .ui-evidence-item__meta {
448
+ color: var(--text-dim);
449
+ font-family: var(--mono);
450
+ font-size: var(--text-2xs);
451
+ letter-spacing: 0;
452
+ }
453
+
454
+ .ui-evidence-item__body {
455
+ color: var(--text-soft);
456
+ font-size: var(--text-sm);
457
+ line-height: 1.55;
458
+ margin: 0;
459
+ }
460
+
461
+ .ui-evidence-item__kind,
462
+ .ui-evidence-item__method,
463
+ .ui-evidence-item__window,
464
+ .ui-evidence-item__value,
465
+ .ui-evidence-item__source,
466
+ .ui-evidence-item__caveat {
467
+ margin: 0;
468
+ }
469
+
470
+ .ui-evidence-item__kind,
471
+ .ui-evidence-item__method,
472
+ .ui-evidence-item__window,
473
+ .ui-evidence-item__source {
474
+ color: var(--text-dim);
475
+ font-family: var(--mono);
476
+ font-size: var(--text-2xs);
477
+ letter-spacing: 0;
478
+ text-transform: uppercase;
479
+ }
480
+
481
+ .ui-evidence-item__value {
482
+ color: var(--text);
483
+ font-size: var(--text-md);
484
+ font-weight: 650;
485
+ }
486
+
487
+ .ui-evidence-item__caveat {
488
+ color: var(--text-dim);
489
+ font-size: var(--text-sm);
490
+ line-height: 1.5;
491
+ }
492
+
493
+ .ui-evidence-ledger {
494
+ display: grid;
495
+ gap: var(--space-sm);
496
+ }
497
+
498
+ .ui-report__actions {
499
+ border-block-start: 1px solid var(--line);
500
+ display: grid;
501
+ gap: 0;
502
+ }
503
+
504
+ .ui-report__action {
505
+ align-items: start;
506
+ border-block-end: 1px solid var(--line);
507
+ display: grid;
508
+ gap: var(--space-xs);
509
+ grid-template-columns: minmax(0, 1fr) auto;
510
+ padding-block: var(--space-sm);
511
+ }
512
+
513
+ .ui-report__action-status {
514
+ align-self: start;
515
+ color: var(--text-dim);
516
+ font-family: var(--mono);
517
+ font-size: var(--text-2xs);
518
+ letter-spacing: var(--tracking-wide);
519
+ text-transform: uppercase;
520
+ }
521
+
522
+ .ui-report__action-title,
523
+ .ui-report__action-owner,
524
+ .ui-report__action-due,
525
+ .ui-report__action-priority,
526
+ .ui-report__action-criteria,
527
+ .ui-report__action-source {
528
+ margin: 0;
529
+ }
530
+
531
+ .ui-report__action-title {
532
+ color: var(--text);
533
+ font-weight: 650;
534
+ line-height: 1.45;
535
+ }
536
+
537
+ .ui-report__action-owner,
538
+ .ui-report__action-due,
539
+ .ui-report__action-priority,
540
+ .ui-report__action-source {
541
+ color: var(--text-dim);
542
+ font-family: var(--mono);
543
+ font-size: var(--text-2xs);
544
+ letter-spacing: 0;
545
+ text-transform: uppercase;
546
+ }
547
+
548
+ .ui-report__action-criteria {
549
+ color: var(--text-soft);
550
+ font-size: var(--text-sm);
551
+ line-height: 1.5;
552
+ }
553
+
554
+ @media (max-width: 32rem) {
555
+ .ui-report__decision-item,
556
+ .ui-report__action {
557
+ grid-template-columns: 1fr;
558
+ }
559
+ }
560
+
212
561
  .ui-report__sources,
213
562
  .ui-report__appendix,
214
563
  .ui-report__footnotes {
@@ -312,10 +661,10 @@
312
661
  }
313
662
 
314
663
  @media print {
315
- /* Re-tokenises the base 18mm default (base.css) so report margins stay
316
- themeable via --report-page-margin. */
664
+ /* Chromium-class print engines do not reliably resolve custom properties in
665
+ @page rules. Keep this literal so reports cannot print edge-to-edge. */
317
666
  @page {
318
- margin: var(--report-page-margin);
667
+ margin: 18mm;
319
668
  }
320
669
 
321
670
  .ui-report {
@@ -346,11 +695,14 @@
346
695
 
347
696
  .ui-report__cover,
348
697
  .ui-report__head,
349
- .ui-report__section,
698
+ .ui-report__decision,
350
699
  .ui-report__summary,
351
700
  .ui-report__finding,
352
701
  .ui-report__evidence,
353
- .ui-report__figure {
702
+ .ui-report__figure,
703
+ .ui-claim,
704
+ .ui-evidence-item,
705
+ .ui-report__action {
354
706
  break-inside: avoid;
355
707
  }
356
708
 
package/css/skins.css CHANGED
@@ -11,44 +11,53 @@
11
11
  /* Amber CRT */
12
12
  :root[data-bronto-skin='amber-crt'] {
13
13
  --accent: oklch(52% 0.11 67deg);
14
+ --dotmatrix-pulse-min: 0.35;
14
15
  }
15
16
 
16
17
  :root[data-theme='dark'][data-bronto-skin='amber-crt'] {
17
18
  --accent: oklch(82% 0.15 82deg);
18
19
  --dotmatrix-glow: 0.4em;
20
+ --dotmatrix-pulse-min: 0.3;
19
21
  }
20
22
 
21
23
  /* E-ink */
22
24
  :root[data-bronto-skin='e-ink'] {
23
25
  --accent: oklch(34% 0.012 250deg);
26
+ --dotmatrix-reveal-step: 0ms;
24
27
  }
25
28
 
26
29
  :root[data-theme='dark'][data-bronto-skin='e-ink'] {
27
30
  --accent: oklch(84% 0.008 250deg);
31
+ --dotmatrix-reveal-step: 0ms;
28
32
  }
29
33
 
30
34
  /* Phosphor Green */
31
35
  :root[data-bronto-skin='phosphor-green'] {
32
36
  --accent: oklch(52% 0.13 150deg);
37
+ --dotmatrix-pulse-min: 0.35;
33
38
  }
34
39
 
35
40
  :root[data-theme='dark'][data-bronto-skin='phosphor-green'] {
36
41
  --accent: oklch(84% 0.19 150deg);
37
42
  --dotmatrix-glow: 0.4em;
43
+ --dotmatrix-pulse-min: 0.3;
38
44
  }
39
45
 
40
46
  @media (prefers-color-scheme: dark) {
41
47
  :root:not([data-theme='light'])[data-bronto-skin='amber-crt'] {
42
48
  --accent: oklch(82% 0.15 82deg);
43
49
  --dotmatrix-glow: 0.4em;
50
+ --dotmatrix-pulse-min: 0.3;
44
51
  }
45
52
 
46
53
  :root:not([data-theme='light'])[data-bronto-skin='e-ink'] {
47
54
  --accent: oklch(84% 0.008 250deg);
55
+ --dotmatrix-reveal-step: 0ms;
48
56
  }
49
57
 
50
58
  :root:not([data-theme='light'])[data-bronto-skin='phosphor-green'] {
51
59
  --accent: oklch(84% 0.19 150deg);
52
60
  --dotmatrix-glow: 0.4em;
61
+ --dotmatrix-pulse-min: 0.3;
53
62
  }
54
63
  }