@mcp-b/design-tokens 0.20.5 → 0.21.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-b/design-tokens",
3
- "version": "0.20.5",
3
+ "version": "0.21.0",
4
4
  "description": "Shared design tokens for MCP-B React applications.",
5
5
  "homepage": "https://mcp-b-design-system-storybook.alexmnahas.workers.dev",
6
6
  "bugs": {
@@ -24,6 +24,8 @@
24
24
  "./index.css": "./src/index.css",
25
25
  "./borders": "./src/borders.css",
26
26
  "./borders.css": "./src/borders.css",
27
+ "./elevation": "./src/elevation.css",
28
+ "./elevation.css": "./src/elevation.css",
27
29
  "./focus": "./src/focus.css",
28
30
  "./focus.css": "./src/focus.css",
29
31
  "./motion": "./src/motion.css",
package/src/borders.css CHANGED
@@ -1,15 +1,58 @@
1
1
  /*
2
2
  * Border Tokens
3
+ *
4
+ * Radii are a base scale multiplied by --sigvelo-radius-scale, so a product,
5
+ * a theme, or one subtree can go rounder or squarer by setting a single
6
+ * variable instead of overriding every radius. Set it on :root for a global
7
+ * change, or on any element to rescale that subtree.
8
+ *
9
+ * --sigvelo-radius-full and --sigvelo-radius-circle stay unscaled: a pill and
10
+ * a circle are shapes, not sizes.
3
11
  */
4
12
 
5
13
  :root {
6
14
  --sigvelo-border-style: solid;
7
15
  --sigvelo-border-width: 1px;
8
- --sigvelo-radius-xs: 0.1875rem; /* 3px */
9
- --sigvelo-radius-sm: 0.25rem; /* 4px */
10
- --sigvelo-radius-md: 0.5rem; /* 8px */
11
- --sigvelo-radius-lg: 0.75rem; /* 12px */
12
- --sigvelo-radius-xl: 1rem; /* 16px */
16
+
17
+ /* Hairline rules and rings. Sub-pixel on 1x, crisp on 2x. */
18
+ --sigvelo-border-width-hairline: 0.5px;
19
+
20
+ --sigvelo-radius-scale: 1;
21
+
22
+ --sigvelo-radius-xs-base: 0.1875rem; /* 3px */
23
+ --sigvelo-radius-sm-base: 0.25rem; /* 4px */
24
+ --sigvelo-radius-md-base: 0.5rem; /* 8px */
25
+ --sigvelo-radius-lg-base: 0.75rem; /* 12px */
26
+ --sigvelo-radius-xl-base: 1rem; /* 16px */
27
+ --sigvelo-radius-2xl-base: 1.25rem; /* 20px */
28
+ --sigvelo-radius-3xl-base: 1.5rem; /* 24px */
29
+
30
+ --sigvelo-radius-xs: calc(var(--sigvelo-radius-xs-base) * var(--sigvelo-radius-scale));
31
+ --sigvelo-radius-sm: calc(var(--sigvelo-radius-sm-base) * var(--sigvelo-radius-scale));
32
+ --sigvelo-radius-md: calc(var(--sigvelo-radius-md-base) * var(--sigvelo-radius-scale));
33
+ --sigvelo-radius-lg: calc(var(--sigvelo-radius-lg-base) * var(--sigvelo-radius-scale));
34
+ --sigvelo-radius-xl: calc(var(--sigvelo-radius-xl-base) * var(--sigvelo-radius-scale));
35
+ --sigvelo-radius-2xl: calc(var(--sigvelo-radius-2xl-base) * var(--sigvelo-radius-scale));
36
+ --sigvelo-radius-3xl: calc(var(--sigvelo-radius-3xl-base) * var(--sigvelo-radius-scale));
37
+
13
38
  --sigvelo-radius-full: 9999px;
14
39
  --sigvelo-radius-circle: 50%;
40
+
41
+ /* Applied by the shared surface, row, control, and button recipes. Only
42
+ rounded rectangles opt in — pills and circles keep a true arc. */
43
+ --sigvelo-corner-shape: round;
44
+ }
45
+
46
+ /*
47
+ * Squircle corners where the browser can draw them. A superellipse cuts less
48
+ * material out of the corner than a circular arc, so the same radius reads
49
+ * tighter; the scale opens up to compensate and the two changes ship together.
50
+ * Browsers without corner-shape keep round corners at the unscaled radii and
51
+ * look exactly as they did before.
52
+ */
53
+ @supports (corner-shape: superellipse(1.5)) {
54
+ :root {
55
+ --sigvelo-corner-shape: superellipse(1.5);
56
+ --sigvelo-radius-scale: 1.25;
57
+ }
15
58
  }
@@ -0,0 +1,50 @@
1
+ /*
2
+ * Increased contrast.
3
+ *
4
+ * A request for more contrast is about the faint end of each ramp — quiet text
5
+ * and hairline edges — not about the whole palette. Brand hues, surfaces, and
6
+ * every on-color pairing stay exactly as authored, so no component opts in and
7
+ * no contrast pair that already passed gets re-tuned.
8
+ *
9
+ * Every declaration here reads a token this block does not itself reassign.
10
+ * Custom properties resolve to the winning value, so a chain of promotions
11
+ * inside one block (subtle -> muted -> base) would collapse all three onto the
12
+ * base and flatten the hierarchy instead of raising it. Borders deliberately do
13
+ * collapse — a divider that cannot be seen has no hierarchy to preserve — while
14
+ * text keeps three distinguishable steps, measured against the canvas.
15
+ *
16
+ * Remapping the resolved aliases rather than the -light/-dark inputs means one
17
+ * block covers system dark mode, both data-theme choices, and the light-dark()
18
+ * path together.
19
+ */
20
+ @media (prefers-contrast: more) {
21
+ :root {
22
+ /* Secondary text is the first thing to go. Muted reaches full foreground;
23
+ the two steps below it stay apart by mixing toward the canvas rather
24
+ than by referencing each other. */
25
+ --sigvelo-color-text-muted: var(--sigvelo-color-text);
26
+ --sigvelo-color-text-subtle: color-mix(
27
+ in oklab,
28
+ var(--sigvelo-color-text),
29
+ var(--sigvelo-color-canvas) 20%
30
+ );
31
+ --sigvelo-color-text-faint: color-mix(
32
+ in oklab,
33
+ var(--sigvelo-color-text),
34
+ var(--sigvelo-color-canvas) 35%
35
+ );
36
+
37
+ /* Hairlines at the subtle and muted steps round to nothing at this
38
+ contrast level, so both take the solid border for their hue. */
39
+ --sigvelo-color-neutral-border-subtle: var(--sigvelo-color-neutral-border);
40
+ --sigvelo-color-neutral-border-muted: var(--sigvelo-color-neutral-border);
41
+ --sigvelo-color-primary-border-subtle: var(--sigvelo-color-primary-border);
42
+ --sigvelo-color-primary-border-muted: var(--sigvelo-color-primary-border);
43
+ --sigvelo-color-success-border-subtle: var(--sigvelo-color-success-border);
44
+ --sigvelo-color-success-border-muted: var(--sigvelo-color-success-border);
45
+ --sigvelo-color-warning-border-subtle: var(--sigvelo-color-warning-border);
46
+ --sigvelo-color-warning-border-muted: var(--sigvelo-color-warning-border);
47
+ --sigvelo-color-danger-border-subtle: var(--sigvelo-color-danger-border);
48
+ --sigvelo-color-danger-border-muted: var(--sigvelo-color-danger-border);
49
+ }
50
+ }
@@ -0,0 +1,28 @@
1
+ /*
2
+ * Elevation Materials
3
+ *
4
+ * The geometry half of elevation: the composed filters that turn a
5
+ * translucent surface into frosted chrome. The color half — the layered
6
+ * shadows themselves — is theme-specific and lives in semantic-colors.css as
7
+ * the --sigvelo-elevation-* family.
8
+ *
9
+ * Elevation here is a stack, not a single shadow: a hairline ring that reads
10
+ * as an edge at any zoom, then a tight contact shadow, then a wide ambient
11
+ * one. That layering is what keeps a raised surface legible on both a white
12
+ * canvas and a near-black one.
13
+ */
14
+
15
+ :root {
16
+ /*
17
+ * Frosted chrome over scrolling content.
18
+ *
19
+ * Held to a single 8px radius, which is what the reference bundles use and as
20
+ * far as this can go without being felt. A backdrop filter repaints the whole
21
+ * area behind the element every frame, so a wider radius or a second pass
22
+ * such as saturate() on a full-viewport scrim costs frames on every dialog
23
+ * open — measurably, not theoretically: at blur(24px) saturate(180%) the
24
+ * Storybook suite dropped roughly a third of its runs to timing failures in
25
+ * stories that had nothing to do with dialogs.
26
+ */
27
+ --sigvelo-glass-filter: blur(8px);
28
+ }
package/src/focus.css CHANGED
@@ -5,7 +5,6 @@
5
5
  :root {
6
6
  --sigvelo-focus-width: 3px;
7
7
  --sigvelo-focus-offset: 1px;
8
- --sigvelo-backdrop-filter: blur(6px);
9
8
  /* Focus ring used in forced-colors mode, where the box-shadow ring is dropped. */
10
9
  --sigvelo-focus-ring-forced: 2px solid Highlight;
11
10
  }
package/src/index.css CHANGED
@@ -5,5 +5,8 @@
5
5
  @import "./focus.css";
6
6
  @import "./spacing.css";
7
7
  @import "./motion.css";
8
+ @import "./layers.css";
9
+ @import "./elevation.css";
8
10
  @import "./semantic-colors.css";
9
11
  @import "./themes.css";
12
+ @import "./contrast.css";
package/src/layers.css ADDED
@@ -0,0 +1,44 @@
1
+ /*
2
+ * Stacking layers.
3
+ *
4
+ * Only the bands that components have to agree on live here. Ordering *inside*
5
+ * a component — a gradient behind its own text, a badge over its own avatar —
6
+ * stays a plain 0/1/2 in that component's stylesheet, because naming a token
7
+ * for it would imply a cross-component contract that does not exist.
8
+ *
9
+ * The gaps between bands are deliberate. A component that needs to sit just
10
+ * above its band says so with calc() against the band it belongs to, which
11
+ * keeps the relationship legible instead of encoding it as a bare 23.
12
+ */
13
+
14
+ :root {
15
+ /* Sticky application chrome: app bars, pinned rows, and hover cards that
16
+ float within a scroll region but below anything modal. */
17
+ --sigvelo-z-chrome: 20;
18
+
19
+ /* Drag affordances — resize handles, splitters — which have to stay grabbable
20
+ above the chrome they resize. */
21
+ --sigvelo-z-panel: 25;
22
+
23
+ /* Base UI popups: dialog, alert dialog, popover, menu, tooltip, preview card.
24
+ One band for all of them, because the library already resolves their order
25
+ among themselves by mount order. */
26
+ --sigvelo-z-overlay: 50;
27
+
28
+ /* Toasts outrank overlays: a toast reporting the result of a dialog action
29
+ has to be readable while that dialog is still closing. */
30
+ --sigvelo-z-toast: 100;
31
+
32
+ /*
33
+ * Overlays drawn on top of a host page this design system does not control —
34
+ * a browser control surface injected into someone else's document. Max int is
35
+ * not a layer, it is a concession that we cannot see the other stylesheet.
36
+ * Nothing that renders inside our own tree may use it.
37
+ *
38
+ * Recorded here so the value has one documented home, but such a surface
39
+ * cannot actually reference it: it mounts in a closed shadow root where this
40
+ * sheet does not exist, so var() would resolve to nothing and z-index would
41
+ * silently fall back to auto. Those stylesheets inline the number instead.
42
+ */
43
+ --sigvelo-z-host-overlay: 2147483647;
44
+ }
package/src/motion.css CHANGED
@@ -7,6 +7,24 @@
7
7
  --sigvelo-ease-standard: cubic-bezier(0.2, 0, 0, 1);
8
8
  --sigvelo-ease-emphasized: cubic-bezier(0.16, 1, 0.3, 1);
9
9
  --sigvelo-ease-accelerate: cubic-bezier(0.4, 0, 1, 1);
10
+ /* Nearly all of the distance in the first third, then a long settle. Reads
11
+ as responsive on entrances that also move a long way. */
12
+ --sigvelo-ease-snappy: cubic-bezier(0.23, 1, 0.32, 1);
13
+ /* Press and release. A damped spring settling in three shrinking bounces —
14
+ a cubic-bezier can only overshoot once, which reads as a wobble rather
15
+ than a physical button. Keep it on transform; on color it just looks slow. */
16
+ --sigvelo-ease-press: linear(
17
+ 0,
18
+ 0.3505,
19
+ 0.7432,
20
+ 0.9336,
21
+ 0.9951,
22
+ 1.0062,
23
+ 1.0045,
24
+ 1.0019,
25
+ 1.0005,
26
+ 1
27
+ );
10
28
 
11
29
  /* Semantic motion roles keep component families on one quiet rhythm. */
12
30
  --sigvelo-motion-duration-interaction: var(--sigvelo-duration-fast);
@@ -16,11 +34,25 @@
16
34
  /* Looping "busy/streaming" text shimmer sweep. Not reduced with the
17
35
  interaction scale — reduced motion turns the shimmer off entirely. */
18
36
  --sigvelo-motion-duration-shimmer: 2400ms;
37
+ /* Breathing rate of a live-state indicator. Slower than a heartbeat on
38
+ purpose: fast enough to read as ongoing, slow enough to sit at the edge of
39
+ vision for minutes without demanding attention. Like the shimmer, reduced
40
+ motion switches it off rather than shortening it. */
41
+ --sigvelo-motion-duration-pulse: 1400ms;
42
+ /* One full turn of a spinner. A loop rate, not a transition duration: the
43
+ transition scale tops out at 360ms, which as a rotation period is a blur —
44
+ which is why every surface that wanted a spinner used to write its own
45
+ literal instead of the shared class. */
46
+ --sigvelo-motion-duration-spin: 900ms;
19
47
 
20
48
  --sigvelo-motion-ease-enter: var(--sigvelo-ease-emphasized);
21
49
  --sigvelo-motion-ease-exit: var(--sigvelo-ease-accelerate);
22
50
  --sigvelo-motion-ease-change: var(--sigvelo-ease-standard);
23
51
 
52
+ /* Delay between neighbours in a revealed list, so a group of rows arrives
53
+ as a sequence instead of a single block. Keep the total under ~200ms. */
54
+ --sigvelo-motion-stagger-step: 35ms;
55
+
24
56
  --sigvelo-motion-distance-xs: 1px;
25
57
  --sigvelo-motion-distance-sm: 4px;
26
58
  --sigvelo-motion-distance-md: 8px;
@@ -14,55 +14,116 @@
14
14
  --sigvelo-color-text-dark: var(--sigvelo-color-neutral-200);
15
15
  --sigvelo-color-text-muted-light: var(--sigvelo-color-neutral-700);
16
16
  --sigvelo-color-text-muted-dark: var(--sigvelo-color-neutral-500);
17
+ /* Two quieter rungs below muted, mixed toward the surface rather than
18
+ picked off the neutral ramp so they stay correct on a tinted surface.
19
+ subtle: de-emphasized label text, still holds ~4.5:1 against its surface.
20
+ faint: icons and resting affordances only — it clears the 3:1 needed for
21
+ a graphic, not the 4.5:1 needed for body copy. */
22
+ --sigvelo-color-text-subtle-light: color-mix(
23
+ in oklab,
24
+ var(--sigvelo-color-text-light),
25
+ var(--sigvelo-color-surface-light) 28%
26
+ );
27
+ --sigvelo-color-text-subtle-dark: color-mix(
28
+ in oklab,
29
+ var(--sigvelo-color-text-dark),
30
+ var(--sigvelo-color-surface-dark) 28%
31
+ );
32
+ --sigvelo-color-text-faint-light: color-mix(
33
+ in oklab,
34
+ var(--sigvelo-color-text-light),
35
+ var(--sigvelo-color-surface-light) 55%
36
+ );
37
+ --sigvelo-color-text-faint-dark: color-mix(
38
+ in oklab,
39
+ var(--sigvelo-color-text-dark),
40
+ var(--sigvelo-color-surface-dark) 55%
41
+ );
42
+ /* Surfaces that sit above the page. In light mode a raised card is the
43
+ same white as the surface and is separated by shadow alone; in dark mode
44
+ shadow does almost nothing, so the card lifts by getting lighter. */
45
+ --sigvelo-color-surface-raised-light: var(--sigvelo-color-surface-light);
46
+ --sigvelo-color-surface-raised-dark: color-mix(
47
+ in oklab,
48
+ var(--sigvelo-color-surface-dark),
49
+ white 5%
50
+ );
51
+ --sigvelo-color-surface-sunken-light: color-mix(
52
+ in oklab,
53
+ var(--sigvelo-color-surface-light),
54
+ var(--sigvelo-color-text-light) 3.5%
55
+ );
56
+ --sigvelo-color-surface-sunken-dark: color-mix(
57
+ in oklab,
58
+ var(--sigvelo-color-surface-dark),
59
+ black 35%
60
+ );
61
+ /* Translucent counterpart of surface-raised, for panels that blur what is
62
+ scrolling underneath. Pair with --sigvelo-glass-filter, and fall back to
63
+ surface-raised where backdrop-filter is unavailable. */
64
+ --sigvelo-color-surface-glass-light: color-mix(
65
+ in oklab,
66
+ var(--sigvelo-color-surface-raised-light),
67
+ transparent 28%
68
+ );
69
+ --sigvelo-color-surface-glass-dark: color-mix(
70
+ in oklab,
71
+ var(--sigvelo-color-surface-raised-dark),
72
+ transparent 20%
73
+ );
17
74
  --sigvelo-color-focus-light: var(--sigvelo-color-primary-bg-light);
18
75
  --sigvelo-color-focus-dark: var(--sigvelo-color-primary-bg-dark);
19
76
  --sigvelo-focus-ring-light: var(--sigvelo-border-style) var(--sigvelo-focus-width)
20
77
  var(--sigvelo-color-focus-light);
21
78
  --sigvelo-focus-ring-dark: var(--sigvelo-border-style) var(--sigvelo-focus-width)
22
79
  var(--sigvelo-color-focus-dark);
23
- --sigvelo-color-backdrop-light: rgb(0 0 0 / 0.5);
24
- --sigvelo-color-backdrop-dark: rgb(0 0 0 / 0.5);
80
+ /* Paired with --sigvelo-glass-filter on dialog scrims. Blur does most of the
81
+ separating, so the sheet itself stays light enough to keep the page behind
82
+ it legible. */
83
+ --sigvelo-color-backdrop-light: rgb(0 0 0 / 0.32);
84
+ --sigvelo-color-backdrop-dark: rgb(0 0 0 / 0.45);
25
85
  --sigvelo-color-selection-bg-light: var(--sigvelo-color-primary-300);
26
86
  --sigvelo-color-selection-bg-dark: var(--sigvelo-color-primary-700);
27
87
  --sigvelo-color-selection-text-light: var(--sigvelo-color-text-light);
28
88
  --sigvelo-color-selection-text-dark: var(--sigvelo-color-text-dark);
29
- --sigvelo-color-shadow-light: black;
30
- --sigvelo-color-shadow-dark: black;
31
- --sigvelo-shadow-xs-light: 0 0.0625rem 0.0625rem
32
- color-mix(in oklab, transparent, var(--sigvelo-color-shadow-light) 4%);
33
- --sigvelo-shadow-xs-dark: 0 1px 2px
34
- color-mix(in oklab, transparent, var(--sigvelo-color-shadow-dark) 8%);
35
- --sigvelo-shadow-sm-light: 0 0.125rem 0.1875rem
36
- color-mix(in oklab, transparent, var(--sigvelo-color-shadow-light) 8%);
37
- --sigvelo-shadow-sm-dark: 0 2px 4px
38
- color-mix(in oklab, transparent, var(--sigvelo-color-shadow-dark) 12%);
39
- --sigvelo-shadow-md-light: 0 0.1875rem 0.375rem
40
- color-mix(in oklab, transparent, var(--sigvelo-color-shadow-light) 10%);
41
- --sigvelo-shadow-md-dark: 0 4px 8px
42
- color-mix(in oklab, transparent, var(--sigvelo-color-shadow-dark) 16%);
43
- --sigvelo-shadow-lg-light: 0 0.375rem 0.75rem
44
- color-mix(in oklab, transparent, var(--sigvelo-color-shadow-light) 12%);
45
- --sigvelo-shadow-lg-dark: 0 8px 16px
46
- color-mix(in oklab, transparent, var(--sigvelo-color-shadow-dark) 20%);
47
- --sigvelo-shadow-xl-light: 0 0.5rem 1rem
48
- color-mix(in oklab, transparent, var(--sigvelo-color-shadow-light) 14%);
49
- --sigvelo-shadow-xl-dark: 0 12px 20px
50
- color-mix(in oklab, transparent, var(--sigvelo-color-shadow-dark) 24%);
51
- --sigvelo-inset-shadow-xs-light: inset 0 0.125rem 0.125rem -0.125rem
52
- color-mix(in oklab, black, transparent 94%);
53
- --sigvelo-inset-shadow-xs-dark: var(--sigvelo-inset-shadow-xs-light);
54
- --sigvelo-inset-shadow-sm-light: inset 0 0.25rem 0.25rem -0.25rem
55
- color-mix(in oklab, black, transparent 90%);
56
- --sigvelo-inset-shadow-sm-dark: var(--sigvelo-inset-shadow-sm-light);
57
- --sigvelo-inset-shadow-md-light: inset 0 0.5rem 0.5rem -0.5rem
58
- color-mix(in oklab, black, transparent 88%);
59
- --sigvelo-inset-shadow-md-dark: var(--sigvelo-inset-shadow-md-light);
60
- --sigvelo-inset-shadow-lg-light: inset 0 1rem 1rem -1rem
61
- color-mix(in oklab, black, transparent 85%);
62
- --sigvelo-inset-shadow-lg-dark: var(--sigvelo-inset-shadow-lg-light);
63
- --sigvelo-inset-shadow-xl-light: inset 0 1.5rem 1.5rem -1.5rem
64
- color-mix(in oklab, black, transparent 82%);
65
- --sigvelo-inset-shadow-xl-dark: var(--sigvelo-inset-shadow-xl-light);
89
+ /* One color for both themes. What differs between light and dark is how much
90
+ of it each stack mixes in, and that lives in the stacks below. */
91
+ --sigvelo-color-shadow: black;
92
+
93
+ /* Elevation stacks. Each begins with the hairline ring below — a sub-pixel
94
+ edge that survives zoom and keeps a shadowed surface from dissolving into
95
+ the canvas when the shadow itself is nearly invisible. */
96
+ --sigvelo-elevation-hairline-light: 0 0 0 var(--sigvelo-border-width-hairline)
97
+ color-mix(in oklab, transparent, var(--sigvelo-color-shadow) 8%);
98
+ --sigvelo-elevation-hairline-dark: 0 0 0 var(--sigvelo-border-width-hairline)
99
+ color-mix(in oklab, transparent, white 10%);
100
+ /* raised: rows, cards, anything one step off the page. */
101
+ --sigvelo-elevation-raised-light:
102
+ var(--sigvelo-elevation-hairline-light),
103
+ 0 1px 2px -1px color-mix(in oklab, transparent, var(--sigvelo-color-shadow) 8%);
104
+ --sigvelo-elevation-raised-dark:
105
+ var(--sigvelo-elevation-hairline-dark),
106
+ 0 1px 2px -1px color-mix(in oklab, transparent, var(--sigvelo-color-shadow) 40%);
107
+ /* floating: composers and toolbars that hover over scrolling content. The
108
+ wide spread-free ambient layer is what reads as "off the page" rather
109
+ than "outlined". */
110
+ --sigvelo-elevation-floating-light:
111
+ var(--sigvelo-elevation-hairline-light),
112
+ 0 3px 7.5px color-mix(in oklab, transparent, var(--sigvelo-color-shadow) 4%),
113
+ 0 0 20px color-mix(in oklab, transparent, var(--sigvelo-color-shadow) 5%);
114
+ --sigvelo-elevation-floating-dark:
115
+ var(--sigvelo-elevation-hairline-dark),
116
+ 0 3px 7.5px color-mix(in oklab, transparent, var(--sigvelo-color-shadow) 32%),
117
+ 0 0 20px color-mix(in oklab, transparent, var(--sigvelo-color-shadow) 28%);
118
+ /* overlay: popovers, menus, dialogs — detached from the page entirely. */
119
+ --sigvelo-elevation-overlay-light:
120
+ var(--sigvelo-elevation-hairline-light),
121
+ 0 8px 16px -4px color-mix(in oklab, transparent, var(--sigvelo-color-shadow) 12%),
122
+ 0 16px 32px -8px color-mix(in oklab, transparent, var(--sigvelo-color-shadow) 19%);
123
+ --sigvelo-elevation-overlay-dark:
124
+ var(--sigvelo-elevation-hairline-dark),
125
+ 0 8px 16px -4px color-mix(in oklab, transparent, var(--sigvelo-color-shadow) 44%),
126
+ 0 16px 32px -8px color-mix(in oklab, transparent, var(--sigvelo-color-shadow) 56%);
66
127
  --sigvelo-color-primary-bg-subtle-light: var(--sigvelo-color-primary-100);
67
128
  --sigvelo-color-primary-bg-subtle-dark: color-mix(
68
129
  in oklab,
package/src/spacing.css CHANGED
@@ -1,29 +1,46 @@
1
1
  /*
2
2
  * Spacing & Form Control Tokens
3
+ *
4
+ * One 4px grid, named by quarter-rem step: --sigvelo-spacing-3 is 3 × 0.25rem
5
+ * = 12px. The scale is dense through the range components actually lay out in
6
+ * and thins out above 48px, where sizing becomes layout rather than spacing.
7
+ *
8
+ * Every control height and gap in this file resolves to a step on that grid.
9
+ * If a value you need is not on the scale, that is the signal to reconsider the
10
+ * value rather than to write the number: audit:css-recipes rejects off-grid
11
+ * lengths in component spacing.
3
12
  */
4
13
 
5
14
  :root {
6
15
  /* Spacing scale */
7
- --sigvelo-spacing-0-5: 0.125rem;
8
- --sigvelo-spacing-1: 0.25rem;
9
- --sigvelo-spacing-1-5: 0.375rem;
10
- --sigvelo-spacing-2: 0.5rem;
11
- --sigvelo-spacing-2-5: 0.625rem;
12
- --sigvelo-spacing-3: 0.75rem;
13
- --sigvelo-spacing-4: 1rem;
14
- --sigvelo-spacing-5: 1.25rem;
15
- --sigvelo-spacing-6: 1.5rem;
16
- --sigvelo-spacing-8: 2rem;
17
- --sigvelo-spacing-12: 3rem;
16
+ --sigvelo-spacing-0-5: 0.125rem; /* 2px */
17
+ --sigvelo-spacing-1: 0.25rem; /* 4px */
18
+ --sigvelo-spacing-1-5: 0.375rem; /* 6px */
19
+ --sigvelo-spacing-2: 0.5rem; /* 8px */
20
+ --sigvelo-spacing-2-5: 0.625rem; /* 10px */
21
+ --sigvelo-spacing-3: 0.75rem; /* 12px */
22
+ --sigvelo-spacing-3-5: 0.875rem; /* 14px */
23
+ --sigvelo-spacing-4: 1rem; /* 16px */
24
+ --sigvelo-spacing-5: 1.25rem; /* 20px */
25
+ --sigvelo-spacing-6: 1.5rem; /* 24px */
26
+ --sigvelo-spacing-7: 1.75rem; /* 28px */
27
+ --sigvelo-spacing-8: 2rem; /* 32px */
28
+ --sigvelo-spacing-9: 2.25rem; /* 36px */
29
+ --sigvelo-spacing-10: 2.5rem; /* 40px */
30
+ --sigvelo-spacing-11: 2.75rem; /* 44px */
31
+ --sigvelo-spacing-12: 3rem; /* 48px */
32
+ --sigvelo-spacing-14: 3.5rem; /* 56px */
33
+ --sigvelo-spacing-16: 4rem; /* 64px */
34
+ --sigvelo-spacing-20: 5rem; /* 80px */
35
+ --sigvelo-spacing-24: 6rem; /* 96px */
18
36
 
19
- --sigvelo-spacing-content: 1.75rem;
20
-
21
- /* Form control heights per size */
22
- --sigvelo-control-height-xs: 1.75rem;
23
- --sigvelo-control-height-sm: 2rem;
24
- --sigvelo-control-height-md: 2.25rem;
25
- --sigvelo-control-height-lg: 2.5rem;
26
- --sigvelo-control-height-xl: 2.75rem;
37
+ /* Form control heights per size. Expressed on the spacing scale so a panel,
38
+ a gap, or a reserved gutter can line up with a control by name. */
39
+ --sigvelo-control-height-xs: var(--sigvelo-spacing-7); /* 28px */
40
+ --sigvelo-control-height-sm: var(--sigvelo-spacing-8); /* 32px */
41
+ --sigvelo-control-height-md: var(--sigvelo-spacing-9); /* 36px */
42
+ --sigvelo-control-height-lg: var(--sigvelo-spacing-10); /* 40px */
43
+ --sigvelo-control-height-xl: var(--sigvelo-spacing-11); /* 44px */
27
44
 
28
45
  /* Form control font sizes per size */
29
46
  --sigvelo-control-text-xs: 0.75rem;
@@ -32,34 +49,46 @@
32
49
  --sigvelo-control-text-lg: 1rem;
33
50
  --sigvelo-control-text-xl: 1.125rem;
34
51
 
52
+ /* The leading that belongs to each of those sizes, from the type ramp's
53
+ whole-pixel partners. A ratio applied to a size that is itself a variable
54
+ lands on fractions — 13px at 1.25 is 16.25px — and a stack of rows then
55
+ drifts off the 4px grid a quarter pixel at a time. Every one of these fits
56
+ inside the matching control height with room to spare, so a control keeps
57
+ its box and gains a predictable baseline. */
58
+ --sigvelo-control-line-height-xs: var(--sigvelo-text-xs-leading); /* 16px */
59
+ --sigvelo-control-line-height-sm: var(--sigvelo-text-compact-leading); /* 18px */
60
+ --sigvelo-control-line-height-md: var(--sigvelo-text-sm-leading); /* 20px */
61
+ --sigvelo-control-line-height-lg: var(--sigvelo-text-base-leading); /* 24px */
62
+ --sigvelo-control-line-height-xl: var(--sigvelo-text-lg-leading); /* 28px */
63
+
35
64
  /* Canonical control geometry derived from the public size scale. */
36
65
  --sigvelo-control-padding-inline-xs: var(--sigvelo-spacing-2);
37
66
  --sigvelo-control-padding-inline-sm: var(--sigvelo-spacing-2-5);
38
67
  --sigvelo-control-padding-inline-md: var(--sigvelo-spacing-3);
39
68
  --sigvelo-control-padding-inline-lg: var(--sigvelo-spacing-4);
40
69
  --sigvelo-control-padding-inline-xl: var(--sigvelo-spacing-5);
41
- --sigvelo-control-icon-size-xs: 0.75rem;
42
- --sigvelo-control-icon-size-sm: 0.875rem;
43
- --sigvelo-control-icon-size-md: 1rem;
44
- --sigvelo-control-icon-size-lg: 1.125rem;
45
- --sigvelo-control-icon-size-xl: 1.25rem;
70
+
71
+ /* Icons ride the type ramp rather than a scale of their own: a glyph beside
72
+ a label should be the size of the label, not a nearby round number. */
73
+ --sigvelo-control-icon-size-xs: var(--sigvelo-text-xs); /* 12px */
74
+ --sigvelo-control-icon-size-sm: var(--sigvelo-text-sm); /* 14px */
75
+ --sigvelo-control-icon-size-md: var(--sigvelo-text-base); /* 16px */
76
+ --sigvelo-control-icon-size-lg: var(--sigvelo-text-lg); /* 18px */
77
+ --sigvelo-control-icon-size-xl: var(--sigvelo-text-xl); /* 20px */
46
78
 
47
79
  /* Compact application density. Product chrome and shared recipes resolve
48
80
  through these aliases so density can be tuned in one place. */
49
81
  --sigvelo-density-compact-control-height: var(--sigvelo-control-height-sm);
50
82
  --sigvelo-density-compact-control-padding-inline: var(--sigvelo-control-padding-inline-sm);
51
83
  --sigvelo-density-compact-control-font-size: var(--sigvelo-control-text-sm);
84
+ --sigvelo-density-compact-control-line-height: var(--sigvelo-control-line-height-sm);
52
85
  --sigvelo-density-compact-control-icon-size: var(--sigvelo-control-icon-size-sm);
53
86
  --sigvelo-density-compact-control-gap: var(--sigvelo-spacing-1-5);
54
87
 
55
88
  /* Form control misc */
56
- --sigvelo-control-required-content: "*";
57
89
  --sigvelo-control-placeholder-color: color-mix(
58
90
  in oklab,
59
91
  var(--sigvelo-color-text-muted),
60
92
  transparent 25%
61
93
  );
62
-
63
- /* Button */
64
- --sigvelo-button-active-offset: 1.5px;
65
94
  }
package/src/themes.css CHANGED
@@ -9,24 +9,22 @@
9
9
  color-scheme: light dark;
10
10
  --sigvelo-color-canvas: var(--sigvelo-color-canvas-light);
11
11
  --sigvelo-color-surface: var(--sigvelo-color-surface-light);
12
+ --sigvelo-color-surface-raised: var(--sigvelo-color-surface-raised-light);
13
+ --sigvelo-color-surface-sunken: var(--sigvelo-color-surface-sunken-light);
14
+ --sigvelo-color-surface-glass: var(--sigvelo-color-surface-glass-light);
12
15
  --sigvelo-color-text: var(--sigvelo-color-text-light);
13
16
  --sigvelo-color-text-muted: var(--sigvelo-color-text-muted-light);
17
+ --sigvelo-color-text-subtle: var(--sigvelo-color-text-subtle-light);
18
+ --sigvelo-color-text-faint: var(--sigvelo-color-text-faint-light);
14
19
  --sigvelo-color-focus: var(--sigvelo-color-focus-light);
15
20
  --sigvelo-focus-ring: var(--sigvelo-focus-ring-light);
16
21
  --sigvelo-color-backdrop: var(--sigvelo-color-backdrop-light);
17
22
  --sigvelo-color-selection-bg: var(--sigvelo-color-selection-bg-light);
18
23
  --sigvelo-color-selection-text: var(--sigvelo-color-selection-text-light);
19
- --sigvelo-color-shadow: var(--sigvelo-color-shadow-light);
20
- --sigvelo-shadow-xs: var(--sigvelo-shadow-xs-light);
21
- --sigvelo-shadow-sm: var(--sigvelo-shadow-sm-light);
22
- --sigvelo-shadow-md: var(--sigvelo-shadow-md-light);
23
- --sigvelo-shadow-lg: var(--sigvelo-shadow-lg-light);
24
- --sigvelo-shadow-xl: var(--sigvelo-shadow-xl-light);
25
- --sigvelo-inset-shadow-xs: var(--sigvelo-inset-shadow-xs-light);
26
- --sigvelo-inset-shadow-sm: var(--sigvelo-inset-shadow-sm-light);
27
- --sigvelo-inset-shadow-md: var(--sigvelo-inset-shadow-md-light);
28
- --sigvelo-inset-shadow-lg: var(--sigvelo-inset-shadow-lg-light);
29
- --sigvelo-inset-shadow-xl: var(--sigvelo-inset-shadow-xl-light);
24
+ --sigvelo-elevation-hairline: var(--sigvelo-elevation-hairline-light);
25
+ --sigvelo-elevation-raised: var(--sigvelo-elevation-raised-light);
26
+ --sigvelo-elevation-floating: var(--sigvelo-elevation-floating-light);
27
+ --sigvelo-elevation-overlay: var(--sigvelo-elevation-overlay-light);
30
28
  --sigvelo-color-primary-bg-subtle: var(--sigvelo-color-primary-bg-subtle-light);
31
29
  --sigvelo-color-primary-bg-muted: var(--sigvelo-color-primary-bg-muted-light);
32
30
  --sigvelo-color-primary-bg: var(--sigvelo-color-primary-bg-light);
@@ -95,24 +93,22 @@
95
93
  :root {
96
94
  --sigvelo-color-canvas: var(--sigvelo-color-canvas-dark);
97
95
  --sigvelo-color-surface: var(--sigvelo-color-surface-dark);
96
+ --sigvelo-color-surface-raised: var(--sigvelo-color-surface-raised-dark);
97
+ --sigvelo-color-surface-sunken: var(--sigvelo-color-surface-sunken-dark);
98
+ --sigvelo-color-surface-glass: var(--sigvelo-color-surface-glass-dark);
98
99
  --sigvelo-color-text: var(--sigvelo-color-text-dark);
99
100
  --sigvelo-color-text-muted: var(--sigvelo-color-text-muted-dark);
101
+ --sigvelo-color-text-subtle: var(--sigvelo-color-text-subtle-dark);
102
+ --sigvelo-color-text-faint: var(--sigvelo-color-text-faint-dark);
100
103
  --sigvelo-color-focus: var(--sigvelo-color-focus-dark);
101
104
  --sigvelo-focus-ring: var(--sigvelo-focus-ring-dark);
102
105
  --sigvelo-color-backdrop: var(--sigvelo-color-backdrop-dark);
103
106
  --sigvelo-color-selection-bg: var(--sigvelo-color-selection-bg-dark);
104
107
  --sigvelo-color-selection-text: var(--sigvelo-color-selection-text-dark);
105
- --sigvelo-color-shadow: var(--sigvelo-color-shadow-dark);
106
- --sigvelo-shadow-xs: var(--sigvelo-shadow-xs-dark);
107
- --sigvelo-shadow-sm: var(--sigvelo-shadow-sm-dark);
108
- --sigvelo-shadow-md: var(--sigvelo-shadow-md-dark);
109
- --sigvelo-shadow-lg: var(--sigvelo-shadow-lg-dark);
110
- --sigvelo-shadow-xl: var(--sigvelo-shadow-xl-dark);
111
- --sigvelo-inset-shadow-xs: var(--sigvelo-inset-shadow-xs-dark);
112
- --sigvelo-inset-shadow-sm: var(--sigvelo-inset-shadow-sm-dark);
113
- --sigvelo-inset-shadow-md: var(--sigvelo-inset-shadow-md-dark);
114
- --sigvelo-inset-shadow-lg: var(--sigvelo-inset-shadow-lg-dark);
115
- --sigvelo-inset-shadow-xl: var(--sigvelo-inset-shadow-xl-dark);
108
+ --sigvelo-elevation-hairline: var(--sigvelo-elevation-hairline-dark);
109
+ --sigvelo-elevation-raised: var(--sigvelo-elevation-raised-dark);
110
+ --sigvelo-elevation-floating: var(--sigvelo-elevation-floating-dark);
111
+ --sigvelo-elevation-overlay: var(--sigvelo-elevation-overlay-dark);
116
112
  --sigvelo-color-primary-bg-subtle: var(--sigvelo-color-primary-bg-subtle-dark);
117
113
  --sigvelo-color-primary-bg-muted: var(--sigvelo-color-primary-bg-muted-dark);
118
114
  --sigvelo-color-primary-bg: var(--sigvelo-color-primary-bg-dark);
@@ -180,24 +176,22 @@
180
176
  color-scheme: light;
181
177
  --sigvelo-color-canvas: var(--sigvelo-color-canvas-light);
182
178
  --sigvelo-color-surface: var(--sigvelo-color-surface-light);
179
+ --sigvelo-color-surface-raised: var(--sigvelo-color-surface-raised-light);
180
+ --sigvelo-color-surface-sunken: var(--sigvelo-color-surface-sunken-light);
181
+ --sigvelo-color-surface-glass: var(--sigvelo-color-surface-glass-light);
183
182
  --sigvelo-color-text: var(--sigvelo-color-text-light);
184
183
  --sigvelo-color-text-muted: var(--sigvelo-color-text-muted-light);
184
+ --sigvelo-color-text-subtle: var(--sigvelo-color-text-subtle-light);
185
+ --sigvelo-color-text-faint: var(--sigvelo-color-text-faint-light);
185
186
  --sigvelo-color-focus: var(--sigvelo-color-focus-light);
186
187
  --sigvelo-focus-ring: var(--sigvelo-focus-ring-light);
187
188
  --sigvelo-color-backdrop: var(--sigvelo-color-backdrop-light);
188
189
  --sigvelo-color-selection-bg: var(--sigvelo-color-selection-bg-light);
189
190
  --sigvelo-color-selection-text: var(--sigvelo-color-selection-text-light);
190
- --sigvelo-color-shadow: var(--sigvelo-color-shadow-light);
191
- --sigvelo-shadow-xs: var(--sigvelo-shadow-xs-light);
192
- --sigvelo-shadow-sm: var(--sigvelo-shadow-sm-light);
193
- --sigvelo-shadow-md: var(--sigvelo-shadow-md-light);
194
- --sigvelo-shadow-lg: var(--sigvelo-shadow-lg-light);
195
- --sigvelo-shadow-xl: var(--sigvelo-shadow-xl-light);
196
- --sigvelo-inset-shadow-xs: var(--sigvelo-inset-shadow-xs-light);
197
- --sigvelo-inset-shadow-sm: var(--sigvelo-inset-shadow-sm-light);
198
- --sigvelo-inset-shadow-md: var(--sigvelo-inset-shadow-md-light);
199
- --sigvelo-inset-shadow-lg: var(--sigvelo-inset-shadow-lg-light);
200
- --sigvelo-inset-shadow-xl: var(--sigvelo-inset-shadow-xl-light);
191
+ --sigvelo-elevation-hairline: var(--sigvelo-elevation-hairline-light);
192
+ --sigvelo-elevation-raised: var(--sigvelo-elevation-raised-light);
193
+ --sigvelo-elevation-floating: var(--sigvelo-elevation-floating-light);
194
+ --sigvelo-elevation-overlay: var(--sigvelo-elevation-overlay-light);
201
195
  --sigvelo-color-primary-bg-subtle: var(--sigvelo-color-primary-bg-subtle-light);
202
196
  --sigvelo-color-primary-bg-muted: var(--sigvelo-color-primary-bg-muted-light);
203
197
  --sigvelo-color-primary-bg: var(--sigvelo-color-primary-bg-light);
@@ -265,24 +259,22 @@
265
259
  color-scheme: dark;
266
260
  --sigvelo-color-canvas: var(--sigvelo-color-canvas-dark);
267
261
  --sigvelo-color-surface: var(--sigvelo-color-surface-dark);
262
+ --sigvelo-color-surface-raised: var(--sigvelo-color-surface-raised-dark);
263
+ --sigvelo-color-surface-sunken: var(--sigvelo-color-surface-sunken-dark);
264
+ --sigvelo-color-surface-glass: var(--sigvelo-color-surface-glass-dark);
268
265
  --sigvelo-color-text: var(--sigvelo-color-text-dark);
269
266
  --sigvelo-color-text-muted: var(--sigvelo-color-text-muted-dark);
267
+ --sigvelo-color-text-subtle: var(--sigvelo-color-text-subtle-dark);
268
+ --sigvelo-color-text-faint: var(--sigvelo-color-text-faint-dark);
270
269
  --sigvelo-color-focus: var(--sigvelo-color-focus-dark);
271
270
  --sigvelo-focus-ring: var(--sigvelo-focus-ring-dark);
272
271
  --sigvelo-color-backdrop: var(--sigvelo-color-backdrop-dark);
273
272
  --sigvelo-color-selection-bg: var(--sigvelo-color-selection-bg-dark);
274
273
  --sigvelo-color-selection-text: var(--sigvelo-color-selection-text-dark);
275
- --sigvelo-color-shadow: var(--sigvelo-color-shadow-dark);
276
- --sigvelo-shadow-xs: var(--sigvelo-shadow-xs-dark);
277
- --sigvelo-shadow-sm: var(--sigvelo-shadow-sm-dark);
278
- --sigvelo-shadow-md: var(--sigvelo-shadow-md-dark);
279
- --sigvelo-shadow-lg: var(--sigvelo-shadow-lg-dark);
280
- --sigvelo-shadow-xl: var(--sigvelo-shadow-xl-dark);
281
- --sigvelo-inset-shadow-xs: var(--sigvelo-inset-shadow-xs-dark);
282
- --sigvelo-inset-shadow-sm: var(--sigvelo-inset-shadow-sm-dark);
283
- --sigvelo-inset-shadow-md: var(--sigvelo-inset-shadow-md-dark);
284
- --sigvelo-inset-shadow-lg: var(--sigvelo-inset-shadow-lg-dark);
285
- --sigvelo-inset-shadow-xl: var(--sigvelo-inset-shadow-xl-dark);
274
+ --sigvelo-elevation-hairline: var(--sigvelo-elevation-hairline-dark);
275
+ --sigvelo-elevation-raised: var(--sigvelo-elevation-raised-dark);
276
+ --sigvelo-elevation-floating: var(--sigvelo-elevation-floating-dark);
277
+ --sigvelo-elevation-overlay: var(--sigvelo-elevation-overlay-dark);
286
278
  --sigvelo-color-primary-bg-subtle: var(--sigvelo-color-primary-bg-subtle-dark);
287
279
  --sigvelo-color-primary-bg-muted: var(--sigvelo-color-primary-bg-muted-dark);
288
280
  --sigvelo-color-primary-bg: var(--sigvelo-color-primary-bg-dark);
@@ -359,6 +351,18 @@
359
351
  var(--sigvelo-color-surface-light),
360
352
  var(--sigvelo-color-surface-dark)
361
353
  );
354
+ --sigvelo-color-surface-raised: light-dark(
355
+ var(--sigvelo-color-surface-raised-light),
356
+ var(--sigvelo-color-surface-raised-dark)
357
+ );
358
+ --sigvelo-color-surface-sunken: light-dark(
359
+ var(--sigvelo-color-surface-sunken-light),
360
+ var(--sigvelo-color-surface-sunken-dark)
361
+ );
362
+ --sigvelo-color-surface-glass: light-dark(
363
+ var(--sigvelo-color-surface-glass-light),
364
+ var(--sigvelo-color-surface-glass-dark)
365
+ );
362
366
  --sigvelo-color-text: light-dark(
363
367
  var(--sigvelo-color-text-light),
364
368
  var(--sigvelo-color-text-dark)
@@ -367,6 +371,14 @@
367
371
  var(--sigvelo-color-text-muted-light),
368
372
  var(--sigvelo-color-text-muted-dark)
369
373
  );
374
+ --sigvelo-color-text-subtle: light-dark(
375
+ var(--sigvelo-color-text-subtle-light),
376
+ var(--sigvelo-color-text-subtle-dark)
377
+ );
378
+ --sigvelo-color-text-faint: light-dark(
379
+ var(--sigvelo-color-text-faint-light),
380
+ var(--sigvelo-color-text-faint-dark)
381
+ );
370
382
  --sigvelo-color-focus: light-dark(
371
383
  var(--sigvelo-color-focus-light),
372
384
  var(--sigvelo-color-focus-dark)
@@ -383,10 +395,6 @@
383
395
  var(--sigvelo-color-selection-text-light),
384
396
  var(--sigvelo-color-selection-text-dark)
385
397
  );
386
- --sigvelo-color-shadow: light-dark(
387
- var(--sigvelo-color-shadow-light),
388
- var(--sigvelo-color-shadow-dark)
389
- );
390
398
  --sigvelo-color-primary-bg-subtle: light-dark(
391
399
  var(--sigvelo-color-primary-bg-subtle-light),
392
400
  var(--sigvelo-color-primary-bg-subtle-dark)
@@ -9,6 +9,22 @@
9
9
  SFMono-Regular, Consolas, Menlo, Monaco, "liberation mono", "Courier New", monospace;
10
10
  --sigvelo-text-root: 16px;
11
11
 
12
+ /*
13
+ * Reading roles. Interface chrome, the assistant's prose, and the user's own
14
+ * words are three different reading tasks, and products routinely want them
15
+ * set differently — a serif response against a sans UI is the common one.
16
+ * All three resolve to the sans face until a consumer says otherwise, so
17
+ * nothing changes by default.
18
+ */
19
+ --sigvelo-font-ui: var(--sigvelo-font-sans);
20
+ --sigvelo-font-response: var(--sigvelo-font-sans);
21
+ --sigvelo-font-user-message: var(--sigvelo-font-sans);
22
+
23
+ /* Named so [data-font="dyslexic"] has something to point at. The face is not
24
+ bundled; a consumer that wants it self-hosts OpenDyslexic and the stack
25
+ falls through to a wide-spaced serif everywhere else. */
26
+ --sigvelo-font-dyslexic: "OpenDyslexic", "Comic Sans MS", Georgia, serif;
27
+
12
28
  /* Type scale */
13
29
  --sigvelo-text-3xs: 0.625rem;
14
30
  --sigvelo-text-2xs: 0.6875rem;
@@ -35,8 +51,15 @@
35
51
  --sigvelo-font-weight-semibold: 500;
36
52
  --sigvelo-font-weight-bold: 700;
37
53
 
38
- /* Line heights */
39
- --sigvelo-leading-body: 1.6;
54
+ /*
55
+ * Line heights.
56
+ *
57
+ * The ratio scale below is for prose, where leading should grow with the
58
+ * reader's font size. For interface text, prefer the paired absolutes
59
+ * further down: they are quantized to whole pixels, so a stack of labels,
60
+ * rows, and icons lands on the same rhythm the spacing scale uses instead of
61
+ * accumulating fractional drift.
62
+ */
40
63
  --sigvelo-leading-none: 1;
41
64
  --sigvelo-leading-tight: 1.2;
42
65
  --sigvelo-leading-compact: 1.25;
@@ -45,8 +68,62 @@
45
68
  --sigvelo-leading-relaxed: 1.625;
46
69
  --sigvelo-leading-loose: 2;
47
70
 
48
- /* Letter spacing */
71
+ /*
72
+ * One leading per type step. Setting a size and its partner keeps every
73
+ * label of that size on the same baseline rhythm without anyone choosing a
74
+ * ratio by eye. Small text takes a proportionally tighter measure and large
75
+ * text a looser one, which is why these are not one multiplier.
76
+ */
77
+ --sigvelo-text-3xs-leading: 0.875rem; /* 14px */
78
+ --sigvelo-text-2xs-leading: 1rem; /* 16px */
79
+ --sigvelo-text-xs-leading: 1rem; /* 16px */
80
+ --sigvelo-text-compact-leading: 1.125rem; /* 18px */
81
+ --sigvelo-text-sm-leading: 1.25rem; /* 20px */
82
+ --sigvelo-text-base-leading: 1.5rem; /* 24px */
83
+ --sigvelo-text-lg-leading: 1.75rem; /* 28px */
84
+ --sigvelo-text-xl-leading: 1.75rem; /* 28px */
85
+ --sigvelo-text-2xl-leading: 2rem; /* 32px */
86
+ --sigvelo-text-3xl-leading: 2.25rem; /* 36px */
87
+ --sigvelo-text-4xl-leading: 2.5rem; /* 40px */
88
+ --sigvelo-text-5xl-leading: 3rem; /* 48px */
89
+
90
+ /* Letter spacing. Large type set at the default tracking looks loose, so
91
+ display headings tighten as they grow. */
92
+ --sigvelo-tracking-tighter: -0.03em;
93
+ --sigvelo-tracking-tight: -0.015em;
49
94
  --sigvelo-tracking-normal: 0;
50
95
  --sigvelo-tracking-wide: 0.025em;
51
96
  --sigvelo-tracking-wider: 0.05em;
97
+
98
+ /*
99
+ * Measure. Line length is the readability control with the most evidence
100
+ * behind it and the one nothing in the system could express, so long-form
101
+ * agent output ran the full width of whatever panel it landed in. Character
102
+ * units, not rem: the comfortable measure is a count of characters, and it
103
+ * should follow the reader's font size rather than fight it.
104
+ */
105
+ --sigvelo-measure-prose: 68ch;
106
+ /* Code, tables, and diagrams read worse when wrapped than when wide. */
107
+ --sigvelo-measure-wide-block: 100ch;
108
+
109
+ /*
110
+ * Reader text scale. Applied by .sigvelo-reader-text to prose only, never to
111
+ * chrome: a reader who wants larger message text is not asking for taller
112
+ * toolbars, and scaling both is how a side panel runs out of room. Controls
113
+ * keep resolving through the rem type ramp.
114
+ */
115
+ --sigvelo-chat-font-scale: 1;
116
+ }
117
+
118
+ /*
119
+ * Opt-in dyslexia-friendly face. Set on :root for the whole document or on any
120
+ * subtree. Only the reading roles change — mono stays mono, because a
121
+ * proportional face makes code worse for everyone.
122
+ */
123
+ :root[data-font="dyslexic"],
124
+ [data-font="dyslexic"] {
125
+ --sigvelo-font-ui: var(--sigvelo-font-dyslexic);
126
+ --sigvelo-font-response: var(--sigvelo-font-dyslexic);
127
+ --sigvelo-font-user-message: var(--sigvelo-font-dyslexic);
128
+ --sigvelo-font-heading: var(--sigvelo-font-dyslexic);
52
129
  }