@n8mills/design-tokens 1.0.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/DESIGN.md +429 -0
- package/LICENSE +21 -0
- package/README.md +126 -0
- package/components.css +943 -0
- package/design-system.md +466 -0
- package/package.json +58 -0
- package/tokens.css +498 -0
- package/tokens.d.ts +266 -0
- package/tokens.js +265 -0
- package/tokens.json +441 -0
package/tokens.json
ADDED
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$description": "Portfolio design tokens, DTCG source of truth. Generated artifact is tokens.css (symlinked into the portfolio + case studies). Three tiers: primitives (hue+stop ramps) feed semantics (role), and component tokens (btn/card/chip/badge) alias semantics, never primitives. Faithful v1 transcription of the hand-written tokens.css; naming aliases + $type annotations layered in a later stage.",
|
|
3
|
+
|
|
4
|
+
"neutral": {
|
|
5
|
+
"$type": "color",
|
|
6
|
+
"0": { "$value": { "colorSpace": "oklch", "components": [1, 0, 0], "alpha": 1, "hex": "#ffffff" }, "$description": "Card surface; text on an accent fill." },
|
|
7
|
+
"50": { "$value": { "colorSpace": "oklch", "components": [0.985, 0, 0], "alpha": 1, "hex": "#fafafa" }, "$description": "Elevated surface (legacy)." },
|
|
8
|
+
"100": { "$value": { "colorSpace": "oklch", "components": [0.97, 0, 0], "alpha": 1, "hex": "#f5f5f5" }, "$description": "Page background, the brand off-white." },
|
|
9
|
+
"150": { "$value": { "colorSpace": "oklch", "components": [0.967, 0.001, 286.4], "alpha": 1, "hex": "#f4f4f5" }, "$description": "Half-step. accent-subtle on light; text-primary on dark." },
|
|
10
|
+
"200": { "$value": { "colorSpace": "oklch", "components": [0.943, 0, 0], "alpha": 1, "hex": "#ececec" }, "$description": "Subtle surface; surface-sunken on light." },
|
|
11
|
+
"300": { "$value": { "colorSpace": "oklch", "components": [0.92, 0.004, 286.3], "alpha": 1, "hex": "#e4e4e7" }, "$description": "Hairline border on light (--color-border)." },
|
|
12
|
+
"400": { "$value": { "colorSpace": "oklch", "components": [0.871, 0.005, 286.3], "alpha": 1, "hex": "#d4d4d8" }, "$description": "Strong border on light (--color-border-strong)." },
|
|
13
|
+
"500": { "$value": { "colorSpace": "oklch", "components": [0.712, 0.013, 286.1], "alpha": 1, "hex": "#a1a1aa" }, "$description": "Text-secondary on dark." },
|
|
14
|
+
"550": { "$value": { "colorSpace": "oklch", "components": [0.655, 0.009, 286.2], "alpha": 1, "hex": "#909096" }, "$description": "Half-step. Text-tertiary on dark." },
|
|
15
|
+
"600": { "$value": { "colorSpace": "oklch", "components": [0.517, 0.012, 286], "alpha": 1, "hex": "#67676f" }, "$description": "Text-tertiary on light; section labels." },
|
|
16
|
+
"700": { "$value": { "colorSpace": "oklch", "components": [0.37, 0.012, 285.8], "alpha": 1, "hex": "#3f3f46" }, "$description": "Text-secondary on light; strong border on dark." },
|
|
17
|
+
"800": { "$value": { "colorSpace": "oklch", "components": [0.274, 0.005, 286], "alpha": 1, "hex": "#27272a" }, "$description": "Border on dark." },
|
|
18
|
+
"850": { "$value": { "colorSpace": "oklch", "components": [0.228, 0.006, 285.9], "alpha": 1, "hex": "#1c1c1f" }, "$description": "Half-step. Brand ink; accent on light; surface on dark." },
|
|
19
|
+
"900": { "$value": { "colorSpace": "oklch", "components": [0.192, 0.004, 286], "alpha": 1, "hex": "#141416" }, "$description": "surface-sunken on dark." },
|
|
20
|
+
"950": { "$value": { "colorSpace": "oklch", "components": [0.145, 0.002, 286.1], "alpha": 1, "hex": "#0a0a0b" }, "$description": "bg on dark; text-primary on light; accent-hover on light." }
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
"green": {
|
|
24
|
+
"$type": "color",
|
|
25
|
+
"50": { "$value": { "colorSpace": "oklch", "components": [0.991, 0.027, 118.3], "alpha": 1, "hex": "#faffeb" }, "$description": "Near-white lime tint, decorative only." },
|
|
26
|
+
"100": { "$value": { "colorSpace": "oklch", "components": [0.982, 0.054, 118.5], "alpha": 1, "hex": "#f5ffd6" }, "$description": "Pale lime tint band." },
|
|
27
|
+
"200": { "$value": { "colorSpace": "oklch", "components": [0.967, 0.106, 119], "alpha": 1, "hex": "#ecffad" }, "$description": "Light lime tint band." },
|
|
28
|
+
"300": { "$value": { "colorSpace": "oklch", "components": [0.9538, 0.151, 120.4], "alpha": 1, "hex": "#e2ff85" }, "$description": "Light lime tint band." },
|
|
29
|
+
"400": { "$value": { "colorSpace": "oklch", "components": [0.944, 0.185, 121.3], "alpha": 1, "hex": "#daff61" }, "$description": "Lime tint, one step under the brand value." },
|
|
30
|
+
"500": { "$value": { "colorSpace": "oklch", "components": [0.936, 0.2134, 122.24], "alpha": 1, "hex": "#d2ff37" }, "$description": "Brand lime. The single canonical lime, the only stop consumed as identity (--brand-lime).", "$extensions": { "me.natemills.usage": { "role": "The single canonical brand identity lime (--brand-lime).", "use": "Brand identity only: primary button fill, brand outlines, focus rings on dark surfaces, the lime period and active dot.", "doNotUse": "Never as body text or links on a light background (composites to ~1.4:1, fails WCAG AA), and never as a theme-aware accent; the theme-aware role is color.accent, not this fixed identity value.", "decision": "Fixed brand identity value (audit TK-05); other green stops are supporting tints, not identity." } } },
|
|
31
|
+
"550": { "$value": { "colorSpace": "oklch", "components": [0.912, 0.229, 124.9], "alpha": 1, "hex": "#c0fa00" }, "$description": "Saturated vivid lime; the highest-chroma stop (OKLCH chroma 0.229), sitting between 500 and 600 in lightness." },
|
|
32
|
+
"600": { "$value": { "colorSpace": "oklch", "components": [0.849, 0.193, 122.3], "alpha": 1, "hex": "#b8e030" }, "$description": "Hover-dim lime, one step darker than brand identity; the target of --brand-lime-dim." },
|
|
33
|
+
"700": { "$value": { "colorSpace": "oklch", "components": [0.7247, 0.1815, 124.72], "alpha": 1, "hex": "#8db800" }, "$description": "Mid lime shade." },
|
|
34
|
+
"800": { "$value": { "colorSpace": "oklch", "components": [0.538, 0.134, 124.1], "alpha": 1, "hex": "#5e7a00" }, "$description": "Deep lime shade." },
|
|
35
|
+
"900": { "$value": { "colorSpace": "oklch", "components": [0.335, 0.082, 122.9], "alpha": 1, "hex": "#2f3d00" }, "$description": "Darkest usable lime, a near-black green." },
|
|
36
|
+
"950": { "$value": { "colorSpace": "oklch", "components": [0.223, 0.054, 122.4], "alpha": 1, "hex": "#171f00" }, "$description": "Lime-black; accent-subtle on dark (--color-accent-subtle)." }
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
"brand": {
|
|
40
|
+
"lime": { "$value": "{green.500}", "$type": "color" },
|
|
41
|
+
"lime-rgb": { "$value": "{green.500}", "$extensions": { "portfolio": { "format": "rgb-channels", "cssOnly": true } }, "$description": "Channel form of --brand-lime for decorative alpha shadows: rgb(var(--brand-lime-rgb) / 0.2). DERIVED by build.mjs from the referenced colour's hex anchor (audit TK-05), never hand-typed." },
|
|
42
|
+
"lime-dim": { "$value": "{green.600}", "$type": "color", "$description": "Hover-dim step of the brand lime (green.600)." },
|
|
43
|
+
"lime-vivid": { "$value": { "colorSpace": "oklch", "components": [0.955, 0.216, 114.6], "alpha": 1, "hex": "#eeff00" }, "$type": "color", "$description": "The hot vivid-yellow end of brand.gradient (#eeff00). Gradient stop only, never themed. Renamed from --brand-emphasis-2 (2026-07-02; the dangling -2 had no -1)." },
|
|
44
|
+
"ink": { "$value": "{neutral.850}", "$type": "color" },
|
|
45
|
+
"ink-rgb": { "$value": "{neutral.850}", "$extensions": { "portfolio": { "format": "rgb-channels", "cssOnly": true } }, "$description": "Channel form of --brand-ink for ink-at-alpha: rgb(var(--brand-ink-rgb) / 0.65). DERIVED by build.mjs from the referenced colour's hex anchor (audit TK-05)." },
|
|
46
|
+
"on-lime": { "$value": "{neutral.850}", "$type": "color" },
|
|
47
|
+
"on-ink": { "$value": "{green.500}", "$type": "color" },
|
|
48
|
+
"gradient": { "$value": "linear-gradient(135deg, var(--brand-lime) 0%, var(--brand-lime-vivid) 100%)", "$extensions": { "portfolio": { "cssOnly": true } }, "$description": "CSS-only composite; reads var(--brand-lime) and var(--brand-lime-vivid) so the gradient follows a brand re-point at CSS level (audit TK-05; DTCG forbids embedded aliases inside string values, review 2026-06-10)." }
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
"ext-brand": {
|
|
52
|
+
"$type": "color",
|
|
53
|
+
"anthropic-large": { "$value": "#d97757", "$description": "Anthropic orange, 18px+ bold. EXTERNAL brand: a locked, theme-agnostic constant, never aliased into a semantic token, not part of our palette." },
|
|
54
|
+
"anthropic-body": { "$value": "#b85033", "$description": "Anthropic orange, darker 12-14px variant for contrast. External brand: locked constant." },
|
|
55
|
+
"linkedin": { "$value": "#0a66c2", "$description": "LinkedIn brand blue, the LinkedIn mark only. External brand: locked constant." },
|
|
56
|
+
"bupa-blue": { "$value": "#0079c8", "$description": "Bupa brand blue, Bupa case-study context only. External brand: locked constant." },
|
|
57
|
+
"bupa-blue-dark": { "$value": "#00609f", "$description": "Bupa brand blue, darker variant. External brand: locked constant." },
|
|
58
|
+
"bupa-blue-subtle": { "$value": "#e6f2fa", "$description": "Bupa brand blue, subtle tint. External brand: locked constant." }
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
"fx": {
|
|
62
|
+
"$type": "color",
|
|
63
|
+
"glitch-magenta": { "$value": "#ff2bd6", "$description": "Decorative glitch effect only (footer wordmark). Not a palette colour, never themed." },
|
|
64
|
+
"glitch-cyan": { "$value": "#00d4ff", "$description": "Decorative glitch effect only. Not a palette colour, never themed." }
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
"color": {
|
|
68
|
+
"$type": "color",
|
|
69
|
+
"bg": { "$value": "{neutral.100}", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "The page canvas. Brand off-white in light, near-black in dark." },
|
|
70
|
+
"surface": { "$value": "{neutral.0}", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "The default card / panel surface. White card on the grey page in light (a genuine lift); the lighter near-black (#1c1c1f) in dark." },
|
|
71
|
+
"surface-sunken": { "$value": "{neutral.200}", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "Recessed wells, insets, thumbnails, chips. A step below the card surface: light grey in light; the darker near-black (#141416) in dark." },
|
|
72
|
+
"surface-inverse": { "$value": "{neutral.950}", "$description": "Always-dark slab surface, theme-invariant near-black (#0a0a0b). The full-bleed testimonials section stays near-black in BOTH themes (the metrics band matches it via a local theme scope); never overridden per theme, like static-white in reverse.", "$extensions": { "me.natemills.usage": { "role": "Theme-invariant always-dark slab surface (near-black).", "use": "Full-bleed inverse bands that must stay near-black in BOTH themes, e.g. the testimonials section and the matching metrics band.", "doNotUse": "Do not use as a normal card or panel surface (that is color.surface), and never add a per-theme override; it is intentionally not theme-reactive, like static-white in reverse.", "decision": "Theme-invariant by design: resolves to the darkest stop in every theme so the inverse band reads identically." } } },
|
|
73
|
+
"surface-inverse-sunken": { "$value": "{neutral.900}", "$description": "Inset on an inverse slab, theme-invariant near-black (#141416), the same dark value as surface-sunken. The testimonial portrait image-load fallback; never overridden per theme. Reads lighter than surface-inverse because neutral.950 is the darkest stop in the scale." },
|
|
74
|
+
"text-primary": { "$value": "{neutral.950}", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "Default reading text. Near-black on light, near-white on dark." },
|
|
75
|
+
"text-secondary": { "$value": "{neutral.700}", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "Secondary text: supporting copy one step quieter than text-primary." },
|
|
76
|
+
"text-tertiary": { "$value": "{neutral.600}", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "Tertiary text: section labels and quiet meta copy; the last step that still clears 4.5:1 on light." },
|
|
77
|
+
"border": { "$value": "{neutral.300}", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "Default hairline border and divider colour, theme-aware." },
|
|
78
|
+
"border-strong": { "$value": "{neutral.400}", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "Heavier border for edges that must read past a hairline (secondary-button outlines)." },
|
|
79
|
+
"border-brand": { "$value": "{brand.lime}", "$description": "The brand-lime outline accent (active selection, link underline, brand ring). Theme-invariant lime, never overridden per theme; the semantic the brand outlines read instead of the raw primitive." },
|
|
80
|
+
"border-hover": { "$value": "{brand.ink}", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "Border colour on hover: ink on light, lime on dark." },
|
|
81
|
+
"accent": { "$value": "{neutral.850}", "$description": "The single theme-aware interactive role: ink on light, brand lime on dark. Active and selected states.", "$extensions": { "portfolio": { "themeLight": true }, "me.natemills.usage": { "role": "The theme-aware accent role: ink (neutral.850) on light, brand lime on dark.", "use": "Anywhere the accent should follow the theme, e.g. the active carousel dot and accent surfaces.", "doNotUse": "Do not assume this is lime or hardcode lime here; on the light page it is ink and only flips to lime on dark. For the fixed brand lime use brand.lime / green.500." } } },
|
|
82
|
+
"accent-hover": { "$value": "{neutral.950}", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "Hover step of the accent role." },
|
|
83
|
+
"accent-subtle": { "$value": "{neutral.150}", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "Quiet accent wash for subtle active or highlighted surfaces." },
|
|
84
|
+
"on-accent": { "$value": "{neutral.0}", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "Text or icons sitting on an accent fill; the contrast pair of color.accent. Renamed from --color-accent-foreground (2026-07-02) to join the on-* family." },
|
|
85
|
+
"focus-ring": { "$value": "{neutral.850}", "$description": "Theme-aware keyboard-focus colour: ink on light, lime on dark. Consumed via border.focus.", "$extensions": { "portfolio": { "themeLight": true }, "me.natemills.usage": { "role": "Theme-aware keyboard-focus colour: ink on light, lime on dark.", "use": "The focus indicator colour, consumed via border.focus.", "doNotUse": "Do not hardcode a single colour and do not remove it without a replacement focus style; it must flip per theme to stay visible." } } },
|
|
86
|
+
"link": { "$value": "{neutral.850}", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "Underlined navigational link text: ink on light, lime on dark. Distinct role from accent (Section 10)." },
|
|
87
|
+
"link-hover": { "$value": "{neutral.950}", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "Link hover colour." },
|
|
88
|
+
|
|
89
|
+
"on-ink-emphasis": { "$value": "{neutral.0}", "$description": "Solid-white emphasis step of the on-ink family (full white, above the 88% on-ink-primary); theme-invariant. Reserved for full-white emphasis on always-dark slabs; currently unconsumed outside the Under-the-Hood gallery (the hero headline moved to --color-text-primary with the 2026-06-25 editorial hero). Renamed from --color-hero-text-primary (2026-07-02; a component name squatting in the semantic namespace)." },
|
|
90
|
+
"on-ink-primary": { "$value": "rgba(255, 255, 255, 0.88)", "$description": "Primary text on an always-dark slab (88% white).", "$extensions": { "me.natemills.usage": { "role": "Primary text colour for content sitting on an always-dark slab (88% white).", "use": "Headings and body text on an ink or dark band.", "doNotUse": "Never on a light surface; it is white-on-dark only and will vanish on a white card. For text on light use color.text-primary." } } },
|
|
91
|
+
"on-ink-secondary": { "$value": "rgba(255, 255, 255, 0.66)", "$description": "Secondary text on an always-dark slab (66% white).", "$extensions": { "me.natemills.usage": { "role": "Secondary text colour for content on an always-dark slab (66% white).", "use": "Muted or secondary copy on an ink or dark band.", "doNotUse": "Never on a light surface; white-on-dark only. For muted text on light use color.text-secondary." } } },
|
|
92
|
+
"on-ink-muted": { "$value": "rgba(255, 255, 255, 0.4)", "$description": "Muted text on an always-dark slab (40% white); also the inactive dot on inverse bands." },
|
|
93
|
+
"on-ink-border": { "$value": "rgba(255, 255, 255, 0.08)", "$description": "Hairline border on an always-dark slab (8% white)." },
|
|
94
|
+
"on-ink-subtle": { "$value": "{neutral.50}", "$description": "Quiet near-white text on an always-dark slab (neutral.50), the softest step of the on-ink family, a hair below on-ink-emphasis. Theme-invariant, never on a light surface. Used for dark-section titles and muted hover text on inverse bands. Renamed from --color-neutral-subtle (2026-07-07; a surface-family name squatting on a text role)." },
|
|
95
|
+
"static-white": { "$value": "{neutral.0}", "$description": "Theme-invariant white, never overridden per theme." },
|
|
96
|
+
"static-white-hover": { "$value": "{neutral.200}", "$description": "Hover step for static-white surfaces; theme-invariant light grey." },
|
|
97
|
+
"accent-emphasis": { "$value": "{neutral.850}", "$description": "Theme-aware emphasis text following the accent role: ink on light, lime on dark. For text on theme-following surfaces; on-* tokens are for fixed-colour surfaces. Renamed from --color-brand-emphasis (2026-07-02; one interactive role, accent)." },
|
|
98
|
+
"dot-inactive": { "$value": "{neutral.600}", "$description": "Inactive carousel dot. Solid theme-aware grey: clears the SC 1.4.11 3:1 floor on light surfaces (the old rgba(127,127,127,0.45) composited to 1.67:1); dark themes override to neutral-500. Inverse bands re-scope to on-ink-muted.", "$extensions": { "me.natemills.usage": { "role": "Inactive carousel dot; a solid theme-aware grey tuned for contrast.", "use": "Inactive pagination dots on standard surfaces.", "doNotUse": "Do not substitute a translucent grey: the old rgba(127,127,127,0.45) was only 1.67:1. On inverse bands it must re-scope to color.on-ink-muted.", "decision": "Tuned to clear the SC 1.4.11 3:1 non-text contrast floor." } } },
|
|
99
|
+
"dot-active": { "$value": "{color.accent}", "$description": "Active carousel dot and position indicator. Follows the accent: ink on light, lime on dark (lime on the light page was 1.06:1, audit AX-01). Inverse bands re-scope to brand lime." },
|
|
100
|
+
"text-muted-emphasis": { "$value": "rgb(var(--brand-ink-rgb) / 0.55)", "$extensions": { "portfolio": { "cssOnly": true }, "me.natemills.usage": { "role": "Muted italic emphasis text (decorative).", "use": "Large or decorative muted-emphasis text only.", "doNotUse": "Never on small body text: it composites to ~3.7:1 on light surfaces, below the 4.5:1 small-text floor.", "decision": "Contrast-gated decorative use (audit TK-07, C-01)." } }, "$description": "C-01 muted italic emphasis. 55% ink on light, flips to brand-lime on dark. Decorative and large-text use only: composites to ~3.7:1 on light surfaces, below the 4.5:1 small-text floor (audit TK-07). Renamed from --color-text-muted-em (2026-07-02; em read as the CSS unit)." },
|
|
101
|
+
"on-ink-hover": { "$value": "rgba(255, 255, 255, 0.18)", "$description": "C-12 hover/focus tint on dark backgrounds." },
|
|
102
|
+
"overlay-soft": { "$value": "rgba(0, 0, 0, 0.35)", "$description": "Soft scrim behind floating chrome (35% black)." },
|
|
103
|
+
"overlay-base": { "$value": "rgba(0, 0, 0, 0.62)", "$description": "Standard modal and lightbox scrim (62% black)." },
|
|
104
|
+
"overlay-strong": { "$value": "rgba(0, 0, 0, 0.88)", "$description": "Heavy scrim for maximum content isolation (88% black)." }
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
"font": {
|
|
108
|
+
"display": { "$value": "\"Inter\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif", "$description": "Display headings (h1, h2, h3) and large numbers." },
|
|
109
|
+
"body": { "$value": "\"Inter\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif", "$description": "Body copy, lists, and buttons." },
|
|
110
|
+
"mono": { "$value": "\"JetBrains Mono\", ui-monospace, \"SF Mono\", Menlo, Consolas, monospace", "$description": "Tabular numbers, code, and eyebrow labels. Absorbed --font-mono-metric (2026-07-02): the metric alias had an identical stack; the IBM Plex Mono drift it once guarded against is documented in Section 4 history." },
|
|
111
|
+
"serif": { "$value": "\"PT Serif\", Georgia, serif", "$description": "Editorial pull quotes, testimonials only." },
|
|
112
|
+
"feature-mono": { "$value": "\"zero\" 1", "$description": "OpenType slashed-zero feature for mono specimens." }
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
"size": {
|
|
116
|
+
"2xs": { "$value": "11px", "$description": "11px. M-61 chip/section-label tier; --text-label resolves here." },
|
|
117
|
+
"xs": { "$value": "12px", "$description": "12px. Captions, footnotes, fine print; --text-caption resolves here." },
|
|
118
|
+
"sm": { "$value": "14px", "$description": "14px. Compact body: footer text, card bullets, dense UI copy." },
|
|
119
|
+
"base": { "$value": "16px", "$description": "16px. The body stop; --text-body resolves here." },
|
|
120
|
+
"lg": { "$value": "18px", "$description": "18px. Intro lines, award titles, component names." },
|
|
121
|
+
"xl": { "$value": "24px", "$description": "24px. Modal and tile titles." },
|
|
122
|
+
"2xl": { "$value": "32px", "$description": "32px. Small display headings (UTH section heads, print stat numerals)." },
|
|
123
|
+
"3xl": { "$value": "48px", "$description": "48px. The largest fixed stop; the fluid display clamps take over above it." }
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
"text": {
|
|
127
|
+
"h1": { "$value": "clamp(34px, 5.8vw, 72px)", "$description": "Page-level section headings (every section h2). The hero h1 is a documented exception with its own mobile-tuned clamp.", "$extensions": { "doc": { "lineHeight": "1.05" }, "me.natemills.usage": { "role": "The standard page-level section heading size (every section h2).", "use": "Normal section headings across the page.", "doNotUse": "Do not use for the hero headline; the hero is a documented exception with its own mobile-tuned clamp (use display.hero)." } } },
|
|
128
|
+
"h2": { "$value": "clamp(22px, 4vw, 32px)", "$description": "Card titles, intro lines, sub-headings inside section bodies.", "$extensions": { "doc": { "lineHeight": "1.15" } } },
|
|
129
|
+
"body": { "$value": "{size.base}", "$description": "Paragraphs, lists, default reading text, card body copy.", "$extensions": { "doc": { "lineHeight": "1.5" } } },
|
|
130
|
+
"label": { "$value": "{size.2xs}", "$description": "Uppercase mono labels, eyebrows, stat labels, badges.", "$extensions": { "doc": { "lineHeight": "1.4" } } },
|
|
131
|
+
"caption": { "$value": "{size.xs}", "$description": "Tiny captions, footnotes, stat descriptions.", "$extensions": { "doc": { "lineHeight": "1.5" } } },
|
|
132
|
+
"meta": { "$value": "13px", "$description": "13px meta/caption tier (M-63), between caption (12px) and compact body (14px). Raw value like text.h1; no matching size stop exists. Renamed from --size-meta (2026-07-02; a role name that sat in the size ramp)." },
|
|
133
|
+
"nav": { "$value": "{size.2xs}", "$description": "Header menu links; equals --text-label today, kept separate so nav can diverge." }
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
"display": {
|
|
137
|
+
"hero": { "$value": "clamp(40px, 9vw, 118px)", "$description": "The hero headline. Fluid 40 to 118px, the biggest type on the site.", "$extensions": { "me.natemills.usage": { "role": "The hero headline size; the single biggest type on the site (40 to 118px).", "use": "The hero headline only.", "doNotUse": "Do not use for ordinary section headings (use text.h1); it scales to 118px and will dwarf normal content." } } },
|
|
138
|
+
"section": { "$value": "clamp(28px, 5.8vw, 72px)", "$description": "Oversized display headings; the Under-the-Hood section heads run on it." },
|
|
139
|
+
"card-title": { "$value": "clamp(22px, 4vw, 44px)", "$description": "Large feature-card and tile titles." },
|
|
140
|
+
"stat-num": { "$value": "clamp(40px, 7vw, 88px)", "$description": "The Key metrics band numerals (18h, $4M+, 74%)." },
|
|
141
|
+
"intro": { "$value": "clamp(20px, 5vw, 24px)", "$description": "Section intro lines and emphasis copy under a heading." },
|
|
142
|
+
"tight": { "$value": "-0.04em", "$description": "Display tracking. Pairs with every heading above card size." },
|
|
143
|
+
"weight": { "$value": "{weight.semibold}", "$description": "The single weight every display preset carries (semibold). Display headings are always roman, never italic." },
|
|
144
|
+
"quote": { "$value": "clamp(96px, 12vw, 140px)", "$description": "The testimonials' giant serif quotation marks. Decorative punctuation, not data. Renamed from --display-stat in W40 (it never sized a stat)." }
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
"measure": { "$value": "52ch", "$description": "Line-length cap; 52ch Inter renders ~66 real chars." },
|
|
148
|
+
|
|
149
|
+
"btn": {
|
|
150
|
+
"sm": { "$value": "32px", "$description": "Compact: dense cards, toolbars, filters. Clears the WCAG 2.5.8 AA 24px target minimum." },
|
|
151
|
+
"md": { "$value": "{touch-target-min}", "$description": "Default. Most CTAs. Equals the base .btn height and meets the WCAG 2.5.5 AAA 44px touch target." },
|
|
152
|
+
"lg": { "$value": "52px", "$description": "Hero CTAs and primary conversion actions." },
|
|
153
|
+
|
|
154
|
+
"pad-x": { "$value": "18px", "$description": "Base button inline (left/right) padding. Component-level literal; sits off the 4px space scale by design (the historic DC-03 value, kept so the live button is unchanged).", "$extensions": { "me.natemills.usage": { "role": "Base button inline (left/right) padding; an intentional off-scale literal.", "use": "As-is for button left/right padding.", "doNotUse": "Do not normalise it to a space.* token; 18px sits off the 4px scale by design so the live button stays unchanged.", "decision": "Historic DC-03 value, kept deliberately off-scale." } } },
|
|
155
|
+
"pad-y": { "$value": "10px", "$description": "Base button block (top/bottom) padding. Component-level literal, paired with --btn-pad-x.", "$extensions": { "me.natemills.usage": { "role": "Base button block (top/bottom) padding; an intentional off-scale literal, paired with btn.pad-x.", "use": "As-is for button top/bottom padding.", "doNotUse": "Do not swap it for a space.* token; 10px is an intentional off-scale component literal.", "decision": "Paired with the DC-03 off-scale btn.pad-x." } } },
|
|
156
|
+
"gap": { "$value": "{space.2}", "$description": "Space between a button's icon and its label." },
|
|
157
|
+
"radius": { "$value": "{radius.full}", "$description": "Button corner radius; full pill." },
|
|
158
|
+
"font": { "$value": "{font.body}", "$description": "Button label typeface (Inter)." },
|
|
159
|
+
"font-size": { "$value": "{size.sm}", "$description": "Button label size at the default (md) button." },
|
|
160
|
+
"font-weight": { "$value": "{weight.semibold}", "$description": "Button label weight; semibold on every button." },
|
|
161
|
+
"glyph": { "$value": "16px", "$description": "Lucide glyph size inside a default button." },
|
|
162
|
+
"glyph-sm": { "$value": "14px", "$description": "Lucide glyph size inside a --sm button." },
|
|
163
|
+
"glyph-lg": { "$value": "18px", "$description": "Lucide glyph size inside a --lg button." },
|
|
164
|
+
"transition": { "$value": "background var(--duration-fast) var(--ease-default), border-color var(--duration-fast) var(--ease-default), color var(--duration-fast) var(--ease-default), transform var(--duration-fast) var(--ease-default)", "$extensions": { "portfolio": { "cssOnly": true } }, "$description": "CSS composite: the button's hover/focus transition across its four animated properties. Reads var(--duration-fast)/var(--ease-default) directly so it follows a motion re-point (same pattern as --gradient; DTCG forbids embedded aliases inside string values)." },
|
|
165
|
+
"focus-ring": { "$value": "{color.focus-ring}", "$type": "color", "$description": "Button focus-visible outline colour." },
|
|
166
|
+
|
|
167
|
+
"primary-bg": { "$value": "{brand.lime}", "$type": "color", "$description": "Primary button fill." },
|
|
168
|
+
"primary-fg": { "$value": "{brand.ink}", "$type": "color", "$description": "Primary button label and glyph." },
|
|
169
|
+
"primary-border": { "$value": "{color.border-brand}", "$type": "color", "$description": "Primary button border." },
|
|
170
|
+
"primary-bg-hover": { "$value": "{brand.ink}", "$type": "color", "$description": "Primary button fill on hover/focus (inverts to ink)." },
|
|
171
|
+
"primary-fg-hover": { "$value": "{brand.lime}", "$type": "color", "$description": "Primary button label on hover/focus (inverts to lime)." },
|
|
172
|
+
"secondary-fg": { "$value": "{color.text-primary}", "$type": "color", "$description": "Secondary button label (transparent fill)." },
|
|
173
|
+
"secondary-border": { "$value": "{color.text-tertiary}", "$type": "color", "$description": "Secondary button border (meets WCAG 1.4.11 3:1 non-text contrast; matches icon-border)." },
|
|
174
|
+
"secondary-bg-hover": { "$value": "{color.surface-sunken}", "$type": "color", "$description": "Secondary button fill on hover/focus." },
|
|
175
|
+
"secondary-border-hover": { "$value": "{color.text-primary}", "$type": "color", "$description": "Secondary button border on hover/focus." },
|
|
176
|
+
"icon-border": { "$value": "{color.text-tertiary}", "$type": "color", "$description": "Icon button border (meets WCAG 1.4.11 3:1 non-text contrast)." },
|
|
177
|
+
"icon-fg": { "$value": "{color.text-secondary}", "$type": "color", "$description": "Icon button glyph at rest." }
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
"card": {
|
|
181
|
+
"radius": { "$value": "{radius.lg}", "$description": "Card corner radius; the default for content cards and modals." },
|
|
182
|
+
"padding": { "$value": "{space.5}", "$description": "Card content inset; the standard 24px card padding." },
|
|
183
|
+
"border": { "$value": "{border.hairline}", "$description": "Card edge; 1px hairline that follows the theme border colour." },
|
|
184
|
+
"bg": { "$value": "{color.surface}", "$type": "color", "$description": "Card surface fill on light slabs." },
|
|
185
|
+
"fg": { "$value": "{color.text-primary}", "$type": "color", "$description": "Card body text." },
|
|
186
|
+
"dark-bg": { "$value": "{brand.ink}", "$type": "color", "$description": "Card surface fill on dark slabs (.card--dark).", "$extensions": { "me.natemills.usage": { "role": "Card surface fill specifically for cards on an always-dark slab (.card--dark).", "use": "Only on cards sitting on an always-dark band.", "doNotUse": "Do not use as the default card surface (that is card.bg / color.surface), and do not theme-flip it." } } },
|
|
187
|
+
"dark-fg": { "$value": "{color.on-ink-primary}", "$type": "color", "$description": "Card body text on dark slabs." },
|
|
188
|
+
"dark-border": { "$value": "{color.on-ink-border}", "$type": "color", "$description": "Card edge on dark slabs." }
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
"chip": {
|
|
192
|
+
"pad-x": { "$value": "10px", "$description": "Chip inline (left/right) padding. Component-level literal; sits off the 4px space scale by design (between space-2 and space-3), kept so the live chip is unchanged." },
|
|
193
|
+
"pad-y": { "$value": "{space.1}", "$description": "Chip block (top/bottom) padding; 4px." },
|
|
194
|
+
"gap": { "$value": "{space.2}", "$description": "Space between a chip's icon and its label." },
|
|
195
|
+
"icon-size": { "$value": "14px", "$description": "Icon footprint inside a chip (Lucide stroke icon or normalised brand mark). Component-level literal." },
|
|
196
|
+
"radius": { "$value": "{radius.full}", "$description": "Chip corner radius; full pill." },
|
|
197
|
+
"font": { "$value": "{font.mono}", "$description": "Chip label typeface (JetBrains Mono)." },
|
|
198
|
+
"font-size": { "$value": "{text.label}", "$description": "Chip label size." },
|
|
199
|
+
"font-weight": { "$value": "{weight.medium}", "$description": "Chip label weight." },
|
|
200
|
+
"line": { "$value": "1.4", "$description": "Chip label line height. Component-level literal, sized to the mono label; off the named line scale by design." },
|
|
201
|
+
"fg": { "$value": "{color.text-primary}", "$type": "color", "$description": "Chip label and icon colour." },
|
|
202
|
+
"bg": { "$value": "{color.surface-sunken}", "$type": "color", "$description": "Chip fill at rest (and on active)." },
|
|
203
|
+
"border": { "$value": "{color.border}", "$type": "color", "$description": "Chip border at rest." },
|
|
204
|
+
"border-hover": { "$value": "{color.border-strong}", "$type": "color", "$description": "Chip border on hover and active." }
|
|
205
|
+
},
|
|
206
|
+
|
|
207
|
+
"badge": {
|
|
208
|
+
"pad-x": { "$value": "{space.3}", "$description": "Badge inline (left/right) padding; 12px." },
|
|
209
|
+
"pad-y": { "$value": "{space.1}", "$description": "Badge block (top/bottom) padding; 4px." },
|
|
210
|
+
"gap": { "$value": "{space.2}", "$description": "Space between a badge's dot or icon and its label." },
|
|
211
|
+
"radius": { "$value": "{radius.full}", "$description": "Badge corner radius; full pill." },
|
|
212
|
+
"font": { "$value": "{font.mono}", "$description": "Badge label typeface (JetBrains Mono)." },
|
|
213
|
+
"font-size": { "$value": "{text.label}", "$description": "Badge label size." },
|
|
214
|
+
"font-weight": { "$value": "{weight.medium}", "$description": "Badge label weight." },
|
|
215
|
+
"icon-size": { "$value": "14px", "$description": "Leading icon footprint inside a badge (Lucide stroke icon). Component-level literal." },
|
|
216
|
+
"dot-size": { "$value": "6px", "$description": "Status-dot diameter inside a badge. Component-level literal." },
|
|
217
|
+
"fg": { "$value": "{color.text-secondary}", "$type": "color", "$description": "Badge label and icon colour; quiet by design, auto-flips per theme." },
|
|
218
|
+
"border": { "$value": "{color.border}", "$type": "color", "$description": "Badge outline; hairline, auto-flips per theme." },
|
|
219
|
+
"dot": { "$value": "{brand.lime}", "$type": "color", "$description": "Status-dot fill; brand lime in both themes (the dot is decorative, the label carries the meaning)." }
|
|
220
|
+
},
|
|
221
|
+
|
|
222
|
+
"line": {
|
|
223
|
+
"display": { "$value": "1.05", "$description": "Display-grade headings (--text-h1, section h2s). Big text wants the tightest leading." },
|
|
224
|
+
"heading": { "$value": "1.15", "$description": "Card titles and section sub-headings (--text-h2, UTH section heads)." },
|
|
225
|
+
"title": { "$value": "1.25", "$description": "Smaller standalone titles (modal and tile titles)." },
|
|
226
|
+
"snug": { "$value": "1.45", "$description": "Intro lines, award titles, compact meta text. A half-step tighter than body." },
|
|
227
|
+
"body": { "$value": "1.5", "$description": "Default reading text: paragraphs, lists, captions. The workhorse." }
|
|
228
|
+
},
|
|
229
|
+
|
|
230
|
+
"weight": {
|
|
231
|
+
"regular": { "$value": "400", "$description": "400. Body copy and captions." },
|
|
232
|
+
"medium": { "$value": "500", "$description": "500. UI text, chips, mono labels." },
|
|
233
|
+
"semibold": { "$value": "600", "$description": "600. The workhorse emphasis: buttons, subheads, labels." },
|
|
234
|
+
"bold": { "$value": "700", "$description": "700. Strong emphasis inside body copy." },
|
|
235
|
+
"extrabold": { "$value": "800", "$description": "Five distinct weights; Inter is loaded at 400/500/600/700/800." }
|
|
236
|
+
},
|
|
237
|
+
|
|
238
|
+
"tracking": {
|
|
239
|
+
"tight": { "$value": "-0.02em", "$description": "-0.02em. Tightens large text below display size." },
|
|
240
|
+
"normal": { "$value": "0", "$description": "0. The body default; most text sits here." },
|
|
241
|
+
"wide": { "$value": "0.02em", "$description": "0.02em. Opens subheads a touch at mid sizes." },
|
|
242
|
+
"mono": { "$value": "0.01em", "$description": "0.01em. Tabular numbers and code; keeps digit columns steady." },
|
|
243
|
+
"eyebrow": { "$value": "0.18em", "$description": "Wide tracking for uppercase eyebrows." },
|
|
244
|
+
"label": { "$value": "0.08em", "$description": "Small uppercase labels." }
|
|
245
|
+
},
|
|
246
|
+
|
|
247
|
+
"space": {
|
|
248
|
+
"1": { "$value": "4px", "$description": "Hairline gap. Icon-to-label, tight inline spacing." },
|
|
249
|
+
"2": { "$value": "8px", "$description": "Tight gap. Chip padding, small stacks." },
|
|
250
|
+
"3": { "$value": "12px", "$description": "Medium-tight break (added between 2 and 4). Heading-to-body, compact rows." },
|
|
251
|
+
"4": { "$value": "16px", "$description": "Base unit. Default gap between related elements; the compact card-padding tier (--card-pad-compact)." },
|
|
252
|
+
"5": { "$value": "24px", "$description": "Medium break (added between 4 and 6). Group separation inside a section; the standard card-padding tier (--card-pad-standard)." },
|
|
253
|
+
"6": { "$value": "32px", "$description": "Large gap. Between subsections and card to card; the spacious card-padding tier (--card-pad-spacious)." },
|
|
254
|
+
"7": { "$value": "48px", "$description": "Block spacing between stacked content blocks." },
|
|
255
|
+
"8": { "$value": "64px", "$description": "Major block separation and section inner padding." },
|
|
256
|
+
"9": { "$value": "96px", "$description": "Section rhythm. The lower bound of vertical section padding (--section-padding)." },
|
|
257
|
+
"10": { "$value": "128px", "$description": "Section rhythm. The upper bound of vertical section padding (--section-padding)." },
|
|
258
|
+
"11": { "$value": "192px", "$description": "Outsized spacing for full-bleed editorial breaks." },
|
|
259
|
+
"12": { "$value": "256px", "$description": "Largest step. Rare, marquee-scale vertical space." }
|
|
260
|
+
},
|
|
261
|
+
|
|
262
|
+
"section-padding": { "$value": "clamp(var(--space-9), 12vw, var(--space-10))", "$extensions": { "portfolio": { "cssOnly": true } } },
|
|
263
|
+
|
|
264
|
+
"card-pad": {
|
|
265
|
+
"compact": { "$value": "{space.4}", "$description": "Compact card-padding tier (16px). Dense content tiles: credential cards, health-check tiles, inner controls." },
|
|
266
|
+
"standard": { "$value": "{space.5}", "$description": "Standard card-padding tier (24px). The default content-card inset; matches the base .card. The standard, resolving the old 16-vs-24 doc conflict." },
|
|
267
|
+
"spacious": { "$value": "{space.6}", "$description": "Spacious card-padding tier (32px). Large feature, award, and full-testimonial cards (often the desktop step up from standard)." }
|
|
268
|
+
},
|
|
269
|
+
|
|
270
|
+
"duration": {
|
|
271
|
+
"fast": { "$value": "150ms", "$description": "Hover, focus, and micro state feedback." },
|
|
272
|
+
"base": { "$value": "220ms", "$description": "Reveal, modal, and swap transitions." },
|
|
273
|
+
"slow": { "$value": "400ms", "$description": "Context shift and slide transitions." },
|
|
274
|
+
"expressive": { "$value": "1300ms", "$description": "Expressive tier: the slow, cinematic duration for a single large hero moment (the two-phone Spline scene scales in over this). Deliberately longer than the general-purpose slow tier and reserved for one large-surface entrance, never UI feedback. Collapsed to 1ms under reduced motion by the block in tokens/build.mjs." }
|
|
275
|
+
},
|
|
276
|
+
|
|
277
|
+
"ease": {
|
|
278
|
+
"default": { "$value": "cubic-bezier(0.4, 0, 0.2, 1)", "$description": "The workhorse symmetric curve. Begins and ends on screen." },
|
|
279
|
+
"entrance": { "$value": "cubic-bezier(0, 0, 0.2, 1)", "$description": "Decelerate, for elements entering the screen." },
|
|
280
|
+
"exit": { "$value": "cubic-bezier(0.4, 0, 1, 1)", "$description": "Accelerate, for elements leaving the screen." },
|
|
281
|
+
"emphasized": { "$value": "cubic-bezier(0.16, 1, 0.3, 1)", "$description": "Pronounced ease-out for overlay and menu entrance motion (items rising into view). A stronger, slower-settling decelerate than --ease-entrance." },
|
|
282
|
+
"linear": { "$value": "cubic-bezier(0, 0, 1, 1)", "$description": "Constant rate, no acceleration. For continuous loop motion: the hero ticker, both marquees, the glass column scroll, and the loading-icon cycles. Authored as a cubic-bezier twin of the linear keyword so it lives in the ease group with its siblings." }
|
|
283
|
+
},
|
|
284
|
+
|
|
285
|
+
"motion": {
|
|
286
|
+
"$description": "Scroll-reveal entrance geometry for the native scroll-driven .nm-sr pattern (animation-timeline: view()). The settle curve is {ease.emphasized}; the range/stagger are percentages of each element's view() timeline. See design-system.md Section 7.",
|
|
287
|
+
"reveal-rise": { "$value": "64px", "$description": "translateY start for the signature reveal (settles to 0)." },
|
|
288
|
+
"reveal-shift": { "$value": "48px", "$description": "translateX start that gives the signature reveal its diagonal." },
|
|
289
|
+
"reveal-scale": { "$value": "0.9", "$description": "start scale for the signature reveal (settles to 1)." },
|
|
290
|
+
"reveal-slide": { "$value": "80px", "$description": "translateX start for the slide-from-right reveal: featured + testimonial carousels and the design-system plate illustrations." },
|
|
291
|
+
"reveal-stagger": { "$value": "4%", "$description": "per-item view()-range offset so grouped items deal out (animation-delay is ignored on scroll timelines)." }
|
|
292
|
+
},
|
|
293
|
+
|
|
294
|
+
"radius": {
|
|
295
|
+
"none": { "$value": "0", "$description": "Square. No rounding, for sharp-cornered surfaces and full-bleed media." },
|
|
296
|
+
"sm": { "$value": "8px", "$description": "Small radius. The workhorse for inputs, chips, and small controls." },
|
|
297
|
+
"md": { "$value": "10px", "$description": "Medium radius. Mid-size controls and insets, a touch rounder than sm." },
|
|
298
|
+
"lg": { "$value": "14px", "$description": "Large radius. The default for cards and modals." },
|
|
299
|
+
"xl": { "$value": "20px", "$description": "Extra-large radius. Prominent panels and feature surfaces." },
|
|
300
|
+
"full": { "$value": "999px", "$description": "Full round. Pills, tags, and circular buttons; forces a complete radius at any height." }
|
|
301
|
+
},
|
|
302
|
+
|
|
303
|
+
"border": {
|
|
304
|
+
"hairline": { "$value": "1px solid var(--color-border)", "$extensions": { "portfolio": { "cssOnly": true } }, "$description": "Default 1px hairline border; reads --color-border so it follows the theme. The standard card edge and divider." },
|
|
305
|
+
"strong": { "$value": "1px solid var(--color-border-strong)", "$extensions": { "portfolio": { "cssOnly": true } }, "$description": "Heavier 1px border; reads --color-border-strong. For edges that need to read past a hairline, such as interactive-card hover outlines. (Button borders moved to the btn.* component tokens in Task 87.)" },
|
|
306
|
+
"focus": { "$value": "2px solid var(--color-focus-ring)", "$extensions": { "portfolio": { "cssOnly": true }, "me.natemills.usage": { "role": "The 2px keyboard-focus outline composite.", "use": "As the full focus-visible outline on interactive elements.", "doNotUse": "Never delete it without providing a replacement focus style; it is the keyboard-focus indicator." } }, "$description": "2px focus outline; reads --color-focus-ring (ink on light, lime on dark). The keyboard-focus indicator, never removed without a replacement." }
|
|
307
|
+
},
|
|
308
|
+
|
|
309
|
+
"focus-ring-offset": { "$value": "2px", "$description": "Offset between an element and its focus ring. Outsets the 2px ring so it clears the element edge." },
|
|
310
|
+
|
|
311
|
+
"container": {
|
|
312
|
+
"base": { "$value": "960px" },
|
|
313
|
+
"wide": { "$value": "min(92vw, 1680px)", "$description": "Main content band. Stays proportional at 92vw (4% side gutters, matching the tablet/laptop feel) up to ~1826px viewport, then caps at 1680px so ultrawide layouts do not stretch without earning it (W38 ceiling kept, like the type and spacing scales). The old clamp(1440px,...) floor was removed: it froze the band at 1440px across the whole 1565-2181px range, so side margins ballooned to 240px on a 1920px screen (the 16-inch boxed-in bug, 2026-06-21)." }
|
|
314
|
+
},
|
|
315
|
+
|
|
316
|
+
"bp": {
|
|
317
|
+
"$description": "Breakpoint reference values for documentation and audits only. CSS custom properties cannot be read inside media queries and no JS consumes these; the real breakpoints live in the media queries themselves, guarded by bp-lint.mjs.",
|
|
318
|
+
"mobile": { "$value": "375px" },
|
|
319
|
+
"tablet": { "$value": "768px" },
|
|
320
|
+
"desktop": { "$value": "1024px" },
|
|
321
|
+
"wide": { "$value": "1440px" },
|
|
322
|
+
"ultrawide": { "$value": "1600px" }
|
|
323
|
+
},
|
|
324
|
+
|
|
325
|
+
"touch-target-min": { "$value": "44px" },
|
|
326
|
+
"touch-target-dot": { "$value": "24px", "$description": "Carousel-dot hit area (WCAG 2.5.8 AA floor). Was consumed with an inline fallback but defined nowhere (audit TK-09)." },
|
|
327
|
+
|
|
328
|
+
"z": {
|
|
329
|
+
"base": { "$value": "0", "$description": "Base stacking level. The default flow; nothing is lifted." },
|
|
330
|
+
"dropdown": { "$value": "1000", "$description": "Dropdowns, popovers, and menus that open over page content." },
|
|
331
|
+
"sticky": { "$value": "1100", "$description": "Sticky and fixed chrome: the site header and pinned bars." },
|
|
332
|
+
"overlay": { "$value": "1200", "$description": "Scrims and floating chrome above the sticky layer (backdrops, the floating action button)." },
|
|
333
|
+
"modal": { "$value": "1300", "$description": "Modal dialogs and lightboxes sitting above their scrim." },
|
|
334
|
+
"tooltip": { "$value": "1400", "$description": "Tooltips and hover hints above modals." },
|
|
335
|
+
"toast": { "$value": "1500", "$description": "Toasts and the scroll-progress bar: the top-most transient chrome. Wide 100-unit gaps leave room to insert a layer without renumbering." },
|
|
336
|
+
"skip-link": { "$value": "1600", "$description": "Skip-to-content link on focus: the top-most element of all, so keyboard users can always reach it over any chrome." }
|
|
337
|
+
},
|
|
338
|
+
|
|
339
|
+
"shadow": {
|
|
340
|
+
"none": { "$value": "none", "$description": "No shadow. The default; the system favours borders over shadows." },
|
|
341
|
+
"soft": { "$value": "0 1px 2px rgb(var(--brand-ink-rgb) / 0.04), 0 1px 3px rgb(var(--brand-ink-rgb) / 0.06)", "$extensions": { "portfolio": { "cssOnly": true } }, "$description": "Subtle resting elevation, two stacked ink-alpha layers, for cards that lift just off the page. Dark mode swaps to deeper black-alpha." },
|
|
342
|
+
"lift": { "$value": "0 4px 12px rgb(var(--brand-ink-rgb) / 0.06), 0 2px 4px rgb(var(--brand-ink-rgb) / 0.04)", "$extensions": { "portfolio": { "cssOnly": true } }, "$description": "Stronger elevation for overlays and float-on-scroll chrome only, not resting cards." },
|
|
343
|
+
"modal": { "$value": "0 24px 64px rgba(0, 0, 0, 0.5), 0 8px 16px rgba(0, 0, 0, 0.18)", "$extensions": { "portfolio": { "cssOnly": true } }, "$description": "Modal and lightbox elevation. The deepest shadow, for surfaces floating above a scrim." }
|
|
344
|
+
},
|
|
345
|
+
|
|
346
|
+
"accent-period-shadow": { "$value": "0 1px 2px rgba(0,0,0,0.42), 0 0 0 1px rgba(0,0,0,0.18)", "$description": "Depth under the lime period in section titles. Keeps the lime dot legible on light surfaces; resolves to none in dark, where lime already reads." },
|
|
347
|
+
"accent-dot-shadow": { "$value": "0 1px 3px rgba(0,0,0,0.24)", "$description": "Depth under the active carousel pagination dot. Keeps the lime dot legible on light surfaces; resolves to none in dark." },
|
|
348
|
+
|
|
349
|
+
"glass": {
|
|
350
|
+
"$description": "Liquid-frosted header glass (.m-liquidfrostlit). Light defaults here; dark overrides under darkTheme + osDark. The #lg-dist refraction (feDisplacementMap scale 100) is JS-injected and gated to desktop + hover.",
|
|
351
|
+
"tint": { "$value": "rgb(250 250 252 / 0.4)", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "Frosted fill colour, painted as the panel's padding-box layer. Near-white at 40% in light, ink at 50% in dark, so the bar tints whatever scrolls behind it toward the page substrate." },
|
|
352
|
+
"edge-top": { "$value": "rgb(255 255 255 / 0.9)", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "Top stop of the lit border gradient: a bright highlight along the top edge, as if light is catching the rim, giving the panel its 3D lift." },
|
|
353
|
+
"edge-bottom": { "$value": "rgb(255 255 255 / 0.06)", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "Bottom stop of the lit border gradient: near transparent, so the lit edge fades from top to bottom like a real bevel." },
|
|
354
|
+
"specular": { "$value": "inset 0 1px 0 rgb(255 255 255 / 0.7)", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "Inner top highlight, an inset box-shadow drawing the sharp specular line across the panel's top edge. A transparent no-op in dark, where the tint alone reads." },
|
|
355
|
+
"shadow": { "$value": "0 10px 30px rgb(0 0 0 / 0.18)", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "Drop shadow that lifts the floating pill off the page once the header condenses on scroll. Tighter contact shadow plus soft ambient in dark." },
|
|
356
|
+
"blur": { "$value": "10px", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "Backdrop blur on the Chromium refraction path (desktop with a hover pointer), where it pairs with the #lg-dist displacement filter. 10px in light, 7px in dark." },
|
|
357
|
+
"blur-webkit": { "$value": "14px", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "Backdrop blur on the plain-frost fallback used everywhere without the displacement filter (Safari, iOS, mobile). 14px in light, 11px in dark." },
|
|
358
|
+
"saturate": { "$value": "170%", "$description": "Backdrop saturation boost. Pumps the colour of whatever scrolls behind the bar so the frost reads as live glass, not a grey haze." },
|
|
359
|
+
"dim": { "$value": "1", "$description": "Backdrop brightness clamp at rest (1, no dimming). The Apple Liquid Glass trick: nudge the content behind the panel toward one substrate so nav text keeps AA contrast over anything. The scrolled value lives in glass.dim-scrolled." },
|
|
360
|
+
"dim-scrolled": { "$value": "1.15", "$extensions": { "portfolio": { "themeLight": true } }, "$description": "Backdrop brightness clamp once the header condenses into the floating pill. Light brightens the content behind it so dark nav text stays legible; dark darkens it to protect the near-white nav (see darkTheme)." }
|
|
361
|
+
},
|
|
362
|
+
|
|
363
|
+
"darkTheme": {
|
|
364
|
+
"$description": "[data-theme=\"dark\"] semantic overrides (explicit toggle).",
|
|
365
|
+
"color-bg": { "$value": "{neutral.950}" },
|
|
366
|
+
"color-surface": { "$value": "{neutral.850}" },
|
|
367
|
+
"color-surface-sunken": { "$value": "{neutral.900}" },
|
|
368
|
+
"color-text-primary": { "$value": "{neutral.150}" },
|
|
369
|
+
"color-text-secondary": { "$value": "{neutral.500}" },
|
|
370
|
+
"color-text-tertiary": { "$value": "{neutral.550}" },
|
|
371
|
+
"color-border": { "$value": "{neutral.800}" },
|
|
372
|
+
"color-border-strong": { "$value": "{neutral.700}" },
|
|
373
|
+
"color-border-hover": { "$value": "{brand.lime}" },
|
|
374
|
+
"color-accent": { "$value": "{green.500}" },
|
|
375
|
+
"color-accent-hover": { "$value": "{brand.lime-dim}" },
|
|
376
|
+
"color-accent-subtle": { "$value": "{green.950}" },
|
|
377
|
+
"color-on-accent": { "$value": "{neutral.950}" },
|
|
378
|
+
"color-focus-ring": { "$value": "{green.500}" },
|
|
379
|
+
"color-link": { "$value": "{green.500}" },
|
|
380
|
+
"color-link-hover": { "$value": "{neutral.0}" },
|
|
381
|
+
"color-accent-emphasis": { "$value": "{green.500}" },
|
|
382
|
+
"shadow-soft": { "$value": "0 1px 2px rgba(0, 0, 0, 0.5), 0 1px 3px rgba(0, 0, 0, 0.3)" },
|
|
383
|
+
"shadow-lift": { "$value": "0 4px 12px rgba(0, 0, 0, 0.6), 0 2px 4px rgba(0, 0, 0, 0.4)" },
|
|
384
|
+
"accent-period-shadow": { "$value": "none" },
|
|
385
|
+
"accent-dot-shadow": { "$value": "none" },
|
|
386
|
+
"color-text-muted-emphasis": { "$value": "{brand.lime}" },
|
|
387
|
+
"color-dot-inactive": { "$value": "{neutral.500}", "$description": "Inactive dot on dark: brighter grey to clear 3:1 on the near-black page." },
|
|
388
|
+
"glass-tint": { "$value": "rgb(var(--brand-ink-rgb) / 0.5)" },
|
|
389
|
+
"glass-edge-top": { "$value": "rgb(255 255 255 / 0.6)" },
|
|
390
|
+
"glass-edge-bottom": { "$value": "rgb(255 255 255 / 0.05)" },
|
|
391
|
+
"glass-specular": { "$value": "inset 0 0 0 0 rgb(255 255 255 / 0)", "$description": "Dark: no inner specular (transparent no-op so the box-shadow list stays valid). Tuned by Nathan 2026-06-04." },
|
|
392
|
+
"glass-shadow": { "$value": "0 1px 2px rgb(0 0 0 / 0.77), 0 10px 30px rgb(0 0 0 / 0.42)", "$description": "Dark: tight contact shadow plus soft ambient. Tuned 2026-06-04." },
|
|
393
|
+
"glass-blur": { "$value": "7px", "$description": "Dark override (light keeps the :root 10px). Tuned 2026-06-04." },
|
|
394
|
+
"glass-blur-webkit": { "$value": "11px", "$description": "Dark override (light keeps the :root 14px)." },
|
|
395
|
+
"glass-dim-scrolled": { "$value": "1.05", "$description": "Scrolled backdrop dim, dark: near-neutral per Nathan's 2026-06-04 tuning (was 0.4). NOTE: the old 0.4 darkened content behind the floating pill to protect near-white nav contrast over light images; verify legibility over light content." }
|
|
396
|
+
},
|
|
397
|
+
|
|
398
|
+
"highContrast": {
|
|
399
|
+
"$description": "prefers-contrast: more overrides layered on light. Authored here so the token source owns every theme path (audit TK-03); build.mjs emits the media query. Every value is an existing primitive.",
|
|
400
|
+
"color-bg": { "$value": "{neutral.0}" },
|
|
401
|
+
"color-surface": { "$value": "{neutral.0}" },
|
|
402
|
+
"color-surface-sunken": { "$value": "{neutral.0}" },
|
|
403
|
+
"color-text-primary": { "$value": "{neutral.950}" },
|
|
404
|
+
"color-text-secondary": { "$value": "{neutral.950}" },
|
|
405
|
+
"color-text-tertiary": { "$value": "{neutral.850}" },
|
|
406
|
+
"color-border": { "$value": "{neutral.950}" },
|
|
407
|
+
"color-border-strong": { "$value": "{neutral.950}" },
|
|
408
|
+
"color-border-hover": { "$value": "{neutral.950}" },
|
|
409
|
+
"color-border-brand": { "$value": "{neutral.950}" },
|
|
410
|
+
"color-focus-ring": { "$value": "{neutral.950}" },
|
|
411
|
+
"color-link": { "$value": "{neutral.950}" },
|
|
412
|
+
"color-link-hover": { "$value": "{neutral.950}" },
|
|
413
|
+
"color-accent": { "$value": "{neutral.950}" },
|
|
414
|
+
"color-accent-hover": { "$value": "{neutral.850}" },
|
|
415
|
+
"color-on-accent": { "$value": "{neutral.0}" },
|
|
416
|
+
"color-accent-subtle": { "$value": "{neutral.200}" },
|
|
417
|
+
"color-accent-emphasis": { "$value": "{neutral.950}" }
|
|
418
|
+
},
|
|
419
|
+
|
|
420
|
+
"highContrastDark": {
|
|
421
|
+
"$description": "prefers-contrast: more overrides layered on dark (explicit toggle AND OS dark; build.mjs emits both scopes from this one group).",
|
|
422
|
+
"color-bg": { "$value": "{neutral.950}" },
|
|
423
|
+
"color-surface": { "$value": "{neutral.950}" },
|
|
424
|
+
"color-surface-sunken": { "$value": "{neutral.950}" },
|
|
425
|
+
"color-text-primary": { "$value": "{neutral.0}" },
|
|
426
|
+
"color-text-secondary": { "$value": "{neutral.0}" },
|
|
427
|
+
"color-text-tertiary": { "$value": "{neutral.150}" },
|
|
428
|
+
"color-border": { "$value": "{neutral.0}" },
|
|
429
|
+
"color-border-strong": { "$value": "{neutral.0}" },
|
|
430
|
+
"color-border-hover": { "$value": "{green.500}" },
|
|
431
|
+
"color-border-brand": { "$value": "{green.500}" },
|
|
432
|
+
"color-focus-ring": { "$value": "{green.500}" },
|
|
433
|
+
"color-link": { "$value": "{green.500}" },
|
|
434
|
+
"color-link-hover": { "$value": "{neutral.0}" },
|
|
435
|
+
"color-accent": { "$value": "{green.500}" },
|
|
436
|
+
"color-accent-hover": { "$value": "{brand.lime-dim}" },
|
|
437
|
+
"color-on-accent": { "$value": "{neutral.950}" },
|
|
438
|
+
"color-accent-subtle": { "$value": "{green.950}" },
|
|
439
|
+
"color-accent-emphasis": { "$value": "{neutral.0}" }
|
|
440
|
+
}
|
|
441
|
+
}
|