@xenosystem/elements-react 0.0.3 → 0.0.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/LICENSE +18 -18
- package/README.md +41 -41
- package/dist/containers/Chip.js +1 -1
- package/dist/containers/Panel.js +1 -1
- package/package.json +58 -58
- package/src/chrome-separated.css +132 -132
- package/src/chrome-unified.css +72 -72
- package/src/containers/Badges.css +116 -116
- package/src/containers/avatar.css +70 -70
- package/src/containers/card.css +75 -75
- package/src/containers/chip.css +103 -103
- package/src/containers/list-row.css +132 -132
- package/src/containers/message-bubble.css +112 -112
- package/src/containers/panel.css +125 -120
- package/src/containers/table.css +102 -102
- package/src/containers/tile.css +17 -17
- package/src/content/callout.css +77 -77
- package/src/content/caret.css +30 -30
- package/src/content/code-block.css +159 -159
- package/src/content/collapsible.css +80 -80
- package/src/content/inline-code.css +14 -14
- package/src/content/model-picker.css +219 -219
- package/src/content/source-card.css +99 -99
- package/src/content/sources-disclosure.css +118 -118
- package/src/controls.css +453 -453
- package/src/fonts.css +34 -34
- package/src/forms/Checkbox.css +114 -114
- package/src/forms/RadioGroup.css +115 -115
- package/src/goo.css +97 -97
- package/src/icon-motion.css +1909 -1909
- package/src/layout/ResizablePanel.css +79 -79
- package/src/nav/sidebar.css +296 -296
- package/src/overlays/date-time-picker.css +238 -238
- package/src/overlays/menu.css +195 -195
- package/src/overlays/modal.css +167 -167
- package/src/overlays/picker-field.css +81 -81
- package/src/overlays/pill-filter.css +129 -129
- package/src/overlays/reveal.css +56 -56
- package/src/overlays/segmented-control.css +185 -185
- package/src/overlays/tabs.css +143 -143
- package/src/overlays/tooltip.css +126 -126
- package/src/scrollbar.css +184 -184
- package/src/size.css +179 -179
- package/src/status/progress-bar.css +88 -88
- package/src/status/spinner.css +33 -33
- package/src/status/statusindicator.css +65 -65
- package/src/status/steptimeline.css +137 -137
- package/src/status/thinkingcube.css +75 -75
- package/src/xeno-element.css +60 -60
- package/src/xeno-elements.css +71 -71
- package/src/xeno-theme.css +112 -99
package/src/chrome-unified.css
CHANGED
|
@@ -1,72 +1,72 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* ══════════════════════════════════════════════════════════════════════════════════════════════
|
|
3
|
-
* OWNED FILE — SOFT (`unified`)
|
|
4
|
-
* ══════════════════════════════════════════════════════════════════════════════════════════════
|
|
5
|
-
*
|
|
6
|
-
* One construction, one file, one owner, so the two can be worked on in parallel without either
|
|
7
|
-
* side touching the other's values. Everything a construction decides lives HERE — colours, box
|
|
8
|
-
* metrics, typography, radii. Nothing construction-specific belongs in a component stylesheet or
|
|
9
|
-
* in `xeno-theme.css`, because those are shared and a change there hits BOTH looks.
|
|
10
|
-
*
|
|
11
|
-
* THE CONTRACT BETWEEN THE TWO FILES, enforced by `theme.test.ts`:
|
|
12
|
-
* 1. Every token declared in `chrome-separated.css` must also be declared here, and vice versa.
|
|
13
|
-
* Adding one on your side and not telling the other side is the failure mode — the missing
|
|
14
|
-
* one silently inherits the other construction's value and half-renders.
|
|
15
|
-
* 2. Every token must actually DIFFER between the two files. If a value is the same in both, it
|
|
16
|
-
* is not a construction decision: move it to the shared base.
|
|
17
|
-
*
|
|
18
|
-
* So adding a token is a two-file change and the suite will say so. That is deliberate: it is the
|
|
19
|
-
* cheapest possible coordination between two people editing in parallel.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
/* ── UNIFIED chrome ────────────────────────────────────────────────────────────────────────────
|
|
23
|
-
* One clipped surface with hairline dividers — the construction this set shipped before the chrome
|
|
24
|
-
* axis existed, preserved deliberately rather than corrected away.
|
|
25
|
-
*
|
|
26
|
-
* It is expressed ENTIRELY as values. Collapsing the gap to 0, painting the shell with the surface
|
|
27
|
-
* colour and making the plates transparent reproduces a single card exactly — same DOM, same
|
|
28
|
-
* components, no second implementation. That is the whole test for whether something may be a theme.
|
|
29
|
-
*/
|
|
30
|
-
[data-chrome='unified'] {
|
|
31
|
-
--xeno-chrome-gap: 0px;
|
|
32
|
-
--xeno-chrome-inset: 0px;
|
|
33
|
-
--xeno-chrome-shell: var(--xeno-surface);
|
|
34
|
-
--xeno-chrome-plate: transparent;
|
|
35
|
-
--xeno-chrome-body: transparent;
|
|
36
|
-
--xeno-chrome-divider: 1px solid var(--xeno-border);
|
|
37
|
-
--xeno-chrome-shadow: 0 12px 48px -16px rgba(0, 0, 0, 0.55);
|
|
38
|
-
--xeno-chrome-radius: var(--xeno-radius-card);
|
|
39
|
-
--xeno-chrome-radius-plate: 0px;
|
|
40
|
-
/* No glass: a single clipped surface has nothing behind a plate to blur. */
|
|
41
|
-
--xeno-chrome-plate-filter: none;
|
|
42
|
-
/* The inverted primary this set already shipped — preserved, not corrected. */
|
|
43
|
-
/* The soft card this set shipped — surface, big radius, hairline, and a real shadow. */
|
|
44
|
-
--xeno-chrome-card-bg: var(--xeno-surface);
|
|
45
|
-
--xeno-chrome-card-border: 1px solid var(--xeno-border);
|
|
46
|
-
--xeno-chrome-card-radius: var(--xeno-radius-card);
|
|
47
|
-
--xeno-chrome-card-pad: 13px 15px;
|
|
48
|
-
--xeno-chrome-card-shadow: 0 1px 2px rgba(0, 0, 0, 0.28);
|
|
49
|
-
--xeno-chrome-card-lift: 0 8px 24px -10px rgba(0, 0, 0, 0.45);
|
|
50
|
-
|
|
51
|
-
/* Restores every pre-axis value exactly. Verified against the baseline, not eyeballed. */
|
|
52
|
-
--xeno-chrome-border: var(--xeno-border);
|
|
53
|
-
--xeno-chrome-panel-header-pad: 11px 15px;
|
|
54
|
-
--xeno-chrome-panel-header-min-h: auto;
|
|
55
|
-
--xeno-chrome-panel-body-pad: 15px;
|
|
56
|
-
--xeno-chrome-title-size: 14px;
|
|
57
|
-
--xeno-chrome-title-color: var(--xeno-text);
|
|
58
|
-
--xeno-chrome-title-transform: none;
|
|
59
|
-
--xeno-chrome-title-spacing: normal;
|
|
60
|
-
--xeno-chrome-dialog-header-pad: 16px 16px 12px 20px;
|
|
61
|
-
--xeno-chrome-dialog-title-size: 16px;
|
|
62
|
-
--xeno-chrome-dialog-title-weight: 600;
|
|
63
|
-
--xeno-chrome-dialog-body-pad: 4px 20px 20px;
|
|
64
|
-
--xeno-chrome-dialog-body-size: 14px;
|
|
65
|
-
--xeno-chrome-dialog-footer-pad: 12px 20px;
|
|
66
|
-
--xeno-chrome-dialog-footer-gap: 8px;
|
|
67
|
-
--xeno-chrome-card-elevated-bg: var(--xeno-elevated);
|
|
68
|
-
|
|
69
|
-
--xeno-chrome-btn-primary-bg: var(--xeno-text);
|
|
70
|
-
--xeno-chrome-btn-primary-fg: var(--xeno-on-accent);
|
|
71
|
-
--xeno-chrome-btn-radius: var(--xeno-radius-control);
|
|
72
|
-
}
|
|
1
|
+
/*
|
|
2
|
+
* ══════════════════════════════════════════════════════════════════════════════════════════════
|
|
3
|
+
* OWNED FILE — SOFT (`unified`)
|
|
4
|
+
* ══════════════════════════════════════════════════════════════════════════════════════════════
|
|
5
|
+
*
|
|
6
|
+
* One construction, one file, one owner, so the two can be worked on in parallel without either
|
|
7
|
+
* side touching the other's values. Everything a construction decides lives HERE — colours, box
|
|
8
|
+
* metrics, typography, radii. Nothing construction-specific belongs in a component stylesheet or
|
|
9
|
+
* in `xeno-theme.css`, because those are shared and a change there hits BOTH looks.
|
|
10
|
+
*
|
|
11
|
+
* THE CONTRACT BETWEEN THE TWO FILES, enforced by `theme.test.ts`:
|
|
12
|
+
* 1. Every token declared in `chrome-separated.css` must also be declared here, and vice versa.
|
|
13
|
+
* Adding one on your side and not telling the other side is the failure mode — the missing
|
|
14
|
+
* one silently inherits the other construction's value and half-renders.
|
|
15
|
+
* 2. Every token must actually DIFFER between the two files. If a value is the same in both, it
|
|
16
|
+
* is not a construction decision: move it to the shared base.
|
|
17
|
+
*
|
|
18
|
+
* So adding a token is a two-file change and the suite will say so. That is deliberate: it is the
|
|
19
|
+
* cheapest possible coordination between two people editing in parallel.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/* ── UNIFIED chrome ────────────────────────────────────────────────────────────────────────────
|
|
23
|
+
* One clipped surface with hairline dividers — the construction this set shipped before the chrome
|
|
24
|
+
* axis existed, preserved deliberately rather than corrected away.
|
|
25
|
+
*
|
|
26
|
+
* It is expressed ENTIRELY as values. Collapsing the gap to 0, painting the shell with the surface
|
|
27
|
+
* colour and making the plates transparent reproduces a single card exactly — same DOM, same
|
|
28
|
+
* components, no second implementation. That is the whole test for whether something may be a theme.
|
|
29
|
+
*/
|
|
30
|
+
[data-chrome='unified'] {
|
|
31
|
+
--xeno-chrome-gap: 0px;
|
|
32
|
+
--xeno-chrome-inset: 0px;
|
|
33
|
+
--xeno-chrome-shell: var(--xeno-surface);
|
|
34
|
+
--xeno-chrome-plate: transparent;
|
|
35
|
+
--xeno-chrome-body: transparent;
|
|
36
|
+
--xeno-chrome-divider: 1px solid var(--xeno-border);
|
|
37
|
+
--xeno-chrome-shadow: 0 12px 48px -16px rgba(0, 0, 0, 0.55);
|
|
38
|
+
--xeno-chrome-radius: var(--xeno-radius-card);
|
|
39
|
+
--xeno-chrome-radius-plate: 0px;
|
|
40
|
+
/* No glass: a single clipped surface has nothing behind a plate to blur. */
|
|
41
|
+
--xeno-chrome-plate-filter: none;
|
|
42
|
+
/* The inverted primary this set already shipped — preserved, not corrected. */
|
|
43
|
+
/* The soft card this set shipped — surface, big radius, hairline, and a real shadow. */
|
|
44
|
+
--xeno-chrome-card-bg: var(--xeno-surface);
|
|
45
|
+
--xeno-chrome-card-border: 1px solid var(--xeno-border);
|
|
46
|
+
--xeno-chrome-card-radius: var(--xeno-radius-card);
|
|
47
|
+
--xeno-chrome-card-pad: 13px 15px;
|
|
48
|
+
--xeno-chrome-card-shadow: 0 1px 2px rgba(0, 0, 0, 0.28);
|
|
49
|
+
--xeno-chrome-card-lift: 0 8px 24px -10px rgba(0, 0, 0, 0.45);
|
|
50
|
+
|
|
51
|
+
/* Restores every pre-axis value exactly. Verified against the baseline, not eyeballed. */
|
|
52
|
+
--xeno-chrome-border: var(--xeno-border);
|
|
53
|
+
--xeno-chrome-panel-header-pad: 11px 15px;
|
|
54
|
+
--xeno-chrome-panel-header-min-h: auto;
|
|
55
|
+
--xeno-chrome-panel-body-pad: 15px;
|
|
56
|
+
--xeno-chrome-title-size: 14px;
|
|
57
|
+
--xeno-chrome-title-color: var(--xeno-text);
|
|
58
|
+
--xeno-chrome-title-transform: none;
|
|
59
|
+
--xeno-chrome-title-spacing: normal;
|
|
60
|
+
--xeno-chrome-dialog-header-pad: 16px 16px 12px 20px;
|
|
61
|
+
--xeno-chrome-dialog-title-size: 16px;
|
|
62
|
+
--xeno-chrome-dialog-title-weight: 600;
|
|
63
|
+
--xeno-chrome-dialog-body-pad: 4px 20px 20px;
|
|
64
|
+
--xeno-chrome-dialog-body-size: 14px;
|
|
65
|
+
--xeno-chrome-dialog-footer-pad: 12px 20px;
|
|
66
|
+
--xeno-chrome-dialog-footer-gap: 8px;
|
|
67
|
+
--xeno-chrome-card-elevated-bg: var(--xeno-elevated);
|
|
68
|
+
|
|
69
|
+
--xeno-chrome-btn-primary-bg: var(--xeno-text);
|
|
70
|
+
--xeno-chrome-btn-primary-fg: var(--xeno-on-accent);
|
|
71
|
+
--xeno-chrome-btn-radius: var(--xeno-radius-control);
|
|
72
|
+
}
|
|
@@ -1,116 +1,116 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Badges — inline monochrome markers (Badge / StatusPill / CountBadge / CitationBadge).
|
|
3
|
-
*
|
|
4
|
-
* CSS-first, driven by the theme custom properties from `xeno-theme.css`. These elements are STATIC
|
|
5
|
-
* (no interaction), so the only state seam is `data-tone` on the tonal members. Colours stay in the
|
|
6
|
-
* monochrome shell; the sole exception is the StatusPill status hue — `success`/`warning` arrive as
|
|
7
|
-
* the inline `--xeno-pill-tone` var (set from the status token by the renderer) and `danger` maps to
|
|
8
|
-
* `--xeno-danger`. Grammar: rounded squares, never circles. No literal colours here.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
/* ── Badge ─────────────────────────────────────────────────────────────────────────── */
|
|
12
|
-
.xeno-badge {
|
|
13
|
-
display: inline-flex;
|
|
14
|
-
align-items: center;
|
|
15
|
-
gap: 4px;
|
|
16
|
-
height: 16px;
|
|
17
|
-
padding: 0 6px;
|
|
18
|
-
font-family: inherit;
|
|
19
|
-
font-size: 10px;
|
|
20
|
-
font-weight: 600;
|
|
21
|
-
line-height: 1;
|
|
22
|
-
letter-spacing: 0.05em;
|
|
23
|
-
text-transform: uppercase;
|
|
24
|
-
white-space: nowrap;
|
|
25
|
-
color: var(--xeno-muted);
|
|
26
|
-
background: var(--xeno-surface);
|
|
27
|
-
border: 1px solid var(--xeno-border);
|
|
28
|
-
border-radius: var(--xeno-radius-sm);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/* ── StatusPill ────────────────────────────────────────────────────────────────────── */
|
|
32
|
-
.xeno-statuspill {
|
|
33
|
-
display: inline-flex;
|
|
34
|
-
align-items: center;
|
|
35
|
-
gap: 5px;
|
|
36
|
-
height: 16px;
|
|
37
|
-
padding: 0 6px;
|
|
38
|
-
font-family: inherit;
|
|
39
|
-
font-size: 10px;
|
|
40
|
-
font-weight: 600;
|
|
41
|
-
line-height: 1;
|
|
42
|
-
letter-spacing: 0.05em;
|
|
43
|
-
text-transform: uppercase;
|
|
44
|
-
white-space: nowrap;
|
|
45
|
-
color: var(--xeno-muted);
|
|
46
|
-
background: var(--xeno-surface);
|
|
47
|
-
border: 1px solid var(--xeno-border);
|
|
48
|
-
border-radius: var(--xeno-radius-sm);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/* leading dot — a rounded SQUARE (never a circle), inheriting the pill tone via currentColor */
|
|
52
|
-
.xeno-statuspill-dot {
|
|
53
|
-
flex: none;
|
|
54
|
-
width: 5px;
|
|
55
|
-
height: 5px;
|
|
56
|
-
background: currentColor;
|
|
57
|
-
border-radius: var(--xeno-radius-hair);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/* success / warning: colour text + border from the injected status-token var */
|
|
61
|
-
.xeno-statuspill[data-tone='success'],
|
|
62
|
-
.xeno-statuspill[data-tone='warning'] {
|
|
63
|
-
color: var(--xeno-pill-tone);
|
|
64
|
-
border-color: color-mix(in srgb, var(--xeno-pill-tone) 45%, transparent);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/* danger: the one status hue that IS a theme token */
|
|
68
|
-
.xeno-statuspill[data-tone='danger'] {
|
|
69
|
-
color: var(--xeno-danger);
|
|
70
|
-
border-color: color-mix(in srgb, var(--xeno-danger) 45%, transparent);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/* ── CountBadge ────────────────────────────────────────────────────────────────────── */
|
|
74
|
-
.xeno-countbadge {
|
|
75
|
-
display: inline-flex;
|
|
76
|
-
align-items: center;
|
|
77
|
-
justify-content: center;
|
|
78
|
-
box-sizing: border-box;
|
|
79
|
-
min-width: 16px;
|
|
80
|
-
height: 16px;
|
|
81
|
-
padding: 0 4px;
|
|
82
|
-
font-family: inherit;
|
|
83
|
-
font-size: 10px;
|
|
84
|
-
font-weight: 600;
|
|
85
|
-
line-height: 1;
|
|
86
|
-
font-variant-numeric: tabular-nums;
|
|
87
|
-
white-space: nowrap;
|
|
88
|
-
color: var(--xeno-text);
|
|
89
|
-
background: var(--xeno-control);
|
|
90
|
-
border: 1px solid var(--xeno-border);
|
|
91
|
-
border-radius: var(--xeno-radius-sm);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/* ── CitationBadge ─────────────────────────────────────────────────────────────────── */
|
|
95
|
-
.xeno-citation {
|
|
96
|
-
display: inline-flex;
|
|
97
|
-
align-items: center;
|
|
98
|
-
box-sizing: border-box;
|
|
99
|
-
height: 16px;
|
|
100
|
-
padding: 0 4px;
|
|
101
|
-
font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
|
|
102
|
-
font-size: 11px;
|
|
103
|
-
font-weight: 500;
|
|
104
|
-
line-height: 1;
|
|
105
|
-
white-space: nowrap;
|
|
106
|
-
vertical-align: baseline;
|
|
107
|
-
color: var(--xeno-muted);
|
|
108
|
-
background: var(--xeno-surface);
|
|
109
|
-
border: 1px solid var(--xeno-border);
|
|
110
|
-
border-radius: var(--xeno-radius-sm);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/* the index reads brighter than its muted brackets */
|
|
114
|
-
.xeno-citation-index {
|
|
115
|
-
color: var(--xeno-text);
|
|
116
|
-
}
|
|
1
|
+
/*
|
|
2
|
+
* Badges — inline monochrome markers (Badge / StatusPill / CountBadge / CitationBadge).
|
|
3
|
+
*
|
|
4
|
+
* CSS-first, driven by the theme custom properties from `xeno-theme.css`. These elements are STATIC
|
|
5
|
+
* (no interaction), so the only state seam is `data-tone` on the tonal members. Colours stay in the
|
|
6
|
+
* monochrome shell; the sole exception is the StatusPill status hue — `success`/`warning` arrive as
|
|
7
|
+
* the inline `--xeno-pill-tone` var (set from the status token by the renderer) and `danger` maps to
|
|
8
|
+
* `--xeno-danger`. Grammar: rounded squares, never circles. No literal colours here.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/* ── Badge ─────────────────────────────────────────────────────────────────────────── */
|
|
12
|
+
.xeno-badge {
|
|
13
|
+
display: inline-flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
gap: 4px;
|
|
16
|
+
height: 16px;
|
|
17
|
+
padding: 0 6px;
|
|
18
|
+
font-family: inherit;
|
|
19
|
+
font-size: 10px;
|
|
20
|
+
font-weight: 600;
|
|
21
|
+
line-height: 1;
|
|
22
|
+
letter-spacing: 0.05em;
|
|
23
|
+
text-transform: uppercase;
|
|
24
|
+
white-space: nowrap;
|
|
25
|
+
color: var(--xeno-muted);
|
|
26
|
+
background: var(--xeno-surface);
|
|
27
|
+
border: 1px solid var(--xeno-border);
|
|
28
|
+
border-radius: var(--xeno-radius-sm);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* ── StatusPill ────────────────────────────────────────────────────────────────────── */
|
|
32
|
+
.xeno-statuspill {
|
|
33
|
+
display: inline-flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
gap: 5px;
|
|
36
|
+
height: 16px;
|
|
37
|
+
padding: 0 6px;
|
|
38
|
+
font-family: inherit;
|
|
39
|
+
font-size: 10px;
|
|
40
|
+
font-weight: 600;
|
|
41
|
+
line-height: 1;
|
|
42
|
+
letter-spacing: 0.05em;
|
|
43
|
+
text-transform: uppercase;
|
|
44
|
+
white-space: nowrap;
|
|
45
|
+
color: var(--xeno-muted);
|
|
46
|
+
background: var(--xeno-surface);
|
|
47
|
+
border: 1px solid var(--xeno-border);
|
|
48
|
+
border-radius: var(--xeno-radius-sm);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* leading dot — a rounded SQUARE (never a circle), inheriting the pill tone via currentColor */
|
|
52
|
+
.xeno-statuspill-dot {
|
|
53
|
+
flex: none;
|
|
54
|
+
width: 5px;
|
|
55
|
+
height: 5px;
|
|
56
|
+
background: currentColor;
|
|
57
|
+
border-radius: var(--xeno-radius-hair);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* success / warning: colour text + border from the injected status-token var */
|
|
61
|
+
.xeno-statuspill[data-tone='success'],
|
|
62
|
+
.xeno-statuspill[data-tone='warning'] {
|
|
63
|
+
color: var(--xeno-pill-tone);
|
|
64
|
+
border-color: color-mix(in srgb, var(--xeno-pill-tone) 45%, transparent);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* danger: the one status hue that IS a theme token */
|
|
68
|
+
.xeno-statuspill[data-tone='danger'] {
|
|
69
|
+
color: var(--xeno-danger);
|
|
70
|
+
border-color: color-mix(in srgb, var(--xeno-danger) 45%, transparent);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* ── CountBadge ────────────────────────────────────────────────────────────────────── */
|
|
74
|
+
.xeno-countbadge {
|
|
75
|
+
display: inline-flex;
|
|
76
|
+
align-items: center;
|
|
77
|
+
justify-content: center;
|
|
78
|
+
box-sizing: border-box;
|
|
79
|
+
min-width: 16px;
|
|
80
|
+
height: 16px;
|
|
81
|
+
padding: 0 4px;
|
|
82
|
+
font-family: inherit;
|
|
83
|
+
font-size: 10px;
|
|
84
|
+
font-weight: 600;
|
|
85
|
+
line-height: 1;
|
|
86
|
+
font-variant-numeric: tabular-nums;
|
|
87
|
+
white-space: nowrap;
|
|
88
|
+
color: var(--xeno-text);
|
|
89
|
+
background: var(--xeno-control);
|
|
90
|
+
border: 1px solid var(--xeno-border);
|
|
91
|
+
border-radius: var(--xeno-radius-sm);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* ── CitationBadge ─────────────────────────────────────────────────────────────────── */
|
|
95
|
+
.xeno-citation {
|
|
96
|
+
display: inline-flex;
|
|
97
|
+
align-items: center;
|
|
98
|
+
box-sizing: border-box;
|
|
99
|
+
height: 16px;
|
|
100
|
+
padding: 0 4px;
|
|
101
|
+
font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
|
|
102
|
+
font-size: 11px;
|
|
103
|
+
font-weight: 500;
|
|
104
|
+
line-height: 1;
|
|
105
|
+
white-space: nowrap;
|
|
106
|
+
vertical-align: baseline;
|
|
107
|
+
color: var(--xeno-muted);
|
|
108
|
+
background: var(--xeno-surface);
|
|
109
|
+
border: 1px solid var(--xeno-border);
|
|
110
|
+
border-radius: var(--xeno-radius-sm);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* the index reads brighter than its muted brackets */
|
|
114
|
+
.xeno-citation-index {
|
|
115
|
+
color: var(--xeno-text);
|
|
116
|
+
}
|
|
@@ -1,70 +1,70 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Avatar + AvatarStack — a person/agent tile and its overlapping cluster. CSS-first: the square edge is
|
|
3
|
-
* an inline `--xeno-avatar-size` var (set by the component from `size`), so metrics never drift from the
|
|
4
|
-
* data. Rounded SQUARES only (`radius-xs`), never circles. Monochrome shell; depth is a hairline border
|
|
5
|
-
* plus, in the stack, a flat canvas ring. No literal colours — theme tokens only.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
.xeno-avatar {
|
|
9
|
-
display: inline-flex;
|
|
10
|
-
align-items: center;
|
|
11
|
-
justify-content: center;
|
|
12
|
-
flex: none;
|
|
13
|
-
box-sizing: border-box;
|
|
14
|
-
width: var(--xeno-avatar-size, 24px);
|
|
15
|
-
height: var(--xeno-avatar-size, 24px);
|
|
16
|
-
border: 1px solid var(--xeno-border);
|
|
17
|
-
border-radius: var(--xeno-radius-xs);
|
|
18
|
-
background: var(--xeno-control);
|
|
19
|
-
color: var(--xeno-muted);
|
|
20
|
-
overflow: hidden;
|
|
21
|
-
user-select: none;
|
|
22
|
-
vertical-align: middle;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/* Image fill — cover the square, clipped to its rounded corners. */
|
|
26
|
-
.xeno-avatar-img {
|
|
27
|
-
display: block;
|
|
28
|
-
width: 100%;
|
|
29
|
-
height: 100%;
|
|
30
|
-
object-fit: cover;
|
|
31
|
-
border-radius: inherit;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/* Initials + '+N' overflow text — centred, uppercase, muted, scaled off the edge length. */
|
|
35
|
-
.xeno-avatar-initials {
|
|
36
|
-
font-family: inherit;
|
|
37
|
-
font-size: calc(var(--xeno-avatar-size, 24px) * 0.4);
|
|
38
|
-
font-weight: 600;
|
|
39
|
-
line-height: 1;
|
|
40
|
-
letter-spacing: 0.02em;
|
|
41
|
-
color: var(--xeno-muted);
|
|
42
|
-
text-transform: uppercase;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/* Glyph fallback inherits the tile's muted ink via currentColor. */
|
|
46
|
-
.xeno-avatar[data-variant='icon'] {
|
|
47
|
-
color: var(--xeno-muted);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/* ── AvatarStack ─────────────────────────────────────────────────────────────────── */
|
|
51
|
-
.xeno-avatar-stack {
|
|
52
|
-
display: inline-flex;
|
|
53
|
-
align-items: center;
|
|
54
|
-
vertical-align: middle;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/* Overlap: pull each tile left and ring it in the canvas so the stack reads as separated squares. */
|
|
58
|
-
.xeno-avatar-stack > .xeno-avatar {
|
|
59
|
-
position: relative;
|
|
60
|
-
margin-left: -8px;
|
|
61
|
-
box-shadow: 0 0 0 2px var(--xeno-canvas);
|
|
62
|
-
}
|
|
63
|
-
.xeno-avatar-stack > .xeno-avatar:first-child {
|
|
64
|
-
margin-left: 0;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/* The '+N' tile sits on the elevated surface to distinguish it from the people tiles. */
|
|
68
|
-
.xeno-avatar-more {
|
|
69
|
-
background: var(--xeno-elevated);
|
|
70
|
-
}
|
|
1
|
+
/*
|
|
2
|
+
* Avatar + AvatarStack — a person/agent tile and its overlapping cluster. CSS-first: the square edge is
|
|
3
|
+
* an inline `--xeno-avatar-size` var (set by the component from `size`), so metrics never drift from the
|
|
4
|
+
* data. Rounded SQUARES only (`radius-xs`), never circles. Monochrome shell; depth is a hairline border
|
|
5
|
+
* plus, in the stack, a flat canvas ring. No literal colours — theme tokens only.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
.xeno-avatar {
|
|
9
|
+
display: inline-flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
justify-content: center;
|
|
12
|
+
flex: none;
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
width: var(--xeno-avatar-size, 24px);
|
|
15
|
+
height: var(--xeno-avatar-size, 24px);
|
|
16
|
+
border: 1px solid var(--xeno-border);
|
|
17
|
+
border-radius: var(--xeno-radius-xs);
|
|
18
|
+
background: var(--xeno-control);
|
|
19
|
+
color: var(--xeno-muted-text);
|
|
20
|
+
overflow: hidden;
|
|
21
|
+
user-select: none;
|
|
22
|
+
vertical-align: middle;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* Image fill — cover the square, clipped to its rounded corners. */
|
|
26
|
+
.xeno-avatar-img {
|
|
27
|
+
display: block;
|
|
28
|
+
width: 100%;
|
|
29
|
+
height: 100%;
|
|
30
|
+
object-fit: cover;
|
|
31
|
+
border-radius: inherit;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* Initials + '+N' overflow text — centred, uppercase, muted, scaled off the edge length. */
|
|
35
|
+
.xeno-avatar-initials {
|
|
36
|
+
font-family: inherit;
|
|
37
|
+
font-size: calc(var(--xeno-avatar-size, 24px) * 0.4);
|
|
38
|
+
font-weight: 600;
|
|
39
|
+
line-height: 1;
|
|
40
|
+
letter-spacing: 0.02em;
|
|
41
|
+
color: var(--xeno-muted-text);
|
|
42
|
+
text-transform: uppercase;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* Glyph fallback inherits the tile's muted ink via currentColor. */
|
|
46
|
+
.xeno-avatar[data-variant='icon'] {
|
|
47
|
+
color: var(--xeno-muted-text);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* ── AvatarStack ─────────────────────────────────────────────────────────────────── */
|
|
51
|
+
.xeno-avatar-stack {
|
|
52
|
+
display: inline-flex;
|
|
53
|
+
align-items: center;
|
|
54
|
+
vertical-align: middle;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* Overlap: pull each tile left and ring it in the canvas so the stack reads as separated squares. */
|
|
58
|
+
.xeno-avatar-stack > .xeno-avatar {
|
|
59
|
+
position: relative;
|
|
60
|
+
margin-left: -8px;
|
|
61
|
+
box-shadow: 0 0 0 2px var(--xeno-canvas);
|
|
62
|
+
}
|
|
63
|
+
.xeno-avatar-stack > .xeno-avatar:first-child {
|
|
64
|
+
margin-left: 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* The '+N' tile sits on the elevated surface to distinguish it from the people tiles. */
|
|
68
|
+
.xeno-avatar-more {
|
|
69
|
+
background: var(--xeno-elevated);
|
|
70
|
+
}
|