@ponchia/ui 0.6.0 → 0.6.4

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 (162) hide show
  1. package/CHANGELOG.md +82 -4
  2. package/README.md +1 -1
  3. package/annotations/index.d.ts.map +1 -1
  4. package/annotations/index.js +36 -33
  5. package/behaviors/carousel.d.ts +28 -0
  6. package/behaviors/carousel.d.ts.map +1 -0
  7. package/behaviors/carousel.js +3 -0
  8. package/behaviors/combobox.d.ts +40 -0
  9. package/behaviors/combobox.d.ts.map +1 -0
  10. package/behaviors/combobox.js +71 -20
  11. package/behaviors/command.d.ts +41 -0
  12. package/behaviors/command.d.ts.map +1 -0
  13. package/behaviors/command.js +9 -0
  14. package/behaviors/connectors.d.ts +17 -0
  15. package/behaviors/connectors.d.ts.map +1 -0
  16. package/behaviors/connectors.js +3 -0
  17. package/behaviors/crosshair.d.ts +42 -0
  18. package/behaviors/crosshair.d.ts.map +1 -0
  19. package/behaviors/crosshair.js +19 -1
  20. package/behaviors/dialog.d.ts +20 -0
  21. package/behaviors/dialog.d.ts.map +1 -0
  22. package/behaviors/dialog.js +3 -0
  23. package/behaviors/disclosure.d.ts +10 -0
  24. package/behaviors/disclosure.d.ts.map +1 -0
  25. package/behaviors/disclosure.js +3 -0
  26. package/behaviors/dismissible.d.ts +10 -0
  27. package/behaviors/dismissible.d.ts.map +1 -0
  28. package/behaviors/dismissible.js +3 -0
  29. package/behaviors/forms.d.ts +27 -0
  30. package/behaviors/forms.d.ts.map +1 -0
  31. package/behaviors/forms.js +18 -5
  32. package/behaviors/glyph.d.ts +21 -0
  33. package/behaviors/glyph.d.ts.map +1 -0
  34. package/behaviors/glyph.js +82 -4
  35. package/behaviors/index.d.ts +31 -237
  36. package/behaviors/index.d.ts.map +1 -0
  37. package/behaviors/index.js +17 -0
  38. package/behaviors/inert.d.ts +20 -0
  39. package/behaviors/inert.d.ts.map +1 -0
  40. package/behaviors/inert.js +46 -0
  41. package/behaviors/internal.d.ts +25 -0
  42. package/behaviors/internal.d.ts.map +1 -0
  43. package/behaviors/internal.js +30 -1
  44. package/behaviors/legend.d.ts +35 -0
  45. package/behaviors/legend.d.ts.map +1 -0
  46. package/behaviors/legend.js +9 -0
  47. package/behaviors/menu.d.ts +16 -0
  48. package/behaviors/menu.d.ts.map +1 -0
  49. package/behaviors/menu.js +3 -0
  50. package/behaviors/modal.d.ts +41 -0
  51. package/behaviors/modal.d.ts.map +1 -0
  52. package/behaviors/modal.js +124 -0
  53. package/behaviors/popover.d.ts +28 -0
  54. package/behaviors/popover.d.ts.map +1 -0
  55. package/behaviors/popover.js +17 -17
  56. package/behaviors/spotlight.d.ts +17 -0
  57. package/behaviors/spotlight.d.ts.map +1 -0
  58. package/behaviors/spotlight.js +3 -0
  59. package/behaviors/table.d.ts +36 -0
  60. package/behaviors/table.d.ts.map +1 -0
  61. package/behaviors/table.js +48 -8
  62. package/behaviors/tabs.d.ts +20 -0
  63. package/behaviors/tabs.d.ts.map +1 -0
  64. package/behaviors/tabs.js +3 -0
  65. package/behaviors/theme.d.ts +54 -0
  66. package/behaviors/theme.d.ts.map +1 -0
  67. package/behaviors/theme.js +17 -0
  68. package/behaviors/toast.d.ts +49 -0
  69. package/behaviors/toast.d.ts.map +1 -0
  70. package/behaviors/toast.js +34 -2
  71. package/classes/classes.json +747 -15
  72. package/classes/index.d.ts +118 -3
  73. package/classes/index.js +264 -66
  74. package/connectors/index.d.ts +12 -0
  75. package/connectors/index.d.ts.map +1 -1
  76. package/connectors/index.js +23 -2
  77. package/css/app.css +26 -0
  78. package/css/bullet.css +108 -0
  79. package/css/code.css +98 -0
  80. package/css/content.css +15 -2
  81. package/css/crosshair.css +7 -7
  82. package/css/diff.css +153 -0
  83. package/css/disclosure.css +18 -4
  84. package/css/dots.css +246 -9
  85. package/css/feedback.css +39 -7
  86. package/css/forms.css +71 -3
  87. package/css/legend.css +5 -2
  88. package/css/motion.css +79 -14
  89. package/css/overlay.css +59 -2
  90. package/css/primitives.css +67 -8
  91. package/css/report.css +43 -4
  92. package/css/sidenote.css +67 -0
  93. package/css/skins.css +9 -0
  94. package/css/spark.css +76 -0
  95. package/css/table.css +16 -3
  96. package/css/term.css +110 -0
  97. package/css/textref.css +63 -0
  98. package/css/toc.css +91 -0
  99. package/css/tokens.css +14 -1
  100. package/css/tree.css +134 -0
  101. package/dist/bronto.css +1 -1
  102. package/dist/css/analytical.css +1 -1
  103. package/dist/css/app.css +1 -1
  104. package/dist/css/bullet.css +1 -0
  105. package/dist/css/code.css +1 -0
  106. package/dist/css/content.css +1 -1
  107. package/dist/css/crosshair.css +1 -1
  108. package/dist/css/diff.css +1 -0
  109. package/dist/css/disclosure.css +1 -1
  110. package/dist/css/dots.css +1 -1
  111. package/dist/css/feedback.css +1 -1
  112. package/dist/css/forms.css +1 -1
  113. package/dist/css/legend.css +1 -1
  114. package/dist/css/motion.css +1 -1
  115. package/dist/css/overlay.css +1 -1
  116. package/dist/css/primitives.css +1 -1
  117. package/dist/css/report.css +1 -1
  118. package/dist/css/sidenote.css +1 -0
  119. package/dist/css/skins.css +1 -1
  120. package/dist/css/spark.css +1 -0
  121. package/dist/css/table.css +1 -1
  122. package/dist/css/term.css +1 -0
  123. package/dist/css/textref.css +1 -0
  124. package/dist/css/toc.css +1 -0
  125. package/dist/css/tokens.css +1 -1
  126. package/dist/css/tree.css +1 -0
  127. package/docs/annotations.md +39 -0
  128. package/docs/architecture.md +2 -3
  129. package/docs/bullet.md +78 -0
  130. package/docs/code.md +76 -0
  131. package/docs/d2.md +4 -3
  132. package/docs/diff.md +146 -0
  133. package/docs/dots.md +146 -0
  134. package/docs/glyphs.md +114 -0
  135. package/docs/legends.md +8 -4
  136. package/docs/mermaid.md +21 -4
  137. package/docs/reference.md +168 -8
  138. package/docs/reporting.md +49 -17
  139. package/docs/sidenote.md +64 -0
  140. package/docs/spark.md +78 -0
  141. package/docs/stability.md +1 -0
  142. package/docs/term.md +81 -0
  143. package/docs/textref.md +78 -0
  144. package/docs/theming.md +44 -5
  145. package/docs/toc.md +83 -0
  146. package/docs/tree.md +74 -0
  147. package/docs/usage.md +264 -23
  148. package/docs/vega.md +22 -3
  149. package/glyphs/glyphs.d.ts +61 -0
  150. package/glyphs/glyphs.js +600 -31
  151. package/llms.txt +169 -15
  152. package/package.json +51 -7
  153. package/qwik/index.d.ts +4 -2
  154. package/qwik/index.d.ts.map +1 -1
  155. package/qwik/index.js +10 -0
  156. package/react/index.d.ts +4 -2
  157. package/react/index.d.ts.map +1 -1
  158. package/react/index.js +6 -0
  159. package/solid/index.d.ts +6 -2
  160. package/solid/index.d.ts.map +1 -1
  161. package/solid/index.js +6 -0
  162. package/tokens/skins.js +22 -9
package/css/app.css CHANGED
@@ -118,6 +118,25 @@
118
118
  opacity: 1;
119
119
  }
120
120
 
121
+ /* Forced colours flatten var(--accent) (border + bg + text) to a single system
122
+ colour, so the active link collapses into its inactive siblings — only a
123
+ near-imperceptible tint/dot opacity delta survives, and current-page becomes
124
+ invisible to HCM users. Re-assert "current" on channels HCM preserves: a
125
+ Highlight start-border and marker dot, plus a NON-colour bold weight so the
126
+ cue does not rely on colour alone (WCAG 1.4.1). (component audit C8.) */
127
+ @media (forced-colors: active) {
128
+ .ui-app-nav a.is-active,
129
+ .ui-app-nav a[aria-current]:not([aria-current='false']) {
130
+ border-inline-start-color: Highlight;
131
+ font-weight: 700;
132
+ }
133
+
134
+ .ui-app-nav a.is-active::before,
135
+ .ui-app-nav a[aria-current]:not([aria-current='false'])::before {
136
+ background: Highlight;
137
+ }
138
+ }
139
+
121
140
  .ui-app-rail__foot {
122
141
  border-block-start: 1px solid var(--line);
123
142
  color: var(--text-dim);
@@ -253,6 +272,13 @@
253
272
  @media (max-width: 880px) {
254
273
  .ui-app-shell {
255
274
  grid-template-columns: minmax(0, 1fr);
275
+
276
+ /* The shell keeps `min-block-size: 100dvh`, so with two auto rows the default
277
+ `align-content: stretch` distributes the leftover viewport across BOTH
278
+ tracks — ballooning the horizontal rail to ~half the screen. Pin tracks to
279
+ their content and let the content row absorb the slack. (component audit C7.) */
280
+ align-content: start;
281
+ grid-template-rows: auto 1fr;
256
282
  }
257
283
 
258
284
  .ui-app-rail {
package/css/bullet.css ADDED
@@ -0,0 +1,108 @@
1
+ /* ==========================================================================
2
+ bullet — opt-in Stephen-Few bullet graph (measure vs target vs bands).
3
+
4
+ The canonical "is this measure inside its qualitative budget, and how does it
5
+ compare to target?" figure: a thin measure bar over 2–3 grayscale qualitative
6
+ range bands, with a perpendicular target tick. The SLO / error-budget figure
7
+ `ui-meter` (report.css) structurally cannot encode — a meter is a single
8
+ label|bar|value reading, a bullet carries bands + target too. Few designed it
9
+ grayscale on purpose, which is exactly the Nothing palette. Pure CSS,
10
+ SSR-static, print-survivable. Not imported by core.css.
11
+
12
+ Boundary: the HOST normalises EVERY value to 0..1 and sets custom props —
13
+ `--v` (measure), `--t` (target), `--b1`/`--b2` (the band boundaries). Bronto
14
+ only paints geometry; it refuses raw values and min/max/scale computation —
15
+ the same contract as `ui-spark`. A bare bullet is opaque to assistive tech, so
16
+ `.ui-bullet` MUST carry a host-written `role="img"` + `aria-label` text
17
+ equivalent (e.g. "uptime 99.62%, inside target 99.9%, in the warning band").
18
+ Colour is never the only channel — the reading lives in that label.
19
+ ========================================================================== */
20
+
21
+ .ui-bullet {
22
+ --band-lo: 0.5;
23
+ --band-hi: 0.8;
24
+
25
+ background: linear-gradient(
26
+ to right,
27
+ var(--surface-4) 0 calc(var(--band-lo) * 100%),
28
+ var(--surface-3) calc(var(--band-lo) * 100%) calc(var(--band-hi) * 100%),
29
+ var(--surface-2) calc(var(--band-hi) * 100%) 100%
30
+ );
31
+ block-size: 1.25rem;
32
+ border-radius: var(--radius-sm);
33
+ inline-size: 100%;
34
+ position: relative;
35
+ }
36
+
37
+ /* The measure bar — a thinner dark bar centred in the track, the primary value.
38
+ `--v` is the normalised reading; with none it collapses to a hairline. */
39
+ .ui-bullet__measure {
40
+ background: var(--text);
41
+ border-radius: var(--radius-sm);
42
+ inline-size: max(2px, calc(var(--v, 0) * 100%));
43
+ inset-block: 30%;
44
+ inset-inline-start: 0;
45
+ position: absolute;
46
+ }
47
+
48
+ /* Tone a measure for emphasis or status — the meaning still has to be in the
49
+ aria-label (WCAG 1.4.1), tone is decoration. */
50
+ .ui-bullet__measure--accent {
51
+ background: var(--accent);
52
+ }
53
+
54
+ .ui-bullet__measure--pos {
55
+ background: var(--success);
56
+ }
57
+
58
+ .ui-bullet__measure--neg {
59
+ background: var(--danger);
60
+ }
61
+
62
+ /* The target tick — a full-height perpendicular mark at `--t`. Shape, not
63
+ colour, distinguishes it from the measure bar (Few's grayscale rule). */
64
+ .ui-bullet__target {
65
+ background: var(--text);
66
+ inline-size: 2px;
67
+ inset-block: 8%;
68
+ inset-inline-start: calc(var(--t, 0) * 100%);
69
+ position: absolute;
70
+ transform: translateX(-50%);
71
+ }
72
+
73
+ /* Optional caption row beneath the track — label + reading in mono, matching
74
+ the report meter's value treatment. */
75
+ .ui-bullet__label {
76
+ color: var(--text-dim);
77
+ display: flex;
78
+ font-family: var(--mono);
79
+ font-size: var(--text-2xs);
80
+ gap: var(--space-sm);
81
+ justify-content: space-between;
82
+ letter-spacing: var(--tracking-wide);
83
+ margin-block-start: 0.3rem;
84
+ }
85
+
86
+ /* Forced colours flatten the band gradient to one system surface — the bands
87
+ would merge. Re-assert a track border so the figure keeps a frame, and repaint
88
+ the marks in the system text colour so measure + target survive (the band
89
+ distinction is carried by the required aria-label). */
90
+ @media (forced-colors: active) {
91
+ .ui-bullet {
92
+ border: 1px solid CanvasText;
93
+ }
94
+
95
+ .ui-bullet__measure,
96
+ .ui-bullet__target {
97
+ background: CanvasText;
98
+ }
99
+ }
100
+
101
+ /* Print: the bands + marks are background/currentColor fills the print economy
102
+ would drop. */
103
+ @media print {
104
+ .ui-bullet {
105
+ -webkit-print-color-adjust: exact;
106
+ print-color-adjust: exact;
107
+ }
108
+ }
package/css/code.css ADDED
@@ -0,0 +1,98 @@
1
+ /* ==========================================================================
2
+ code — opt-in fenced-code evidence chrome.
3
+
4
+ Paints already-tokenized code: a head bar, an optional line-number gutter
5
+ (CSS counters), and add / del / highlight line states. It NEVER parses or
6
+ tokenizes — the host (or Shiki, via the shipped `shiki/nothing.json` token
7
+ theme) supplies the coloured spans; Bronto owns only the chrome. Code-as-
8
+ evidence for changelogs, version history, and generated reports; pairs with
9
+ the `.ui-src` provenance pill and marks. Not imported by core.css.
10
+
11
+ Long lines wrap (no horizontal scroll) so the surface prints cleanly. Put a
12
+ `.ui-code__line` around each line to opt into numbering / line states; plain
13
+ text inside `.ui-code__body` works too (no numbers).
14
+ ========================================================================== */
15
+
16
+ .ui-code {
17
+ border: 1px solid var(--line);
18
+ border-radius: var(--radius-sm);
19
+ font-family: var(--mono);
20
+ font-size: var(--text-xs);
21
+ overflow: hidden;
22
+ }
23
+
24
+ .ui-code__head {
25
+ background: var(--surface-2);
26
+ border-block-end: 1px solid var(--line);
27
+ color: var(--text-dim);
28
+ display: flex;
29
+ gap: var(--space-sm);
30
+ justify-content: space-between;
31
+ padding: var(--space-2xs) var(--space-sm);
32
+ }
33
+
34
+ .ui-code__body {
35
+ counter-reset: ui-code-ln;
36
+ margin: 0;
37
+ overflow-wrap: anywhere;
38
+ padding: var(--space-sm) 0;
39
+ white-space: pre-wrap;
40
+ }
41
+
42
+ .ui-code__line {
43
+ display: block;
44
+ padding-inline: var(--space-sm);
45
+ }
46
+
47
+ /* Opt-in line-number gutter — counts each `.ui-code__line`. */
48
+ .ui-code--numbered .ui-code__line {
49
+ padding-inline-start: 0;
50
+ }
51
+
52
+ .ui-code--numbered .ui-code__line::before {
53
+ color: var(--text-dim);
54
+ content: counter(ui-code-ln);
55
+ counter-increment: ui-code-ln;
56
+ display: inline-block;
57
+ inline-size: 3ch;
58
+ margin-inline-end: var(--space-sm);
59
+ text-align: end;
60
+ /* stylelint-disable-next-line property-no-vendor-prefix -- WebKit still requires the prefixed slot for this selection opt-out. */
61
+ -webkit-user-select: none;
62
+ user-select: none;
63
+ }
64
+
65
+ /* Line states — the host classifies; Bronto tints. Kept as a faint wash so the
66
+ token colours stay legible on top. */
67
+ .ui-code__line--add {
68
+ background: color-mix(in srgb, var(--success) 14%, transparent);
69
+ }
70
+
71
+ .ui-code__line--remove {
72
+ background: color-mix(in srgb, var(--danger) 14%, transparent);
73
+ }
74
+
75
+ .ui-code__line--hl {
76
+ background: color-mix(in srgb, var(--accent) 14%, transparent);
77
+ }
78
+
79
+ /* Forced colours drop the tint — add an inline-start border so the line state
80
+ still reads without colour. */
81
+ @media (forced-colors: active) {
82
+ .ui-code__line--add,
83
+ .ui-code__line--remove,
84
+ .ui-code__line--hl {
85
+ border-inline-start: 3px solid currentColor;
86
+ }
87
+ }
88
+
89
+ /* Print: the line-state tints are meaning-carrying backgrounds. */
90
+ @media print {
91
+ .ui-code__head,
92
+ .ui-code__line--add,
93
+ .ui-code__line--remove,
94
+ .ui-code__line--hl {
95
+ -webkit-print-color-adjust: exact;
96
+ print-color-adjust: exact;
97
+ }
98
+ }
package/css/content.css CHANGED
@@ -104,7 +104,12 @@
104
104
  color: var(--text);
105
105
  }
106
106
 
107
- .ui-prose mark {
107
+ /* The bare prose `<mark>` is the plain UA-reset highlight. A `<mark class="ui-mark">`
108
+ is the opt-in marks leaf (marks.css) and must win: this rule is higher-specificity
109
+ (0,1,1) than `.ui-mark` (0,1,0) and sits in the same `bronto` layer, so without the
110
+ `:not(.ui-mark)` it silently overrides every `.ui-mark` tone/draw modifier in prose —
111
+ the most-documented mark usage. (component audit C1.) */
112
+ .ui-prose mark:not(.ui-mark) {
108
113
  background: var(--accent-soft);
109
114
  color: var(--text);
110
115
  padding: 0.02em 0.22em;
@@ -242,7 +247,15 @@
242
247
  text-transform: uppercase;
243
248
  }
244
249
 
245
- /* --- Table — raw Markdown tables look like ui-table --- */
250
+ /* --- Table — raw Markdown tables look like ui-table ---
251
+ `display: block` makes a wide markdown table scroll horizontally (markdown
252
+ emits a bare <table> with no wrappable container, so the scroll has to live on
253
+ the element itself). Caveat: `display: block` can drop the implicit `table`
254
+ ARIA role in WebKit/Safari (intact in Chromium/Firefox). It is acceptable here
255
+ because `.ui-prose` is generated prose, not a data grid — but for a table whose
256
+ semantics MUST survive on WebKit, author the `.ui-table` component inside a
257
+ `.ui-table-wrap` instead (the wrap scrolls, the <table> keeps `display: table`),
258
+ or add `role="table"` to the markdown output. (component audit C29.) */
246
259
 
247
260
  .ui-prose table {
248
261
  border: 1px solid var(--line);
package/css/crosshair.css CHANGED
@@ -40,18 +40,19 @@
40
40
  position: absolute;
41
41
  }
42
42
 
43
+ /* Positioned with logical insets, not a physical translateX/Y: --crosshair-x
44
+ is the offset from the inline-start edge (initCrosshair flips it in RTL), so
45
+ the vertical rule tracks the pointer correctly in both directions. */
43
46
  .ui-crosshair__line--x {
44
47
  inline-size: 1px;
45
48
  inset-block: 0;
46
- inset-inline-start: 0;
47
- transform: translateX(var(--crosshair-x));
49
+ inset-inline-start: var(--crosshair-x);
48
50
  }
49
51
 
50
52
  .ui-crosshair__line--y {
51
53
  block-size: 1px;
52
- inset-block-start: 0;
54
+ inset-block-start: var(--crosshair-y);
53
55
  inset-inline: 0;
54
- transform: translateY(var(--crosshair-y));
55
56
  }
56
57
 
57
58
  /* An axis value chip (host sets its text + which edge it sits on). On the
@@ -84,13 +85,12 @@
84
85
  color: var(--text);
85
86
  font-family: var(--mono);
86
87
  font-size: var(--text-xs);
87
- inset-block-start: 0;
88
- inset-inline-start: 0;
88
+ inset-block-start: var(--crosshair-y);
89
+ inset-inline-start: var(--crosshair-x);
89
90
  padding-block: 0.2rem;
90
91
  padding-inline: 0.4rem;
91
92
  pointer-events: none;
92
93
  position: absolute;
93
- transform: translate(var(--crosshair-x), var(--crosshair-y));
94
94
  }
95
95
 
96
96
  @media (forced-colors: active) {
package/css/diff.css ADDED
@@ -0,0 +1,153 @@
1
+ /* ==========================================================================
2
+ diff — opt-in line/row change-review grammar.
3
+
4
+ The review counterpart to the report layer: marks call out a sentence, diff
5
+ calls out what CHANGED. A CSS-grid gutter grammar for added / removed /
6
+ context rows with a redundant +/− sign glyph (so the meaning survives forced
7
+ colours and print, where the tint is dropped), tone tints, and tabular
8
+ line-number gutters. Not imported by core.css.
9
+
10
+ Boundary: the HOST supplies pre-classified rows — it owns tokenizing, hunk
11
+ computation, and row alignment; Bronto only paints. The moment this parsed or
12
+ aligned source it would cross the line that deleted the bar renderer in
13
+ 0.6.0. Pairs with `.ui-compare--2up` and the `.ui-src` provenance pill.
14
+
15
+ Unified (default): rows are direct children of `.ui-diff` (or a
16
+ `.ui-diff__hunk` rowgroup); columns are [old-ln] [new-ln] [code].
17
+ Split: `.ui-diff--split` holds two `.ui-diff__pane` columns, each [ln] [code];
18
+ the host emits the matching rows per side.
19
+
20
+ Long lines wrap (no horizontal scroll) so the surface prints cleanly; line
21
+ numbers pin to the top of a wrapped line. Line numbers are `user-select:none`
22
+ and should be `aria-hidden` in markup — the `__code` carries the content.
23
+ ========================================================================== */
24
+
25
+ .ui-diff {
26
+ --diff-add-bg: color-mix(in srgb, var(--success) 14%, transparent);
27
+ --diff-remove-bg: color-mix(in srgb, var(--danger) 14%, transparent);
28
+ --diff-add-ink: var(--success);
29
+ --diff-remove-ink: var(--danger);
30
+
31
+ border: 1px solid var(--line);
32
+ border-radius: var(--radius-sm);
33
+ display: grid;
34
+ font-family: var(--mono);
35
+ font-size: var(--text-xs);
36
+ grid-template-columns: auto auto minmax(0, 1fr);
37
+ line-height: 1.6;
38
+ overflow: hidden;
39
+ }
40
+
41
+ /* Split view: two independent panes side by side. Each pane is its own
42
+ [ln] [code] grid; the host aligns rows across panes (its job). */
43
+ .ui-diff--split {
44
+ grid-template-columns: 1fr 1fr;
45
+ }
46
+
47
+ .ui-diff__pane {
48
+ display: grid;
49
+ grid-template-columns: auto minmax(0, 1fr);
50
+ min-inline-size: 0;
51
+ }
52
+
53
+ .ui-diff--split > .ui-diff__pane + .ui-diff__pane {
54
+ border-inline-start: 1px solid var(--line);
55
+ }
56
+
57
+ /* A hunk groups rows under an optional header without breaking the grid:
58
+ display:contents keeps its rows as the grid's own items. */
59
+ .ui-diff__hunk {
60
+ display: contents;
61
+ }
62
+
63
+ /* Rows are layout-transparent — their cells are the real grid items, so the
64
+ tone tint paints on the cells (a display:contents row generates no box, and
65
+ the custom properties still inherit down the DOM to the cells). */
66
+ .ui-diff__row {
67
+ display: contents;
68
+ }
69
+
70
+ /* The hunk / file header spans every column. */
71
+ .ui-diff__head {
72
+ background: var(--surface-2);
73
+ color: var(--text-dim);
74
+ grid-column: 1 / -1;
75
+ padding: var(--space-2xs) var(--space-sm);
76
+ }
77
+
78
+ .ui-diff__ln {
79
+ align-self: start;
80
+ color: var(--text-dim);
81
+ font-variant-numeric: tabular-nums;
82
+ padding: 0 var(--space-sm);
83
+ text-align: end;
84
+ /* stylelint-disable-next-line property-no-vendor-prefix -- WebKit still requires the prefixed slot for this selection opt-out. */
85
+ -webkit-user-select: none;
86
+ user-select: none;
87
+ }
88
+
89
+ .ui-diff__code {
90
+ overflow-wrap: anywhere;
91
+ padding: 0 var(--space-sm);
92
+ white-space: pre-wrap;
93
+ }
94
+
95
+ /* The redundant sign glyph in the code gutter — a non-colour channel, so add /
96
+ remove still read once the tint is dropped (forced colours, print economy).
97
+ Context defaults to a non-breaking space so the code column stays aligned. */
98
+ .ui-diff__code::before {
99
+ color: var(--diff-tint, var(--text-dim));
100
+ content: var(--diff-sign, '\00a0');
101
+ display: inline-block;
102
+ inline-size: 1ch;
103
+ margin-inline-end: var(--space-2xs);
104
+ /* stylelint-disable-next-line property-no-vendor-prefix -- WebKit still requires the prefixed slot for this selection opt-out. */
105
+ -webkit-user-select: none;
106
+ user-select: none;
107
+ }
108
+
109
+ .ui-diff__row--add {
110
+ --diff-sign: '+';
111
+ --diff-tint: var(--diff-add-ink);
112
+ }
113
+
114
+ .ui-diff__row--remove {
115
+ --diff-sign: '\2212'; /* − U+2212 minus sign (decorative; not copied) */
116
+ --diff-tint: var(--diff-remove-ink);
117
+ }
118
+
119
+ .ui-diff__row--context {
120
+ --diff-sign: '\00a0';
121
+ }
122
+
123
+ .ui-diff__row--add > .ui-diff__ln,
124
+ .ui-diff__row--add > .ui-diff__code {
125
+ background: var(--diff-add-bg);
126
+ }
127
+
128
+ .ui-diff__row--remove > .ui-diff__ln,
129
+ .ui-diff__row--remove > .ui-diff__code {
130
+ background: var(--diff-remove-bg);
131
+ }
132
+
133
+ /* Forced colours drop the tint — the +/− glyph already carries the channel; add
134
+ an inline-start border on the changed code cell as a second, colour-free cue. */
135
+ @media (forced-colors: active) {
136
+ .ui-diff__row--add > .ui-diff__code,
137
+ .ui-diff__row--remove > .ui-diff__code {
138
+ border-inline-start: 2px solid currentColor;
139
+ }
140
+ }
141
+
142
+ /* Print: the tints are meaning-carrying backgrounds, so force them through the
143
+ print "economy" default that would otherwise drop them. */
144
+ @media print {
145
+ .ui-diff__head,
146
+ .ui-diff__row--add > .ui-diff__ln,
147
+ .ui-diff__row--add > .ui-diff__code,
148
+ .ui-diff__row--remove > .ui-diff__ln,
149
+ .ui-diff__row--remove > .ui-diff__code {
150
+ -webkit-print-color-adjust: exact;
151
+ print-color-adjust: exact;
152
+ }
153
+ }
@@ -303,14 +303,23 @@
303
303
  color var(--duration-fast) var(--ease-standard);
304
304
  }
305
305
 
306
- .ui-pagination__item.is-active {
306
+ /* Active page keys on BOTH `.is-active` and `[aria-current]` — usage.md calls
307
+ aria-current "the framework rule", and every nav sibling (breadcrumb, sitenav,
308
+ app-nav) highlights on it, so a pagination author who sets only aria-current
309
+ must still get the highlight. (component audit C17.) */
310
+ .ui-pagination__item.is-active,
311
+ .ui-pagination__item[aria-current]:not([aria-current='false']) {
307
312
  border-color: var(--accent);
308
313
  color: var(--accent-text);
309
314
  }
310
315
 
311
316
  /* Disabled covers BOTH the native `<button disabled>` the demo ships and the
312
- `aria-disabled="true"` ARIA path; `pointer-events: none` makes the
313
- aria-disabled item genuinely inert (it was clickable before C5). */
317
+ `aria-disabled="true"` ARIA path. `pointer-events: none` blocks POINTER
318
+ activation only a focused aria-disabled item still fires on Enter/Space
319
+ (CSS can't intercept keys). For a fully-inert control prefer native
320
+ `<button disabled>`, run `initDisabledGuard()` (intercepts Enter/Space), or
321
+ pair aria-disabled with `tabindex="-1"`. See docs/usage.md "Disabled vs
322
+ aria-disabled". (audit C4.) */
314
323
  .ui-pagination__item[aria-disabled='true'],
315
324
  .ui-pagination__item:disabled {
316
325
  cursor: not-allowed;
@@ -319,7 +328,12 @@
319
328
  }
320
329
 
321
330
  @media (hover: hover) {
322
- .ui-pagination__item:not(.is-active, [aria-disabled='true'], :disabled):hover {
331
+ .ui-pagination__item:not(
332
+ .is-active,
333
+ [aria-current]:not([aria-current='false']),
334
+ [aria-disabled='true'],
335
+ :disabled
336
+ ):hover {
323
337
  border-color: var(--line-strong);
324
338
  color: var(--text);
325
339
  }