@refrakt-md/lumina 0.15.0 → 0.16.1

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/base.css CHANGED
@@ -19,6 +19,7 @@
19
19
  @import './styles/layouts/blog.css';
20
20
  @import './styles/layouts/on-this-page.css';
21
21
  @import './styles/layouts/search.css';
22
+ @import './styles/layouts/theme-toggle.css';
22
23
  @import './styles/layouts/version-switcher.css';
23
24
  @import './styles/layouts/split.css';
24
25
 
@@ -200,6 +200,77 @@
200
200
  "{content}"
201
201
  ]
202
202
  },
203
+ "Badge": {
204
+ "block": "badge",
205
+ "root": ".rf-badge",
206
+ "dataRune": "badge",
207
+ "childOrder": [
208
+ "{content}"
209
+ ]
210
+ },
211
+ "Collection": {
212
+ "block": "collection",
213
+ "root": ".rf-collection",
214
+ "dataRune": "collection",
215
+ "childOrder": [
216
+ "{content}"
217
+ ]
218
+ },
219
+ "Relationships": {
220
+ "block": "relationships",
221
+ "root": ".rf-relationships",
222
+ "dataRune": "relationships",
223
+ "childOrder": [
224
+ "{content}"
225
+ ]
226
+ },
227
+ "FileRef": {
228
+ "block": "file-ref",
229
+ "root": ".rf-file-ref",
230
+ "dataRune": "file-ref",
231
+ "childOrder": [
232
+ "{content}"
233
+ ]
234
+ },
235
+ "Aggregate": {
236
+ "block": "aggregate",
237
+ "root": ".rf-aggregate",
238
+ "dataRune": "aggregate",
239
+ "childOrder": [
240
+ "{content}"
241
+ ]
242
+ },
243
+ "Progress": {
244
+ "block": "progress",
245
+ "root": ".rf-progress",
246
+ "dataRune": "progress",
247
+ "childOrder": [
248
+ "{content}"
249
+ ],
250
+ "modifiers": {
251
+ "sentiment": {
252
+ "source": "meta",
253
+ "classPattern": ".rf-progress--{value}",
254
+ "dataAttribute": "data-sentiment"
255
+ }
256
+ }
257
+ },
258
+ "Card": {
259
+ "block": "card",
260
+ "root": ".rf-card",
261
+ "dataRune": "card",
262
+ "childOrder": [
263
+ "{content}"
264
+ ],
265
+ "modifiers": {
266
+ "layout": {
267
+ "source": "meta",
268
+ "default": "stacked",
269
+ "classPattern": ".rf-card--{value}",
270
+ "dataAttribute": "data-layout"
271
+ }
272
+ }
273
+ },
203
274
  "Embed": {
204
275
  "block": "embed",
205
276
  "root": ".rf-embed",
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,YAAY,EAAE,iBAiL1B,CAAC"}
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,YAAY,EAAE,iBA6L1B,CAAC"}
package/dist/tokens.js CHANGED
@@ -64,6 +64,17 @@ export const luminaTokens = {
64
64
  // alias via `extra` below for downstream CSS that still reads it.
65
65
  'inline-bg': '#e6e5e3',
66
66
  },
67
+ // WORK-304 — line-level annotation tokens shared by snippet /
68
+ // codegroup / diff. `highlight` is the neutral surface tint applied
69
+ // to `[data-line-status="highlight"]` rows; `highlight-rail` is the
70
+ // left-edge border colour (left as a soft accent so themes can
71
+ // repaint just the rail without touching the row background);
72
+ // `number` is the gutter colour for `pre[data-linenumbers]`.
73
+ line: {
74
+ highlight: 'color-mix(in srgb, var(--rf-color-text) 6%, transparent)',
75
+ 'highlight-rail': 'var(--rf-color-primary, var(--rf-color-text))',
76
+ number: 'var(--rf-color-muted)',
77
+ },
67
78
  },
68
79
  radius: {
69
80
  sm: '6px',
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"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"}
package/index.css CHANGED
@@ -19,6 +19,7 @@
19
19
  @import './styles/layouts/blog.css';
20
20
  @import './styles/layouts/on-this-page.css';
21
21
  @import './styles/layouts/search.css';
22
+ @import './styles/layouts/theme-toggle.css';
22
23
  @import './styles/layouts/version-switcher.css';
23
24
  @import './styles/layouts/split.css';
24
25
  @import './styles/layouts/plan.css';
@@ -41,6 +42,7 @@
41
42
  @import './styles/runes/annotate.css';
42
43
  @import './styles/runes/audio.css';
43
44
  @import './styles/runes/api.css';
45
+ @import './styles/runes/card.css';
44
46
  @import './styles/runes/badge.css';
45
47
  @import './styles/runes/bento.css';
46
48
  @import './styles/runes/blog.css';
@@ -49,6 +51,11 @@
49
51
  @import './styles/runes/budget.css';
50
52
  @import './styles/runes/cast.css';
51
53
  @import './styles/runes/character.css';
54
+ @import './styles/runes/collection.css';
55
+ @import './styles/runes/relationships.css';
56
+ @import './styles/runes/aggregate.css';
57
+ @import './styles/runes/file-ref.css';
58
+ @import './styles/runes/progress.css';
52
59
  @import './styles/runes/changelog.css';
53
60
  @import './styles/runes/chart.css';
54
61
  @import './styles/runes/compare.css';
@@ -117,11 +124,6 @@
117
124
  @import './styles/runes/bug.css';
118
125
  @import './styles/runes/decision.css';
119
126
  @import './styles/runes/milestone.css';
120
- @import './styles/runes/backlog.css';
121
- @import './styles/runes/decision-log.css';
122
127
  @import './styles/runes/plan-progress.css';
123
- @import './styles/runes/plan-activity.css';
124
128
  @import './styles/runes/plan-ref.css';
125
- @import './styles/runes/plan-relationships.css';
126
129
  @import './styles/runes/plan-history.css';
127
- @import './styles/runes/plan-entity-tabs.css';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@refrakt-md/lumina",
3
3
  "description": "Lumina theme for refrakt.md — design tokens, CSS, identity transform, and layout configs",
4
- "version": "0.15.0",
4
+ "version": "0.16.1",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -83,9 +83,9 @@
83
83
  "build": "tsc"
84
84
  },
85
85
  "dependencies": {
86
- "@refrakt-md/runes": "0.15.0",
87
- "@refrakt-md/transform": "0.15.0",
88
- "@refrakt-md/types": "0.15.0"
86
+ "@refrakt-md/runes": "0.16.1",
87
+ "@refrakt-md/transform": "0.16.1",
88
+ "@refrakt-md/types": "0.16.1"
89
89
  },
90
90
  "devDependencies": {
91
91
  "postcss": "^8.4.0"
@@ -42,3 +42,75 @@
42
42
  opacity: 1 !important;
43
43
  color: var(--rf-color-success, #4ade80);
44
44
  }
45
+
46
+ /* WORK-304 — fence-level annotations: line numbers + line highlight.
47
+ *
48
+ * Shiki renders each line as `<span class="line">…</span>`. The fence
49
+ * schema forwards `data-linenumbers` / `data-highlight-lines` /
50
+ * `data-lines` (start offset) from the AST node onto both `<pre>` and
51
+ * `<code>`; the highlight transform sets `data-line-status="highlight"`
52
+ * on the matching `span.line` rows post-Shiki (file-coordinate math
53
+ * lives there, not in CSS).
54
+ *
55
+ * The starting line counter is seeded from `--rf-start-line` which the
56
+ * fence transform inlines on `<pre>` when `data-lines` is set
57
+ * (e.g. lines="74-125" → --rf-start-line: 73 so the first
58
+ * counter-increment lands on 74). Defaults to 0 so unannotated fences
59
+ * count from 1.
60
+ *
61
+ * `<code>` becomes a CSS grid so:
62
+ * - consecutive `.line` rows tile perfectly with no subpixel cracks
63
+ * at non-100% zoom (the previous inline-block stacking left faint
64
+ * gaps the rail and bg shone through);
65
+ * - line bg + rail extend across the full horizontal scroll region
66
+ * (grid track width = max-content keeps lines full-width even
67
+ * when the pre scrolls).
68
+ *
69
+ * Every line carries a 3px transparent left border so geometry stays
70
+ * consistent across highlighted and plain rows — matches the diff row
71
+ * primitive at `runes/diff.css`. Highlighted rows just colour the
72
+ * border + add the surface tint. */
73
+ .rf-codeblock pre code {
74
+ display: grid;
75
+ min-width: max-content;
76
+ }
77
+
78
+ .rf-codeblock pre code .line {
79
+ border-left: 3px solid transparent;
80
+ }
81
+
82
+ /* Line numbers — gutter::before owns the left column. Strip the pre's
83
+ * horizontal padding when linenumbers are on so the gutter sits flush
84
+ * against the codeblock edge; the gutter's own padding + right border
85
+ * provides the visual separation from the code body. */
86
+ .rf-codeblock pre[data-linenumbers] {
87
+ padding-left: 0;
88
+ }
89
+
90
+ .rf-codeblock pre[data-linenumbers] code {
91
+ counter-reset: rf-line var(--rf-start-line, 0);
92
+ }
93
+
94
+ .rf-codeblock pre[data-linenumbers] code .line::before {
95
+ counter-increment: rf-line;
96
+ content: counter(rf-line);
97
+ display: inline-block;
98
+ width: 3em;
99
+ padding-inline: 0.75rem 0.5rem;
100
+ margin-right: 0.75rem;
101
+ text-align: right;
102
+ color: var(--rf-color-line-number);
103
+ font-variant-numeric: tabular-nums;
104
+ user-select: none;
105
+ border-right: 1px solid var(--rf-color-border);
106
+ }
107
+
108
+ /* Highlighted lines share diff's row template — neutral surface tint
109
+ * + primary-coloured left rail, no `+`/`-` sigil. The grid layout on
110
+ * `<code>` above keeps consecutive highlighted rows continuous (no
111
+ * subpixel gaps between the rails). Border is on every `.line` (above)
112
+ * so the content alignment doesn't jump when highlighting a row. */
113
+ .rf-codeblock pre code .line[data-line-status="highlight"] {
114
+ background: var(--rf-color-line-highlight);
115
+ border-left-color: var(--rf-color-line-highlight-rail);
116
+ }
@@ -100,6 +100,15 @@
100
100
  background: var(--rf-color-bg, #fff);
101
101
  z-index: 5;
102
102
  }
103
+ /* Match the sticky offset in the natural-flow position too. The fixed header
104
+ * is out of flow so `.rf-docs-body` starts at viewport top; without this
105
+ * margin, the sidebar's static position sits at Y=0 with its top 3.125rem
106
+ * hidden under the header — visible only when the page scrolls enough for
107
+ * sticky to activate. Scoped to `:has(.rf-docs-header)` so layouts without a
108
+ * header don't gain an unwanted top gap. */
109
+ html:has(.rf-docs-header) .rf-docs-sidebar {
110
+ margin-top: 3.125rem;
111
+ }
103
112
  .rf-docs-sidebar::-webkit-scrollbar {
104
113
  width: 0;
105
114
  }
@@ -190,6 +199,8 @@ html:has(.rf-docs-header) {
190
199
  padding: 0.625rem 1rem;
191
200
  border-bottom: 1px solid var(--rf-color-border);
192
201
  background: var(--rf-color-bg, #fff);
202
+ max-width: 100%;
203
+ overflow: hidden;
193
204
  }
194
205
  .rf-docs-toolbar__hamburger {
195
206
  background: none;
@@ -206,6 +217,12 @@ html:has(.rf-docs-header) {
206
217
  .rf-docs-toolbar__breadcrumb {
207
218
  font-size: 0.8rem;
208
219
  color: var(--rf-color-muted);
220
+ /* `flex: 1 1 0` (basis 0, not auto) so the breadcrumb shrinks against
221
+ * the available space rather than starting at its full content width —
222
+ * combined with `min-width: 0` this is what triggers ellipsis on long
223
+ * titles. Without basis 0 a long page title overflows the toolbar and
224
+ * forces horizontal page scroll on narrow viewports. */
225
+ flex: 1 1 0;
209
226
  min-width: 0;
210
227
  overflow: hidden;
211
228
  text-overflow: ellipsis;
@@ -43,22 +43,40 @@
43
43
 
44
44
  /* ─── Media zone base styles ──────────────────────────────────────── */
45
45
 
46
- /* Only clip overflow when media zone contains an image. Interactive content
47
- (preview, juxtapose) needs overflow visible for bleed effects. */
48
- [data-section="media"]:has(> img) {
46
+ /* Clip overflow + round corners when the media zone holds media-like
47
+ content: an image, or a self-contained block rune that wants the same
48
+ "fills the slot" treatment (codegroup, snippet, chart, sandbox). Anything
49
+ else keeps overflow visible so interactive bleed effects (preview,
50
+ juxtapose) still work. Add new rune-typed media here when they should
51
+ participate in the same chrome. */
52
+ [data-section="media"]:where(
53
+ :has(> img),
54
+ :has(> [data-rune="code-group"]),
55
+ :has(> [data-rune="snippet"]),
56
+ :has(> [data-rune="chart"]),
57
+ :has(> [data-rune="sandbox"])
58
+ ) {
49
59
  border-radius: var(--rf-radius-lg);
50
60
  overflow: hidden;
51
61
  }
52
- [data-section="media"] img {
62
+ [data-section="media"] > :where(
63
+ img,
64
+ [data-rune="code-group"],
65
+ [data-rune="snippet"],
66
+ [data-rune="chart"],
67
+ [data-rune="sandbox"]
68
+ ) {
53
69
  display: block;
54
70
  width: 100%;
55
71
  height: auto;
56
72
  border-radius: var(--rf-radius-lg);
73
+ margin: 0;
57
74
  }
58
75
 
59
- /* Split layout media gets subtle depth */
60
- [data-layout="split"] > [data-section="media"] img,
61
- [data-layout="split-reverse"] > [data-section="media"] img {
76
+ /* Split layout images get subtle depth. Block runes carry their own visual
77
+ weight (topbars, frames) so the shadow is image-only. */
78
+ [data-layout="split"] > [data-section="media"] > img,
79
+ [data-layout="split-reverse"] > [data-section="media"] > img {
62
80
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
63
81
  }
64
82
 
@@ -109,7 +127,13 @@
109
127
  margin-bottom: var(--rune-padding, var(--rf-spacing-md));
110
128
  border-radius: 0;
111
129
  }
112
- [data-media-position="top"] > [data-section="media"] img {
130
+ [data-media-position="top"] > [data-section="media"] > :where(
131
+ img,
132
+ [data-rune="code-group"],
133
+ [data-rune="snippet"],
134
+ [data-rune="chart"],
135
+ [data-rune="sandbox"]
136
+ ) {
113
137
  border-radius: var(--rf-radius-md) var(--rf-radius-md) 0 0;
114
138
  }
115
139
 
@@ -134,7 +158,13 @@
134
158
  margin-bottom: var(--rune-padding, var(--rf-spacing-md));
135
159
  border-radius: 0;
136
160
  }
137
- [data-media-position="top"][data-collapse="sm"] > [data-section="media"] img {
161
+ [data-media-position="top"][data-collapse="sm"] > [data-section="media"] > :where(
162
+ img,
163
+ [data-rune="code-group"],
164
+ [data-rune="snippet"],
165
+ [data-rune="chart"],
166
+ [data-rune="sandbox"]
167
+ ) {
138
168
  border-radius: var(--rf-radius-md) var(--rf-radius-md) 0 0;
139
169
  }
140
170
  /* Reset grid placement on collapse for header/content */
@@ -157,7 +187,13 @@
157
187
  margin-bottom: var(--rune-padding, var(--rf-spacing-md));
158
188
  border-radius: 0;
159
189
  }
160
- [data-media-position="top"][data-collapse="md"] > [data-section="media"] img {
190
+ [data-media-position="top"][data-collapse="md"] > [data-section="media"] > :where(
191
+ img,
192
+ [data-rune="code-group"],
193
+ [data-rune="snippet"],
194
+ [data-rune="chart"],
195
+ [data-rune="sandbox"]
196
+ ) {
161
197
  border-radius: var(--rf-radius-md) var(--rf-radius-md) 0 0;
162
198
  }
163
199
  [data-media-position="top"][data-collapse="md"] > [data-section="header"],
@@ -179,7 +215,13 @@
179
215
  margin-bottom: var(--rune-padding, var(--rf-spacing-md));
180
216
  border-radius: 0;
181
217
  }
182
- [data-media-position="top"][data-collapse="lg"] > [data-section="media"] img {
218
+ [data-media-position="top"][data-collapse="lg"] > [data-section="media"] > :where(
219
+ img,
220
+ [data-rune="code-group"],
221
+ [data-rune="snippet"],
222
+ [data-rune="chart"],
223
+ [data-rune="sandbox"]
224
+ ) {
183
225
  border-radius: var(--rf-radius-md) var(--rf-radius-md) 0 0;
184
226
  }
185
227
  [data-media-position="top"][data-collapse="lg"] > [data-section="header"],
@@ -0,0 +1,67 @@
1
+ /* Theme-mode toggle button (SPEC-073).
2
+ *
3
+ * Layout chrome — a peer of the search trigger, placed in the header/toolbar.
4
+ * The `theme-toggle` behavior cycles auto → light → dark and reflects the
5
+ * current preference onto the button as `data-theme-pref`; the icon below
6
+ * tracks that. Ported verbatim from the former `ThemeToggle.svelte` so the
7
+ * look is unchanged, with the icon selector rekeyed from a swapped class to
8
+ * the `data-theme-pref` attribute. */
9
+ .rf-theme-toggle {
10
+ display: inline-flex;
11
+ align-items: center;
12
+ justify-content: center;
13
+ width: 2rem;
14
+ height: 2rem;
15
+ padding: 0;
16
+ border: 1px solid var(--rf-color-border);
17
+ border-radius: var(--rf-radius-md);
18
+ background: transparent;
19
+ color: var(--rf-color-text);
20
+ cursor: pointer;
21
+ transition: background-color 120ms ease, border-color 120ms ease;
22
+ }
23
+ .rf-theme-toggle:hover {
24
+ background: var(--rf-color-surface-hover);
25
+ }
26
+ .rf-theme-toggle:focus-visible {
27
+ outline: 2px solid var(--rf-color-primary);
28
+ outline-offset: 2px;
29
+ }
30
+
31
+ /* In the header chrome the brand/nav and the controls are flex siblings
32
+ * arranged by `order` (search is order 1, nav/menu order 3). Without this the
33
+ * toggle defaults to order 0 and groups with the brand on the left; order 2
34
+ * places it just after the right-aligned search trigger — matching the former
35
+ * component. The plan toolbar arranges by DOM order, so it isn't included. */
36
+ .rf-header__inner .rf-theme-toggle,
37
+ .rf-docs-header__inner .rf-theme-toggle,
38
+ .rf-blog-header__inner .rf-theme-toggle {
39
+ order: 2;
40
+ }
41
+
42
+ /* Hidden on tint-locked pages: the saved preference is preserved but ignored
43
+ * while the lock is active (SPEC-052), so a toggle that does nothing would be
44
+ * confusing. Pure CSS — the lock lands on <html> at SSR and on client nav. */
45
+ html[data-tint-lock="true"] .rf-theme-toggle {
46
+ display: none;
47
+ }
48
+
49
+ /* Icon — a currentColor-tinted mask. Defaults to the auto glyph so the SSR'd
50
+ * button shows an icon before the behavior sets data-theme-pref; the light and
51
+ * dark glyphs swap in by state. */
52
+ .rf-theme-toggle__icon {
53
+ display: inline-block;
54
+ width: 1rem;
55
+ height: 1rem;
56
+ background: currentColor;
57
+ mask-size: contain;
58
+ mask-repeat: no-repeat;
59
+ mask-position: center;
60
+ mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'/><path d='M12 2a10 10 0 0 0 0 20Z' fill='currentColor'/></svg>");
61
+ }
62
+ .rf-theme-toggle[data-theme-pref="light"] .rf-theme-toggle__icon {
63
+ mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='4'/><path d='M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41'/></svg>");
64
+ }
65
+ .rf-theme-toggle[data-theme-pref="dark"] .rf-theme-toggle__icon {
66
+ mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z'/></svg>");
67
+ }
@@ -1,9 +1,6 @@
1
1
  /* Accordion */
2
- .rf-accordion {
3
- border: 1px solid var(--rf-color-border);
4
- border-radius: var(--rf-radius-md);
5
- overflow: hidden;
6
- }
2
+ /* No wrapping border / radius — the only chrome is the divider between items. */
3
+ .rf-accordion {}
7
4
  .rf-accordion__preamble {
8
5
  margin-bottom: 1.5rem;
9
6
  }
@@ -52,35 +49,69 @@
52
49
  .rf-accordion-item__header {
53
50
  display: flex;
54
51
  align-items: center;
55
- justify-content: space-between;
56
- padding: 0.875rem 1.25rem;
52
+ gap: 0.5rem;
53
+ padding: 0.875rem 0rem;
57
54
  font-weight: 600;
58
55
  font-size: 0.95rem;
59
56
  cursor: pointer;
60
57
  user-select: none;
61
- transition: background-color 200ms ease;
62
58
  list-style: none;
63
59
  }
64
60
  .rf-accordion-item__header::-webkit-details-marker { display: none; }
65
61
  .rf-accordion-item__header::marker { display: none; content: ''; }
66
- .rf-accordion-item__header:hover {
67
- background: var(--rf-color-surface);
68
- }
69
- .rf-accordion-item__header::after {
70
- content: '';
62
+ /* Chevron in front of the label — points right when collapsed, rotates 90°
63
+ * to point down when expanded. SVG mask so the glyph is crisp at any size
64
+ * and tints with the muted text color. */
65
+ .rf-accordion-item__header::before {
66
+ content: '';
71
67
  flex-shrink: 0;
72
- color: var(--rf-color-muted);
68
+ width: 0.75rem;
69
+ height: 0.75rem;
70
+ background: var(--rf-color-muted);
71
+ mask-size: contain;
72
+ mask-repeat: no-repeat;
73
+ mask-position: center;
74
+ mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='9 18 15 12 9 6'/></svg>");
73
75
  transition: transform 200ms ease;
74
76
  }
75
- .rf-accordion-item[open] .rf-accordion-item__header::after {
76
- transform: rotate(180deg);
77
+ .rf-accordion-item[open] .rf-accordion-item__header::before {
78
+ transform: rotate(90deg);
77
79
  }
78
80
  .rf-accordion-item__title {
79
81
  flex: 1;
80
82
  min-width: 0;
81
83
  }
84
+ /* Per-group count for collection/relationships group-display="accordion".
85
+ * Inherits the header's font (weight + color) so the count reads as part
86
+ * of the same label. The header's `gap` handles spacing — no margins needed. */
87
+ .rf-accordion-item__count {
88
+ flex-shrink: 0;
89
+ }
90
+ /* Animate the panel's collapse / expand. `::details-content` (the auto-generated
91
+ * wrapper for non-summary content) + `interpolate-size: allow-keywords` lets the
92
+ * height transition between 0 and auto. `transition-behavior: allow-discrete`
93
+ * on `content-visibility` keeps the panel reachable during the open animation.
94
+ * Browsers without `::details-content` support fall back to the native snap. */
95
+ .rf-accordion-item {
96
+ interpolate-size: allow-keywords;
97
+ }
98
+ .rf-accordion-item::details-content {
99
+ block-size: 0;
100
+ overflow: hidden;
101
+ transition: block-size 250ms ease, content-visibility 250ms allow-discrete;
102
+ }
103
+ .rf-accordion-item[open]::details-content {
104
+ block-size: auto;
105
+ }
82
106
  .rf-accordion-item__body {
83
107
  padding: 0 1.25rem 1rem;
108
+ }
109
+ /* Prose styles for the standalone accordion rune's bodies (paragraphs,
110
+ * lists, etc.). Scoped to `:not(:has([data-block]))` so they don't bleed into
111
+ * block-content children like cards inside a collection/relationships
112
+ * `group-display="accordion"` panel, where the card's own typography
113
+ * should govern. */
114
+ .rf-accordion-item__body:not(:has([data-block])) {
84
115
  font-size: 0.925rem;
85
116
  line-height: 1.65;
86
117
  color: var(--rf-color-muted);
@@ -88,3 +119,12 @@
88
119
  .rf-accordion-item__body p:last-child {
89
120
  margin-bottom: 0;
90
121
  }
122
+ /* Block-content children — collection / relationships mark their body-template
123
+ * items `data-block`. A panel housing them (group-display="accordion") switches
124
+ * to a flex column with the small gap so cards get the same spacing they'd have
125
+ * under a heading-grouped layout. */
126
+ .rf-accordion-item__body:has([data-block]) {
127
+ display: flex;
128
+ flex-direction: column;
129
+ gap: var(--rf-spacing-sm);
130
+ }
@@ -0,0 +1,75 @@
1
+ /* Aggregate — counts and per-group breakdowns from the registry (SPEC-076).
2
+ *
3
+ * Two modes share the same block class. The no-body inline form is a `<span>`
4
+ * carrying the integer; the body-zoned form is a `<section>` rendering
5
+ * preamble / per-group template / fallback. Most of the visual weight inside
6
+ * the body comes from other runes (`progress`, `badge`, `humanize` text), so
7
+ * this stylesheet sticks to container chrome and the inline single-number
8
+ * form.
9
+ */
10
+
11
+ /* Block container — vertical rhythm matches collection / relationships. The
12
+ * bare selector also matches the inline form's `<span>`, but vertical margin
13
+ * on an inline span has no effect so it's safe to share. */
14
+ .rf-aggregate {
15
+ margin: var(--rf-spacing-md) 0;
16
+ }
17
+
18
+ /* Inline single-number form — `<span class="rf-aggregate" data-aggregate="count">`.
19
+ * Tabular nums keep digits aligned when the count changes between renders;
20
+ * weight tuned to stand out modestly in prose. */
21
+ .rf-aggregate[data-aggregate='count'] {
22
+ font-variant-numeric: tabular-nums;
23
+ font-weight: 600;
24
+ color: var(--rf-color-text);
25
+ }
26
+
27
+ /* Preamble — totals chrome above the breakdown (e.g. a progress bar). Trim
28
+ * first/last-child block margins so the rune's outer rhythm wins over the
29
+ * template's inner block margins (same pattern collection uses). */
30
+ .rf-aggregate__preamble > :first-child { margin-top: 0; }
31
+ .rf-aggregate__preamble > :last-child { margin-bottom: 0; }
32
+
33
+ /* Empty state — replaces the breakdown when the query yields nothing. */
34
+ .rf-aggregate__empty {
35
+ color: var(--rf-color-muted);
36
+ font-size: 0.9375em;
37
+ }
38
+ .rf-aggregate__empty > :first-child { margin-top: 0; }
39
+ .rf-aggregate__empty > :last-child { margin-bottom: 0; }
40
+
41
+ /* Items — either the per-group breakdown row, or the ungrouped single-render
42
+ * slot. Default stack handles the ungrouped case (one block element from the
43
+ * body). With groups, switch to a wrapping inline row so per-group renders
44
+ * (badges, pills, …) flow across the page. */
45
+ .rf-aggregate__items {
46
+ display: flex;
47
+ flex-direction: column;
48
+ gap: var(--rf-spacing-sm);
49
+ margin-top: var(--rf-spacing-sm);
50
+ }
51
+ .rf-aggregate__items:has(.rf-aggregate__group) {
52
+ flex-direction: row;
53
+ flex-wrap: wrap;
54
+ gap: var(--rf-spacing-xs) var(--rf-spacing-sm);
55
+ }
56
+
57
+ /* Direct children of __items (the ungrouped template render) — trim outer
58
+ * block margins so the rune's outer rhythm wins, same pattern as preamble /
59
+ * empty. */
60
+ .rf-aggregate__items > :first-child { margin-top: 0; }
61
+ .rf-aggregate__items > :last-child { margin-bottom: 0; }
62
+
63
+ /* Per-group block — wraps one render of the template. `data-block` is set
64
+ * by the resolver so we trim its outer block margins (the items-row `gap`
65
+ * governs inter-group spacing) — same pattern collection / relationships
66
+ * use for `__item[data-block]`. */
67
+ .rf-aggregate__group {
68
+ min-width: 0;
69
+ }
70
+ .rf-aggregate__group[data-block] > :first-child {
71
+ margin-top: 0;
72
+ }
73
+ .rf-aggregate__group[data-block] > :last-child {
74
+ margin-bottom: 0;
75
+ }